xref: /freebsd/contrib/tcpdump/print-ip.c (revision 6990ffd8a95caaba6858ad44ff1b3157d1efba8f)
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.92 2001/01/02 23:00:01 guy 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 
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43 
44 #include "addrtoname.h"
45 #include "interface.h"
46 #include "extract.h"			/* must come after interface.h */
47 
48 #include "ip.h"
49 
50 /* Compatibility */
51 #ifndef	IPPROTO_ND
52 #define	IPPROTO_ND	77
53 #endif
54 
55 /*
56  * print the recorded route in an IP RR, LSRR or SSRR option.
57  */
58 static void
59 ip_printroute(const char *type, register const u_char *cp, u_int length)
60 {
61 	register u_int ptr = cp[2] - 1;
62 	register u_int len;
63 
64 	printf(" %s{", type);
65 	if ((length + 1) & 3)
66 		printf(" [bad length %d]", length);
67 	if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
68 		printf(" [bad ptr %d]", cp[2]);
69 
70 	type = "";
71 	for (len = 3; len < length; len += 4) {
72 		if (ptr == len)
73 			type = "#";
74 		printf("%s%s", type, ipaddr_string(&cp[len]));
75 		type = " ";
76 	}
77 	printf("%s}", ptr == len? "#" : "");
78 }
79 
80 static void
81 ip_printts(register const u_char *cp, u_int length)
82 {
83 	register u_int ptr = cp[2] - 1;
84 	register u_int len = 0;
85 	int hoplen;
86 	char *type;
87 
88 	printf(" TS{");
89 	hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
90 	if ((length - 4) & (hoplen-1))
91 		printf("[bad length %d]", length);
92 	if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
93 		printf("[bad ptr %d]", cp[2]);
94 	switch (cp[3]&0xF) {
95 	case IPOPT_TS_TSONLY:
96 		printf("TSONLY");
97 		break;
98 	case IPOPT_TS_TSANDADDR:
99 		printf("TS+ADDR");
100 		break;
101 	/*
102 	 * prespecified should really be 3, but some ones might send 2
103 	 * instead, and the IPOPT_TS_PRESPEC constant can apparently
104 	 * have both values, so we have to hard-code it here.
105 	 */
106 
107 	case 2:
108 		printf("PRESPEC2.0");
109 		break;
110 	case 3:			/* IPOPT_TS_PRESPEC */
111 		printf("PRESPEC");
112 		break;
113 	default:
114 		printf("[bad ts type %d]", cp[3]&0xF);
115 		goto done;
116 	}
117 
118 	type = " ";
119 	for (len = 4; len < length; len += hoplen) {
120 		if (ptr == len)
121 			type = " ^ ";
122 		printf("%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]),
123 		       hoplen!=8 ? "" : ipaddr_string(&cp[len]));
124 		type = " ";
125 	}
126 
127 done:
128 	printf("%s", ptr == len ? " ^ " : "");
129 
130 	if (cp[3]>>4)
131 		printf(" [%d hops not recorded]} ", cp[3]>>4);
132 	else
133 		printf("}");
134 }
135 
136 /*
137  * print IP options.
138  */
139 static void
140 ip_optprint(register const u_char *cp, u_int length)
141 {
142 	register u_int len;
143 
144 	for (; length > 0; cp += len, length -= len) {
145 		int tt = *cp;
146 
147 		if (tt == IPOPT_NOP || tt == IPOPT_EOL)
148 			len = 1;
149 		else {
150 			if (&cp[1] >= snapend) {
151 				printf("[|ip]");
152 				return;
153 			}
154 			len = cp[1];
155 		}
156 		if (len <= 0) {
157 			printf("[|ip op len %d]", len);
158 			return;
159 		}
160 		if (&cp[1] >= snapend || cp + len > snapend) {
161 			printf("[|ip]");
162 			return;
163 		}
164 		switch (tt) {
165 
166 		case IPOPT_EOL:
167 			printf(" EOL");
168 			if (length > 1)
169 				printf("-%d", length - 1);
170 			return;
171 
172 		case IPOPT_NOP:
173 			printf(" NOP");
174 			break;
175 
176 		case IPOPT_TS:
177 			ip_printts(cp, len);
178 			break;
179 
180 #ifndef IPOPT_SECURITY
181 #define IPOPT_SECURITY 130
182 #endif /* IPOPT_SECURITY */
183 		case IPOPT_SECURITY:
184 			printf(" SECURITY{%d}", len);
185 			break;
186 
187 		case IPOPT_RR:
188 			ip_printroute("RR", cp, len);
189 			break;
190 
191 		case IPOPT_SSRR:
192 			ip_printroute("SSRR", cp, len);
193 			break;
194 
195 		case IPOPT_LSRR:
196 			ip_printroute("LSRR", cp, len);
197 			break;
198 
199 #ifndef IPOPT_RA
200 #define IPOPT_RA 148		/* router alert */
201 #endif
202 		case IPOPT_RA:
203 			printf(" RA");
204 			if (len != 4)
205 				printf("{%d}", len);
206 			else if (cp[2] || cp[3])
207 				printf("%d.%d", cp[2], cp[3]);
208  			break;
209 
210 		default:
211 			printf(" IPOPT-%d{%d}", cp[0], len);
212 			break;
213 		}
214 	}
215 }
216 
217 /*
218  * compute an IP header checksum.
219  * don't modifiy the packet.
220  */
221 u_short
222 in_cksum(const u_short *addr, register int len, u_short csum)
223 {
224 	int nleft = len;
225 	const u_short *w = addr;
226 	u_short answer;
227 	int sum = csum;
228 
229  	/*
230 	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
231 	 *  we add sequential 16 bit words to it, and at the end, fold
232 	 *  back all the carry bits from the top 16 bits into the lower
233 	 *  16 bits.
234  	 */
235 	while (nleft > 1)  {
236 		sum += *w++;
237 		nleft -= 2;
238 	}
239 	if (nleft == 1)
240 		sum += htons(*(u_char *)w<<8);
241 
242 	/*
243 	 * add back carry outs from top 16 bits to low 16 bits
244 	 */
245 	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
246 	sum += (sum >> 16);			/* add carry */
247 	answer = ~sum;				/* truncate to 16 bits */
248 	return (answer);
249 }
250 
251 /*
252  * print an IP datagram.
253  */
254 void
255 ip_print(register const u_char *bp, register u_int length)
256 {
257 	register const struct ip *ip;
258 	register u_int hlen, len, len0, off;
259 	register const u_char *cp;
260 	u_char nh;
261 	int advance;
262 
263 	ip = (const struct ip *)bp;
264 #ifdef LBL_ALIGN
265 	/*
266 	 * If the IP header is not aligned, copy into abuf.
267 	 * This will never happen with BPF.  It does happen raw packet
268 	 * dumps from -r.
269 	 */
270 	if ((long)ip & 3) {
271 		static u_char *abuf = NULL;
272 		static int didwarn = 0;
273 
274 		if (abuf == NULL) {
275 			abuf = (u_char *)malloc(snaplen);
276 			if (abuf == NULL)
277 				error("ip_print: malloc");
278 		}
279 		memcpy((char *)abuf, (char *)ip, min(length, snaplen));
280 		snapend += abuf - (u_char *)ip;
281 		packetp = abuf;
282 		ip = (struct ip *)abuf;
283 		/* We really want libpcap to give us aligned packets */
284 		if (!didwarn) {
285 			warning("compensating for unaligned libpcap packets");
286 			++didwarn;
287 		}
288 	}
289 #endif
290 	if ((u_char *)(ip + 1) > snapend) {
291 		printf("[|ip]");
292 		return;
293 	}
294 	if (length < sizeof (struct ip)) {
295 		(void)printf("truncated-ip %d", length);
296 		return;
297 	}
298 	hlen = IP_HL(ip) * 4;
299 	if (hlen < sizeof (struct ip)) {
300 		(void)printf("bad-hlen %d", hlen);
301 		return;
302 	}
303 
304 	len = ntohs(ip->ip_len);
305 	if (length < len)
306 		(void)printf("truncated-ip - %d bytes missing!",
307 			len - length);
308 	len -= hlen;
309 	len0 = len;
310 
311 	/*
312 	 * If this is fragment zero, hand it to the next higher
313 	 * level protocol.
314 	 */
315 	off = ntohs(ip->ip_off);
316 	if ((off & 0x1fff) == 0) {
317 		cp = (const u_char *)ip + hlen;
318 		nh = ip->ip_p;
319 
320 		if (nh != IPPROTO_TCP && nh != IPPROTO_UDP) {
321 			(void)printf("%s > %s: ", ipaddr_string(&ip->ip_src),
322 				ipaddr_string(&ip->ip_dst));
323 		}
324 again:
325 		switch (nh) {
326 
327 #ifndef IPPROTO_AH
328 #define IPPROTO_AH	51
329 #endif
330 		case IPPROTO_AH:
331 			nh = *cp;
332 			advance = ah_print(cp, (const u_char *)ip);
333 			cp += advance;
334 			len -= advance;
335 			goto again;
336 
337 #ifndef IPPROTO_ESP
338 #define IPPROTO_ESP	50
339 #endif
340 		case IPPROTO_ESP:
341 		    {
342 			int enh;
343 			advance = esp_print(cp, (const u_char *)ip, &enh);
344 			cp += advance;
345 			len -= advance;
346 			if (enh < 0)
347 				break;
348 			nh = enh & 0xff;
349 			goto again;
350 		    }
351 
352 #ifndef IPPROTO_IPCOMP
353 #define IPPROTO_IPCOMP	108
354 #endif
355 		case IPPROTO_IPCOMP:
356 		    {
357 			int enh;
358 			advance = ipcomp_print(cp, (const u_char *)ip, &enh);
359 			cp += advance;
360 			len -= advance;
361 			if (enh < 0)
362 				break;
363 			nh = enh & 0xff;
364 			goto again;
365 		    }
366 
367 		case IPPROTO_TCP:
368 			tcp_print(cp, len, (const u_char *)ip, (off &~ 0x6000));
369 			break;
370 
371 		case IPPROTO_UDP:
372 			udp_print(cp, len, (const u_char *)ip, (off &~ 0x6000));
373 			break;
374 
375 		case IPPROTO_ICMP:
376 			icmp_print(cp, len, (const u_char *)ip);
377 			break;
378 
379 #ifndef IPPROTO_IGRP
380 #define IPPROTO_IGRP 9
381 #endif
382 		case IPPROTO_IGRP:
383 			igrp_print(cp, len, (const u_char *)ip);
384 			break;
385 
386 		case IPPROTO_ND:
387 #if 0
388 			(void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
389 				ipaddr_string(&ip->ip_dst));
390 #endif
391 			(void)printf(" nd %d", len);
392 			break;
393 
394 		case IPPROTO_EGP:
395 			egp_print(cp, len, (const u_char *)ip);
396 			break;
397 
398 #ifndef IPPROTO_OSPF
399 #define IPPROTO_OSPF 89
400 #endif
401 		case IPPROTO_OSPF:
402 			ospf_print(cp, len, (const u_char *)ip);
403 			break;
404 
405 #ifndef IPPROTO_IGMP
406 #define IPPROTO_IGMP 2
407 #endif
408 		case IPPROTO_IGMP:
409 			igmp_print(cp, len, (const u_char *)ip);
410 			break;
411 
412 		case 4:
413 			/* DVMRP multicast tunnel (ip-in-ip encapsulation) */
414 #if 0
415 			if (vflag)
416 				(void)printf("%s > %s: ",
417 					     ipaddr_string(&ip->ip_src),
418 					     ipaddr_string(&ip->ip_dst));
419 #endif
420 			ip_print(cp, len);
421 			if (! vflag) {
422 				printf(" (ipip)");
423 				return;
424 			}
425 			break;
426 
427 #ifdef INET6
428 #ifndef IP6PROTO_ENCAP
429 #define IP6PROTO_ENCAP 41
430 #endif
431 		case IP6PROTO_ENCAP:
432 			/* ip6-in-ip encapsulation */
433 #if 0
434 			if (vflag)
435 				(void)printf("%s > %s: ",
436 					     ipaddr_string(&ip->ip_src),
437 					     ipaddr_string(&ip->ip_dst));
438 #endif
439 			ip6_print(cp, len);
440 			if (! vflag) {
441 				printf(" (encap)");
442 				return;
443 			}
444 			break;
445 #endif /*INET6*/
446 
447 
448 #ifndef IPPROTO_GRE
449 #define IPPROTO_GRE 47
450 #endif
451 		case IPPROTO_GRE:
452 			if (vflag)
453 				(void)printf("gre %s > %s: ",
454 					     ipaddr_string(&ip->ip_src),
455 					     ipaddr_string(&ip->ip_dst));
456 			/* do it */
457 			gre_print(cp, len);
458 			if (! vflag) {
459 				printf(" (gre encap)");
460 				return;
461   			}
462   			break;
463 
464 #ifndef IPPROTO_MOBILE
465 #define IPPROTO_MOBILE 55
466 #endif
467 		case IPPROTO_MOBILE:
468 			if (vflag)
469 				(void)printf("mobile %s > %s: ",
470 					     ipaddr_string(&ip->ip_src),
471 					     ipaddr_string(&ip->ip_dst));
472 			mobile_print(cp, len);
473 			if (! vflag) {
474 				printf(" (mobile encap)");
475 				return;
476 			}
477 			break;
478 
479 #ifndef IPPROTO_PIM
480 #define IPPROTO_PIM	103
481 #endif
482 		case IPPROTO_PIM:
483 			pim_print(cp, len);
484 			break;
485 
486 #ifndef IPPROTO_VRRP
487 #define IPPROTO_VRRP	112
488 #endif
489 		case IPPROTO_VRRP:
490 			if (vflag)
491 				(void)printf("vrrp %s > %s: ",
492 					     ipaddr_string(&ip->ip_src),
493 					     ipaddr_string(&ip->ip_dst));
494 			vrrp_print(cp, len, ip->ip_ttl);
495 			break;
496 
497 		default:
498 #if 0
499 			(void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
500 				ipaddr_string(&ip->ip_dst));
501 #endif
502 			(void)printf(" ip-proto-%d %d", nh, len);
503 			break;
504 		}
505 	}
506 
507  	/* Ultra quiet now means that all this stuff should be suppressed */
508  	/* res 3-Nov-98 */
509  	if (qflag > 1) return;
510 
511 
512 	/*
513 	 * for fragmented datagrams, print id:size@offset.  On all
514 	 * but the last stick a "+".  For unfragmented datagrams, note
515 	 * the don't fragment flag.
516 	 */
517 	len = len0;	/* get the original length */
518 	if (off & 0x3fff) {
519 		/*
520 		 * if this isn't the first frag, we're missing the
521 		 * next level protocol header.  print the ip addr.
522 		 */
523 		if (off & 0x1fff)
524 			(void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
525 				      ipaddr_string(&ip->ip_dst));
526 #ifndef IP_MF
527 #define IP_MF 0x2000
528 #endif /* IP_MF */
529 #ifndef IP_DF
530 #define IP_DF 0x4000
531 #endif /* IP_DF */
532 		(void)printf(" (frag %d:%u@%d%s)", ntohs(ip->ip_id), len,
533 			(off & 0x1fff) * 8,
534 			(off & IP_MF)? "+" : "");
535 
536 	} else if (off & IP_DF)
537 		(void)printf(" (DF)");
538 
539 	if (ip->ip_tos) {
540 		(void)printf(" [tos 0x%x", (int)ip->ip_tos);
541 		/* ECN bits */
542 		if (ip->ip_tos&0x02) {
543 			(void)printf(",ECT");
544 			if (ip->ip_tos&0x01)
545 				(void)printf(",CE");
546 		}
547 		(void)printf("] ");
548 	}
549 
550 	if (ip->ip_ttl <= 1)
551 		(void)printf(" [ttl %d]", (int)ip->ip_ttl);
552 
553 	if (vflag) {
554 		int sum;
555 		char *sep = "";
556 
557 		printf(" (");
558 		if (ip->ip_ttl > 1) {
559 			(void)printf("%sttl %d", sep, (int)ip->ip_ttl);
560 			sep = ", ";
561 		}
562 		if ((off & 0x3fff) == 0) {
563 			(void)printf("%sid %d", sep, (int)ntohs(ip->ip_id));
564 			sep = ", ";
565 		}
566 		(void)printf("%slen %d", sep, (int)ntohs(ip->ip_len));
567 		sep = ", ";
568 		if ((u_char *)ip + hlen <= snapend) {
569 			sum = in_cksum((const u_short *)ip, hlen, 0);
570 			if (sum != 0) {
571 				(void)printf("%sbad cksum %x!", sep,
572 					     ntohs(ip->ip_sum));
573 				sep = ", ";
574 			}
575 		}
576 		if ((hlen -= sizeof(struct ip)) > 0) {
577 			(void)printf("%soptlen=%d", sep, hlen);
578 			ip_optprint((u_char *)(ip + 1), hlen);
579 		}
580 		printf(")");
581 	}
582 }
583 
584 void
585 ipN_print(register const u_char *bp, register u_int length)
586 {
587 	struct ip *ip, hdr;
588 
589 	ip = (struct ip *)bp;
590 	if (length < 4) {
591 		(void)printf("truncated-ip %d", length);
592 		return;
593 	}
594 	memcpy (&hdr, (char *)ip, 4);
595 	switch (IP_V(&hdr)) {
596 	case 4:
597 	    ip_print (bp, length);
598 	    return;
599 #ifdef INET6
600 	case 6:
601 	    ip6_print (bp, length);
602 	    return;
603 #endif
604 	default:
605 	    (void)printf("unknown ip %d", IP_V(&hdr));
606 	    return;
607 	}
608 }
609