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