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