xref: /freebsd/contrib/tcpdump/print-ip.c (revision f9218d3d4fd34f082473b3a021c6d4d109fb47cf)
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.4.1 2002/01/25 05:39:54 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 <netdb.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <unistd.h>
44 
45 #include "addrtoname.h"
46 #include "interface.h"
47 #include "extract.h"			/* must come after interface.h */
48 
49 #include "ip.h"
50 
51 /* Compatibility */
52 #ifndef	IPPROTO_ND
53 #define	IPPROTO_ND	77
54 #endif
55 
56 /*
57  * print the recorded route in an IP RR, LSRR or SSRR option.
58  */
59 static void
60 ip_printroute(const char *type, register const u_char *cp, u_int length)
61 {
62 	register u_int ptr = cp[2] - 1;
63 	register u_int len;
64 
65 	printf(" %s{", type);
66 	if ((length + 1) & 3)
67 		printf(" [bad length %d]", length);
68 	if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
69 		printf(" [bad ptr %d]", cp[2]);
70 
71 	type = "";
72 	for (len = 3; len < length; len += 4) {
73 		if (ptr == len)
74 			type = "#";
75 		printf("%s%s", type, ipaddr_string(&cp[len]));
76 		type = " ";
77 	}
78 	printf("%s}", ptr == len? "#" : "");
79 }
80 
81 static void
82 ip_printts(register const u_char *cp, u_int length)
83 {
84 	register u_int ptr = cp[2] - 1;
85 	register u_int len = 0;
86 	int hoplen;
87 	char *type;
88 
89 	printf(" TS{");
90 	hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
91 	if ((length - 4) & (hoplen-1))
92 		printf("[bad length %d]", length);
93 	if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
94 		printf("[bad ptr %d]", cp[2]);
95 	switch (cp[3]&0xF) {
96 	case IPOPT_TS_TSONLY:
97 		printf("TSONLY");
98 		break;
99 	case IPOPT_TS_TSANDADDR:
100 		printf("TS+ADDR");
101 		break;
102 	/*
103 	 * prespecified should really be 3, but some ones might send 2
104 	 * instead, and the IPOPT_TS_PRESPEC constant can apparently
105 	 * have both values, so we have to hard-code it here.
106 	 */
107 
108 	case 2:
109 		printf("PRESPEC2.0");
110 		break;
111 	case 3:			/* IPOPT_TS_PRESPEC */
112 		printf("PRESPEC");
113 		break;
114 	default:
115 		printf("[bad ts type %d]", cp[3]&0xF);
116 		goto done;
117 	}
118 
119 	type = " ";
120 	for (len = 4; len < length; len += hoplen) {
121 		if (ptr == len)
122 			type = " ^ ";
123 		printf("%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]),
124 		       hoplen!=8 ? "" : ipaddr_string(&cp[len]));
125 		type = " ";
126 	}
127 
128 done:
129 	printf("%s", ptr == len ? " ^ " : "");
130 
131 	if (cp[3]>>4)
132 		printf(" [%d hops not recorded]} ", cp[3]>>4);
133 	else
134 		printf("}");
135 }
136 
137 /*
138  * print IP options.
139  */
140 static void
141 ip_optprint(register const u_char *cp, u_int length)
142 {
143 	register u_int len;
144 
145 	for (; length > 0; cp += len, length -= len) {
146 		int tt = *cp;
147 
148 		if (tt == IPOPT_NOP || tt == IPOPT_EOL)
149 			len = 1;
150 		else {
151 			if (&cp[1] >= snapend) {
152 				printf("[|ip]");
153 				return;
154 			}
155 			len = cp[1];
156 		}
157 		if (len <= 0) {
158 			printf("[|ip op len %d]", len);
159 			return;
160 		}
161 		if (&cp[1] >= snapend || cp + len > snapend) {
162 			printf("[|ip]");
163 			return;
164 		}
165 		switch (tt) {
166 
167 		case IPOPT_EOL:
168 			printf(" EOL");
169 			if (length > 1)
170 				printf("-%d", length - 1);
171 			return;
172 
173 		case IPOPT_NOP:
174 			printf(" NOP");
175 			break;
176 
177 		case IPOPT_TS:
178 			ip_printts(cp, len);
179 			break;
180 
181 #ifndef IPOPT_SECURITY
182 #define IPOPT_SECURITY 130
183 #endif /* IPOPT_SECURITY */
184 		case IPOPT_SECURITY:
185 			printf(" SECURITY{%d}", len);
186 			break;
187 
188 		case IPOPT_RR:
189 			ip_printroute("RR", cp, len);
190 			break;
191 
192 		case IPOPT_SSRR:
193 			ip_printroute("SSRR", cp, len);
194 			break;
195 
196 		case IPOPT_LSRR:
197 			ip_printroute("LSRR", cp, len);
198 			break;
199 
200 #ifndef IPOPT_RA
201 #define IPOPT_RA 148		/* router alert */
202 #endif
203 		case IPOPT_RA:
204 			printf(" RA");
205 			if (len != 4)
206 				printf("{%d}", len);
207 			else if (cp[2] || cp[3])
208 				printf("%d.%d", cp[2], cp[3]);
209 			break;
210 
211 		default:
212 			printf(" IPOPT-%d{%d}", cp[0], len);
213 			break;
214 		}
215 	}
216 }
217 
218 /*
219  * compute an IP header checksum.
220  * don't modifiy the packet.
221  */
222 u_short
223 in_cksum(const u_short *addr, register u_int len, int csum)
224 {
225 	int nleft = len;
226 	const u_short *w = addr;
227 	u_short answer;
228 	int sum = csum;
229 
230  	/*
231 	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
232 	 *  we add sequential 16 bit words to it, and at the end, fold
233 	 *  back all the carry bits from the top 16 bits into the lower
234 	 *  16 bits.
235  	 */
236 	while (nleft > 1)  {
237 		sum += *w++;
238 		nleft -= 2;
239 	}
240 	if (nleft == 1)
241 		sum += htons(*(u_char *)w<<8);
242 
243 	/*
244 	 * add back carry outs from top 16 bits to low 16 bits
245 	 */
246 	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
247 	sum += (sum >> 16);			/* add carry */
248 	answer = ~sum;				/* truncate to 16 bits */
249 	return (answer);
250 }
251 
252 /*
253  * print an IP datagram.
254  */
255 void
256 ip_print(register const u_char *bp, register u_int length)
257 {
258 	register const struct ip *ip;
259 	register u_int hlen, len, len0, off;
260 	register const u_char *cp;
261 	u_char nh;
262 	int advance;
263 	struct protoent *proto;
264 
265 	ip = (const struct ip *)bp;
266 #ifdef LBL_ALIGN
267 	/*
268 	 * If the IP header is not aligned, copy into abuf.
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 			if ((proto = getprotobynumber(nh)) != NULL)
467 				(void)printf(" %s", proto->p_name);
468 			else
469 				(void)printf(" ip-proto-%d", nh);
470 			printf(" %d", len);
471 			break;
472 		}
473 	}
474 
475  	/* Ultra quiet now means that all this stuff should be suppressed */
476  	/* res 3-Nov-98 */
477  	if (qflag > 1) return;
478 
479 
480 	/*
481 	 * for fragmented datagrams, print id:size@offset.  On all
482 	 * but the last stick a "+".  For unfragmented datagrams, note
483 	 * the don't fragment flag.
484 	 */
485 	len = len0;	/* get the original length */
486 	if (off & 0x3fff) {
487 		/*
488 		 * if this isn't the first frag, we're missing the
489 		 * next level protocol header.  print the ip addr
490 		 * and the protocol.
491 		 */
492 		if (off & 0x1fff) {
493 			(void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
494 				      ipaddr_string(&ip->ip_dst));
495 			if ((proto = getprotobynumber(ip->ip_p)) != NULL)
496 				(void)printf(" %s", proto->p_name);
497 			else
498 				(void)printf(" ip-proto-%d", ip->ip_p);
499 		}
500 #ifndef IP_MF
501 #define IP_MF 0x2000
502 #endif /* IP_MF */
503 #ifndef IP_DF
504 #define IP_DF 0x4000
505 #endif /* IP_DF */
506 		(void)printf(" (frag %d:%u@%d%s)", ntohs(ip->ip_id), len,
507 			(off & 0x1fff) * 8,
508 			(off & IP_MF)? "+" : "");
509 
510 	} else if (off & IP_DF)
511 		(void)printf(" (DF)");
512 
513 	if (ip->ip_tos) {
514 		(void)printf(" [tos 0x%x", (int)ip->ip_tos);
515 		/* ECN bits */
516 		if (ip->ip_tos & 0x03) {
517 			switch (ip->ip_tos & 0x03) {
518 			case 1:
519 				(void)printf(",ECT(1)");
520 				break;
521 			case 2:
522 				(void)printf(",ECT(0)");
523 				break;
524 			case 3:
525 				(void)printf(",CE");
526 			}
527 		}
528 		(void)printf("] ");
529 	}
530 
531 	if (ip->ip_ttl <= 1)
532 		(void)printf(" [ttl %d]", (int)ip->ip_ttl);
533 
534 	if (vflag) {
535 		int sum;
536 		char *sep = "";
537 
538 		printf(" (");
539 		if (ip->ip_ttl > 1) {
540 			(void)printf("%sttl %d", sep, (int)ip->ip_ttl);
541 			sep = ", ";
542 		}
543 		if ((off & 0x3fff) == 0) {
544 			(void)printf("%sid %d", sep, (int)ntohs(ip->ip_id));
545 			sep = ", ";
546 		}
547 		(void)printf("%slen %d", sep, (int)ntohs(ip->ip_len));
548 		sep = ", ";
549 		if ((u_char *)ip + hlen <= snapend) {
550 			sum = in_cksum((const u_short *)ip, hlen, 0);
551 			if (sum != 0) {
552 				(void)printf("%sbad cksum %x!", sep,
553 					     ntohs(ip->ip_sum));
554 				sep = ", ";
555 			}
556 		}
557 		if ((hlen -= sizeof(struct ip)) > 0) {
558 			(void)printf("%soptlen=%d", sep, hlen);
559 			ip_optprint((u_char *)(ip + 1), hlen);
560 		}
561 		printf(")");
562 	}
563 }
564 
565 void
566 ipN_print(register const u_char *bp, register u_int length)
567 {
568 	struct ip *ip, hdr;
569 
570 	ip = (struct ip *)bp;
571 	if (length < 4) {
572 		(void)printf("truncated-ip %d", length);
573 		return;
574 	}
575 	memcpy (&hdr, (char *)ip, 4);
576 	switch (IP_V(&hdr)) {
577 	case 4:
578 		ip_print (bp, length);
579 		return;
580 #ifdef INET6
581 	case 6:
582 		ip6_print (bp, length);
583 		return;
584 #endif
585 	default:
586 		(void)printf("unknown ip %d", IP_V(&hdr));
587 		return;
588 	}
589 }
590