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