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