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