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