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