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