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