print-ip.c revision 111729
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 111729 2003-03-02 08:25:48Z fenner $
2217680Spst */
2317680Spst
2417680Spst#ifndef lint
2526183Sfennerstatic const char rcsid[] =
26111729Sfenner    "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.100.4.1 2002/01/25 05:39:54 guy 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
39111729Sfenner#include <netdb.h>
4017680Spst#include <stdio.h>
4117680Spst#include <stdlib.h>
4217680Spst#include <string.h>
4317680Spst#include <unistd.h>
4417680Spst
4517680Spst#include "addrtoname.h"
4617680Spst#include "interface.h"
4717680Spst#include "extract.h"			/* must come after interface.h */
4817680Spst
4975118Sfenner#include "ip.h"
5075118Sfenner
5117680Spst/* Compatibility */
5217680Spst#ifndef	IPPROTO_ND
5317680Spst#define	IPPROTO_ND	77
5417680Spst#endif
5517680Spst
5617680Spst/*
5717680Spst * print the recorded route in an IP RR, LSRR or SSRR option.
5817680Spst */
5917680Spststatic void
6017680Spstip_printroute(const char *type, register const u_char *cp, u_int length)
6117680Spst{
6217680Spst	register u_int ptr = cp[2] - 1;
6317680Spst	register u_int len;
6417680Spst
6517680Spst	printf(" %s{", type);
6617680Spst	if ((length + 1) & 3)
6717680Spst		printf(" [bad length %d]", length);
6817680Spst	if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
6917680Spst		printf(" [bad ptr %d]", cp[2]);
7017680Spst
7117680Spst	type = "";
7217680Spst	for (len = 3; len < length; len += 4) {
7317680Spst		if (ptr == len)
7417680Spst			type = "#";
7517680Spst		printf("%s%s", type, ipaddr_string(&cp[len]));
7617680Spst		type = " ";
7717680Spst	}
7817680Spst	printf("%s}", ptr == len? "#" : "");
7917680Spst}
8017680Spst
8156896Sfennerstatic void
8256896Sfennerip_printts(register const u_char *cp, u_int length)
8356896Sfenner{
8456896Sfenner	register u_int ptr = cp[2] - 1;
8556896Sfenner	register u_int len = 0;
8656896Sfenner	int hoplen;
8756896Sfenner	char *type;
8856896Sfenner
8956896Sfenner	printf(" TS{");
9056896Sfenner	hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
9156896Sfenner	if ((length - 4) & (hoplen-1))
9256896Sfenner		printf("[bad length %d]", length);
9356896Sfenner	if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
9456896Sfenner		printf("[bad ptr %d]", cp[2]);
9556896Sfenner	switch (cp[3]&0xF) {
9656896Sfenner	case IPOPT_TS_TSONLY:
9756896Sfenner		printf("TSONLY");
9856896Sfenner		break;
9956896Sfenner	case IPOPT_TS_TSANDADDR:
10056896Sfenner		printf("TS+ADDR");
10156896Sfenner		break;
10256896Sfenner	/*
10356896Sfenner	 * prespecified should really be 3, but some ones might send 2
10456896Sfenner	 * instead, and the IPOPT_TS_PRESPEC constant can apparently
10556896Sfenner	 * have both values, so we have to hard-code it here.
10656896Sfenner	 */
10756896Sfenner
10856896Sfenner	case 2:
10956896Sfenner		printf("PRESPEC2.0");
11056896Sfenner		break;
11156896Sfenner	case 3:			/* IPOPT_TS_PRESPEC */
11256896Sfenner		printf("PRESPEC");
11356896Sfenner		break;
11456896Sfenner	default:
11556896Sfenner		printf("[bad ts type %d]", cp[3]&0xF);
11656896Sfenner		goto done;
11756896Sfenner	}
11856896Sfenner
11956896Sfenner	type = " ";
12056896Sfenner	for (len = 4; len < length; len += hoplen) {
12156896Sfenner		if (ptr == len)
12256896Sfenner			type = " ^ ";
12356896Sfenner		printf("%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]),
12456896Sfenner		       hoplen!=8 ? "" : ipaddr_string(&cp[len]));
12556896Sfenner		type = " ";
12656896Sfenner	}
12756896Sfenner
12856896Sfennerdone:
12956896Sfenner	printf("%s", ptr == len ? " ^ " : "");
13056896Sfenner
13156896Sfenner	if (cp[3]>>4)
13256896Sfenner		printf(" [%d hops not recorded]} ", cp[3]>>4);
13356896Sfenner	else
13456896Sfenner		printf("}");
13556896Sfenner}
13656896Sfenner
13717680Spst/*
13817680Spst * print IP options.
13917680Spst */
14017680Spststatic void
14117680Spstip_optprint(register const u_char *cp, u_int length)
14217680Spst{
14317680Spst	register u_int len;
14417680Spst
14517680Spst	for (; length > 0; cp += len, length -= len) {
14617680Spst		int tt = *cp;
14717680Spst
14875118Sfenner		if (tt == IPOPT_NOP || tt == IPOPT_EOL)
14975118Sfenner			len = 1;
15075118Sfenner		else {
15175118Sfenner			if (&cp[1] >= snapend) {
15275118Sfenner				printf("[|ip]");
15375118Sfenner				return;
15475118Sfenner			}
15575118Sfenner			len = cp[1];
15675118Sfenner		}
15717680Spst		if (len <= 0) {
15817680Spst			printf("[|ip op len %d]", len);
15917680Spst			return;
16017680Spst		}
16117680Spst		if (&cp[1] >= snapend || cp + len > snapend) {
16217680Spst			printf("[|ip]");
16317680Spst			return;
16417680Spst		}
16517680Spst		switch (tt) {
16617680Spst
16717680Spst		case IPOPT_EOL:
16817680Spst			printf(" EOL");
16917680Spst			if (length > 1)
17017680Spst				printf("-%d", length - 1);
17117680Spst			return;
17217680Spst
17317680Spst		case IPOPT_NOP:
17417680Spst			printf(" NOP");
17517680Spst			break;
17617680Spst
17717680Spst		case IPOPT_TS:
17856896Sfenner			ip_printts(cp, len);
17917680Spst			break;
18017680Spst
18156896Sfenner#ifndef IPOPT_SECURITY
18256896Sfenner#define IPOPT_SECURITY 130
18356896Sfenner#endif /* IPOPT_SECURITY */
18417680Spst		case IPOPT_SECURITY:
18517680Spst			printf(" SECURITY{%d}", len);
18617680Spst			break;
18717680Spst
18817680Spst		case IPOPT_RR:
18917680Spst			ip_printroute("RR", cp, len);
19017680Spst			break;
19117680Spst
19217680Spst		case IPOPT_SSRR:
19317680Spst			ip_printroute("SSRR", cp, len);
19417680Spst			break;
19517680Spst
19617680Spst		case IPOPT_LSRR:
19717680Spst			ip_printroute("LSRR", cp, len);
19817680Spst			break;
19917680Spst
20056896Sfenner#ifndef IPOPT_RA
20156896Sfenner#define IPOPT_RA 148		/* router alert */
20256896Sfenner#endif
20317691Spst		case IPOPT_RA:
20456896Sfenner			printf(" RA");
20556896Sfenner			if (len != 4)
20656896Sfenner				printf("{%d}", len);
20756896Sfenner			else if (cp[2] || cp[3])
20856896Sfenner				printf("%d.%d", cp[2], cp[3]);
20998527Sfenner			break;
21017691Spst
21117680Spst		default:
21217680Spst			printf(" IPOPT-%d{%d}", cp[0], len);
21317680Spst			break;
21417680Spst		}
21517680Spst	}
21617680Spst}
21717680Spst
21817680Spst/*
21917680Spst * compute an IP header checksum.
22017680Spst * don't modifiy the packet.
22117680Spst */
22256896Sfenneru_short
22398527Sfennerin_cksum(const u_short *addr, register u_int len, int csum)
22417680Spst{
22556896Sfenner	int nleft = len;
22656896Sfenner	const u_short *w = addr;
22756896Sfenner	u_short answer;
22856896Sfenner	int sum = csum;
22917680Spst
23056896Sfenner 	/*
23156896Sfenner	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
23256896Sfenner	 *  we add sequential 16 bit words to it, and at the end, fold
23356896Sfenner	 *  back all the carry bits from the top 16 bits into the lower
23456896Sfenner	 *  16 bits.
23556896Sfenner 	 */
23656896Sfenner	while (nleft > 1)  {
23756896Sfenner		sum += *w++;
23856896Sfenner		nleft -= 2;
23956896Sfenner	}
24056896Sfenner	if (nleft == 1)
24156896Sfenner		sum += htons(*(u_char *)w<<8);
24256896Sfenner
24317680Spst	/*
24456896Sfenner	 * add back carry outs from top 16 bits to low 16 bits
24517680Spst	 */
24656896Sfenner	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
24756896Sfenner	sum += (sum >> 16);			/* add carry */
24856896Sfenner	answer = ~sum;				/* truncate to 16 bits */
24956896Sfenner	return (answer);
25017680Spst}
25117680Spst
25217680Spst/*
25317680Spst * print an IP datagram.
25417680Spst */
25517680Spstvoid
25617680Spstip_print(register const u_char *bp, register u_int length)
25717680Spst{
25817680Spst	register const struct ip *ip;
25956896Sfenner	register u_int hlen, len, len0, off;
26017680Spst	register const u_char *cp;
26156896Sfenner	u_char nh;
26256896Sfenner	int advance;
263111729Sfenner	struct protoent *proto;
26417680Spst
26517680Spst	ip = (const struct ip *)bp;
26617680Spst#ifdef LBL_ALIGN
26717680Spst	/*
26817680Spst	 * If the IP header is not aligned, copy into abuf.
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:
466111729Sfenner			if ((proto = getprotobynumber(nh)) != NULL)
467111729Sfenner				(void)printf(" %s", proto->p_name);
468111729Sfenner			else
469111729Sfenner				(void)printf(" ip-proto-%d", nh);
470111729Sfenner			printf(" %d", len);
47117680Spst			break;
47217680Spst		}
47317680Spst	}
47456896Sfenner
47556896Sfenner 	/* Ultra quiet now means that all this stuff should be suppressed */
47656896Sfenner 	/* res 3-Nov-98 */
47756896Sfenner 	if (qflag > 1) return;
47856896Sfenner
47956896Sfenner
48017680Spst	/*
48117680Spst	 * for fragmented datagrams, print id:size@offset.  On all
48217680Spst	 * but the last stick a "+".  For unfragmented datagrams, note
48317680Spst	 * the don't fragment flag.
48417680Spst	 */
48556896Sfenner	len = len0;	/* get the original length */
48617680Spst	if (off & 0x3fff) {
48717680Spst		/*
48817680Spst		 * if this isn't the first frag, we're missing the
489111729Sfenner		 * next level protocol header.  print the ip addr
490111729Sfenner		 * and the protocol.
49117680Spst		 */
492111729Sfenner		if (off & 0x1fff) {
49317680Spst			(void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
49417680Spst				      ipaddr_string(&ip->ip_dst));
495111729Sfenner			if ((proto = getprotobynumber(ip->ip_p)) != NULL)
496111729Sfenner				(void)printf(" %s", proto->p_name);
497111729Sfenner			else
498111729Sfenner				(void)printf(" ip-proto-%d", ip->ip_p);
499111729Sfenner		}
50056896Sfenner#ifndef IP_MF
50156896Sfenner#define IP_MF 0x2000
50256896Sfenner#endif /* IP_MF */
50356896Sfenner#ifndef IP_DF
50456896Sfenner#define IP_DF 0x4000
50556896Sfenner#endif /* IP_DF */
50656896Sfenner		(void)printf(" (frag %d:%u@%d%s)", ntohs(ip->ip_id), len,
50717680Spst			(off & 0x1fff) * 8,
50817680Spst			(off & IP_MF)? "+" : "");
50956896Sfenner
51017680Spst	} else if (off & IP_DF)
51117680Spst		(void)printf(" (DF)");
51217680Spst
51356896Sfenner	if (ip->ip_tos) {
51456896Sfenner		(void)printf(" [tos 0x%x", (int)ip->ip_tos);
51556896Sfenner		/* ECN bits */
51698527Sfenner		if (ip->ip_tos & 0x03) {
51798527Sfenner			switch (ip->ip_tos & 0x03) {
51898527Sfenner			case 1:
51998527Sfenner				(void)printf(",ECT(1)");
52098527Sfenner				break;
52198527Sfenner			case 2:
52298527Sfenner				(void)printf(",ECT(0)");
52398527Sfenner				break;
52498527Sfenner			case 3:
52556896Sfenner				(void)printf(",CE");
52698527Sfenner			}
52756896Sfenner		}
52856896Sfenner		(void)printf("] ");
52956896Sfenner	}
53056896Sfenner
53117680Spst	if (ip->ip_ttl <= 1)
53217680Spst		(void)printf(" [ttl %d]", (int)ip->ip_ttl);
53317680Spst
53417680Spst	if (vflag) {
53517680Spst		int sum;
53617680Spst		char *sep = "";
53717680Spst
53817680Spst		printf(" (");
53917680Spst		if (ip->ip_ttl > 1) {
54017680Spst			(void)printf("%sttl %d", sep, (int)ip->ip_ttl);
54117680Spst			sep = ", ";
54217680Spst		}
54317680Spst		if ((off & 0x3fff) == 0) {
54417680Spst			(void)printf("%sid %d", sep, (int)ntohs(ip->ip_id));
54517680Spst			sep = ", ";
54617680Spst		}
54775118Sfenner		(void)printf("%slen %d", sep, (int)ntohs(ip->ip_len));
54875118Sfenner		sep = ", ";
54917680Spst		if ((u_char *)ip + hlen <= snapend) {
55056896Sfenner			sum = in_cksum((const u_short *)ip, hlen, 0);
55117680Spst			if (sum != 0) {
55217680Spst				(void)printf("%sbad cksum %x!", sep,
55317680Spst					     ntohs(ip->ip_sum));
55417680Spst				sep = ", ";
55517680Spst			}
55617680Spst		}
55717680Spst		if ((hlen -= sizeof(struct ip)) > 0) {
55817680Spst			(void)printf("%soptlen=%d", sep, hlen);
55917680Spst			ip_optprint((u_char *)(ip + 1), hlen);
56017680Spst		}
56117680Spst		printf(")");
56217680Spst	}
56317680Spst}
56475118Sfenner
56575118Sfennervoid
56675118SfenneripN_print(register const u_char *bp, register u_int length)
56775118Sfenner{
56875118Sfenner	struct ip *ip, hdr;
56975118Sfenner
57075118Sfenner	ip = (struct ip *)bp;
57175118Sfenner	if (length < 4) {
57275118Sfenner		(void)printf("truncated-ip %d", length);
57375118Sfenner		return;
57475118Sfenner	}
57575118Sfenner	memcpy (&hdr, (char *)ip, 4);
57675118Sfenner	switch (IP_V(&hdr)) {
57775118Sfenner	case 4:
57898527Sfenner		ip_print (bp, length);
57998527Sfenner		return;
58075118Sfenner#ifdef INET6
58175118Sfenner	case 6:
58298527Sfenner		ip6_print (bp, length);
58398527Sfenner		return;
58475118Sfenner#endif
58575118Sfenner	default:
58698527Sfenner		(void)printf("unknown ip %d", IP_V(&hdr));
58798527Sfenner		return;
58875118Sfenner	}
58975118Sfenner}
590