xref: /freebsd/contrib/tcpdump/print-ip.c (revision cb166ce422ac2bc81f42c2a2e2cd68625c11478d)
1 /*
2  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * $FreeBSD$
22  */
23 
24 #ifndef lint
25 static const char rcsid[] =
26     "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.79 1999/12/22 06:27:21 itojun Exp $ (LBL)";
27 #endif
28 
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 
33 #include <sys/param.h>
34 #include <sys/time.h>
35 #include <sys/socket.h>
36 
37 #include <netinet/in.h>
38 #include <netinet/in_systm.h>
39 #include <netinet/ip.h>
40 #include <netinet/ip_var.h>
41 #include <netinet/udp.h>
42 #include <netinet/udp_var.h>
43 #include <netinet/tcp.h>
44 
45 #ifdef HAVE_MALLOC_H
46 #include <malloc.h>
47 #endif
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <unistd.h>
52 
53 #include "addrtoname.h"
54 #include "interface.h"
55 #include "extract.h"			/* must come after interface.h */
56 
57 /* Compatibility */
58 #ifndef	IPPROTO_ND
59 #define	IPPROTO_ND	77
60 #endif
61 
62 #ifndef IN_CLASSD
63 #define IN_CLASSD(i) (((int32_t)(i) & 0xf0000000) == 0xe0000000)
64 #endif
65 
66 /* (following from ipmulti/mrouted/prune.h) */
67 
68 /*
69  * The packet format for a traceroute request.
70  */
71 struct tr_query {
72 	u_int  tr_src;			/* traceroute source */
73 	u_int  tr_dst;			/* traceroute destination */
74 	u_int  tr_raddr;		/* traceroute response address */
75  	u_int  tr_rttlqid;		/* response ttl and qid */
76 };
77 
78 #define TR_GETTTL(x)		(int)(((x) >> 24) & 0xff)
79 #define TR_GETQID(x)		((x) & 0x00ffffff)
80 
81 /*
82  * Traceroute response format.  A traceroute response has a tr_query at the
83  * beginning, followed by one tr_resp for each hop taken.
84  */
85 struct tr_resp {
86 	u_int tr_qarr;			/* query arrival time */
87 	u_int tr_inaddr;		/* incoming interface address */
88 	u_int tr_outaddr;		/* outgoing interface address */
89 	u_int tr_rmtaddr;		/* parent address in source tree */
90 	u_int tr_vifin;			/* input packet count on interface */
91 	u_int tr_vifout;		/* output packet count on interface */
92 	u_int tr_pktcnt;		/* total incoming packets for src-grp */
93 	u_char  tr_rproto;		/* routing proto deployed on router */
94 	u_char  tr_fttl;		/* ttl required to forward on outvif */
95 	u_char  tr_smask;		/* subnet mask for src addr */
96 	u_char  tr_rflags;		/* forwarding error codes */
97 };
98 
99 /* defs within mtrace */
100 #define TR_QUERY 1
101 #define TR_RESP	2
102 
103 /* fields for tr_rflags (forwarding error codes) */
104 #define TR_NO_ERR	0
105 #define TR_WRONG_IF	1
106 #define TR_PRUNED	2
107 #define TR_OPRUNED	3
108 #define TR_SCOPED	4
109 #define TR_NO_RTE	5
110 #define TR_NO_FWD	7
111 #define TR_NO_SPACE	0x81
112 #define TR_OLD_ROUTER	0x82
113 
114 /* fields for tr_rproto (routing protocol) */
115 #define TR_PROTO_DVMRP	1
116 #define TR_PROTO_MOSPF	2
117 #define TR_PROTO_PIM	3
118 #define TR_PROTO_CBT	4
119 
120 static void print_mtrace(register const u_char *bp, register u_int len)
121 {
122 	register struct tr_query *tr = (struct tr_query *)(bp + 8);
123 
124 	printf("mtrace %lu: %s to %s reply-to %s",
125 		(u_long)TR_GETQID(ntohl(tr->tr_rttlqid)),
126 		ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst),
127 		ipaddr_string(&tr->tr_raddr));
128 	if (IN_CLASSD(ntohl(tr->tr_raddr)))
129 		printf(" with-ttl %d", TR_GETTTL(ntohl(tr->tr_rttlqid)));
130 }
131 
132 static void print_mresp(register const u_char *bp, register u_int len)
133 {
134 	register struct tr_query *tr = (struct tr_query *)(bp + 8);
135 
136 	printf("mresp %lu: %s to %s reply-to %s",
137 		(u_long)TR_GETQID(ntohl(tr->tr_rttlqid)),
138 		ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst),
139 		ipaddr_string(&tr->tr_raddr));
140 	if (IN_CLASSD(ntohl(tr->tr_raddr)))
141 		printf(" with-ttl %d", TR_GETTTL(ntohl(tr->tr_rttlqid)));
142 }
143 
144 static void
145 igmp_print(register const u_char *bp, register u_int len,
146 	   register const u_char *bp2)
147 {
148 	register const struct ip *ip;
149 
150 	ip = (const struct ip *)bp2;
151         (void)printf("%s > %s: ",
152 		ipaddr_string(&ip->ip_src),
153 		ipaddr_string(&ip->ip_dst));
154 
155 	if (qflag) {
156 		(void)printf("igmp");
157 		return;
158 	}
159 
160 	TCHECK2(bp[0], 8);
161 	switch (bp[0]) {
162 	case 0x11:
163 		(void)printf("igmp %s query", bp[1] ? "v2" : "v1");
164 		if (bp[1] && bp[1] != 100)
165 			(void)printf(" [intvl %d]", bp[1]);
166 		(void)printf("igmp query");
167 		if (EXTRACT_32BITS(&bp[4]))
168 			(void)printf(" [gaddr %s]", ipaddr_string(&bp[4]));
169 		if (len != 8)
170 			(void)printf(" [len %d]", len);
171 		break;
172 	case 0x12:
173 	case 0x16:
174 		(void)printf("igmp %s report %s",
175 			     (bp[0] & 0x0f) == 6 ? "v2" : "v1",
176 			     ipaddr_string(&bp[4]));
177 		if (len != 8)
178 			(void)printf(" [len %d]", len);
179 		if (bp[1])
180 			(void)printf(" [b1=0x%x]", bp[1]);
181 		break;
182 	case 0x17:
183 		(void)printf("igmp leave %s", ipaddr_string(&bp[4]));
184 		if (len != 8)
185 			(void)printf(" [len %d]", len);
186 		if (bp[1])
187 			(void)printf(" [b1=0x%x]", bp[1]);
188 		break;
189 	case 0x13:
190 		(void)printf("igmp dvmrp");
191 		if (len < 8)
192 			(void)printf(" [len %d]", len);
193 		else
194 			dvmrp_print(bp, len);
195 		break;
196 	case 0x14:
197 		(void)printf("igmp pimv1");
198 		pimv1_print(bp, len);
199   		break;
200 	case 0x1e:
201 		print_mresp(bp, len);
202 		break;
203 	case 0x1f:
204 		print_mtrace(bp, len);
205 		break;
206 	default:
207 		(void)printf("igmp-%d", bp[0] & 0xf);
208 		if (bp[1])
209 			(void)printf(" [b1=0x%02x]", bp[1]);
210 		break;
211 	}
212 
213 	if (vflag && TTEST2(bp[0], len)) {
214 		/* Check the IGMP checksum */
215 		if (in_cksum((const u_short*)bp, len, 0))
216 			printf(" bad igmp cksum %x!", EXTRACT_16BITS(&bp[2]));
217 	}
218 	return;
219 trunc:
220 	fputs("[|igmp]", stdout);
221 }
222 
223 /*
224  * print the recorded route in an IP RR, LSRR or SSRR option.
225  */
226 static void
227 ip_printroute(const char *type, register const u_char *cp, u_int length)
228 {
229 	register u_int ptr = cp[2] - 1;
230 	register u_int len;
231 
232 	printf(" %s{", type);
233 	if ((length + 1) & 3)
234 		printf(" [bad length %d]", length);
235 	if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
236 		printf(" [bad ptr %d]", cp[2]);
237 
238 	type = "";
239 	for (len = 3; len < length; len += 4) {
240 		if (ptr == len)
241 			type = "#";
242 		printf("%s%s", type, ipaddr_string(&cp[len]));
243 		type = " ";
244 	}
245 	printf("%s}", ptr == len? "#" : "");
246 }
247 
248 static void
249 ip_printts(register const u_char *cp, u_int length)
250 {
251 	register u_int ptr = cp[2] - 1;
252 	register u_int len = 0;
253 	int hoplen;
254 	char *type;
255 
256 	printf(" TS{");
257 	hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
258 	if ((length - 4) & (hoplen-1))
259 		printf("[bad length %d]", length);
260 	if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
261 		printf("[bad ptr %d]", cp[2]);
262 	switch (cp[3]&0xF) {
263 	case IPOPT_TS_TSONLY:
264 		printf("TSONLY");
265 		break;
266 	case IPOPT_TS_TSANDADDR:
267 		printf("TS+ADDR");
268 		break;
269 	/*
270 	 * prespecified should really be 3, but some ones might send 2
271 	 * instead, and the IPOPT_TS_PRESPEC constant can apparently
272 	 * have both values, so we have to hard-code it here.
273 	 */
274 
275 	case 2:
276 		printf("PRESPEC2.0");
277 		break;
278 	case 3:			/* IPOPT_TS_PRESPEC */
279 		printf("PRESPEC");
280 		break;
281 	default:
282 		printf("[bad ts type %d]", cp[3]&0xF);
283 		goto done;
284 	}
285 
286 	type = " ";
287 	for (len = 4; len < length; len += hoplen) {
288 		if (ptr == len)
289 			type = " ^ ";
290 		printf("%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]),
291 		       hoplen!=8 ? "" : ipaddr_string(&cp[len]));
292 		type = " ";
293 	}
294 
295 done:
296 	printf("%s", ptr == len ? " ^ " : "");
297 
298 	if (cp[3]>>4)
299 		printf(" [%d hops not recorded]} ", cp[3]>>4);
300 	else
301 		printf("}");
302 }
303 
304 /*
305  * print IP options.
306  */
307 static void
308 ip_optprint(register const u_char *cp, u_int length)
309 {
310 	register u_int len;
311 
312 	for (; length > 0; cp += len, length -= len) {
313 		int tt = *cp;
314 
315 		len = (tt == IPOPT_NOP || tt == IPOPT_EOL) ? 1 : cp[1];
316 		if (len <= 0) {
317 			printf("[|ip op len %d]", len);
318 			return;
319 		}
320 		if (&cp[1] >= snapend || cp + len > snapend) {
321 			printf("[|ip]");
322 			return;
323 		}
324 		switch (tt) {
325 
326 		case IPOPT_EOL:
327 			printf(" EOL");
328 			if (length > 1)
329 				printf("-%d", length - 1);
330 			return;
331 
332 		case IPOPT_NOP:
333 			printf(" NOP");
334 			break;
335 
336 		case IPOPT_TS:
337 			ip_printts(cp, len);
338 			break;
339 
340 #ifndef IPOPT_SECURITY
341 #define IPOPT_SECURITY 130
342 #endif /* IPOPT_SECURITY */
343 		case IPOPT_SECURITY:
344 			printf(" SECURITY{%d}", len);
345 			break;
346 
347 		case IPOPT_RR:
348 			ip_printroute("RR", cp, len);
349 			break;
350 
351 		case IPOPT_SSRR:
352 			ip_printroute("SSRR", cp, len);
353 			break;
354 
355 		case IPOPT_LSRR:
356 			ip_printroute("LSRR", cp, len);
357 			break;
358 
359 #ifndef IPOPT_RA
360 #define IPOPT_RA 148		/* router alert */
361 #endif
362 		case IPOPT_RA:
363 			printf(" RA");
364 			if (len != 4)
365 				printf("{%d}", len);
366 			else if (cp[2] || cp[3])
367 				printf("%d.%d", cp[2], cp[3]);
368  			break;
369 
370 		default:
371 			printf(" IPOPT-%d{%d}", cp[0], len);
372 			break;
373 		}
374 	}
375 }
376 
377 /*
378  * compute an IP header checksum.
379  * don't modifiy the packet.
380  */
381 u_short
382 in_cksum(const u_short *addr, register int len, u_short csum)
383 {
384 	int nleft = len;
385 	const u_short *w = addr;
386 	u_short answer;
387 	int sum = csum;
388 
389  	/*
390 	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
391 	 *  we add sequential 16 bit words to it, and at the end, fold
392 	 *  back all the carry bits from the top 16 bits into the lower
393 	 *  16 bits.
394  	 */
395 	while (nleft > 1)  {
396 		sum += *w++;
397 		nleft -= 2;
398 	}
399 	if (nleft == 1)
400 		sum += htons(*(u_char *)w<<8);
401 
402 	/*
403 	 * add back carry outs from top 16 bits to low 16 bits
404 	 */
405 	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
406 	sum += (sum >> 16);			/* add carry */
407 	answer = ~sum;				/* truncate to 16 bits */
408 	return (answer);
409 }
410 
411 /*
412  * print an IP datagram.
413  */
414 void
415 ip_print(register const u_char *bp, register u_int length)
416 {
417 	register const struct ip *ip;
418 	register u_int hlen, len, len0, off;
419 	register const u_char *cp;
420 	u_char nh;
421 	int advance;
422 
423 	ip = (const struct ip *)bp;
424 #ifdef LBL_ALIGN
425 	/*
426 	 * If the IP header is not aligned, copy into abuf.
427 	 * This will never happen with BPF.  It does happen raw packet
428 	 * dumps from -r.
429 	 */
430 	if ((long)ip & 3) {
431 		static u_char *abuf = NULL;
432 		static int didwarn = 0;
433 
434 		if (abuf == NULL) {
435 			abuf = (u_char *)malloc(snaplen);
436 			if (abuf == NULL)
437 				error("ip_print: malloc");
438 		}
439 		memcpy((char *)abuf, (char *)ip, min(length, snaplen));
440 		snapend += abuf - (u_char *)ip;
441 		packetp = abuf;
442 		ip = (struct ip *)abuf;
443 		/* We really want libpcap to give us aligned packets */
444 		if (!didwarn) {
445 			warning("compensating for unaligned libpcap packets");
446 			++didwarn;
447 		}
448 	}
449 #endif
450 	if ((u_char *)(ip + 1) > snapend) {
451 		printf("[|ip]");
452 		return;
453 	}
454 	if (length < sizeof (struct ip)) {
455 		(void)printf("truncated-ip %d", length);
456 		return;
457 	}
458 	hlen = ip->ip_hl * 4;
459 
460 	len = ntohs(ip->ip_len);
461 	if (length < len)
462 		(void)printf("truncated-ip - %d bytes missing!",
463 			len - length);
464 	len -= hlen;
465 	len0 = len;
466 
467 	/*
468 	 * If this is fragment zero, hand it to the next higher
469 	 * level protocol.
470 	 */
471 	off = ntohs(ip->ip_off);
472 	if ((off & 0x1fff) == 0) {
473 		cp = (const u_char *)ip + hlen;
474 		nh = ip->ip_p;
475 
476 		if (nh != IPPROTO_TCP && nh != IPPROTO_UDP) {
477 			(void)printf("%s > %s: ", ipaddr_string(&ip->ip_src),
478 				ipaddr_string(&ip->ip_dst));
479 		}
480 again:
481 		switch (nh) {
482 
483 #ifndef IPPROTO_AH
484 #define IPPROTO_AH	51
485 #endif
486 		case IPPROTO_AH:
487 			nh = *cp;
488 			advance = ah_print(cp, (const u_char *)ip);
489 			cp += advance;
490 			len -= advance;
491 			goto again;
492 
493 #ifndef IPPROTO_ESP
494 #define IPPROTO_ESP	50
495 #endif
496 		case IPPROTO_ESP:
497 		    {
498 			int enh;
499 			advance = esp_print(cp, (const u_char *)ip, &enh);
500 			cp += advance;
501 			len -= advance;
502 			if (enh < 0)
503 				break;
504 			nh = enh & 0xff;
505 			goto again;
506 		    }
507 
508 #ifndef IPPROTO_IPCOMP
509 #define IPPROTO_IPCOMP	108
510 #endif
511 		case IPPROTO_IPCOMP:
512 		    {
513 			int enh;
514 			advance = ipcomp_print(cp, (const u_char *)ip, &enh);
515 			cp += advance;
516 			len -= advance;
517 			if (enh < 0)
518 				break;
519 			nh = enh & 0xff;
520 			goto again;
521 		    }
522 
523 		case IPPROTO_TCP:
524 			tcp_print(cp, len, (const u_char *)ip);
525 			break;
526 
527 		case IPPROTO_UDP:
528 			udp_print(cp, len, (const u_char *)ip);
529 			break;
530 
531 		case IPPROTO_ICMP:
532 			icmp_print(cp, len, (const u_char *)ip);
533 			break;
534 
535 #ifndef IPPROTO_IGRP
536 #define IPPROTO_IGRP 9
537 #endif
538 		case IPPROTO_IGRP:
539 			igrp_print(cp, len, (const u_char *)ip);
540 			break;
541 
542 		case IPPROTO_ND:
543 #if 0
544 			(void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
545 				ipaddr_string(&ip->ip_dst));
546 #endif
547 			(void)printf(" nd %d", len);
548 			break;
549 
550 		case IPPROTO_EGP:
551 			egp_print(cp, len, (const u_char *)ip);
552 			break;
553 
554 #ifndef IPPROTO_OSPF
555 #define IPPROTO_OSPF 89
556 #endif
557 		case IPPROTO_OSPF:
558 			ospf_print(cp, len, (const u_char *)ip);
559 			break;
560 
561 #ifndef IPPROTO_IGMP
562 #define IPPROTO_IGMP 2
563 #endif
564 		case IPPROTO_IGMP:
565 			igmp_print(cp, len, (const u_char *)ip);
566 			break;
567 
568 		case 4:
569 			/* DVMRP multicast tunnel (ip-in-ip encapsulation) */
570 #if 0
571 			if (vflag)
572 				(void)printf("%s > %s: ",
573 					     ipaddr_string(&ip->ip_src),
574 					     ipaddr_string(&ip->ip_dst));
575 #endif
576 			ip_print(cp, len);
577 			if (! vflag) {
578 				printf(" (ipip)");
579 				return;
580 			}
581 			break;
582 
583 #ifdef INET6
584 #ifndef IP6PROTO_ENCAP
585 #define IP6PROTO_ENCAP 41
586 #endif
587 		case IP6PROTO_ENCAP:
588 			/* ip6-in-ip encapsulation */
589 #if 0
590 			if (vflag)
591 				(void)printf("%s > %s: ",
592 					     ipaddr_string(&ip->ip_src),
593 					     ipaddr_string(&ip->ip_dst));
594 #endif
595 			ip6_print(cp, len);
596 			if (! vflag) {
597 				printf(" (encap)");
598 				return;
599 			}
600 			break;
601 #endif /*INET6*/
602 
603 
604 #ifndef IPPROTO_GRE
605 #define IPPROTO_GRE 47
606 #endif
607 		case IPPROTO_GRE:
608 			if (vflag)
609 				(void)printf("gre %s > %s: ",
610 					     ipaddr_string(&ip->ip_src),
611 					     ipaddr_string(&ip->ip_dst));
612 			/* do it */
613 			gre_print(cp, len);
614 			if (! vflag) {
615 				printf(" (gre encap)");
616 				return;
617   			}
618   			break;
619 
620 #ifndef IPPROTO_MOBILE
621 #define IPPROTO_MOBILE 55
622 #endif
623 		case IPPROTO_MOBILE:
624 			if (vflag)
625 				(void)printf("mobile %s > %s: ",
626 					     ipaddr_string(&ip->ip_src),
627 					     ipaddr_string(&ip->ip_dst));
628 			mobile_print(cp, len);
629 			if (! vflag) {
630 				printf(" (mobile encap)");
631 				return;
632 			}
633 			break;
634 
635 #ifndef IPPROTO_PIM
636 #define IPPROTO_PIM	103
637 #endif
638 		case IPPROTO_PIM:
639 			pim_print(cp, len);
640 			break;
641 
642 		default:
643 #if 0
644 			(void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
645 				ipaddr_string(&ip->ip_dst));
646 #endif
647 			(void)printf(" ip-proto-%d %d", nh, len);
648 			break;
649 		}
650 	}
651 
652  	/* Ultra quiet now means that all this stuff should be suppressed */
653  	/* res 3-Nov-98 */
654  	if (qflag > 1) return;
655 
656 
657 	/*
658 	 * for fragmented datagrams, print id:size@offset.  On all
659 	 * but the last stick a "+".  For unfragmented datagrams, note
660 	 * the don't fragment flag.
661 	 */
662 	len = len0;	/* get the original length */
663 	if (off & 0x3fff) {
664 		/*
665 		 * if this isn't the first frag, we're missing the
666 		 * next level protocol header.  print the ip addr.
667 		 */
668 		if (off & 0x1fff)
669 			(void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
670 				      ipaddr_string(&ip->ip_dst));
671 #ifndef IP_MF
672 #define IP_MF 0x2000
673 #endif /* IP_MF */
674 #ifndef IP_DF
675 #define IP_DF 0x4000
676 #endif /* IP_DF */
677 		(void)printf(" (frag %d:%u@%d%s)", ntohs(ip->ip_id), len,
678 			(off & 0x1fff) * 8,
679 			(off & IP_MF)? "+" : "");
680 
681 	} else if (off & IP_DF)
682 		(void)printf(" (DF)");
683 
684 	if (ip->ip_tos) {
685 		(void)printf(" [tos 0x%x", (int)ip->ip_tos);
686 		/* ECN bits */
687 		if (ip->ip_tos&0x02) {
688 			(void)printf(",ECT");
689 			if (ip->ip_tos&0x01)
690 				(void)printf(",CE");
691 		}
692 		(void)printf("] ");
693 	}
694 
695 	if (ip->ip_ttl <= 1)
696 		(void)printf(" [ttl %d]", (int)ip->ip_ttl);
697 
698 	if (vflag) {
699 		int sum;
700 		char *sep = "";
701 
702 		printf(" (");
703 		if (ip->ip_ttl > 1) {
704 			(void)printf("%sttl %d", sep, (int)ip->ip_ttl);
705 			sep = ", ";
706 		}
707 		if ((off & 0x3fff) == 0) {
708 			(void)printf("%sid %d", sep, (int)ntohs(ip->ip_id));
709 			sep = ", ";
710 		}
711 		if ((u_char *)ip + hlen <= snapend) {
712 			sum = in_cksum((const u_short *)ip, hlen, 0);
713 			if (sum != 0) {
714 				(void)printf("%sbad cksum %x!", sep,
715 					     ntohs(ip->ip_sum));
716 				sep = ", ";
717 			}
718 		}
719 		if ((hlen -= sizeof(struct ip)) > 0) {
720 			(void)printf("%soptlen=%d", sep, hlen);
721 			ip_optprint((u_char *)(ip + 1), hlen);
722 		}
723 		printf(")");
724 	}
725 }
726