print-ip.c revision 98527
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 98527 2002-06-21 00:49:02Z fenner $
2217680Spst */
2317680Spst
2417680Spst#ifndef lint
2526183Sfennerstatic const char rcsid[] =
2698527Sfenner    "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.100 2001/09/17 21:58:03 fenner Exp $ (LBL)";
2717680Spst#endif
2817680Spst
2956896Sfenner#ifdef HAVE_CONFIG_H
3056896Sfenner#include "config.h"
3156896Sfenner#endif
3256896Sfenner
3317680Spst#include <sys/param.h>
3417680Spst#include <sys/time.h>
3517680Spst#include <sys/socket.h>
3617680Spst
3717680Spst#include <netinet/in.h>
3817680Spst
3917680Spst#include <stdio.h>
4017680Spst#include <stdlib.h>
4117680Spst#include <string.h>
4217680Spst#include <unistd.h>
4317680Spst
4417680Spst#include "addrtoname.h"
4517680Spst#include "interface.h"
4617680Spst#include "extract.h"			/* must come after interface.h */
4717680Spst
4875118Sfenner#include "ip.h"
4975118Sfenner
5017680Spst/* Compatibility */
5117680Spst#ifndef	IPPROTO_ND
5217680Spst#define	IPPROTO_ND	77
5317680Spst#endif
5417680Spst
5517680Spst/*
5617680Spst * print the recorded route in an IP RR, LSRR or SSRR option.
5717680Spst */
5817680Spststatic void
5917680Spstip_printroute(const char *type, register const u_char *cp, u_int length)
6017680Spst{
6117680Spst	register u_int ptr = cp[2] - 1;
6217680Spst	register u_int len;
6317680Spst
6417680Spst	printf(" %s{", type);
6517680Spst	if ((length + 1) & 3)
6617680Spst		printf(" [bad length %d]", length);
6717680Spst	if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
6817680Spst		printf(" [bad ptr %d]", cp[2]);
6917680Spst
7017680Spst	type = "";
7117680Spst	for (len = 3; len < length; len += 4) {
7217680Spst		if (ptr == len)
7317680Spst			type = "#";
7417680Spst		printf("%s%s", type, ipaddr_string(&cp[len]));
7517680Spst		type = " ";
7617680Spst	}
7717680Spst	printf("%s}", ptr == len? "#" : "");
7817680Spst}
7917680Spst
8056896Sfennerstatic void
8156896Sfennerip_printts(register const u_char *cp, u_int length)
8256896Sfenner{
8356896Sfenner	register u_int ptr = cp[2] - 1;
8456896Sfenner	register u_int len = 0;
8556896Sfenner	int hoplen;
8656896Sfenner	char *type;
8756896Sfenner
8856896Sfenner	printf(" TS{");
8956896Sfenner	hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
9056896Sfenner	if ((length - 4) & (hoplen-1))
9156896Sfenner		printf("[bad length %d]", length);
9256896Sfenner	if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
9356896Sfenner		printf("[bad ptr %d]", cp[2]);
9456896Sfenner	switch (cp[3]&0xF) {
9556896Sfenner	case IPOPT_TS_TSONLY:
9656896Sfenner		printf("TSONLY");
9756896Sfenner		break;
9856896Sfenner	case IPOPT_TS_TSANDADDR:
9956896Sfenner		printf("TS+ADDR");
10056896Sfenner		break;
10156896Sfenner	/*
10256896Sfenner	 * prespecified should really be 3, but some ones might send 2
10356896Sfenner	 * instead, and the IPOPT_TS_PRESPEC constant can apparently
10456896Sfenner	 * have both values, so we have to hard-code it here.
10556896Sfenner	 */
10656896Sfenner
10756896Sfenner	case 2:
10856896Sfenner		printf("PRESPEC2.0");
10956896Sfenner		break;
11056896Sfenner	case 3:			/* IPOPT_TS_PRESPEC */
11156896Sfenner		printf("PRESPEC");
11256896Sfenner		break;
11356896Sfenner	default:
11456896Sfenner		printf("[bad ts type %d]", cp[3]&0xF);
11556896Sfenner		goto done;
11656896Sfenner	}
11756896Sfenner
11856896Sfenner	type = " ";
11956896Sfenner	for (len = 4; len < length; len += hoplen) {
12056896Sfenner		if (ptr == len)
12156896Sfenner			type = " ^ ";
12256896Sfenner		printf("%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]),
12356896Sfenner		       hoplen!=8 ? "" : ipaddr_string(&cp[len]));
12456896Sfenner		type = " ";
12556896Sfenner	}
12656896Sfenner
12756896Sfennerdone:
12856896Sfenner	printf("%s", ptr == len ? " ^ " : "");
12956896Sfenner
13056896Sfenner	if (cp[3]>>4)
13156896Sfenner		printf(" [%d hops not recorded]} ", cp[3]>>4);
13256896Sfenner	else
13356896Sfenner		printf("}");
13456896Sfenner}
13556896Sfenner
13617680Spst/*
13717680Spst * print IP options.
13817680Spst */
13917680Spststatic void
14017680Spstip_optprint(register const u_char *cp, u_int length)
14117680Spst{
14217680Spst	register u_int len;
14317680Spst
14417680Spst	for (; length > 0; cp += len, length -= len) {
14517680Spst		int tt = *cp;
14617680Spst
14775118Sfenner		if (tt == IPOPT_NOP || tt == IPOPT_EOL)
14875118Sfenner			len = 1;
14975118Sfenner		else {
15075118Sfenner			if (&cp[1] >= snapend) {
15175118Sfenner				printf("[|ip]");
15275118Sfenner				return;
15375118Sfenner			}
15475118Sfenner			len = cp[1];
15575118Sfenner		}
15617680Spst		if (len <= 0) {
15717680Spst			printf("[|ip op len %d]", len);
15817680Spst			return;
15917680Spst		}
16017680Spst		if (&cp[1] >= snapend || cp + len > snapend) {
16117680Spst			printf("[|ip]");
16217680Spst			return;
16317680Spst		}
16417680Spst		switch (tt) {
16517680Spst
16617680Spst		case IPOPT_EOL:
16717680Spst			printf(" EOL");
16817680Spst			if (length > 1)
16917680Spst				printf("-%d", length - 1);
17017680Spst			return;
17117680Spst
17217680Spst		case IPOPT_NOP:
17317680Spst			printf(" NOP");
17417680Spst			break;
17517680Spst
17617680Spst		case IPOPT_TS:
17756896Sfenner			ip_printts(cp, len);
17817680Spst			break;
17917680Spst
18056896Sfenner#ifndef IPOPT_SECURITY
18156896Sfenner#define IPOPT_SECURITY 130
18256896Sfenner#endif /* IPOPT_SECURITY */
18317680Spst		case IPOPT_SECURITY:
18417680Spst			printf(" SECURITY{%d}", len);
18517680Spst			break;
18617680Spst
18717680Spst		case IPOPT_RR:
18817680Spst			ip_printroute("RR", cp, len);
18917680Spst			break;
19017680Spst
19117680Spst		case IPOPT_SSRR:
19217680Spst			ip_printroute("SSRR", cp, len);
19317680Spst			break;
19417680Spst
19517680Spst		case IPOPT_LSRR:
19617680Spst			ip_printroute("LSRR", cp, len);
19717680Spst			break;
19817680Spst
19956896Sfenner#ifndef IPOPT_RA
20056896Sfenner#define IPOPT_RA 148		/* router alert */
20156896Sfenner#endif
20217691Spst		case IPOPT_RA:
20356896Sfenner			printf(" RA");
20456896Sfenner			if (len != 4)
20556896Sfenner				printf("{%d}", len);
20656896Sfenner			else if (cp[2] || cp[3])
20756896Sfenner				printf("%d.%d", cp[2], cp[3]);
20898527Sfenner			break;
20917691Spst
21017680Spst		default:
21117680Spst			printf(" IPOPT-%d{%d}", cp[0], len);
21217680Spst			break;
21317680Spst		}
21417680Spst	}
21517680Spst}
21617680Spst
21717680Spst/*
21817680Spst * compute an IP header checksum.
21917680Spst * don't modifiy the packet.
22017680Spst */
22156896Sfenneru_short
22298527Sfennerin_cksum(const u_short *addr, register u_int len, int csum)
22317680Spst{
22456896Sfenner	int nleft = len;
22556896Sfenner	const u_short *w = addr;
22656896Sfenner	u_short answer;
22756896Sfenner	int sum = csum;
22817680Spst
22956896Sfenner 	/*
23056896Sfenner	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
23156896Sfenner	 *  we add sequential 16 bit words to it, and at the end, fold
23256896Sfenner	 *  back all the carry bits from the top 16 bits into the lower
23356896Sfenner	 *  16 bits.
23456896Sfenner 	 */
23556896Sfenner	while (nleft > 1)  {
23656896Sfenner		sum += *w++;
23756896Sfenner		nleft -= 2;
23856896Sfenner	}
23956896Sfenner	if (nleft == 1)
24056896Sfenner		sum += htons(*(u_char *)w<<8);
24156896Sfenner
24217680Spst	/*
24356896Sfenner	 * add back carry outs from top 16 bits to low 16 bits
24417680Spst	 */
24556896Sfenner	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
24656896Sfenner	sum += (sum >> 16);			/* add carry */
24756896Sfenner	answer = ~sum;				/* truncate to 16 bits */
24856896Sfenner	return (answer);
24917680Spst}
25017680Spst
25117680Spst/*
25217680Spst * print an IP datagram.
25317680Spst */
25417680Spstvoid
25517680Spstip_print(register const u_char *bp, register u_int length)
25617680Spst{
25717680Spst	register const struct ip *ip;
25856896Sfenner	register u_int hlen, len, len0, off;
25917680Spst	register const u_char *cp;
26056896Sfenner	u_char nh;
26156896Sfenner	int advance;
26217680Spst
26317680Spst	ip = (const struct ip *)bp;
26417680Spst#ifdef LBL_ALIGN
26517680Spst	/*
26617680Spst	 * If the IP header is not aligned, copy into abuf.
26717680Spst	 * This will never happen with BPF.  It does happen raw packet
26817680Spst	 * dumps from -r.
26917680Spst	 */
27017680Spst	if ((long)ip & 3) {
27117680Spst		static u_char *abuf = NULL;
27217680Spst		static int didwarn = 0;
27317680Spst
27417680Spst		if (abuf == NULL) {
27517680Spst			abuf = (u_char *)malloc(snaplen);
27617680Spst			if (abuf == NULL)
27717680Spst				error("ip_print: malloc");
27817680Spst		}
27917680Spst		memcpy((char *)abuf, (char *)ip, min(length, snaplen));
28017680Spst		snapend += abuf - (u_char *)ip;
28117680Spst		packetp = abuf;
28217680Spst		ip = (struct ip *)abuf;
28317680Spst		/* We really want libpcap to give us aligned packets */
28417680Spst		if (!didwarn) {
28517680Spst			warning("compensating for unaligned libpcap packets");
28617680Spst			++didwarn;
28717680Spst		}
28817680Spst	}
28917680Spst#endif
29017680Spst	if ((u_char *)(ip + 1) > snapend) {
29117680Spst		printf("[|ip]");
29217680Spst		return;
29317680Spst	}
29417680Spst	if (length < sizeof (struct ip)) {
29517680Spst		(void)printf("truncated-ip %d", length);
29617680Spst		return;
29717680Spst	}
29875118Sfenner	hlen = IP_HL(ip) * 4;
29975118Sfenner	if (hlen < sizeof (struct ip)) {
30075118Sfenner		(void)printf("bad-hlen %d", hlen);
30175118Sfenner		return;
30275118Sfenner	}
30317680Spst
30417680Spst	len = ntohs(ip->ip_len);
30517680Spst	if (length < len)
30698527Sfenner		(void)printf("truncated-ip - %d bytes missing! ",
30717680Spst			len - length);
30817680Spst	len -= hlen;
30956896Sfenner	len0 = len;
31017680Spst
31117680Spst	/*
31217680Spst	 * If this is fragment zero, hand it to the next higher
31317680Spst	 * level protocol.
31417680Spst	 */
31517680Spst	off = ntohs(ip->ip_off);
31617680Spst	if ((off & 0x1fff) == 0) {
31717680Spst		cp = (const u_char *)ip + hlen;
31856896Sfenner		nh = ip->ip_p;
31917680Spst
32098527Sfenner#ifndef IPPROTO_SCTP
32198527Sfenner#define IPPROTO_SCTP 132
32298527Sfenner#endif
32398527Sfenner		if (nh != IPPROTO_TCP && nh != IPPROTO_UDP &&
32498527Sfenner		    nh != IPPROTO_SCTP) {
32556896Sfenner			(void)printf("%s > %s: ", ipaddr_string(&ip->ip_src),
32656896Sfenner				ipaddr_string(&ip->ip_dst));
32756896Sfenner		}
32856896Sfenneragain:
32956896Sfenner		switch (nh) {
33056896Sfenner
33156896Sfenner#ifndef IPPROTO_AH
33256896Sfenner#define IPPROTO_AH	51
33356896Sfenner#endif
33456896Sfenner		case IPPROTO_AH:
33556896Sfenner			nh = *cp;
33656896Sfenner			advance = ah_print(cp, (const u_char *)ip);
33756896Sfenner			cp += advance;
33856896Sfenner			len -= advance;
33956896Sfenner			goto again;
34056896Sfenner
34156896Sfenner#ifndef IPPROTO_ESP
34256896Sfenner#define IPPROTO_ESP	50
34356896Sfenner#endif
34456896Sfenner		case IPPROTO_ESP:
34556896Sfenner		    {
34698527Sfenner			int enh, padlen;
34798527Sfenner			advance = esp_print(cp, (const u_char *)ip, &enh, &padlen);
34856896Sfenner			cp += advance;
34998527Sfenner			len -= advance + padlen;
35056896Sfenner			if (enh < 0)
35156896Sfenner				break;
35256896Sfenner			nh = enh & 0xff;
35356896Sfenner			goto again;
35456896Sfenner		    }
35556896Sfenner
35656896Sfenner#ifndef IPPROTO_IPCOMP
35756896Sfenner#define IPPROTO_IPCOMP	108
35856896Sfenner#endif
35956896Sfenner		case IPPROTO_IPCOMP:
36056896Sfenner		    {
36156896Sfenner			int enh;
36256896Sfenner			advance = ipcomp_print(cp, (const u_char *)ip, &enh);
36356896Sfenner			cp += advance;
36456896Sfenner			len -= advance;
36556896Sfenner			if (enh < 0)
36656896Sfenner				break;
36756896Sfenner			nh = enh & 0xff;
36856896Sfenner			goto again;
36956896Sfenner		    }
37056896Sfenner
37198527Sfenner		case IPPROTO_SCTP:
37298527Sfenner  			sctp_print(cp, (const u_char *)ip, len);
37398527Sfenner			break;
37498527Sfenner
37517680Spst		case IPPROTO_TCP:
37675118Sfenner			tcp_print(cp, len, (const u_char *)ip, (off &~ 0x6000));
37717680Spst			break;
37817680Spst
37917680Spst		case IPPROTO_UDP:
38075118Sfenner			udp_print(cp, len, (const u_char *)ip, (off &~ 0x6000));
38117680Spst			break;
38217680Spst
38317680Spst		case IPPROTO_ICMP:
38456896Sfenner			icmp_print(cp, len, (const u_char *)ip);
38517680Spst			break;
38617680Spst
38717680Spst#ifndef IPPROTO_IGRP
38817680Spst#define IPPROTO_IGRP 9
38917680Spst#endif
39017680Spst		case IPPROTO_IGRP:
39117680Spst			igrp_print(cp, len, (const u_char *)ip);
39217680Spst			break;
39317680Spst
39417680Spst		case IPPROTO_ND:
39517680Spst			(void)printf(" nd %d", len);
39617680Spst			break;
39717680Spst
39817680Spst		case IPPROTO_EGP:
39917680Spst			egp_print(cp, len, (const u_char *)ip);
40017680Spst			break;
40117680Spst
40217680Spst#ifndef IPPROTO_OSPF
40317680Spst#define IPPROTO_OSPF 89
40417680Spst#endif
40517680Spst		case IPPROTO_OSPF:
40617680Spst			ospf_print(cp, len, (const u_char *)ip);
40717680Spst			break;
40817680Spst
40917680Spst#ifndef IPPROTO_IGMP
41017680Spst#define IPPROTO_IGMP 2
41117680Spst#endif
41217680Spst		case IPPROTO_IGMP:
41398527Sfenner			igmp_print(cp, len);
41417680Spst			break;
41517680Spst
41639300Sfenner		case 4:
41739300Sfenner			/* DVMRP multicast tunnel (ip-in-ip encapsulation) */
41817680Spst			ip_print(cp, len);
41917680Spst			if (! vflag) {
42098527Sfenner				printf(" (ipip-proto-4)");
42117680Spst				return;
42217680Spst			}
42317680Spst			break;
42417680Spst
42556896Sfenner#ifdef INET6
42656896Sfenner#ifndef IP6PROTO_ENCAP
42756896Sfenner#define IP6PROTO_ENCAP 41
42856896Sfenner#endif
42956896Sfenner		case IP6PROTO_ENCAP:
43056896Sfenner			/* ip6-in-ip encapsulation */
43156896Sfenner			ip6_print(cp, len);
43256896Sfenner			break;
43356896Sfenner#endif /*INET6*/
43456896Sfenner
43556896Sfenner
43626183Sfenner#ifndef IPPROTO_GRE
43726183Sfenner#define IPPROTO_GRE 47
43826183Sfenner#endif
43926183Sfenner		case IPPROTO_GRE:
44026183Sfenner			/* do it */
44126183Sfenner			gre_print(cp, len);
44298527Sfenner			break;
44326183Sfenner
44456896Sfenner#ifndef IPPROTO_MOBILE
44556896Sfenner#define IPPROTO_MOBILE 55
44656896Sfenner#endif
44756896Sfenner		case IPPROTO_MOBILE:
44856896Sfenner			mobile_print(cp, len);
44956896Sfenner			break;
45056896Sfenner
45156896Sfenner#ifndef IPPROTO_PIM
45256896Sfenner#define IPPROTO_PIM	103
45356896Sfenner#endif
45456896Sfenner		case IPPROTO_PIM:
45556896Sfenner			pim_print(cp, len);
45656896Sfenner			break;
45756896Sfenner
45875118Sfenner#ifndef IPPROTO_VRRP
45975118Sfenner#define IPPROTO_VRRP	112
46075118Sfenner#endif
46175118Sfenner		case IPPROTO_VRRP:
46275118Sfenner			vrrp_print(cp, len, ip->ip_ttl);
46375118Sfenner			break;
46475118Sfenner
46517680Spst		default:
46656896Sfenner			(void)printf(" ip-proto-%d %d", nh, len);
46717680Spst			break;
46817680Spst		}
46917680Spst	}
47056896Sfenner
47156896Sfenner 	/* Ultra quiet now means that all this stuff should be suppressed */
47256896Sfenner 	/* res 3-Nov-98 */
47356896Sfenner 	if (qflag > 1) return;
47456896Sfenner
47556896Sfenner
47617680Spst	/*
47717680Spst	 * for fragmented datagrams, print id:size@offset.  On all
47817680Spst	 * but the last stick a "+".  For unfragmented datagrams, note
47917680Spst	 * the don't fragment flag.
48017680Spst	 */
48156896Sfenner	len = len0;	/* get the original length */
48217680Spst	if (off & 0x3fff) {
48317680Spst		/*
48417680Spst		 * if this isn't the first frag, we're missing the
48517680Spst		 * next level protocol header.  print the ip addr.
48617680Spst		 */
48717680Spst		if (off & 0x1fff)
48817680Spst			(void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
48917680Spst				      ipaddr_string(&ip->ip_dst));
49056896Sfenner#ifndef IP_MF
49156896Sfenner#define IP_MF 0x2000
49256896Sfenner#endif /* IP_MF */
49356896Sfenner#ifndef IP_DF
49456896Sfenner#define IP_DF 0x4000
49556896Sfenner#endif /* IP_DF */
49656896Sfenner		(void)printf(" (frag %d:%u@%d%s)", ntohs(ip->ip_id), len,
49717680Spst			(off & 0x1fff) * 8,
49817680Spst			(off & IP_MF)? "+" : "");
49956896Sfenner
50017680Spst	} else if (off & IP_DF)
50117680Spst		(void)printf(" (DF)");
50217680Spst
50356896Sfenner	if (ip->ip_tos) {
50456896Sfenner		(void)printf(" [tos 0x%x", (int)ip->ip_tos);
50556896Sfenner		/* ECN bits */
50698527Sfenner		if (ip->ip_tos & 0x03) {
50798527Sfenner			switch (ip->ip_tos & 0x03) {
50898527Sfenner			case 1:
50998527Sfenner				(void)printf(",ECT(1)");
51098527Sfenner				break;
51198527Sfenner			case 2:
51298527Sfenner				(void)printf(",ECT(0)");
51398527Sfenner				break;
51498527Sfenner			case 3:
51556896Sfenner				(void)printf(",CE");
51698527Sfenner			}
51756896Sfenner		}
51856896Sfenner		(void)printf("] ");
51956896Sfenner	}
52056896Sfenner
52117680Spst	if (ip->ip_ttl <= 1)
52217680Spst		(void)printf(" [ttl %d]", (int)ip->ip_ttl);
52317680Spst
52417680Spst	if (vflag) {
52517680Spst		int sum;
52617680Spst		char *sep = "";
52717680Spst
52817680Spst		printf(" (");
52917680Spst		if (ip->ip_ttl > 1) {
53017680Spst			(void)printf("%sttl %d", sep, (int)ip->ip_ttl);
53117680Spst			sep = ", ";
53217680Spst		}
53317680Spst		if ((off & 0x3fff) == 0) {
53417680Spst			(void)printf("%sid %d", sep, (int)ntohs(ip->ip_id));
53517680Spst			sep = ", ";
53617680Spst		}
53775118Sfenner		(void)printf("%slen %d", sep, (int)ntohs(ip->ip_len));
53875118Sfenner		sep = ", ";
53917680Spst		if ((u_char *)ip + hlen <= snapend) {
54056896Sfenner			sum = in_cksum((const u_short *)ip, hlen, 0);
54117680Spst			if (sum != 0) {
54217680Spst				(void)printf("%sbad cksum %x!", sep,
54317680Spst					     ntohs(ip->ip_sum));
54417680Spst				sep = ", ";
54517680Spst			}
54617680Spst		}
54717680Spst		if ((hlen -= sizeof(struct ip)) > 0) {
54817680Spst			(void)printf("%soptlen=%d", sep, hlen);
54917680Spst			ip_optprint((u_char *)(ip + 1), hlen);
55017680Spst		}
55117680Spst		printf(")");
55217680Spst	}
55317680Spst}
55475118Sfenner
55575118Sfennervoid
55675118SfenneripN_print(register const u_char *bp, register u_int length)
55775118Sfenner{
55875118Sfenner	struct ip *ip, hdr;
55975118Sfenner
56075118Sfenner	ip = (struct ip *)bp;
56175118Sfenner	if (length < 4) {
56275118Sfenner		(void)printf("truncated-ip %d", length);
56375118Sfenner		return;
56475118Sfenner	}
56575118Sfenner	memcpy (&hdr, (char *)ip, 4);
56675118Sfenner	switch (IP_V(&hdr)) {
56775118Sfenner	case 4:
56898527Sfenner		ip_print (bp, length);
56998527Sfenner		return;
57075118Sfenner#ifdef INET6
57175118Sfenner	case 6:
57298527Sfenner		ip6_print (bp, length);
57398527Sfenner		return;
57475118Sfenner#endif
57575118Sfenner	default:
57698527Sfenner		(void)printf("unknown ip %d", IP_V(&hdr));
57798527Sfenner		return;
57875118Sfenner	}
57975118Sfenner}
580