xref: /freebsd/contrib/tcpdump/print-ip.c (revision 09e8dea79366f1e5b3a73e8a271b26e4b6bf2e6a)
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.100 2001/09/17 21:58:03 fenner 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 u_int len, int 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 #ifndef IPPROTO_SCTP
321 #define IPPROTO_SCTP 132
322 #endif
323 		if (nh != IPPROTO_TCP && nh != IPPROTO_UDP &&
324 		    nh != IPPROTO_SCTP) {
325 			(void)printf("%s > %s: ", ipaddr_string(&ip->ip_src),
326 				ipaddr_string(&ip->ip_dst));
327 		}
328 again:
329 		switch (nh) {
330 
331 #ifndef IPPROTO_AH
332 #define IPPROTO_AH	51
333 #endif
334 		case IPPROTO_AH:
335 			nh = *cp;
336 			advance = ah_print(cp, (const u_char *)ip);
337 			cp += advance;
338 			len -= advance;
339 			goto again;
340 
341 #ifndef IPPROTO_ESP
342 #define IPPROTO_ESP	50
343 #endif
344 		case IPPROTO_ESP:
345 		    {
346 			int enh, padlen;
347 			advance = esp_print(cp, (const u_char *)ip, &enh, &padlen);
348 			cp += advance;
349 			len -= advance + padlen;
350 			if (enh < 0)
351 				break;
352 			nh = enh & 0xff;
353 			goto again;
354 		    }
355 
356 #ifndef IPPROTO_IPCOMP
357 #define IPPROTO_IPCOMP	108
358 #endif
359 		case IPPROTO_IPCOMP:
360 		    {
361 			int enh;
362 			advance = ipcomp_print(cp, (const u_char *)ip, &enh);
363 			cp += advance;
364 			len -= advance;
365 			if (enh < 0)
366 				break;
367 			nh = enh & 0xff;
368 			goto again;
369 		    }
370 
371 		case IPPROTO_SCTP:
372   			sctp_print(cp, (const u_char *)ip, len);
373 			break;
374 
375 		case IPPROTO_TCP:
376 			tcp_print(cp, len, (const u_char *)ip, (off &~ 0x6000));
377 			break;
378 
379 		case IPPROTO_UDP:
380 			udp_print(cp, len, (const u_char *)ip, (off &~ 0x6000));
381 			break;
382 
383 		case IPPROTO_ICMP:
384 			icmp_print(cp, len, (const u_char *)ip);
385 			break;
386 
387 #ifndef IPPROTO_IGRP
388 #define IPPROTO_IGRP 9
389 #endif
390 		case IPPROTO_IGRP:
391 			igrp_print(cp, len, (const u_char *)ip);
392 			break;
393 
394 		case IPPROTO_ND:
395 			(void)printf(" nd %d", len);
396 			break;
397 
398 		case IPPROTO_EGP:
399 			egp_print(cp, len, (const u_char *)ip);
400 			break;
401 
402 #ifndef IPPROTO_OSPF
403 #define IPPROTO_OSPF 89
404 #endif
405 		case IPPROTO_OSPF:
406 			ospf_print(cp, len, (const u_char *)ip);
407 			break;
408 
409 #ifndef IPPROTO_IGMP
410 #define IPPROTO_IGMP 2
411 #endif
412 		case IPPROTO_IGMP:
413 			igmp_print(cp, len);
414 			break;
415 
416 		case 4:
417 			/* DVMRP multicast tunnel (ip-in-ip encapsulation) */
418 			ip_print(cp, len);
419 			if (! vflag) {
420 				printf(" (ipip-proto-4)");
421 				return;
422 			}
423 			break;
424 
425 #ifdef INET6
426 #ifndef IP6PROTO_ENCAP
427 #define IP6PROTO_ENCAP 41
428 #endif
429 		case IP6PROTO_ENCAP:
430 			/* ip6-in-ip encapsulation */
431 			ip6_print(cp, len);
432 			break;
433 #endif /*INET6*/
434 
435 
436 #ifndef IPPROTO_GRE
437 #define IPPROTO_GRE 47
438 #endif
439 		case IPPROTO_GRE:
440 			/* do it */
441 			gre_print(cp, len);
442 			break;
443 
444 #ifndef IPPROTO_MOBILE
445 #define IPPROTO_MOBILE 55
446 #endif
447 		case IPPROTO_MOBILE:
448 			mobile_print(cp, len);
449 			break;
450 
451 #ifndef IPPROTO_PIM
452 #define IPPROTO_PIM	103
453 #endif
454 		case IPPROTO_PIM:
455 			pim_print(cp, len);
456 			break;
457 
458 #ifndef IPPROTO_VRRP
459 #define IPPROTO_VRRP	112
460 #endif
461 		case IPPROTO_VRRP:
462 			vrrp_print(cp, len, ip->ip_ttl);
463 			break;
464 
465 		default:
466 			(void)printf(" ip-proto-%d %d", nh, len);
467 			break;
468 		}
469 	}
470 
471  	/* Ultra quiet now means that all this stuff should be suppressed */
472  	/* res 3-Nov-98 */
473  	if (qflag > 1) return;
474 
475 
476 	/*
477 	 * for fragmented datagrams, print id:size@offset.  On all
478 	 * but the last stick a "+".  For unfragmented datagrams, note
479 	 * the don't fragment flag.
480 	 */
481 	len = len0;	/* get the original length */
482 	if (off & 0x3fff) {
483 		/*
484 		 * if this isn't the first frag, we're missing the
485 		 * next level protocol header.  print the ip addr.
486 		 */
487 		if (off & 0x1fff)
488 			(void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
489 				      ipaddr_string(&ip->ip_dst));
490 #ifndef IP_MF
491 #define IP_MF 0x2000
492 #endif /* IP_MF */
493 #ifndef IP_DF
494 #define IP_DF 0x4000
495 #endif /* IP_DF */
496 		(void)printf(" (frag %d:%u@%d%s)", ntohs(ip->ip_id), len,
497 			(off & 0x1fff) * 8,
498 			(off & IP_MF)? "+" : "");
499 
500 	} else if (off & IP_DF)
501 		(void)printf(" (DF)");
502 
503 	if (ip->ip_tos) {
504 		(void)printf(" [tos 0x%x", (int)ip->ip_tos);
505 		/* ECN bits */
506 		if (ip->ip_tos & 0x03) {
507 			switch (ip->ip_tos & 0x03) {
508 			case 1:
509 				(void)printf(",ECT(1)");
510 				break;
511 			case 2:
512 				(void)printf(",ECT(0)");
513 				break;
514 			case 3:
515 				(void)printf(",CE");
516 			}
517 		}
518 		(void)printf("] ");
519 	}
520 
521 	if (ip->ip_ttl <= 1)
522 		(void)printf(" [ttl %d]", (int)ip->ip_ttl);
523 
524 	if (vflag) {
525 		int sum;
526 		char *sep = "";
527 
528 		printf(" (");
529 		if (ip->ip_ttl > 1) {
530 			(void)printf("%sttl %d", sep, (int)ip->ip_ttl);
531 			sep = ", ";
532 		}
533 		if ((off & 0x3fff) == 0) {
534 			(void)printf("%sid %d", sep, (int)ntohs(ip->ip_id));
535 			sep = ", ";
536 		}
537 		(void)printf("%slen %d", sep, (int)ntohs(ip->ip_len));
538 		sep = ", ";
539 		if ((u_char *)ip + hlen <= snapend) {
540 			sum = in_cksum((const u_short *)ip, hlen, 0);
541 			if (sum != 0) {
542 				(void)printf("%sbad cksum %x!", sep,
543 					     ntohs(ip->ip_sum));
544 				sep = ", ";
545 			}
546 		}
547 		if ((hlen -= sizeof(struct ip)) > 0) {
548 			(void)printf("%soptlen=%d", sep, hlen);
549 			ip_optprint((u_char *)(ip + 1), hlen);
550 		}
551 		printf(")");
552 	}
553 }
554 
555 void
556 ipN_print(register const u_char *bp, register u_int length)
557 {
558 	struct ip *ip, hdr;
559 
560 	ip = (struct ip *)bp;
561 	if (length < 4) {
562 		(void)printf("truncated-ip %d", length);
563 		return;
564 	}
565 	memcpy (&hdr, (char *)ip, 4);
566 	switch (IP_V(&hdr)) {
567 	case 4:
568 		ip_print (bp, length);
569 		return;
570 #ifdef INET6
571 	case 6:
572 		ip6_print (bp, length);
573 		return;
574 #endif
575 	default:
576 		(void)printf("unknown ip %d", IP_V(&hdr));
577 		return;
578 	}
579 }
580