print-ip.c revision 172686
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: head/contrib/tcpdump/print-ip.c 172686 2007-10-16 02:31:48Z mlaier $
22 */
23
24#ifndef lint
25static const char rcsid[] _U_ =
26    "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.149.2.9 2007/09/14 01:30:02 guy Exp $ (LBL)";
27#endif
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include <tcpdump-stdinc.h>
34
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38
39#include "addrtoname.h"
40#include "interface.h"
41#include "extract.h"			/* must come after interface.h */
42
43#include "ip.h"
44#include "ipproto.h"
45
46struct tok ip_option_values[] = {
47    { IPOPT_EOL, "EOL" },
48    { IPOPT_NOP, "NOP" },
49    { IPOPT_TS, "timestamp" },
50    { IPOPT_SECURITY, "security" },
51    { IPOPT_RR, "RR" },
52    { IPOPT_SSRR, "SSRR" },
53    { IPOPT_LSRR, "LSRR" },
54    { IPOPT_RA, "RA" },
55    { IPOPT_RFC1393, "traceroute" },
56    { 0, NULL }
57};
58
59/*
60 * print the recorded route in an IP RR, LSRR or SSRR option.
61 */
62static void
63ip_printroute(register const u_char *cp, u_int length)
64{
65	register u_int ptr;
66	register u_int len;
67
68	if (length < 3) {
69		printf(" [bad length %u]", length);
70		return;
71	}
72	if ((length + 1) & 3)
73		printf(" [bad length %u]", length);
74	ptr = cp[2] - 1;
75	if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
76		printf(" [bad ptr %u]", cp[2]);
77
78	for (len = 3; len < length; len += 4) {
79		printf(" %s", ipaddr_string(&cp[len]));
80                if (ptr > len)
81                        printf(",");
82	}
83}
84
85/*
86 * If source-routing is present and valid, return the final destination.
87 * Otherwise, return IP destination.
88 *
89 * This is used for UDP and TCP pseudo-header in the checksum
90 * calculation.
91 */
92u_int32_t
93ip_finddst(const struct ip *ip)
94{
95	int length;
96	int len;
97	const u_char *cp;
98	u_int32_t retval;
99
100	cp = (const u_char *)(ip + 1);
101	length = (IP_HL(ip) << 2) - sizeof(struct ip);
102
103	for (; length > 0; cp += len, length -= len) {
104		int tt;
105
106		TCHECK(*cp);
107		tt = *cp;
108		if (tt == IPOPT_EOL)
109			break;
110		else if (tt == IPOPT_NOP)
111			len = 1;
112		else {
113			TCHECK(cp[1]);
114			len = cp[1];
115			if (len < 2)
116				break;
117		}
118		TCHECK2(*cp, len);
119		switch (tt) {
120
121		case IPOPT_SSRR:
122		case IPOPT_LSRR:
123			if (len < 7)
124				break;
125			memcpy(&retval, cp + len - 4, 4);
126			return retval;
127		}
128	}
129trunc:
130	memcpy(&retval, &ip->ip_dst.s_addr, sizeof(u_int32_t));
131	return retval;
132}
133
134static void
135ip_printts(register const u_char *cp, u_int length)
136{
137	register u_int ptr;
138	register u_int len;
139	int hoplen;
140	const char *type;
141
142	if (length < 4) {
143		printf("[bad length %u]", length);
144		return;
145	}
146	printf(" TS{");
147	hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
148	if ((length - 4) & (hoplen-1))
149		printf("[bad length %u]", length);
150	ptr = cp[2] - 1;
151	len = 0;
152	if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
153		printf("[bad ptr %u]", cp[2]);
154	switch (cp[3]&0xF) {
155	case IPOPT_TS_TSONLY:
156		printf("TSONLY");
157		break;
158	case IPOPT_TS_TSANDADDR:
159		printf("TS+ADDR");
160		break;
161	/*
162	 * prespecified should really be 3, but some ones might send 2
163	 * instead, and the IPOPT_TS_PRESPEC constant can apparently
164	 * have both values, so we have to hard-code it here.
165	 */
166
167	case 2:
168		printf("PRESPEC2.0");
169		break;
170	case 3:			/* IPOPT_TS_PRESPEC */
171		printf("PRESPEC");
172		break;
173	default:
174		printf("[bad ts type %d]", cp[3]&0xF);
175		goto done;
176	}
177
178	type = " ";
179	for (len = 4; len < length; len += hoplen) {
180		if (ptr == len)
181			type = " ^ ";
182		printf("%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]),
183		       hoplen!=8 ? "" : ipaddr_string(&cp[len]));
184		type = " ";
185	}
186
187done:
188	printf("%s", ptr == len ? " ^ " : "");
189
190	if (cp[3]>>4)
191		printf(" [%d hops not recorded]} ", cp[3]>>4);
192	else
193		printf("}");
194}
195
196/*
197 * print IP options.
198 */
199static void
200ip_optprint(register const u_char *cp, u_int length)
201{
202	register u_int option_len;
203	const char *sep = "";
204
205	for (; length > 0; cp += option_len, length -= option_len) {
206		u_int option_code;
207
208		printf("%s", sep);
209		sep = ",";
210
211		TCHECK(*cp);
212		option_code = *cp;
213
214                printf("%s",
215                        tok2str(ip_option_values,"unknown %u",option_code));
216
217		if (option_code == IPOPT_NOP ||
218                    option_code == IPOPT_EOL)
219			option_len = 1;
220
221		else {
222			TCHECK(cp[1]);
223			option_len = cp[1];
224			if (option_len < 2) {
225		                printf(" [bad length %u]", option_len);
226				return;
227			}
228		}
229
230		if (option_len > length) {
231	                printf(" [bad length %u]", option_len);
232			return;
233		}
234
235                TCHECK2(*cp, option_len);
236
237		switch (option_code) {
238		case IPOPT_EOL:
239			return;
240
241		case IPOPT_TS:
242			ip_printts(cp, option_len);
243			break;
244
245		case IPOPT_RR:       /* fall through */
246		case IPOPT_SSRR:
247		case IPOPT_LSRR:
248			ip_printroute(cp, option_len);
249			break;
250
251		case IPOPT_RA:
252			if (option_len < 4) {
253				printf(" [bad length %u]", option_len);
254				break;
255			}
256                        TCHECK(cp[3]);
257                        if (EXTRACT_16BITS(&cp[2]) != 0)
258                            printf(" value %u", EXTRACT_16BITS(&cp[2]));
259			break;
260
261		case IPOPT_NOP:       /* nothing to print - fall through */
262		case IPOPT_SECURITY:
263		default:
264			break;
265		}
266	}
267	return;
268
269trunc:
270	printf("[|ip]");
271}
272
273/*
274 * compute an IP header checksum.
275 * don't modifiy the packet.
276 */
277u_short
278in_cksum(const u_short *addr, register u_int len, int csum)
279{
280	int nleft = len;
281	const u_short *w = addr;
282	u_short answer;
283	int sum = csum;
284
285	/*
286	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
287	 *  we add sequential 16 bit words to it, and at the end, fold
288	 *  back all the carry bits from the top 16 bits into the lower
289	 *  16 bits.
290	 */
291	while (nleft > 1)  {
292		sum += *w++;
293		nleft -= 2;
294	}
295	if (nleft == 1)
296		sum += htons(*(u_char *)w<<8);
297
298	/*
299	 * add back carry outs from top 16 bits to low 16 bits
300	 */
301	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
302	sum += (sum >> 16);			/* add carry */
303	answer = ~sum;				/* truncate to 16 bits */
304	return (answer);
305}
306
307/*
308 * Given the host-byte-order value of the checksum field in a packet
309 * header, and the network-byte-order computed checksum of the data
310 * that the checksum covers (including the checksum itself), compute
311 * what the checksum field *should* have been.
312 */
313u_int16_t
314in_cksum_shouldbe(u_int16_t sum, u_int16_t computed_sum)
315{
316	u_int32_t shouldbe;
317
318	/*
319	 * The value that should have gone into the checksum field
320	 * is the negative of the value gotten by summing up everything
321	 * *but* the checksum field.
322	 *
323	 * We can compute that by subtracting the value of the checksum
324	 * field from the sum of all the data in the packet, and then
325	 * computing the negative of that value.
326	 *
327	 * "sum" is the value of the checksum field, and "computed_sum"
328	 * is the negative of the sum of all the data in the packets,
329	 * so that's -(-computed_sum - sum), or (sum + computed_sum).
330	 *
331	 * All the arithmetic in question is one's complement, so the
332	 * addition must include an end-around carry; we do this by
333	 * doing the arithmetic in 32 bits (with no sign-extension),
334	 * and then adding the upper 16 bits of the sum, which contain
335	 * the carry, to the lower 16 bits of the sum, and then do it
336	 * again in case *that* sum produced a carry.
337	 *
338	 * As RFC 1071 notes, the checksum can be computed without
339	 * byte-swapping the 16-bit words; summing 16-bit words
340	 * on a big-endian machine gives a big-endian checksum, which
341	 * can be directly stuffed into the big-endian checksum fields
342	 * in protocol headers, and summing words on a little-endian
343	 * machine gives a little-endian checksum, which must be
344	 * byte-swapped before being stuffed into a big-endian checksum
345	 * field.
346	 *
347	 * "computed_sum" is a network-byte-order value, so we must put
348	 * it in host byte order before subtracting it from the
349	 * host-byte-order value from the header; the adjusted checksum
350	 * will be in host byte order, which is what we'll return.
351	 */
352	shouldbe = sum;
353	shouldbe += ntohs(computed_sum);
354	shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16);
355	shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16);
356	return shouldbe;
357}
358
359#define IP_RES 0x8000
360
361static struct tok ip_frag_values[] = {
362        { IP_MF,        "+" },
363        { IP_DF,        "DF" },
364	{ IP_RES,       "rsvd" }, /* The RFC3514 evil ;-) bit */
365        { 0,            NULL }
366};
367
368struct ip_print_demux_state {
369	const struct ip *ip;
370	const u_char *cp;
371	u_int   len, off;
372	u_char  nh;
373	int     advance;
374};
375
376static void
377ip_print_demux(netdissect_options *ndo,
378	       struct ip_print_demux_state *ipds)
379{
380	struct protoent *proto;
381
382again:
383	switch (ipds->nh) {
384
385	case IPPROTO_AH:
386		ipds->nh = *ipds->cp;
387		ipds->advance = ah_print(ipds->cp);
388		if (ipds->advance <= 0)
389			break;
390		ipds->cp += ipds->advance;
391		ipds->len -= ipds->advance;
392		goto again;
393
394	case IPPROTO_ESP:
395	{
396		int enh, padlen;
397		ipds->advance = esp_print(ndo, ipds->cp, ipds->len,
398				    (const u_char *)ipds->ip,
399				    &enh, &padlen);
400		if (ipds->advance <= 0)
401			break;
402		ipds->cp += ipds->advance;
403		ipds->len -= ipds->advance + padlen;
404		ipds->nh = enh & 0xff;
405		goto again;
406	}
407
408	case IPPROTO_IPCOMP:
409	{
410		int enh;
411		ipds->advance = ipcomp_print(ipds->cp, &enh);
412		if (ipds->advance <= 0)
413			break;
414		ipds->cp += ipds->advance;
415		ipds->len -= ipds->advance;
416		ipds->nh = enh & 0xff;
417		goto again;
418	}
419
420	case IPPROTO_SCTP:
421		sctp_print(ipds->cp, (const u_char *)ipds->ip, ipds->len);
422		break;
423
424	case IPPROTO_DCCP:
425		dccp_print(ipds->cp, (const u_char *)ipds->ip, ipds->len);
426		break;
427
428	case IPPROTO_TCP:
429		/* pass on the MF bit plus the offset to detect fragments */
430		tcp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip,
431			  ipds->off & (IP_MF|IP_OFFMASK));
432		break;
433
434	case IPPROTO_UDP:
435		/* pass on the MF bit plus the offset to detect fragments */
436		udp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip,
437			  ipds->off & (IP_MF|IP_OFFMASK));
438		break;
439
440	case IPPROTO_ICMP:
441		/* pass on the MF bit plus the offset to detect fragments */
442		icmp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip,
443			   ipds->off & (IP_MF|IP_OFFMASK));
444		break;
445
446	case IPPROTO_PIGP:
447		/*
448		 * XXX - the current IANA protocol number assignments
449		 * page lists 9 as "any private interior gateway
450		 * (used by Cisco for their IGRP)" and 88 as
451		 * "EIGRP" from Cisco.
452		 *
453		 * Recent BSD <netinet/in.h> headers define
454		 * IP_PROTO_PIGP as 9 and IP_PROTO_IGRP as 88.
455		 * We define IP_PROTO_PIGP as 9 and
456		 * IP_PROTO_EIGRP as 88; those names better
457		 * match was the current protocol number
458		 * assignments say.
459		 */
460		igrp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip);
461		break;
462
463	case IPPROTO_EIGRP:
464		eigrp_print(ipds->cp, ipds->len);
465		break;
466
467	case IPPROTO_ND:
468		ND_PRINT((ndo, " nd %d", ipds->len));
469		break;
470
471	case IPPROTO_EGP:
472		egp_print(ipds->cp, ipds->len);
473		break;
474
475	case IPPROTO_OSPF:
476		ospf_print(ipds->cp, ipds->len, (const u_char *)ipds->ip);
477		break;
478
479	case IPPROTO_IGMP:
480		igmp_print(ipds->cp, ipds->len);
481		break;
482
483	case IPPROTO_IPV4:
484		/* DVMRP multicast tunnel (ip-in-ip encapsulation) */
485		ip_print(gndo, ipds->cp, ipds->len);
486		if (! vflag) {
487			ND_PRINT((ndo, " (ipip-proto-4)"));
488			return;
489		}
490		break;
491
492#ifdef INET6
493	case IPPROTO_IPV6:
494		/* ip6-in-ip encapsulation */
495		ip6_print(ipds->cp, ipds->len);
496		break;
497#endif /*INET6*/
498
499	case IPPROTO_RSVP:
500		rsvp_print(ipds->cp, ipds->len);
501		break;
502
503	case IPPROTO_GRE:
504		/* do it */
505		gre_print(ipds->cp, ipds->len);
506		break;
507
508	case IPPROTO_MOBILE:
509		mobile_print(ipds->cp, ipds->len);
510		break;
511
512	case IPPROTO_PIM:
513		pim_print(ipds->cp,  ipds->len);
514		break;
515
516	case IPPROTO_VRRP:
517		vrrp_print(ipds->cp, ipds->len, ipds->ip->ip_ttl);
518		break;
519
520	case IPPROTO_PGM:
521		pgm_print(ipds->cp, ipds->len, (const u_char *)ipds->ip);
522		break;
523
524	default:
525		if ((proto = getprotobynumber(ipds->nh)) != NULL)
526			ND_PRINT((ndo, " %s", proto->p_name));
527		else
528			ND_PRINT((ndo, " ip-proto-%d", ipds->nh));
529		ND_PRINT((ndo, " %d", ipds->len));
530		break;
531	}
532}
533
534void
535ip_print_inner(netdissect_options *ndo,
536	       const u_char *bp,
537	       u_int length, u_int nh,
538	       const u_char *bp2)
539{
540	struct ip_print_demux_state  ipd;
541
542	ipd.ip = (const struct ip *)bp2;
543	ipd.cp = bp;
544	ipd.len  = length;
545	ipd.off  = 0;
546	ipd.nh   = nh;
547	ipd.advance = 0;
548
549	ip_print_demux(ndo, &ipd);
550}
551
552
553/*
554 * print an IP datagram.
555 */
556void
557ip_print(netdissect_options *ndo,
558	 const u_char *bp,
559	 u_int length)
560{
561	struct ip_print_demux_state  ipd;
562	struct ip_print_demux_state *ipds=&ipd;
563	const u_char *ipend;
564	u_int hlen;
565	u_int16_t sum, ip_sum;
566	struct protoent *proto;
567
568	ipds->ip = (const struct ip *)bp;
569	if (IP_V(ipds->ip) != 4) { /* print version if != 4 */
570	    printf("IP%u ", IP_V(ipds->ip));
571	    if (IP_V(ipds->ip) == 6)
572		printf(", wrong link-layer encapsulation");
573	}
574        else if (!eflag)
575	    printf("IP ");
576
577	if ((u_char *)(ipds->ip + 1) > snapend) {
578		printf("[|ip]");
579		return;
580	}
581	if (length < sizeof (struct ip)) {
582		(void)printf("truncated-ip %u", length);
583		return;
584	}
585	hlen = IP_HL(ipds->ip) * 4;
586	if (hlen < sizeof (struct ip)) {
587		(void)printf("bad-hlen %u", hlen);
588		return;
589	}
590
591	ipds->len = EXTRACT_16BITS(&ipds->ip->ip_len);
592	if (length < ipds->len)
593		(void)printf("truncated-ip - %u bytes missing! ",
594			ipds->len - length);
595	if (ipds->len < hlen) {
596#ifdef GUESS_TSO
597            if (ipds->len) {
598                (void)printf("bad-len %u", ipds->len);
599                return;
600            }
601            else {
602                /* we guess that it is a TSO send */
603                ipds->len = length;
604            }
605#else
606            (void)printf("bad-len %u", ipds->len);
607            return;
608#endif /* GUESS_TSO */
609	}
610
611	/*
612	 * Cut off the snapshot length to the end of the IP payload.
613	 */
614	ipend = bp + ipds->len;
615	if (ipend < snapend)
616		snapend = ipend;
617
618	ipds->len -= hlen;
619
620	ipds->off = EXTRACT_16BITS(&ipds->ip->ip_off);
621
622        if (vflag) {
623            (void)printf("(tos 0x%x", (int)ipds->ip->ip_tos);
624            /* ECN bits */
625            if (ipds->ip->ip_tos & 0x03) {
626                switch (ipds->ip->ip_tos & 0x03) {
627                case 1:
628                    (void)printf(",ECT(1)");
629                    break;
630                case 2:
631                    (void)printf(",ECT(0)");
632                    break;
633                case 3:
634                    (void)printf(",CE");
635                }
636            }
637
638            if (ipds->ip->ip_ttl >= 1)
639                (void)printf(", ttl %u", ipds->ip->ip_ttl);
640
641	    /*
642	     * for the firewall guys, print id, offset.
643             * On all but the last stick a "+" in the flags portion.
644	     * For unfragmented datagrams, note the don't fragment flag.
645	     */
646
647	    (void)printf(", id %u, offset %u, flags [%s], proto %s (%u)",
648                         EXTRACT_16BITS(&ipds->ip->ip_id),
649                         (ipds->off & 0x1fff) * 8,
650                         bittok2str(ip_frag_values, "none", ipds->off&0xe000),
651                         tok2str(ipproto_values,"unknown",ipds->ip->ip_p),
652                         ipds->ip->ip_p);
653
654            (void)printf(", length %u", EXTRACT_16BITS(&ipds->ip->ip_len));
655
656            if ((hlen - sizeof(struct ip)) > 0) {
657                printf(", options (");
658                ip_optprint((u_char *)(ipds->ip + 1), hlen - sizeof(struct ip));
659                printf(")");
660            }
661
662	    if ((u_char *)ipds->ip + hlen <= snapend) {
663	        sum = in_cksum((const u_short *)ipds->ip, hlen, 0);
664		if (sum != 0) {
665		    ip_sum = EXTRACT_16BITS(&ipds->ip->ip_sum);
666		    (void)printf(", bad cksum %x (->%x)!", ip_sum,
667			     in_cksum_shouldbe(ip_sum, sum));
668		}
669	    }
670
671            printf(") ");
672	}
673
674	/*
675	 * If this is fragment zero, hand it to the next higher
676	 * level protocol.
677	 */
678	if ((ipds->off & 0x1fff) == 0) {
679		ipds->cp = (const u_char *)ipds->ip + hlen;
680		ipds->nh = ipds->ip->ip_p;
681
682		if (ipds->nh != IPPROTO_TCP && ipds->nh != IPPROTO_UDP &&
683		    ipds->nh != IPPROTO_SCTP && ipds->nh != IPPROTO_DCCP) {
684			(void)printf("%s > %s: ",
685				     ipaddr_string(&ipds->ip->ip_src),
686				     ipaddr_string(&ipds->ip->ip_dst));
687		}
688		ip_print_demux(ndo, ipds);
689	} else {
690	    /* Ultra quiet now means that all this stuff should be suppressed */
691	    if (qflag > 1) return;
692
693	    /*
694	     * if this isn't the first frag, we're missing the
695	     * next level protocol header.  print the ip addr
696	     * and the protocol.
697	     */
698	    if (ipds->off & 0x1fff) {
699	        (void)printf("%s > %s:", ipaddr_string(&ipds->ip->ip_src),
700			     ipaddr_string(&ipds->ip->ip_dst));
701		if ((proto = getprotobynumber(ipds->ip->ip_p)) != NULL)
702		    (void)printf(" %s", proto->p_name);
703		else
704		    (void)printf(" ip-proto-%d", ipds->ip->ip_p);
705	    }
706	}
707}
708
709void
710ipN_print(register const u_char *bp, register u_int length)
711{
712	struct ip *ip, hdr;
713
714	ip = (struct ip *)bp;
715	if (length < 4) {
716		(void)printf("truncated-ip %d", length);
717		return;
718	}
719	memcpy (&hdr, (char *)ip, 4);
720	switch (IP_V(&hdr)) {
721	case 4:
722		ip_print (gndo, bp, length);
723		return;
724#ifdef INET6
725	case 6:
726		ip6_print (bp, length);
727		return;
728#endif
729	default:
730		(void)printf("unknown ip %d", IP_V(&hdr));
731		return;
732	}
733}
734
735/*
736 * Local Variables:
737 * c-style: whitesmith
738 * c-basic-offset: 8
739 * End:
740 */
741
742
743