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