print-ip.c revision 127675
117680Spst/*
239300Sfenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
317680Spst *	The Regents of the University of California.  All rights reserved.
417680Spst *
517680Spst * Redistribution and use in source and binary forms, with or without
617680Spst * modification, are permitted provided that: (1) source code distributions
717680Spst * retain the above copyright notice and this paragraph in its entirety, (2)
817680Spst * distributions including binary code include the above copyright notice and
917680Spst * this paragraph in its entirety in the documentation or other materials
1017680Spst * provided with the distribution, and (3) all advertising materials mentioning
1117680Spst * features or use of this software display the following acknowledgement:
1217680Spst * ``This product includes software developed by the University of California,
1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1417680Spst * the University nor the names of its contributors may be used to endorse
1517680Spst * or promote products derived from this software without specific prior
1617680Spst * written permission.
1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2056896Sfenner *
2156896Sfenner * $FreeBSD: head/contrib/tcpdump/print-ip.c 127675 2004-03-31 14:57:24Z bms $
2217680Spst */
2317680Spst
2417680Spst#ifndef lint
25127675Sbmsstatic const char rcsid[] _U_ =
26127675Sbms    "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.128.2.6 2004/03/24 09:01:39 guy Exp $ (LBL)";
2717680Spst#endif
2817680Spst
2956896Sfenner#ifdef HAVE_CONFIG_H
3056896Sfenner#include "config.h"
3156896Sfenner#endif
3256896Sfenner
33127675Sbms#include <tcpdump-stdinc.h>
3417680Spst
3517680Spst#include <stdio.h>
3617680Spst#include <stdlib.h>
3717680Spst#include <string.h>
3817680Spst
3917680Spst#include "addrtoname.h"
4017680Spst#include "interface.h"
4117680Spst#include "extract.h"			/* must come after interface.h */
4217680Spst
4375118Sfenner#include "ip.h"
44127675Sbms#include "ipproto.h"
4575118Sfenner
4617680Spst/*
4717680Spst * print the recorded route in an IP RR, LSRR or SSRR option.
4817680Spst */
4917680Spststatic void
5017680Spstip_printroute(const char *type, register const u_char *cp, u_int length)
5117680Spst{
52127675Sbms	register u_int ptr;
5317680Spst	register u_int len;
5417680Spst
55127675Sbms	if (length < 3) {
56127675Sbms		printf(" [bad length %u]", length);
57127675Sbms		return;
58127675Sbms	}
5917680Spst	printf(" %s{", type);
6017680Spst	if ((length + 1) & 3)
61127675Sbms		printf(" [bad length %u]", length);
62127675Sbms	ptr = cp[2] - 1;
6317680Spst	if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
64127675Sbms		printf(" [bad ptr %u]", cp[2]);
6517680Spst
6617680Spst	type = "";
6717680Spst	for (len = 3; len < length; len += 4) {
6817680Spst		if (ptr == len)
6917680Spst			type = "#";
7017680Spst		printf("%s%s", type, ipaddr_string(&cp[len]));
7117680Spst		type = " ";
7217680Spst	}
7317680Spst	printf("%s}", ptr == len? "#" : "");
7417680Spst}
7517680Spst
76127675Sbms/*
77127675Sbms * If source-routing is present, return the final destination.
78127675Sbms * Otherwise, return IP destination.
79127675Sbms *
80127675Sbms * This is used for UDP and TCP pseudo-header in the checksum
81127675Sbms * calculation.
82127675Sbms */
83127675Sbmsu_int32_t
84127675Sbmsip_finddst(const struct ip *ip)
85127675Sbms{
86127675Sbms	int length;
87127675Sbms	int len;
88127675Sbms	const u_char *cp;
89127675Sbms	u_int32_t retval;
90127675Sbms
91127675Sbms	cp = (const u_char *)(ip + 1);
92127675Sbms	length = (IP_HL(ip) << 2) - sizeof(struct ip);
93127675Sbms
94127675Sbms	for (; length > 0; cp += len, length -= len) {
95127675Sbms		int tt;
96127675Sbms
97127675Sbms		TCHECK(*cp);
98127675Sbms		tt = *cp;
99127675Sbms		if (tt == IPOPT_NOP || tt == IPOPT_EOL)
100127675Sbms			len = 1;
101127675Sbms		else {
102127675Sbms			TCHECK(cp[1]);
103127675Sbms			len = cp[1];
104127675Sbms		}
105127675Sbms		if (len < 2) {
106127675Sbms			return 0;
107127675Sbms		}
108127675Sbms		TCHECK2(*cp, len);
109127675Sbms		switch (tt) {
110127675Sbms
111127675Sbms		case IPOPT_SSRR:
112127675Sbms		case IPOPT_LSRR:
113127675Sbms			if (len < 7)
114127675Sbms				return 0;
115127675Sbms			memcpy(&retval, cp + len - 4, 4);
116127675Sbms			return retval;
117127675Sbms		}
118127675Sbms	}
119127675Sbms	return ip->ip_dst.s_addr;
120127675Sbms
121127675Sbmstrunc:
122127675Sbms	return 0;
123127675Sbms}
124127675Sbms
12556896Sfennerstatic void
12656896Sfennerip_printts(register const u_char *cp, u_int length)
12756896Sfenner{
128127675Sbms	register u_int ptr;
129127675Sbms	register u_int len;
13056896Sfenner	int hoplen;
131127675Sbms	const char *type;
13256896Sfenner
133127675Sbms	if (length < 4) {
134127675Sbms		printf("[bad length %d]", length);
135127675Sbms		return;
136127675Sbms	}
13756896Sfenner	printf(" TS{");
13856896Sfenner	hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
13956896Sfenner	if ((length - 4) & (hoplen-1))
14056896Sfenner		printf("[bad length %d]", length);
141127675Sbms	ptr = cp[2] - 1;
142127675Sbms	len = 0;
14356896Sfenner	if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
14456896Sfenner		printf("[bad ptr %d]", cp[2]);
14556896Sfenner	switch (cp[3]&0xF) {
14656896Sfenner	case IPOPT_TS_TSONLY:
14756896Sfenner		printf("TSONLY");
14856896Sfenner		break;
14956896Sfenner	case IPOPT_TS_TSANDADDR:
15056896Sfenner		printf("TS+ADDR");
15156896Sfenner		break;
15256896Sfenner	/*
15356896Sfenner	 * prespecified should really be 3, but some ones might send 2
15456896Sfenner	 * instead, and the IPOPT_TS_PRESPEC constant can apparently
15556896Sfenner	 * have both values, so we have to hard-code it here.
15656896Sfenner	 */
15756896Sfenner
15856896Sfenner	case 2:
15956896Sfenner		printf("PRESPEC2.0");
16056896Sfenner		break;
16156896Sfenner	case 3:			/* IPOPT_TS_PRESPEC */
16256896Sfenner		printf("PRESPEC");
16356896Sfenner		break;
164127675Sbms	default:
16556896Sfenner		printf("[bad ts type %d]", cp[3]&0xF);
16656896Sfenner		goto done;
16756896Sfenner	}
16856896Sfenner
16956896Sfenner	type = " ";
17056896Sfenner	for (len = 4; len < length; len += hoplen) {
17156896Sfenner		if (ptr == len)
17256896Sfenner			type = " ^ ";
17356896Sfenner		printf("%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]),
17456896Sfenner		       hoplen!=8 ? "" : ipaddr_string(&cp[len]));
17556896Sfenner		type = " ";
17656896Sfenner	}
17756896Sfenner
17856896Sfennerdone:
17956896Sfenner	printf("%s", ptr == len ? " ^ " : "");
18056896Sfenner
18156896Sfenner	if (cp[3]>>4)
18256896Sfenner		printf(" [%d hops not recorded]} ", cp[3]>>4);
18356896Sfenner	else
18456896Sfenner		printf("}");
18556896Sfenner}
18656896Sfenner
18717680Spst/*
18817680Spst * print IP options.
18917680Spst */
19017680Spststatic void
19117680Spstip_optprint(register const u_char *cp, u_int length)
19217680Spst{
19317680Spst	register u_int len;
19417680Spst
19517680Spst	for (; length > 0; cp += len, length -= len) {
196127675Sbms		int tt;
19717680Spst
198127675Sbms		TCHECK(*cp);
199127675Sbms		tt = *cp;
20075118Sfenner		if (tt == IPOPT_NOP || tt == IPOPT_EOL)
20175118Sfenner			len = 1;
20275118Sfenner		else {
203127675Sbms			TCHECK(cp[1]);
204127675Sbms			len = cp[1];
205127675Sbms			if (len < 2) {
206127675Sbms				printf("[|ip op len %d]", len);
20775118Sfenner				return;
20875118Sfenner			}
209127675Sbms			TCHECK2(*cp, len);
21075118Sfenner		}
21117680Spst		switch (tt) {
21217680Spst
21317680Spst		case IPOPT_EOL:
21417680Spst			printf(" EOL");
21517680Spst			if (length > 1)
21617680Spst				printf("-%d", length - 1);
21717680Spst			return;
21817680Spst
21917680Spst		case IPOPT_NOP:
22017680Spst			printf(" NOP");
22117680Spst			break;
22217680Spst
22317680Spst		case IPOPT_TS:
22456896Sfenner			ip_printts(cp, len);
22517680Spst			break;
22617680Spst
22756896Sfenner#ifndef IPOPT_SECURITY
22856896Sfenner#define IPOPT_SECURITY 130
22956896Sfenner#endif /* IPOPT_SECURITY */
23017680Spst		case IPOPT_SECURITY:
23117680Spst			printf(" SECURITY{%d}", len);
23217680Spst			break;
23317680Spst
23417680Spst		case IPOPT_RR:
23517680Spst			ip_printroute("RR", cp, len);
23617680Spst			break;
23717680Spst
23817680Spst		case IPOPT_SSRR:
23917680Spst			ip_printroute("SSRR", cp, len);
24017680Spst			break;
24117680Spst
24217680Spst		case IPOPT_LSRR:
24317680Spst			ip_printroute("LSRR", cp, len);
24417680Spst			break;
24517680Spst
24656896Sfenner#ifndef IPOPT_RA
24756896Sfenner#define IPOPT_RA 148		/* router alert */
24856896Sfenner#endif
24917691Spst		case IPOPT_RA:
25056896Sfenner			printf(" RA");
25156896Sfenner			if (len != 4)
25256896Sfenner				printf("{%d}", len);
253127675Sbms			else {
254127675Sbms				TCHECK(cp[3]);
255127675Sbms				if (cp[2] || cp[3])
256127675Sbms					printf("%d.%d", cp[2], cp[3]);
257127675Sbms			}
25898527Sfenner			break;
25917691Spst
26017680Spst		default:
26117680Spst			printf(" IPOPT-%d{%d}", cp[0], len);
26217680Spst			break;
26317680Spst		}
26417680Spst	}
265127675Sbms	return;
266127675Sbms
267127675Sbmstrunc:
268127675Sbms	printf("[|ip]");
26917680Spst}
27017680Spst
27117680Spst/*
27217680Spst * compute an IP header checksum.
27317680Spst * don't modifiy the packet.
27417680Spst */
27556896Sfenneru_short
27698527Sfennerin_cksum(const u_short *addr, register u_int len, int csum)
27717680Spst{
27856896Sfenner	int nleft = len;
27956896Sfenner	const u_short *w = addr;
28056896Sfenner	u_short answer;
28156896Sfenner	int sum = csum;
28217680Spst
283127675Sbms	/*
28456896Sfenner	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
28556896Sfenner	 *  we add sequential 16 bit words to it, and at the end, fold
28656896Sfenner	 *  back all the carry bits from the top 16 bits into the lower
28756896Sfenner	 *  16 bits.
288127675Sbms	 */
28956896Sfenner	while (nleft > 1)  {
29056896Sfenner		sum += *w++;
29156896Sfenner		nleft -= 2;
29256896Sfenner	}
29356896Sfenner	if (nleft == 1)
29456896Sfenner		sum += htons(*(u_char *)w<<8);
29556896Sfenner
29617680Spst	/*
29756896Sfenner	 * add back carry outs from top 16 bits to low 16 bits
29817680Spst	 */
29956896Sfenner	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
30056896Sfenner	sum += (sum >> 16);			/* add carry */
30156896Sfenner	answer = ~sum;				/* truncate to 16 bits */
30256896Sfenner	return (answer);
30317680Spst}
30417680Spst
30517680Spst/*
306127675Sbms * Given the host-byte-order value of the checksum field in a packet
307127675Sbms * header, and the network-byte-order computed checksum of the data
308127675Sbms * that the checksum covers (including the checksum itself), compute
309127675Sbms * what the checksum field *should* have been.
310127675Sbms */
311127675Sbmsu_int16_t
312127675Sbmsin_cksum_shouldbe(u_int16_t sum, u_int16_t computed_sum)
313127675Sbms{
314127675Sbms	u_int32_t shouldbe;
315127675Sbms
316127675Sbms	/*
317127675Sbms	 * The value that should have gone into the checksum field
318127675Sbms	 * is the negative of the value gotten by summing up everything
319127675Sbms	 * *but* the checksum field.
320127675Sbms	 *
321127675Sbms	 * We can compute that by subtracting the value of the checksum
322127675Sbms	 * field from the sum of all the data in the packet, and then
323127675Sbms	 * computing the negative of that value.
324127675Sbms	 *
325127675Sbms	 * "sum" is the value of the checksum field, and "computed_sum"
326127675Sbms	 * is the negative of the sum of all the data in the packets,
327127675Sbms	 * so that's -(-computed_sum - sum), or (sum + computed_sum).
328127675Sbms	 *
329127675Sbms	 * All the arithmetic in question is one's complement, so the
330127675Sbms	 * addition must include an end-around carry; we do this by
331127675Sbms	 * doing the arithmetic in 32 bits (with no sign-extension),
332127675Sbms	 * and then adding the upper 16 bits of the sum, which contain
333127675Sbms	 * the carry, to the lower 16 bits of the sum, and then do it
334127675Sbms	 * again in case *that* sum produced a carry.
335127675Sbms	 *
336127675Sbms	 * As RFC 1071 notes, the checksum can be computed without
337127675Sbms	 * byte-swapping the 16-bit words; summing 16-bit words
338127675Sbms	 * on a big-endian machine gives a big-endian checksum, which
339127675Sbms	 * can be directly stuffed into the big-endian checksum fields
340127675Sbms	 * in protocol headers, and summing words on a little-endian
341127675Sbms	 * machine gives a little-endian checksum, which must be
342127675Sbms	 * byte-swapped before being stuffed into a big-endian checksum
343127675Sbms	 * field.
344127675Sbms	 *
345127675Sbms	 * "computed_sum" is a network-byte-order value, so we must put
346127675Sbms	 * it in host byte order before subtracting it from the
347127675Sbms	 * host-byte-order value from the header; the adjusted checksum
348127675Sbms	 * will be in host byte order, which is what we'll return.
349127675Sbms	 */
350127675Sbms	shouldbe = sum;
351127675Sbms	shouldbe += ntohs(computed_sum);
352127675Sbms	shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16);
353127675Sbms	shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16);
354127675Sbms	return shouldbe;
355127675Sbms}
356127675Sbms
357127675Sbms#ifndef IP_MF
358127675Sbms#define IP_MF 0x2000
359127675Sbms#endif /* IP_MF */
360127675Sbms#ifndef IP_DF
361127675Sbms#define IP_DF 0x4000
362127675Sbms#endif /* IP_DF */
363127675Sbms#define IP_RES 0x8000
364127675Sbms
365127675Sbmsstatic struct tok ip_frag_values[] = {
366127675Sbms        { IP_MF,        "+" },
367127675Sbms        { IP_DF,        "DF" },
368127675Sbms	{ IP_RES,       "rsvd" }, /* The RFC3514 evil ;-) bit */
369127675Sbms        { 0,            NULL }
370127675Sbms};
371127675Sbms
372127675Sbms/*
37317680Spst * print an IP datagram.
37417680Spst */
37517680Spstvoid
37617680Spstip_print(register const u_char *bp, register u_int length)
37717680Spst{
37817680Spst	register const struct ip *ip;
37956896Sfenner	register u_int hlen, len, len0, off;
380127675Sbms	const u_char *ipend;
38117680Spst	register const u_char *cp;
38256896Sfenner	u_char nh;
38356896Sfenner	int advance;
384111729Sfenner	struct protoent *proto;
385127675Sbms	u_int16_t sum, ip_sum;
38617680Spst
38717680Spst	ip = (const struct ip *)bp;
388127675Sbms	if (IP_V(ip) != 4) { /* print version if != 4 */
389127675Sbms	    printf("IP%u ", IP_V(ip));
390127675Sbms	    if (IP_V(ip) == 6)
391127675Sbms		printf(", wrong link-layer encapsulation");
392127675Sbms	}
393127675Sbms        else
394127675Sbms	    printf("IP ");
39517680Spst
39617680Spst	if ((u_char *)(ip + 1) > snapend) {
39717680Spst		printf("[|ip]");
39817680Spst		return;
39917680Spst	}
40017680Spst	if (length < sizeof (struct ip)) {
40117680Spst		(void)printf("truncated-ip %d", length);
40217680Spst		return;
40317680Spst	}
40475118Sfenner	hlen = IP_HL(ip) * 4;
40575118Sfenner	if (hlen < sizeof (struct ip)) {
406127675Sbms		(void)printf("bad-hlen %u", hlen);
40775118Sfenner		return;
40875118Sfenner	}
40917680Spst
410127675Sbms	len = EXTRACT_16BITS(&ip->ip_len);
41117680Spst	if (length < len)
412127675Sbms		(void)printf("truncated-ip - %u bytes missing! ",
41317680Spst			len - length);
414127675Sbms	if (len < hlen) {
415127675Sbms		(void)printf("bad-len %u", len);
416127675Sbms		return;
417127675Sbms	}
418127675Sbms
419127675Sbms	/*
420127675Sbms	 * Cut off the snapshot length to the end of the IP payload.
421127675Sbms	 */
422127675Sbms	ipend = bp + len;
423127675Sbms	if (ipend < snapend)
424127675Sbms		snapend = ipend;
425127675Sbms
42617680Spst	len -= hlen;
42756896Sfenner	len0 = len;
42817680Spst
429127675Sbms	off = EXTRACT_16BITS(&ip->ip_off);
430127675Sbms
431127675Sbms        if (vflag) {
432127675Sbms            (void)printf("(tos 0x%x", (int)ip->ip_tos);
433127675Sbms            /* ECN bits */
434127675Sbms            if (ip->ip_tos & 0x03) {
435127675Sbms                switch (ip->ip_tos & 0x03) {
436127675Sbms                case 1:
437127675Sbms                    (void)printf(",ECT(1)");
438127675Sbms                    break;
439127675Sbms                case 2:
440127675Sbms                    (void)printf(",ECT(0)");
441127675Sbms                    break;
442127675Sbms                case 3:
443127675Sbms                    (void)printf(",CE");
444127675Sbms                }
445127675Sbms            }
446127675Sbms
447127675Sbms            if (ip->ip_ttl >= 1)
448127675Sbms                (void)printf(", ttl %3u", ip->ip_ttl);
449127675Sbms
450127675Sbms	    /*
451127675Sbms	     * for the firewall guys, print id, offset.
452127675Sbms             * On all but the last stick a "+" in the flags portion.
453127675Sbms	     * For unfragmented datagrams, note the don't fragment flag.
454127675Sbms	     */
455127675Sbms
456127675Sbms	    (void)printf(", id %u, offset %u, flags [%s]",
457127675Sbms			     EXTRACT_16BITS(&ip->ip_id),
458127675Sbms			     (off & 0x1fff) * 8,
459127675Sbms			     bittok2str(ip_frag_values, "none", off & 0xe000 ));
460127675Sbms
461127675Sbms            (void)printf(", length: %u", EXTRACT_16BITS(&ip->ip_len));
462127675Sbms
463127675Sbms            if ((hlen - sizeof(struct ip)) > 0) {
464127675Sbms                (void)printf(", optlength: %u (", hlen - (u_int)sizeof(struct ip));
465127675Sbms                ip_optprint((u_char *)(ip + 1), hlen - sizeof(struct ip));
466127675Sbms                printf(" )");
467127675Sbms            }
468127675Sbms
469127675Sbms	    if ((u_char *)ip + hlen <= snapend) {
470127675Sbms	        sum = in_cksum((const u_short *)ip, hlen, 0);
471127675Sbms		if (sum != 0) {
472127675Sbms		    ip_sum = EXTRACT_16BITS(&ip->ip_sum);
473127675Sbms		    (void)printf(", bad cksum %x (->%x)!", ip_sum,
474127675Sbms			     in_cksum_shouldbe(ip_sum, sum));
475127675Sbms		}
476127675Sbms	    }
477127675Sbms
478127675Sbms            printf(") ");
479127675Sbms	}
480127675Sbms
48117680Spst	/*
48217680Spst	 * If this is fragment zero, hand it to the next higher
48317680Spst	 * level protocol.
48417680Spst	 */
48517680Spst	if ((off & 0x1fff) == 0) {
48617680Spst		cp = (const u_char *)ip + hlen;
48756896Sfenner		nh = ip->ip_p;
48817680Spst
48998527Sfenner		if (nh != IPPROTO_TCP && nh != IPPROTO_UDP &&
49098527Sfenner		    nh != IPPROTO_SCTP) {
49156896Sfenner			(void)printf("%s > %s: ", ipaddr_string(&ip->ip_src),
49256896Sfenner				ipaddr_string(&ip->ip_dst));
49356896Sfenner		}
49456896Sfenneragain:
49556896Sfenner		switch (nh) {
49656896Sfenner
49756896Sfenner		case IPPROTO_AH:
49856896Sfenner			nh = *cp;
499127675Sbms			advance = ah_print(cp);
500127675Sbms			if (advance <= 0)
501127675Sbms				break;
50256896Sfenner			cp += advance;
50356896Sfenner			len -= advance;
50456896Sfenner			goto again;
50556896Sfenner
50656896Sfenner		case IPPROTO_ESP:
50756896Sfenner		    {
50898527Sfenner			int enh, padlen;
50998527Sfenner			advance = esp_print(cp, (const u_char *)ip, &enh, &padlen);
510127675Sbms			if (advance <= 0)
511127675Sbms				break;
51256896Sfenner			cp += advance;
51398527Sfenner			len -= advance + padlen;
51456896Sfenner			nh = enh & 0xff;
51556896Sfenner			goto again;
51656896Sfenner		    }
51756896Sfenner
51856896Sfenner		case IPPROTO_IPCOMP:
51956896Sfenner		    {
52056896Sfenner			int enh;
521127675Sbms			advance = ipcomp_print(cp, &enh);
522127675Sbms			if (advance <= 0)
523127675Sbms				break;
52456896Sfenner			cp += advance;
52556896Sfenner			len -= advance;
52656896Sfenner			nh = enh & 0xff;
52756896Sfenner			goto again;
52856896Sfenner		    }
52956896Sfenner
53098527Sfenner		case IPPROTO_SCTP:
531127675Sbms			sctp_print(cp, (const u_char *)ip, len);
53298527Sfenner			break;
53398527Sfenner
53417680Spst		case IPPROTO_TCP:
53575118Sfenner			tcp_print(cp, len, (const u_char *)ip, (off &~ 0x6000));
53617680Spst			break;
53717680Spst
53817680Spst		case IPPROTO_UDP:
53975118Sfenner			udp_print(cp, len, (const u_char *)ip, (off &~ 0x6000));
54017680Spst			break;
54117680Spst
54217680Spst		case IPPROTO_ICMP:
543127675Sbms		        /* pass on the MF bit plus the offset to detect fragments */
544127675Sbms			icmp_print(cp, len, (const u_char *)ip, (off & 0x3fff));
54517680Spst			break;
54617680Spst
54717680Spst		case IPPROTO_IGRP:
54817680Spst			igrp_print(cp, len, (const u_char *)ip);
54917680Spst			break;
55017680Spst
55117680Spst		case IPPROTO_ND:
55217680Spst			(void)printf(" nd %d", len);
55317680Spst			break;
55417680Spst
55517680Spst		case IPPROTO_EGP:
556127675Sbms			egp_print(cp);
55717680Spst			break;
55817680Spst
55917680Spst		case IPPROTO_OSPF:
56017680Spst			ospf_print(cp, len, (const u_char *)ip);
56117680Spst			break;
56217680Spst
56317680Spst		case IPPROTO_IGMP:
56498527Sfenner			igmp_print(cp, len);
56517680Spst			break;
56617680Spst
567127675Sbms		case IPPROTO_IPV4:
56839300Sfenner			/* DVMRP multicast tunnel (ip-in-ip encapsulation) */
56917680Spst			ip_print(cp, len);
57017680Spst			if (! vflag) {
57198527Sfenner				printf(" (ipip-proto-4)");
57217680Spst				return;
57317680Spst			}
57417680Spst			break;
57517680Spst
57656896Sfenner#ifdef INET6
577127675Sbms		case IPPROTO_IPV6:
57856896Sfenner			/* ip6-in-ip encapsulation */
57956896Sfenner			ip6_print(cp, len);
58056896Sfenner			break;
58156896Sfenner#endif /*INET6*/
58256896Sfenner
583127675Sbms		case IPPROTO_RSVP:
584127675Sbms			rsvp_print(cp, len);
585127675Sbms			break;
58656896Sfenner
58726183Sfenner		case IPPROTO_GRE:
58826183Sfenner			/* do it */
58926183Sfenner			gre_print(cp, len);
59098527Sfenner			break;
59126183Sfenner
59256896Sfenner		case IPPROTO_MOBILE:
59356896Sfenner			mobile_print(cp, len);
59456896Sfenner			break;
59556896Sfenner
59656896Sfenner		case IPPROTO_PIM:
59756896Sfenner			pim_print(cp, len);
59856896Sfenner			break;
59956896Sfenner
60075118Sfenner		case IPPROTO_VRRP:
60175118Sfenner			vrrp_print(cp, len, ip->ip_ttl);
60275118Sfenner			break;
60375118Sfenner
60417680Spst		default:
605111729Sfenner			if ((proto = getprotobynumber(nh)) != NULL)
606111729Sfenner				(void)printf(" %s", proto->p_name);
607111729Sfenner			else
608111729Sfenner				(void)printf(" ip-proto-%d", nh);
609111729Sfenner			printf(" %d", len);
61017680Spst			break;
61117680Spst		}
612127675Sbms	} else {
613127675Sbms	    /* Ultra quiet now means that all this stuff should be suppressed */
614127675Sbms	    if (qflag > 1) return;
61556896Sfenner
616127675Sbms	    /*
617127675Sbms	     * if this isn't the first frag, we're missing the
618127675Sbms	     * next level protocol header.  print the ip addr
619127675Sbms	     * and the protocol.
620127675Sbms	     */
621127675Sbms	    if (off & 0x1fff) {
622127675Sbms	        (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
623127675Sbms			     ipaddr_string(&ip->ip_dst));
624127675Sbms		if ((proto = getprotobynumber(ip->ip_p)) != NULL)
625127675Sbms		    (void)printf(" %s", proto->p_name);
626127675Sbms		else
627127675Sbms		    (void)printf(" ip-proto-%d", ip->ip_p);
628127675Sbms	    }
62956896Sfenner	}
63017680Spst}
63175118Sfenner
63275118Sfennervoid
63375118SfenneripN_print(register const u_char *bp, register u_int length)
63475118Sfenner{
63575118Sfenner	struct ip *ip, hdr;
63675118Sfenner
63775118Sfenner	ip = (struct ip *)bp;
63875118Sfenner	if (length < 4) {
63975118Sfenner		(void)printf("truncated-ip %d", length);
64075118Sfenner		return;
64175118Sfenner	}
64275118Sfenner	memcpy (&hdr, (char *)ip, 4);
64375118Sfenner	switch (IP_V(&hdr)) {
64475118Sfenner	case 4:
64598527Sfenner		ip_print (bp, length);
64698527Sfenner		return;
64775118Sfenner#ifdef INET6
64875118Sfenner	case 6:
64998527Sfenner		ip6_print (bp, length);
65098527Sfenner		return;
65175118Sfenner#endif
65275118Sfenner	default:
65398527Sfenner		(void)printf("unknown ip %d", IP_V(&hdr));
65498527Sfenner		return;
65575118Sfenner	}
65675118Sfenner}
657127675Sbms
658127675Sbms
659127675Sbms
660