File: | src/sbin/isakmpd/log.c |
Warning: | line 401, column 17 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
61 | static void _log_print(int, int, const char *, va_list, int, int); | |||
62 | ||||
63 | static FILE *log_output; | |||
64 | ||||
65 | int verbose_logging = 0; | |||
66 | static int log_level[LOG_ENDCLASS]; | |||
67 | ||||
68 | #define TCPDUMP_MAGIC0xa1b2c3d4 0xa1b2c3d4 | |||
69 | #define SNAPLEN(64 * 1024) (64 * 1024) | |||
70 | ||||
71 | struct 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 | ||||
80 | struct 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 | ||||
86 | static char *pcaplog_file = NULL((void *)0); | |||
87 | static FILE *packet_log; | |||
88 | static u_int8_t *packet_buf = NULL((void *)0); | |||
89 | ||||
90 | static int udp_cksum(struct packhdr *, const struct udphdr *, | |||
91 | u_int16_t *); | |||
92 | static u_int16_t in_cksum(const u_int16_t *, int); | |||
93 | ||||
94 | void | |||
95 | log_init(int debug) | |||
96 | { | |||
97 | if (debug) | |||
98 | log_output = stderr(&__sF[2]); | |||
99 | else | |||
100 | log_to(0); /* syslog */ | |||
101 | } | |||
102 | ||||
103 | void | |||
104 | log_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 | ||||
136 | void | |||
137 | log_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 | ||||
146 | FILE * | |||
147 | log_current(void) | |||
148 | { | |||
149 | return log_output; | |||
150 | } | |||
151 | ||||
152 | static 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 | ||||
166 | static 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 | ||||
228 | void | |||
229 | log_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 | ||||
244 | void | |||
245 | log_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 | ||||
277 | void | |||
278 | log_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 | ||||
299 | void | |||
300 | log_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 | ||||
317 | void | |||
318 | log_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 | ||||
327 | void | |||
328 | log_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 | ||||
340 | void | |||
341 | log_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 | ||||
350 | void | |||
351 | log_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 | ||||
360 | void | |||
361 | log_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 | ||||
371 | void | |||
372 | log_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 | ||||
382 | void | |||
383 | log_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) | |||
392 | packet_buf = malloc(SNAPLEN(64 * 1024)); | |||
393 | ||||
394 | if (!packet_buf
| |||
395 | log_error("log_packet_init: malloc (%d) failed", SNAPLEN(64 * 1024)); | |||
396 | return; | |||
397 | } | |||
398 | if (pcaplog_file
| |||
399 | free(pcaplog_file); | |||
400 | ||||
401 | pcaplog_file = strdup(newname); | |||
| ||||
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 | ||||
456 | void | |||
457 | log_packet_restart(char *newname) | |||
458 | { | |||
459 | if (packet_log) { | |||
| ||||
460 | log_print("log_packet_restart: capture already active on " | |||
461 | "file \"%s\"", pcaplog_file); | |||
462 | return; | |||
463 | } | |||
464 | if (newname) | |||
465 | log_packet_init(newname); | |||
466 | else if (!pcaplog_file) | |||
467 | log_packet_init(PCAP_FILE_DEFAULT"/var/run/isakmpd.pcap"); | |||
468 | else | |||
469 | log_packet_init(pcaplog_file); | |||
470 | } | |||
471 | ||||
472 | void | |||
473 | log_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 | ||||
483 | void | |||
484 | log_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 | ||||
541 | setup_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. */ | |||
595 | static int | |||
596 | udp_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. */ | |||
675 | static u_int16_t | |||
676 | in_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 | } |