xref: /openbsd/sbin/isakmpd/log.c (revision 76d0caae)
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.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_MAGIC	0xa1b2c3d4
69 #define SNAPLEN		(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;
87 static FILE    *packet_log;
88 static u_int8_t *packet_buf = NULL;
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;
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); logclass;
120 	    logclass = TAILQ_NEXT(logclass, link)) {
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_PID | LOG_CONS, LOG_DAEMON);
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;
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_SIZE], nbuf[LOG_SIZE + 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));
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 ? "Default" : "Report>");
195 		strlcat(nbuf, buffer, sizeof nbuf);
196 		strlcat(nbuf, getuid() ? "" : " [priv]", LOG_SIZE + 32);
197 		strlcat(nbuf, "\n", sizeof nbuf);
198 
199 		if (fwrite(nbuf, strlen(nbuf), 1, log_output) == 0) {
200 			/* Report fallback.  */
201 			syslog(LOG_ALERT, fallback_msg, errno);
202 			fprintf(log_output, fallback_msg, 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) != -1 &&
212 			    fileno(stdout) == fileno(log_output))
213 				fclose(stdout);
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 ? LOG_ALERT :
221 			    syslog_level, "%s", buffer);
222 		}
223 	} else
224 		syslog(class == LOG_REPORT ? LOG_ALERT : 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);
240 	_log_print(0, LOG_INFO, fmt, ap, cls, level);
241 	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: "
306 		    "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: "
312 		    "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);
323 	_log_print(0, LOG_NOTICE, fmt, ap, LOG_PRINT, 0);
324 	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);
336 	_log_print(0, LOG_NOTICE, fmt, ap, LOG_PRINT, 0);
337 	va_end(ap);
338 }
339 
340 void
341 log_error(const char *fmt, ...)
342 {
343 	va_list	ap;
344 
345 	va_start(ap, fmt);
346 	_log_print(1, LOG_ERR, fmt, ap, LOG_PRINT, 0);
347 	va_end(ap);
348 }
349 
350 void
351 log_errorx(const char *fmt, ...)
352 {
353 	va_list ap;
354 
355 	va_start(ap, fmt);
356 	_log_print(0, LOG_ERR, fmt, ap, LOG_PRINT, 0);
357 	va_end(ap);
358 }
359 
360 void
361 log_fatal(const char *fmt, ...)
362 {
363 	va_list	ap;
364 
365 	va_start(ap, fmt);
366 	_log_print(1, LOG_CRIT, fmt, ap, LOG_PRINT, 0);
367 	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);
377 	_log_print(0, LOG_CRIT, fmt, ap, LOG_PRINT, 0);
378 	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);
393 
394 	if (!packet_buf) {
395 		log_error("log_packet_init: malloc (%d) failed", SNAPLEN);
396 		return;
397 	}
398 	if (pcaplog_file && strcmp(pcaplog_file, PCAP_FILE_DEFAULT) != 0)
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)) {
411 			log_print("log_packet_init: existing capture file is "
412 			    "not a regular file");
413 			return;
414 		}
415 		if ((st.st_mode & (S_IRWXG | S_IRWXO)) != 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_IRWXG | S_IRWXO);
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_MAGIC;
444 		sf_hdr.version_major = PCAP_VERSION_MAJOR;
445 		sf_hdr.version_minor = PCAP_VERSION_MINOR;
446 		sf_hdr.thiszone = 0;
447 		sf_hdr.snaplen = SNAPLEN;
448 		sf_hdr.sigfigs = 0;
449 		sf_hdr.linktype = DLT_LOOP;
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);
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)
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_ENC);
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) == 4500 ||
518 	    ntohs(udp.uh_dport) == 4500) { /* XXX Quick and dirty */
519 		add_espmarker = 1;
520 		datalen += sizeof espmarker;
521 	}
522 	udp.uh_ulen = htons(datalen);
523 
524 	/* ip */
525 	hdr.sa_family = htonl(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);
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_INET:
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_UDP;
546 		hdr.ip.ip4.ip_len = htons(datalen + hdrlen);
547 		/* Let's use the IP ID as a "packet counter".  */
548 		i = ntohs(hdr.ip.ip4.ip_id) + 1;
549 		hdr.ip.ip4.ip_id = htons(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_INET6:
556 		hdrlen = sizeof(hdr.ip.ip6);
557 		hdr.ip.ip6.ip6_vfc = IPV6_VERSION;
558 		hdr.ip.ip6.ip6_nxt = IPPROTO_UDP;
559 		hdr.ip.ip6.ip6_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) - 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)) {
626 	case AF_INET:
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_INET6:
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_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) == AF_INET ? 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);
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);
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 }
693