Bug Summary

File:src/sbin/isakmpd/log.c
Warning:line 401, column 17
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name log.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sbin/isakmpd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sbin/isakmpd -I . -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/isakmpd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/sbin/isakmpd/log.c
1/* $OpenBSD: log.c,v 1.64 2018/01/15 09:54:48 mpi Exp $ */
2/* $EOM: log.c,v 1.30 2000/09/29 08:19:23 niklas Exp $ */
3
4/*
5 * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved.
6 * Copyright (c) 1999, 2000, 2001, 2003 Håkan Olsson. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/*
30 * This code was written under funding by Ericsson Radio Systems.
31 */
32
33#include <sys/types.h>
34#include <sys/time.h>
35
36#include <sys/socket.h>
37#include <sys/stat.h>
38#include <sys/uio.h>
39#include <netinet/in.h>
40#include <netinet/ip.h>
41#include <netinet/ip6.h>
42#include <netinet/udp.h>
43#include <arpa/inet.h>
44
45#include <pcap.h>
46
47#include <errno(*__errno()).h>
48#include <stdio.h>
49#include <stdlib.h>
50#include <string.h>
51#include <syslog.h>
52#include <stdarg.h>
53#include <unistd.h>
54
55#include "conf.h"
56#include "isakmp_num.h"
57#include "log.h"
58#include "monitor.h"
59#include "util.h"
60
61static void _log_print(int, int, const char *, va_list, int, int);
62
63static FILE *log_output;
64
65int verbose_logging = 0;
66static int log_level[LOG_ENDCLASS];
67
68#define TCPDUMP_MAGIC0xa1b2c3d4 0xa1b2c3d4
69#define SNAPLEN(64 * 1024) (64 * 1024)
70
71struct packhdr {
72 struct pcap_pkthdr pcap;/* pcap file packet header */
73 u_int32_t sa_family; /* address family */
74 union {
75 struct ip ip4; /* IPv4 header (w/o options) */
76 struct ip6_hdr ip6; /* IPv6 header */
77 } ip;
78};
79
80struct isakmp_hdr {
81 u_int8_t icookie[8], rcookie[8];
82 u_int8_t next, ver, type, flags;
83 u_int32_t msgid, len;
84};
85
86static char *pcaplog_file = NULL((void *)0);
87static FILE *packet_log;
88static u_int8_t *packet_buf = NULL((void *)0);
89
90static int udp_cksum(struct packhdr *, const struct udphdr *,
91 u_int16_t *);
92static u_int16_t in_cksum(const u_int16_t *, int);
93
94void
95log_init(int debug)
96{
97 if (debug)
98 log_output = stderr(&__sF[2]);
99 else
100 log_to(0); /* syslog */
101}
102
103void
104log_reinit(void)
105{
106 struct conf_list *logging;
107 struct conf_list_node *logclass;
108 int class, level;
109
110 logging = conf_get_list("General", "Logverbose");
111 if (logging) {
112 verbose_logging = 1;
113 conf_free_list(logging);
114 }
115 logging = conf_get_list("General", "Loglevel");
116 if (!logging)
117 return;
118
119 for (logclass = TAILQ_FIRST(&logging->fields)((&logging->fields)->tqh_first); logclass;
120 logclass = TAILQ_NEXT(logclass, link)((logclass)->link.tqe_next)) {
121 if (sscanf(logclass->field, "%d=%d", &class, &level) != 2) {
122 if (sscanf(logclass->field, "A=%d", &level) == 1)
123 for (class = 0; class < LOG_ENDCLASS; class++)
124 log_debug_cmd(class, level);
125 else {
126 log_print("init: invalid logging class or "
127 "level: %s", logclass->field);
128 continue;
129 }
130 } else
131 log_debug_cmd(class, level);
132 }
133 conf_free_list(logging);
134}
135
136void
137log_to(FILE *f)
138{
139 if (!log_output && f)
140 closelog();
141 log_output = f;
142 if (!f)
143 openlog("isakmpd", LOG_PID0x01 | LOG_CONS0x02, LOG_DAEMON(3<<3));
144}
145
146FILE *
147log_current(void)
148{
149 return log_output;
150}
151
152static char *
153_log_get_class(int error_class)
154{
155 /* XXX For test purposes. To be removed later on? */
156 static char *class_text[] = LOG_CLASSES_TEXT{ "Misc", "Trpt", "Mesg", "Cryp", "Timr", "Sdep", "SA ", "Exch"
, "Negt", "Plcy", "UI " }
;
157
158 if (error_class < 0)
159 return "Dflt";
160 else if (error_class >= LOG_ENDCLASS)
161 return "Unkn";
162 else
163 return class_text[error_class];
164}
165
166static void
167_log_print(int error, int syslog_level, const char *fmt, va_list ap,
168 int class, int level)
169{
170 char buffer[LOG_SIZE200], nbuf[LOG_SIZE200 + 32];
171 static const char fallback_msg[] =
172 "write to log file failed (errno %d), redirecting to syslog";
173 int len;
174 struct tm *tm;
175 struct timeval now;
176 time_t t;
177
178 len = vsnprintf(buffer, sizeof buffer, fmt, ap);
179 if (len > 0 && len < (int) sizeof buffer - 1 && error)
180 snprintf(buffer + len, sizeof buffer - len, ": %s",
181 strerror(errno(*__errno())));
182 if (log_output) {
183 gettimeofday(&now, 0);
184 t = now.tv_sec;
185 tm = localtime(&t);
186 if (class >= 0)
187 snprintf(nbuf, sizeof nbuf,
188 "%02d%02d%02d.%06ld %s %02d ",
189 tm->tm_hour, tm->tm_min, tm->tm_sec, now.tv_usec,
190 _log_get_class(class), level);
191 else /* LOG_PRINT (-1) or LOG_REPORT (-2) */
192 snprintf(nbuf, sizeof nbuf, "%02d%02d%02d.%06ld %s ",
193 tm->tm_hour, tm->tm_min, tm->tm_sec, now.tv_usec,
194 class == LOG_PRINT-1 ? "Default" : "Report>");
195 strlcat(nbuf, buffer, sizeof nbuf);
196 strlcat(nbuf, getuid() ? "" : " [priv]", LOG_SIZE200 + 32);
197 strlcat(nbuf, "\n", sizeof nbuf);
198
199 if (fwrite(nbuf, strlen(nbuf), 1, log_output) == 0) {
200 /* Report fallback. */
201 syslog(LOG_ALERT1, fallback_msg, errno(*__errno()));
202 fprintf(log_output, fallback_msg, errno(*__errno()));
203
204 /*
205 * Close log_output to prevent isakmpd from locking
206 * the file. We may need to explicitly close stdout
207 * to do this properly.
208 * XXX - Figure out how to match two FILE *'s and
209 * rewrite.
210 */
211 if (fileno(log_output)(!__isthreaded ? ((log_output)->_file) : (fileno)(log_output
))
!= -1 &&
212 fileno(stdout)(!__isthreaded ? (((&__sF[1]))->_file) : (fileno)((&
__sF[1])))
== fileno(log_output)(!__isthreaded ? ((log_output)->_file) : (fileno)(log_output
))
)
213 fclose(stdout(&__sF[1]));
214 fclose(log_output);
215
216 /* Fallback to syslog. */
217 log_to(0);
218
219 /* (Re)send current message to syslog(). */
220 syslog(class == LOG_REPORT-2 ? LOG_ALERT1 :
221 syslog_level, "%s", buffer);
222 }
223 } else
224 syslog(class == LOG_REPORT-2 ? LOG_ALERT1 : syslog_level, "%s",
225 buffer);
226}
227
228void
229log_debug(int cls, int level, const char *fmt, ...)
230{
231 va_list ap;
232
233 /*
234 * If we are not debugging this class, or the level is too low, just
235 * return.
236 */
237 if (cls >= 0 && (log_level[cls] == 0 || level > log_level[cls]))
238 return;
239 va_start(ap, fmt)__builtin_va_start(ap, fmt);
240 _log_print(0, LOG_INFO6, fmt, ap, cls, level);
241 va_end(ap)__builtin_va_end(ap);
242}
243
244void
245log_debug_buf(int cls, int level, const char *header, const u_int8_t *buf,
246 size_t sz)
247{
248 size_t i, j;
249 char s[73];
250
251 /*
252 * If we are not debugging this class, or the level is too low, just
253 * return.
254 */
255 if (cls >= 0 && (log_level[cls] == 0 || level > log_level[cls]))
256 return;
257
258 log_debug(cls, level, "%s:", header);
259 for (i = j = 0; i < sz;) {
260 snprintf(s + j, sizeof s - j, "%02x", buf[i++]);
261 j += strlen(s + j);
262 if (i % 4 == 0) {
263 if (i % 32 == 0) {
264 s[j] = '\0';
265 log_debug(cls, level, "%s", s);
266 j = 0;
267 } else
268 s[j++] = ' ';
269 }
270 }
271 if (j) {
272 s[j] = '\0';
273 log_debug(cls, level, "%s", s);
274 }
275}
276
277void
278log_debug_cmd(int cls, int level)
279{
280 if (cls < 0 || cls >= LOG_ENDCLASS) {
281 log_print("log_debug_cmd: invalid debugging class %d", cls);
282 return;
283 }
284 if (level < 0) {
285 log_print("log_debug_cmd: invalid debugging level %d for "
286 "class %d", level, cls);
287 return;
288 }
289 if (level == log_level[cls])
290 log_print("log_debug_cmd: log level unchanged for class %d",
291 cls);
292 else {
293 log_print("log_debug_cmd: log level changed from %d to %d "
294 "for class %d", log_level[cls], level, cls);
295 log_level[cls] = level;
296 }
297}
298
299void
300log_debug_toggle(void)
301{
302 static int log_level_copy[LOG_ENDCLASS], toggle = 0;
303
304 if (!toggle) {
305 LOG_DBG((LOG_MISC, 50, "log_debug_toggle: "log_debug (LOG_MISC, 50, "log_debug_toggle: " "debug levels cleared"
)
306 "debug levels cleared"))log_debug (LOG_MISC, 50, "log_debug_toggle: " "debug levels cleared"
)
;
307 memcpy(&log_level_copy, &log_level, sizeof log_level);
308 bzero(&log_level, sizeof log_level);
309 } else {
310 memcpy(&log_level, &log_level_copy, sizeof log_level);
311 LOG_DBG((LOG_MISC, 50, "log_debug_toggle: "log_debug (LOG_MISC, 50, "log_debug_toggle: " "debug levels restored"
)
312 "debug levels restored"))log_debug (LOG_MISC, 50, "log_debug_toggle: " "debug levels restored"
)
;
313 }
314 toggle = !toggle;
315}
316
317void
318log_print(const char *fmt, ...)
319{
320 va_list ap;
321
322 va_start(ap, fmt)__builtin_va_start(ap, fmt);
323 _log_print(0, LOG_NOTICE5, fmt, ap, LOG_PRINT-1, 0);
324 va_end(ap)__builtin_va_end(ap);
325}
326
327void
328log_verbose(const char *fmt, ...)
329{
330 va_list ap;
331
332 if (verbose_logging == 0)
333 return;
334
335 va_start(ap, fmt)__builtin_va_start(ap, fmt);
336 _log_print(0, LOG_NOTICE5, fmt, ap, LOG_PRINT-1, 0);
337 va_end(ap)__builtin_va_end(ap);
338}
339
340void
341log_error(const char *fmt, ...)
342{
343 va_list ap;
344
345 va_start(ap, fmt)__builtin_va_start(ap, fmt);
346 _log_print(1, LOG_ERR3, fmt, ap, LOG_PRINT-1, 0);
347 va_end(ap)__builtin_va_end(ap);
348}
349
350void
351log_errorx(const char *fmt, ...)
352{
353 va_list ap;
354
355 va_start(ap, fmt)__builtin_va_start(ap, fmt);
356 _log_print(0, LOG_ERR3, fmt, ap, LOG_PRINT-1, 0);
357 va_end(ap)__builtin_va_end(ap);
358}
359
360void
361log_fatal(const char *fmt, ...)
362{
363 va_list ap;
364
365 va_start(ap, fmt)__builtin_va_start(ap, fmt);
366 _log_print(1, LOG_CRIT2, fmt, ap, LOG_PRINT-1, 0);
367 va_end(ap)__builtin_va_end(ap);
368 monitor_exit(1);
369}
370
371void
372log_fatalx(const char *fmt, ...)
373{
374 va_list ap;
375
376 va_start(ap, fmt)__builtin_va_start(ap, fmt);
377 _log_print(0, LOG_CRIT2, fmt, ap, LOG_PRINT-1, 0);
378 va_end(ap)__builtin_va_end(ap);
379 monitor_exit(1);
380}
381
382void
383log_packet_init(char *newname)
384{
385 struct pcap_file_header sf_hdr;
386 struct stat st;
387 mode_t old_umask;
388 char *mode;
389
390 /* Allocate packet buffer first time through. */
391 if (!packet_buf)
8
Assuming 'packet_buf' is non-null
9
Taking false branch
392 packet_buf = malloc(SNAPLEN(64 * 1024));
393
394 if (!packet_buf
9.1
'packet_buf' is non-null
) {
10
Taking false branch
395 log_error("log_packet_init: malloc (%d) failed", SNAPLEN(64 * 1024));
396 return;
397 }
398 if (pcaplog_file
10.1
'pcaplog_file' is non-null
&& strcmp(pcaplog_file, PCAP_FILE_DEFAULT"/var/run/isakmpd.pcap") != 0)
11
Assuming the condition is true
12
Taking true branch
399 free(pcaplog_file);
13
Memory is released
400
401 pcaplog_file = strdup(newname);
14
Use of memory after it is freed
402 if (!pcaplog_file) {
403 log_error("log_packet_init: strdup (\"%s\") failed", newname);
404 return;
405 }
406 /* Does the file already exist? XXX lstat() or stat()? */
407 /* XXX This is a fstat! */
408 if (monitor_stat(pcaplog_file, &st) == 0) {
409 /* Sanity checks. */
410 if (!S_ISREG(st.st_mode)((st.st_mode & 0170000) == 0100000)) {
411 log_print("log_packet_init: existing capture file is "
412 "not a regular file");
413 return;
414 }
415 if ((st.st_mode & (S_IRWXG0000070 | S_IRWXO0000007)) != 0) {
416 log_print("log_packet_init: existing capture "
417 "file has bad modes");
418 return;
419 }
420 /*
421 * XXX It would be nice to check if it actually is a pcap
422 * file...
423 */
424
425 mode = "a";
426 } else
427 mode = "w";
428
429 old_umask = umask(S_IRWXG0000070 | S_IRWXO0000007);
430 packet_log = monitor_fopen(pcaplog_file, mode);
431 umask(old_umask);
432
433 if (!packet_log) {
434 log_error("log_packet_init: fopen (\"%s\", \"%s\") failed",
435 pcaplog_file, mode);
436 return;
437 }
438 log_print("log_packet_init: "
439 "starting IKE packet capture to file \"%s\"", pcaplog_file);
440
441 /* If this is a new file, we need to write a PCAP header to it. */
442 if (*mode == 'w') {
443 sf_hdr.magic = TCPDUMP_MAGIC0xa1b2c3d4;
444 sf_hdr.version_major = PCAP_VERSION_MAJOR2;
445 sf_hdr.version_minor = PCAP_VERSION_MINOR4;
446 sf_hdr.thiszone = 0;
447 sf_hdr.snaplen = SNAPLEN(64 * 1024);
448 sf_hdr.sigfigs = 0;
449 sf_hdr.linktype = DLT_LOOP12;
450
451 fwrite((char *) &sf_hdr, sizeof sf_hdr, 1, packet_log);
452 fflush(packet_log);
453 }
454}
455
456void
457log_packet_restart(char *newname)
458{
459 if (packet_log) {
1
Assuming 'packet_log' is null
2
Taking false branch
460 log_print("log_packet_restart: capture already active on "
461 "file \"%s\"", pcaplog_file);
462 return;
463 }
464 if (newname)
3
Assuming 'newname' is null
4
Taking false branch
465 log_packet_init(newname);
466 else if (!pcaplog_file)
5
Assuming 'pcaplog_file' is non-null
6
Taking false branch
467 log_packet_init(PCAP_FILE_DEFAULT"/var/run/isakmpd.pcap");
468 else
469 log_packet_init(pcaplog_file);
7
Calling 'log_packet_init'
470}
471
472void
473log_packet_stop(void)
474{
475 /* Stop capture. */
476 if (packet_log) {
477 fclose(packet_log);
478 log_print("log_packet_stop: stopped capture");
479 }
480 packet_log = 0;
481}
482
483void
484log_packet_iov(struct sockaddr *src, struct sockaddr *dst, struct iovec *iov,
485 int iovcnt)
486{
487 struct isakmp_hdr *isakmphdr;
488 struct packhdr hdr;
489 struct udphdr udp;
490 struct timeval tv;
491 int off, datalen, hdrlen, i, add_espmarker = 0;
492 const u_int32_t espmarker = 0;
493
494 for (i = 0, datalen = 0; i < iovcnt; i++)
495 datalen += iov[i].iov_len;
496
497 if (!packet_log || datalen > SNAPLEN(64 * 1024))
498 return;
499
500 /* copy packet into buffer */
501 for (i = 0, off = 0; i < iovcnt; i++) {
502 memcpy(packet_buf + off, iov[i].iov_base, iov[i].iov_len);
503 off += iov[i].iov_len;
504 }
505
506 bzero(&hdr, sizeof hdr);
507 bzero(&udp, sizeof udp);
508
509 /* isakmp - turn off the encryption bit in the isakmp hdr */
510 isakmphdr = (struct isakmp_hdr *) packet_buf;
511 isakmphdr->flags &= ~(ISAKMP_FLAGS_ENC1);
512
513 /* udp */
514 udp.uh_sport = sockaddr_port(src);
515 udp.uh_dport = sockaddr_port(dst);
516 datalen += sizeof udp;
517 if (ntohs(udp.uh_sport)(__uint16_t)(__builtin_constant_p(udp.uh_sport) ? (__uint16_t
)(((__uint16_t)(udp.uh_sport) & 0xffU) << 8 | ((__uint16_t
)(udp.uh_sport) & 0xff00U) >> 8) : __swap16md(udp.uh_sport
))
== 4500 ||
518 ntohs(udp.uh_dport)(__uint16_t)(__builtin_constant_p(udp.uh_dport) ? (__uint16_t
)(((__uint16_t)(udp.uh_dport) & 0xffU) << 8 | ((__uint16_t
)(udp.uh_dport) & 0xff00U) >> 8) : __swap16md(udp.uh_dport
))
== 4500) { /* XXX Quick and dirty */
519 add_espmarker = 1;
520 datalen += sizeof espmarker;
521 }
522 udp.uh_ulen = htons(datalen)(__uint16_t)(__builtin_constant_p(datalen) ? (__uint16_t)(((__uint16_t
)(datalen) & 0xffU) << 8 | ((__uint16_t)(datalen) &
0xff00U) >> 8) : __swap16md(datalen))
;
523
524 /* ip */
525 hdr.sa_family = htonl(src->sa_family)(__uint32_t)(__builtin_constant_p(src->sa_family) ? (__uint32_t
)(((__uint32_t)(src->sa_family) & 0xff) << 24 | (
(__uint32_t)(src->sa_family) & 0xff00) << 8 | ((
__uint32_t)(src->sa_family) & 0xff0000) >> 8 | (
(__uint32_t)(src->sa_family) & 0xff000000) >> 24
) : __swap32md(src->sa_family))
;
526 switch (src->sa_family) {
527 default:
528 /* Assume IPv4. XXX Can 'default' ever happen here? */
529 hdr.sa_family = htonl(AF_INET)(__uint32_t)(__builtin_constant_p(2) ? (__uint32_t)(((__uint32_t
)(2) & 0xff) << 24 | ((__uint32_t)(2) & 0xff00)
<< 8 | ((__uint32_t)(2) & 0xff0000) >> 8 | (
(__uint32_t)(2) & 0xff000000) >> 24) : __swap32md(2
))
;
530 hdr.ip.ip4.ip_src.s_addr = 0x02020202;
531 hdr.ip.ip4.ip_dst.s_addr = 0x01010101;
532 /* The rest of the setup is common to AF_INET. */
533 goto setup_ip4;
534
535 case AF_INET2:
536 hdr.ip.ip4.ip_src.s_addr =
537 ((struct sockaddr_in *)src)->sin_addr.s_addr;
538 hdr.ip.ip4.ip_dst.s_addr =
539 ((struct sockaddr_in *)dst)->sin_addr.s_addr;
540
541setup_ip4:
542 hdrlen = sizeof hdr.ip.ip4;
543 hdr.ip.ip4.ip_v = 0x4;
544 hdr.ip.ip4.ip_hl = 0x5;
545 hdr.ip.ip4.ip_p = IPPROTO_UDP17;
546 hdr.ip.ip4.ip_len = htons(datalen + hdrlen)(__uint16_t)(__builtin_constant_p(datalen + hdrlen) ? (__uint16_t
)(((__uint16_t)(datalen + hdrlen) & 0xffU) << 8 | (
(__uint16_t)(datalen + hdrlen) & 0xff00U) >> 8) : __swap16md
(datalen + hdrlen))
;
547 /* Let's use the IP ID as a "packet counter". */
548 i = ntohs(hdr.ip.ip4.ip_id)(__uint16_t)(__builtin_constant_p(hdr.ip.ip4.ip_id) ? (__uint16_t
)(((__uint16_t)(hdr.ip.ip4.ip_id) & 0xffU) << 8 | (
(__uint16_t)(hdr.ip.ip4.ip_id) & 0xff00U) >> 8) : __swap16md
(hdr.ip.ip4.ip_id))
+ 1;
549 hdr.ip.ip4.ip_id = htons(i)(__uint16_t)(__builtin_constant_p(i) ? (__uint16_t)(((__uint16_t
)(i) & 0xffU) << 8 | ((__uint16_t)(i) & 0xff00U
) >> 8) : __swap16md(i))
;
550 /* Calculate IP header checksum. */
551 hdr.ip.ip4.ip_sum = in_cksum((u_int16_t *) & hdr.ip.ip4,
552 hdr.ip.ip4.ip_hl << 2);
553 break;
554
555 case AF_INET624:
556 hdrlen = sizeof(hdr.ip.ip6);
557 hdr.ip.ip6.ip6_vfcip6_ctlun.ip6_un2_vfc = IPV6_VERSION0x60;
558 hdr.ip.ip6.ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_UDP17;
559 hdr.ip.ip6.ip6_plenip6_ctlun.ip6_un1.ip6_un1_plen = udp.uh_ulen;
560 memcpy(&hdr.ip.ip6.ip6_src,
561 &((struct sockaddr_in6 *)src)->sin6_addr,
562 sizeof hdr.ip.ip6.ip6_src);
563 memcpy(&hdr.ip.ip6.ip6_dst,
564 &((struct sockaddr_in6 *)dst)->sin6_addr,
565 sizeof hdr.ip.ip6.ip6_dst);
566 break;
567 }
568
569 /* Calculate UDP checksum. */
570 udp.uh_sum = udp_cksum(&hdr, &udp, (u_int16_t *) packet_buf);
571 hdrlen += sizeof hdr.sa_family;
572
573 /* pcap file packet header */
574 gettimeofday(&tv, 0);
575 hdr.pcap.ts.tv_sec = tv.tv_sec;
576 hdr.pcap.ts.tv_usec = tv.tv_usec;
577 hdr.pcap.caplen = datalen + hdrlen;
578 hdr.pcap.len = datalen + hdrlen;
579
580 hdrlen += sizeof(struct pcap_pkthdr);
581 datalen -= sizeof(struct udphdr);
582
583 /* Write to pcap file. */
584 fwrite(&hdr, hdrlen, 1, packet_log); /* pcap + IP */
585 fwrite(&udp, sizeof(struct udphdr), 1, packet_log); /* UDP */
586 if (add_espmarker) {
587 fwrite(&espmarker, sizeof espmarker, 1, packet_log);
588 datalen -= sizeof espmarker;
589 }
590 fwrite(packet_buf, datalen, 1, packet_log); /* IKE-data */
591 fflush(packet_log);
592}
593
594/* Copied from tcpdump/print-udp.c, mostly rewritten. */
595static int
596udp_cksum(struct packhdr *hdr, const struct udphdr *u, u_int16_t *d)
597{
598 struct ip *ip4;
599 struct ip6_hdr *ip6;
600 int i, hdrlen, tlen = ntohs(u->uh_ulen)(__uint16_t)(__builtin_constant_p(u->uh_ulen) ? (__uint16_t
)(((__uint16_t)(u->uh_ulen) & 0xffU) << 8 | ((__uint16_t
)(u->uh_ulen) & 0xff00U) >> 8) : __swap16md(u->
uh_ulen))
- sizeof(struct udphdr);
601
602 union phu {
603 struct ip4pseudo {
604 struct in_addr src;
605 struct in_addr dst;
606 u_int8_t z;
607 u_int8_t proto;
608 u_int16_t len;
609 } ip4p;
610 struct ip6pseudo {
611 struct in6_addr src;
612 struct in6_addr dst;
613 u_int32_t plen;
614 u_int16_t z0;
615 u_int8_t z1;
616 u_int8_t nxt;
617 } ip6p;
618 u_int16_t pa[20];
619 } phu;
620 const u_int16_t *sp;
621 u_int32_t sum;
622
623 /* Setup pseudoheader. */
624 bzero(phu.pa, sizeof phu);
625 switch (ntohl(hdr->sa_family)(__uint32_t)(__builtin_constant_p(hdr->sa_family) ? (__uint32_t
)(((__uint32_t)(hdr->sa_family) & 0xff) << 24 | (
(__uint32_t)(hdr->sa_family) & 0xff00) << 8 | ((
__uint32_t)(hdr->sa_family) & 0xff0000) >> 8 | (
(__uint32_t)(hdr->sa_family) & 0xff000000) >> 24
) : __swap32md(hdr->sa_family))
) {
626 case AF_INET2:
627 ip4 = &hdr->ip.ip4;
628 memcpy(&phu.ip4p.src, &ip4->ip_src, sizeof(struct in_addr));
629 memcpy(&phu.ip4p.dst, &ip4->ip_dst, sizeof(struct in_addr));
630 phu.ip4p.proto = ip4->ip_p;
631 phu.ip4p.len = u->uh_ulen;
632 hdrlen = sizeof phu.ip4p;
633 break;
634
635 case AF_INET624:
636 ip6 = &hdr->ip.ip6;
637 memcpy(&phu.ip6p.src, &ip6->ip6_src, sizeof(phu.ip6p.src));
638 memcpy(&phu.ip6p.dst, &ip6->ip6_dst, sizeof(phu.ip6p.dst));
639 phu.ip6p.plen = u->uh_ulen;
640 phu.ip6p.nxt = ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt;
641 hdrlen = sizeof phu.ip6p;
642 break;
643
644 default:
645 return 0;
646 }
647
648 /* IPv6 wants a 0xFFFF checksum "on error", not 0x0. */
649 if (tlen < 0)
650 return (ntohl(hdr->sa_family)(__uint32_t)(__builtin_constant_p(hdr->sa_family) ? (__uint32_t
)(((__uint32_t)(hdr->sa_family) & 0xff) << 24 | (
(__uint32_t)(hdr->sa_family) & 0xff00) << 8 | ((
__uint32_t)(hdr->sa_family) & 0xff0000) >> 8 | (
(__uint32_t)(hdr->sa_family) & 0xff000000) >> 24
) : __swap32md(hdr->sa_family))
== AF_INET2 ? 0 : 0xFFFF);
651
652 sum = 0;
653 for (i = 0; i < hdrlen; i += 2)
654 sum += phu.pa[i / 2];
655
656 sp = (const u_int16_t *)u;
657 for (i = 0; i < (int)sizeof(struct udphdr); i += 2)
658 sum += *sp++;
659
660 sp = d;
661 for (i = 0; i < (tlen & ~1); i += 2)
662 sum += *sp++;
663
664 if (tlen & 1)
665 sum += htons((*(const char *)sp) << 8)(__uint16_t)(__builtin_constant_p((*(const char *)sp) <<
8) ? (__uint16_t)(((__uint16_t)((*(const char *)sp) <<
8) & 0xffU) << 8 | ((__uint16_t)((*(const char *)sp
) << 8) & 0xff00U) >> 8) : __swap16md((*(const
char *)sp) << 8))
;
666
667 while (sum > 0xffff)
668 sum = (sum & 0xffff) + (sum >> 16);
669 sum = ~sum & 0xffff;
670
671 return sum;
672}
673
674/* Copied from tcpdump/print-ip.c, modified. */
675static u_int16_t
676in_cksum(const u_int16_t *w, int len)
677{
678 int nleft = len, sum = 0;
679 u_int16_t answer;
680
681 while (nleft > 1) {
682 sum += *w++;
683 nleft -= 2;
684 }
685 if (nleft == 1)
686 sum += htons(*(const u_char *)w << 8)(__uint16_t)(__builtin_constant_p(*(const u_char *)w <<
8) ? (__uint16_t)(((__uint16_t)(*(const u_char *)w << 8
) & 0xffU) << 8 | ((__uint16_t)(*(const u_char *)w <<
8) & 0xff00U) >> 8) : __swap16md(*(const u_char *)
w << 8))
;
687
688 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
689 sum += (sum >> 16); /* add carry */
690 answer = ~sum; /* truncate to 16 bits */
691 return answer;
692}