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