141c99275SPeter Avalos /*
241c99275SPeter Avalos * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
341c99275SPeter Avalos * The Regents of the University of California. All rights reserved.
441c99275SPeter Avalos *
541c99275SPeter Avalos * Redistribution and use in source and binary forms, with or without
641c99275SPeter Avalos * modification, are permitted provided that: (1) source code distributions
741c99275SPeter Avalos * retain the above copyright notice and this paragraph in its entirety, (2)
841c99275SPeter Avalos * distributions including binary code include the above copyright notice and
941c99275SPeter Avalos * this paragraph in its entirety in the documentation or other materials
1041c99275SPeter Avalos * provided with the distribution, and (3) all advertising materials mentioning
1141c99275SPeter Avalos * features or use of this software display the following acknowledgement:
1241c99275SPeter Avalos * ``This product includes software developed by the University of California,
1341c99275SPeter Avalos * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1441c99275SPeter Avalos * the University nor the names of its contributors may be used to endorse
1541c99275SPeter Avalos * or promote products derived from this software without specific prior
1641c99275SPeter Avalos * written permission.
1741c99275SPeter Avalos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1841c99275SPeter Avalos * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1941c99275SPeter Avalos * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2041c99275SPeter Avalos */
2141c99275SPeter Avalos
22411677aeSAaron LI /* \summary: IP printer */
2341c99275SPeter Avalos
2441c99275SPeter Avalos #ifdef HAVE_CONFIG_H
25*ed775ee7SAntonio Huete Jimenez #include <config.h>
2641c99275SPeter Avalos #endif
2741c99275SPeter Avalos
28*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
2941c99275SPeter Avalos
30411677aeSAaron LI #include "netdissect.h"
3141c99275SPeter Avalos #include "addrtoname.h"
32411677aeSAaron LI #include "extract.h"
3341c99275SPeter Avalos
3441c99275SPeter Avalos #include "ip.h"
3541c99275SPeter Avalos #include "ipproto.h"
3641c99275SPeter Avalos
37411677aeSAaron LI
38411677aeSAaron LI static const struct tok ip_option_values[] = {
3941c99275SPeter Avalos { IPOPT_EOL, "EOL" },
4041c99275SPeter Avalos { IPOPT_NOP, "NOP" },
4141c99275SPeter Avalos { IPOPT_TS, "timestamp" },
4241c99275SPeter Avalos { IPOPT_SECURITY, "security" },
4341c99275SPeter Avalos { IPOPT_RR, "RR" },
4441c99275SPeter Avalos { IPOPT_SSRR, "SSRR" },
4541c99275SPeter Avalos { IPOPT_LSRR, "LSRR" },
4641c99275SPeter Avalos { IPOPT_RA, "RA" },
4741c99275SPeter Avalos { IPOPT_RFC1393, "traceroute" },
4841c99275SPeter Avalos { 0, NULL }
4941c99275SPeter Avalos };
5041c99275SPeter Avalos
5141c99275SPeter Avalos /*
5241c99275SPeter Avalos * print the recorded route in an IP RR, LSRR or SSRR option.
5341c99275SPeter Avalos */
54411677aeSAaron LI static int
ip_printroute(netdissect_options * ndo,const u_char * cp,u_int length)55411677aeSAaron LI ip_printroute(netdissect_options *ndo,
56*ed775ee7SAntonio Huete Jimenez const u_char *cp, u_int length)
5741c99275SPeter Avalos {
58*ed775ee7SAntonio Huete Jimenez u_int ptr;
59*ed775ee7SAntonio Huete Jimenez u_int len;
6041c99275SPeter Avalos
6141c99275SPeter Avalos if (length < 3) {
62*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [bad length %u]", length);
63411677aeSAaron LI return (0);
6441c99275SPeter Avalos }
6541c99275SPeter Avalos if ((length + 1) & 3)
66*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [bad length %u]", length);
67*ed775ee7SAntonio Huete Jimenez ptr = GET_U_1(cp + 2) - 1;
6841c99275SPeter Avalos if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
69*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [bad ptr %u]", GET_U_1(cp + 2));
7041c99275SPeter Avalos
7141c99275SPeter Avalos for (len = 3; len < length; len += 4) {
72*ed775ee7SAntonio Huete Jimenez ND_TCHECK_4(cp + len); /* Needed to print the IP addresses */
73*ed775ee7SAntonio Huete Jimenez ND_PRINT(" %s", GET_IPADDR_STRING(cp + len));
7441c99275SPeter Avalos if (ptr > len)
75*ed775ee7SAntonio Huete Jimenez ND_PRINT(",");
7641c99275SPeter Avalos }
77411677aeSAaron LI return (0);
78411677aeSAaron LI
79411677aeSAaron LI trunc:
80411677aeSAaron LI return (-1);
8141c99275SPeter Avalos }
8241c99275SPeter Avalos
8341c99275SPeter Avalos /*
8441c99275SPeter Avalos * If source-routing is present and valid, return the final destination.
8541c99275SPeter Avalos * Otherwise, return IP destination.
8641c99275SPeter Avalos *
8741c99275SPeter Avalos * This is used for UDP and TCP pseudo-header in the checksum
8841c99275SPeter Avalos * calculation.
8941c99275SPeter Avalos */
90411677aeSAaron LI static uint32_t
ip_finddst(netdissect_options * ndo,const struct ip * ip)91411677aeSAaron LI ip_finddst(netdissect_options *ndo,
92411677aeSAaron LI const struct ip *ip)
9341c99275SPeter Avalos {
94*ed775ee7SAntonio Huete Jimenez u_int length;
95*ed775ee7SAntonio Huete Jimenez u_int len;
9641c99275SPeter Avalos const u_char *cp;
9741c99275SPeter Avalos
9841c99275SPeter Avalos cp = (const u_char *)(ip + 1);
99*ed775ee7SAntonio Huete Jimenez length = IP_HL(ip) * 4;
100*ed775ee7SAntonio Huete Jimenez if (length < sizeof(struct ip))
101*ed775ee7SAntonio Huete Jimenez goto trunc;
102*ed775ee7SAntonio Huete Jimenez length -= sizeof(struct ip);
10341c99275SPeter Avalos
104*ed775ee7SAntonio Huete Jimenez for (; length != 0; cp += len, length -= len) {
10541c99275SPeter Avalos int tt;
10641c99275SPeter Avalos
107*ed775ee7SAntonio Huete Jimenez tt = GET_U_1(cp);
10841c99275SPeter Avalos if (tt == IPOPT_EOL)
10941c99275SPeter Avalos break;
11041c99275SPeter Avalos else if (tt == IPOPT_NOP)
11141c99275SPeter Avalos len = 1;
11241c99275SPeter Avalos else {
113*ed775ee7SAntonio Huete Jimenez len = GET_U_1(cp + 1);
11441c99275SPeter Avalos if (len < 2)
11541c99275SPeter Avalos break;
11641c99275SPeter Avalos }
117*ed775ee7SAntonio Huete Jimenez if (length < len)
118*ed775ee7SAntonio Huete Jimenez goto trunc;
119*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(cp, len);
12041c99275SPeter Avalos switch (tt) {
12141c99275SPeter Avalos
12241c99275SPeter Avalos case IPOPT_SSRR:
12341c99275SPeter Avalos case IPOPT_LSRR:
12441c99275SPeter Avalos if (len < 7)
12541c99275SPeter Avalos break;
126*ed775ee7SAntonio Huete Jimenez return (GET_IPV4_TO_NETWORK_ORDER(cp + len - 4));
12741c99275SPeter Avalos }
12841c99275SPeter Avalos }
12941c99275SPeter Avalos trunc:
130*ed775ee7SAntonio Huete Jimenez return (GET_IPV4_TO_NETWORK_ORDER(ip->ip_dst));
13141c99275SPeter Avalos }
13241c99275SPeter Avalos
13327bfbee1SPeter Avalos /*
13427bfbee1SPeter Avalos * Compute a V4-style checksum by building a pseudoheader.
13527bfbee1SPeter Avalos */
136*ed775ee7SAntonio Huete Jimenez uint16_t
nextproto4_cksum(netdissect_options * ndo,const struct ip * ip,const uint8_t * data,u_int len,u_int covlen,uint8_t next_proto)137411677aeSAaron LI nextproto4_cksum(netdissect_options *ndo,
138411677aeSAaron LI const struct ip *ip, const uint8_t *data,
139*ed775ee7SAntonio Huete Jimenez u_int len, u_int covlen, uint8_t next_proto)
14027bfbee1SPeter Avalos {
14127bfbee1SPeter Avalos struct phdr {
142411677aeSAaron LI uint32_t src;
143411677aeSAaron LI uint32_t dst;
144*ed775ee7SAntonio Huete Jimenez uint8_t mbz;
145*ed775ee7SAntonio Huete Jimenez uint8_t proto;
146411677aeSAaron LI uint16_t len;
14727bfbee1SPeter Avalos } ph;
14827bfbee1SPeter Avalos struct cksum_vec vec[2];
14927bfbee1SPeter Avalos
15027bfbee1SPeter Avalos /* pseudo-header.. */
151411677aeSAaron LI ph.len = htons((uint16_t)len);
15227bfbee1SPeter Avalos ph.mbz = 0;
15327bfbee1SPeter Avalos ph.proto = next_proto;
154*ed775ee7SAntonio Huete Jimenez ph.src = GET_IPV4_TO_NETWORK_ORDER(ip->ip_src);
15527bfbee1SPeter Avalos if (IP_HL(ip) == 5)
156*ed775ee7SAntonio Huete Jimenez ph.dst = GET_IPV4_TO_NETWORK_ORDER(ip->ip_dst);
15727bfbee1SPeter Avalos else
158411677aeSAaron LI ph.dst = ip_finddst(ndo, ip);
15927bfbee1SPeter Avalos
160411677aeSAaron LI vec[0].ptr = (const uint8_t *)(void *)&ph;
16127bfbee1SPeter Avalos vec[0].len = sizeof(ph);
16227bfbee1SPeter Avalos vec[1].ptr = data;
163411677aeSAaron LI vec[1].len = covlen;
16427bfbee1SPeter Avalos return (in_cksum(vec, 2));
16527bfbee1SPeter Avalos }
16627bfbee1SPeter Avalos
167411677aeSAaron LI static int
ip_printts(netdissect_options * ndo,const u_char * cp,u_int length)168411677aeSAaron LI ip_printts(netdissect_options *ndo,
169*ed775ee7SAntonio Huete Jimenez const u_char *cp, u_int length)
17041c99275SPeter Avalos {
171*ed775ee7SAntonio Huete Jimenez u_int ptr;
172*ed775ee7SAntonio Huete Jimenez u_int len;
173*ed775ee7SAntonio Huete Jimenez u_int hoplen;
17441c99275SPeter Avalos const char *type;
17541c99275SPeter Avalos
17641c99275SPeter Avalos if (length < 4) {
177*ed775ee7SAntonio Huete Jimenez ND_PRINT("[bad length %u]", length);
178411677aeSAaron LI return (0);
17941c99275SPeter Avalos }
180*ed775ee7SAntonio Huete Jimenez ND_PRINT(" TS{");
181*ed775ee7SAntonio Huete Jimenez hoplen = ((GET_U_1(cp + 3) & 0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
18241c99275SPeter Avalos if ((length - 4) & (hoplen-1))
183*ed775ee7SAntonio Huete Jimenez ND_PRINT("[bad length %u]", length);
184*ed775ee7SAntonio Huete Jimenez ptr = GET_U_1(cp + 2) - 1;
18541c99275SPeter Avalos len = 0;
18641c99275SPeter Avalos if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
187*ed775ee7SAntonio Huete Jimenez ND_PRINT("[bad ptr %u]", GET_U_1(cp + 2));
188*ed775ee7SAntonio Huete Jimenez switch (GET_U_1(cp + 3)&0xF) {
18941c99275SPeter Avalos case IPOPT_TS_TSONLY:
190*ed775ee7SAntonio Huete Jimenez ND_PRINT("TSONLY");
19141c99275SPeter Avalos break;
19241c99275SPeter Avalos case IPOPT_TS_TSANDADDR:
193*ed775ee7SAntonio Huete Jimenez ND_PRINT("TS+ADDR");
19441c99275SPeter Avalos break;
195*ed775ee7SAntonio Huete Jimenez case IPOPT_TS_PRESPEC:
196*ed775ee7SAntonio Huete Jimenez ND_PRINT("PRESPEC");
19741c99275SPeter Avalos break;
19841c99275SPeter Avalos default:
199*ed775ee7SAntonio Huete Jimenez ND_PRINT("[bad ts type %u]", GET_U_1(cp + 3)&0xF);
20041c99275SPeter Avalos goto done;
20141c99275SPeter Avalos }
20241c99275SPeter Avalos
20341c99275SPeter Avalos type = " ";
20441c99275SPeter Avalos for (len = 4; len < length; len += hoplen) {
20541c99275SPeter Avalos if (ptr == len)
20641c99275SPeter Avalos type = " ^ ";
207*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(cp + len, hoplen);
208*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s%u@%s", type, GET_BE_U_4(cp + len + hoplen - 4),
209*ed775ee7SAntonio Huete Jimenez hoplen!=8 ? "" : GET_IPADDR_STRING(cp + len));
21041c99275SPeter Avalos type = " ";
21141c99275SPeter Avalos }
21241c99275SPeter Avalos
21341c99275SPeter Avalos done:
214*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s", ptr == len ? " ^ " : "");
21541c99275SPeter Avalos
216*ed775ee7SAntonio Huete Jimenez if (GET_U_1(cp + 3) >> 4)
217*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [%u hops not recorded]} ", GET_U_1(cp + 3)>>4);
21841c99275SPeter Avalos else
219*ed775ee7SAntonio Huete Jimenez ND_PRINT("}");
220411677aeSAaron LI return (0);
221411677aeSAaron LI
222411677aeSAaron LI trunc:
223411677aeSAaron LI return (-1);
22441c99275SPeter Avalos }
22541c99275SPeter Avalos
22641c99275SPeter Avalos /*
22741c99275SPeter Avalos * print IP options.
228*ed775ee7SAntonio Huete Jimenez If truncated return -1, else 0.
22941c99275SPeter Avalos */
230*ed775ee7SAntonio Huete Jimenez static int
ip_optprint(netdissect_options * ndo,const u_char * cp,u_int length)231411677aeSAaron LI ip_optprint(netdissect_options *ndo,
232*ed775ee7SAntonio Huete Jimenez const u_char *cp, u_int length)
23341c99275SPeter Avalos {
234*ed775ee7SAntonio Huete Jimenez u_int option_len;
23541c99275SPeter Avalos const char *sep = "";
23641c99275SPeter Avalos
23741c99275SPeter Avalos for (; length > 0; cp += option_len, length -= option_len) {
23841c99275SPeter Avalos u_int option_code;
23941c99275SPeter Avalos
240*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s", sep);
24141c99275SPeter Avalos sep = ",";
24241c99275SPeter Avalos
243*ed775ee7SAntonio Huete Jimenez option_code = GET_U_1(cp);
24441c99275SPeter Avalos
245*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s",
246*ed775ee7SAntonio Huete Jimenez tok2str(ip_option_values,"unknown %u",option_code));
24741c99275SPeter Avalos
24841c99275SPeter Avalos if (option_code == IPOPT_NOP ||
24941c99275SPeter Avalos option_code == IPOPT_EOL)
25041c99275SPeter Avalos option_len = 1;
25141c99275SPeter Avalos
25241c99275SPeter Avalos else {
253*ed775ee7SAntonio Huete Jimenez option_len = GET_U_1(cp + 1);
25441c99275SPeter Avalos if (option_len < 2) {
255*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [bad length %u]", option_len);
256*ed775ee7SAntonio Huete Jimenez return 0;
25741c99275SPeter Avalos }
25841c99275SPeter Avalos }
25941c99275SPeter Avalos
26041c99275SPeter Avalos if (option_len > length) {
261*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [bad length %u]", option_len);
262*ed775ee7SAntonio Huete Jimenez return 0;
26341c99275SPeter Avalos }
26441c99275SPeter Avalos
265*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(cp, option_len);
26641c99275SPeter Avalos
26741c99275SPeter Avalos switch (option_code) {
26841c99275SPeter Avalos case IPOPT_EOL:
269*ed775ee7SAntonio Huete Jimenez return 0;
27041c99275SPeter Avalos
27141c99275SPeter Avalos case IPOPT_TS:
272411677aeSAaron LI if (ip_printts(ndo, cp, option_len) == -1)
273411677aeSAaron LI goto trunc;
27441c99275SPeter Avalos break;
27541c99275SPeter Avalos
27641c99275SPeter Avalos case IPOPT_RR: /* fall through */
27741c99275SPeter Avalos case IPOPT_SSRR:
27841c99275SPeter Avalos case IPOPT_LSRR:
279411677aeSAaron LI if (ip_printroute(ndo, cp, option_len) == -1)
280411677aeSAaron LI goto trunc;
28141c99275SPeter Avalos break;
28241c99275SPeter Avalos
28341c99275SPeter Avalos case IPOPT_RA:
28441c99275SPeter Avalos if (option_len < 4) {
285*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [bad length %u]", option_len);
28641c99275SPeter Avalos break;
28741c99275SPeter Avalos }
288*ed775ee7SAntonio Huete Jimenez ND_TCHECK_1(cp + 3);
289*ed775ee7SAntonio Huete Jimenez if (GET_BE_U_2(cp + 2) != 0)
290*ed775ee7SAntonio Huete Jimenez ND_PRINT(" value %u", GET_BE_U_2(cp + 2));
29141c99275SPeter Avalos break;
29241c99275SPeter Avalos
29341c99275SPeter Avalos case IPOPT_NOP: /* nothing to print - fall through */
29441c99275SPeter Avalos case IPOPT_SECURITY:
29541c99275SPeter Avalos default:
29641c99275SPeter Avalos break;
29741c99275SPeter Avalos }
29841c99275SPeter Avalos }
299*ed775ee7SAntonio Huete Jimenez return 0;
30041c99275SPeter Avalos
30141c99275SPeter Avalos trunc:
302*ed775ee7SAntonio Huete Jimenez return -1;
30341c99275SPeter Avalos }
30441c99275SPeter Avalos
30541c99275SPeter Avalos #define IP_RES 0x8000
30641c99275SPeter Avalos
307411677aeSAaron LI static const struct tok ip_frag_values[] = {
30841c99275SPeter Avalos { IP_MF, "+" },
30941c99275SPeter Avalos { IP_DF, "DF" },
31041c99275SPeter Avalos { IP_RES, "rsvd" }, /* The RFC3514 evil ;-) bit */
31141c99275SPeter Avalos { 0, NULL }
31241c99275SPeter Avalos };
31341c99275SPeter Avalos
31441c99275SPeter Avalos
31541c99275SPeter Avalos /*
31641c99275SPeter Avalos * print an IP datagram.
31741c99275SPeter Avalos */
31841c99275SPeter Avalos void
ip_print(netdissect_options * ndo,const u_char * bp,u_int length)31941c99275SPeter Avalos ip_print(netdissect_options *ndo,
32041c99275SPeter Avalos const u_char *bp,
32141c99275SPeter Avalos u_int length)
32241c99275SPeter Avalos {
323*ed775ee7SAntonio Huete Jimenez const struct ip *ip;
324*ed775ee7SAntonio Huete Jimenez u_int off;
32541c99275SPeter Avalos u_int hlen;
326*ed775ee7SAntonio Huete Jimenez u_int len;
32727bfbee1SPeter Avalos struct cksum_vec vec[1];
328*ed775ee7SAntonio Huete Jimenez uint8_t ip_tos, ip_ttl, ip_proto;
329411677aeSAaron LI uint16_t sum, ip_sum;
330411677aeSAaron LI const char *p_name;
331*ed775ee7SAntonio Huete Jimenez int truncated = 0;
33241c99275SPeter Avalos
333*ed775ee7SAntonio Huete Jimenez ndo->ndo_protocol = "ip";
334*ed775ee7SAntonio Huete Jimenez ip = (const struct ip *)bp;
335*ed775ee7SAntonio Huete Jimenez if (IP_V(ip) != 4) { /* print version and fail if != 4 */
336*ed775ee7SAntonio Huete Jimenez if (IP_V(ip) == 6)
337*ed775ee7SAntonio Huete Jimenez ND_PRINT("IP6, wrong link-layer encapsulation");
338411677aeSAaron LI else
339*ed775ee7SAntonio Huete Jimenez ND_PRINT("IP%u", IP_V(ip));
340*ed775ee7SAntonio Huete Jimenez nd_print_invalid(ndo);
34141c99275SPeter Avalos return;
34241c99275SPeter Avalos }
343411677aeSAaron LI if (!ndo->ndo_eflag)
344*ed775ee7SAntonio Huete Jimenez ND_PRINT("IP ");
345411677aeSAaron LI
346*ed775ee7SAntonio Huete Jimenez ND_TCHECK_SIZE(ip);
34741c99275SPeter Avalos if (length < sizeof (struct ip)) {
348*ed775ee7SAntonio Huete Jimenez ND_PRINT("truncated-ip %u", length);
34941c99275SPeter Avalos return;
35041c99275SPeter Avalos }
351*ed775ee7SAntonio Huete Jimenez hlen = IP_HL(ip) * 4;
35241c99275SPeter Avalos if (hlen < sizeof (struct ip)) {
353*ed775ee7SAntonio Huete Jimenez ND_PRINT("bad-hlen %u", hlen);
35441c99275SPeter Avalos return;
35541c99275SPeter Avalos }
35641c99275SPeter Avalos
357*ed775ee7SAntonio Huete Jimenez len = GET_BE_U_2(ip->ip_len);
358*ed775ee7SAntonio Huete Jimenez if (length < len)
359*ed775ee7SAntonio Huete Jimenez ND_PRINT("truncated-ip - %u bytes missing! ",
360*ed775ee7SAntonio Huete Jimenez len - length);
361*ed775ee7SAntonio Huete Jimenez if (len < hlen) {
36241c99275SPeter Avalos #ifdef GUESS_TSO
363*ed775ee7SAntonio Huete Jimenez if (len) {
364*ed775ee7SAntonio Huete Jimenez ND_PRINT("bad-len %u", len);
36541c99275SPeter Avalos return;
36641c99275SPeter Avalos }
36741c99275SPeter Avalos else {
36841c99275SPeter Avalos /* we guess that it is a TSO send */
369*ed775ee7SAntonio Huete Jimenez len = length;
37041c99275SPeter Avalos }
37141c99275SPeter Avalos #else
372*ed775ee7SAntonio Huete Jimenez ND_PRINT("bad-len %u", len);
37341c99275SPeter Avalos return;
37441c99275SPeter Avalos #endif /* GUESS_TSO */
37541c99275SPeter Avalos }
37641c99275SPeter Avalos
37741c99275SPeter Avalos /*
37841c99275SPeter Avalos * Cut off the snapshot length to the end of the IP payload.
37941c99275SPeter Avalos */
380*ed775ee7SAntonio Huete Jimenez nd_push_snapend(ndo, bp + len);
38141c99275SPeter Avalos
382*ed775ee7SAntonio Huete Jimenez len -= hlen;
38341c99275SPeter Avalos
384*ed775ee7SAntonio Huete Jimenez off = GET_BE_U_2(ip->ip_off);
385*ed775ee7SAntonio Huete Jimenez
386*ed775ee7SAntonio Huete Jimenez ip_proto = GET_U_1(ip->ip_p);
38741c99275SPeter Avalos
388411677aeSAaron LI if (ndo->ndo_vflag) {
389*ed775ee7SAntonio Huete Jimenez ip_tos = GET_U_1(ip->ip_tos);
390*ed775ee7SAntonio Huete Jimenez ND_PRINT("(tos 0x%x", ip_tos);
39141c99275SPeter Avalos /* ECN bits */
392*ed775ee7SAntonio Huete Jimenez switch (ip_tos & 0x03) {
393411677aeSAaron LI
394411677aeSAaron LI case 0:
395411677aeSAaron LI break;
396411677aeSAaron LI
39741c99275SPeter Avalos case 1:
398*ed775ee7SAntonio Huete Jimenez ND_PRINT(",ECT(1)");
39941c99275SPeter Avalos break;
400411677aeSAaron LI
40141c99275SPeter Avalos case 2:
402*ed775ee7SAntonio Huete Jimenez ND_PRINT(",ECT(0)");
40341c99275SPeter Avalos break;
404411677aeSAaron LI
40541c99275SPeter Avalos case 3:
406*ed775ee7SAntonio Huete Jimenez ND_PRINT(",CE");
407411677aeSAaron LI break;
40841c99275SPeter Avalos }
40941c99275SPeter Avalos
410*ed775ee7SAntonio Huete Jimenez ip_ttl = GET_U_1(ip->ip_ttl);
411*ed775ee7SAntonio Huete Jimenez if (ip_ttl >= 1)
412*ed775ee7SAntonio Huete Jimenez ND_PRINT(", ttl %u", ip_ttl);
41341c99275SPeter Avalos
41441c99275SPeter Avalos /*
41541c99275SPeter Avalos * for the firewall guys, print id, offset.
41641c99275SPeter Avalos * On all but the last stick a "+" in the flags portion.
41741c99275SPeter Avalos * For unfragmented datagrams, note the don't fragment flag.
41841c99275SPeter Avalos */
419*ed775ee7SAntonio Huete Jimenez ND_PRINT(", id %u, offset %u, flags [%s], proto %s (%u)",
420*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(ip->ip_id),
421*ed775ee7SAntonio Huete Jimenez (off & IP_OFFMASK) * 8,
422*ed775ee7SAntonio Huete Jimenez bittok2str(ip_frag_values, "none", off & (IP_RES|IP_DF|IP_MF)),
423*ed775ee7SAntonio Huete Jimenez tok2str(ipproto_values, "unknown", ip_proto),
424*ed775ee7SAntonio Huete Jimenez ip_proto);
42541c99275SPeter Avalos
426*ed775ee7SAntonio Huete Jimenez ND_PRINT(", length %u", GET_BE_U_2(ip->ip_len));
42741c99275SPeter Avalos
42841c99275SPeter Avalos if ((hlen - sizeof(struct ip)) > 0) {
429*ed775ee7SAntonio Huete Jimenez ND_PRINT(", options (");
430*ed775ee7SAntonio Huete Jimenez if (ip_optprint(ndo, (const u_char *)(ip + 1),
431*ed775ee7SAntonio Huete Jimenez hlen - sizeof(struct ip)) == -1) {
432*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [truncated-option]");
433*ed775ee7SAntonio Huete Jimenez truncated = 1;
434*ed775ee7SAntonio Huete Jimenez }
435*ed775ee7SAntonio Huete Jimenez ND_PRINT(")");
43641c99275SPeter Avalos }
43741c99275SPeter Avalos
438*ed775ee7SAntonio Huete Jimenez if (!ndo->ndo_Kflag && (const u_char *)ip + hlen <= ndo->ndo_snapend) {
439*ed775ee7SAntonio Huete Jimenez vec[0].ptr = (const uint8_t *)(const void *)ip;
44027bfbee1SPeter Avalos vec[0].len = hlen;
44127bfbee1SPeter Avalos sum = in_cksum(vec, 1);
44241c99275SPeter Avalos if (sum != 0) {
443*ed775ee7SAntonio Huete Jimenez ip_sum = GET_BE_U_2(ip->ip_sum);
444*ed775ee7SAntonio Huete Jimenez ND_PRINT(", bad cksum %x (->%x)!", ip_sum,
445*ed775ee7SAntonio Huete Jimenez in_cksum_shouldbe(ip_sum, sum));
44641c99275SPeter Avalos }
44741c99275SPeter Avalos }
44841c99275SPeter Avalos
449*ed775ee7SAntonio Huete Jimenez ND_PRINT(")\n ");
450*ed775ee7SAntonio Huete Jimenez if (truncated) {
451*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s > %s: ",
452*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(ip->ip_src),
453*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(ip->ip_dst));
454*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
455*ed775ee7SAntonio Huete Jimenez nd_pop_packet_info(ndo);
456*ed775ee7SAntonio Huete Jimenez return;
457*ed775ee7SAntonio Huete Jimenez }
45841c99275SPeter Avalos }
45941c99275SPeter Avalos
46041c99275SPeter Avalos /*
46141c99275SPeter Avalos * If this is fragment zero, hand it to the next higher
462*ed775ee7SAntonio Huete Jimenez * level protocol. Let them know whether there are more
463*ed775ee7SAntonio Huete Jimenez * fragments.
46441c99275SPeter Avalos */
465*ed775ee7SAntonio Huete Jimenez if ((off & IP_OFFMASK) == 0) {
466*ed775ee7SAntonio Huete Jimenez uint8_t nh = GET_U_1(ip->ip_p);
46741c99275SPeter Avalos
468*ed775ee7SAntonio Huete Jimenez if (nh != IPPROTO_TCP && nh != IPPROTO_UDP &&
469*ed775ee7SAntonio Huete Jimenez nh != IPPROTO_SCTP && nh != IPPROTO_DCCP) {
470*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s > %s: ",
471*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(ip->ip_src),
472*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(ip->ip_dst));
47341c99275SPeter Avalos }
474*ed775ee7SAntonio Huete Jimenez /*
475*ed775ee7SAntonio Huete Jimenez * Do a bounds check before calling ip_demux_print().
476*ed775ee7SAntonio Huete Jimenez * At least the header data is required.
477*ed775ee7SAntonio Huete Jimenez */
478*ed775ee7SAntonio Huete Jimenez if (!ND_TTEST_LEN((const u_char *)ip, hlen)) {
479*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [remaining caplen(%u) < header length(%u)]",
480*ed775ee7SAntonio Huete Jimenez ND_BYTES_AVAILABLE_AFTER((const u_char *)ip),
481*ed775ee7SAntonio Huete Jimenez hlen);
482*ed775ee7SAntonio Huete Jimenez nd_trunc_longjmp(ndo);
483*ed775ee7SAntonio Huete Jimenez }
484*ed775ee7SAntonio Huete Jimenez ip_demux_print(ndo, (const u_char *)ip + hlen, len, 4,
485*ed775ee7SAntonio Huete Jimenez off & IP_MF, GET_U_1(ip->ip_ttl), nh, bp);
48641c99275SPeter Avalos } else {
487411677aeSAaron LI /*
488411677aeSAaron LI * Ultra quiet now means that all this stuff should be
489411677aeSAaron LI * suppressed.
490411677aeSAaron LI */
491*ed775ee7SAntonio Huete Jimenez if (ndo->ndo_qflag > 1) {
492*ed775ee7SAntonio Huete Jimenez nd_pop_packet_info(ndo);
493411677aeSAaron LI return;
494*ed775ee7SAntonio Huete Jimenez }
49541c99275SPeter Avalos
49641c99275SPeter Avalos /*
497411677aeSAaron LI * This isn't the first frag, so we're missing the
49841c99275SPeter Avalos * next level protocol header. print the ip addr
49941c99275SPeter Avalos * and the protocol.
50041c99275SPeter Avalos */
501*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s > %s:", GET_IPADDR_STRING(ip->ip_src),
502*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(ip->ip_dst));
503*ed775ee7SAntonio Huete Jimenez if (!ndo->ndo_nflag && (p_name = netdb_protoname(ip_proto)) != NULL)
504*ed775ee7SAntonio Huete Jimenez ND_PRINT(" %s", p_name);
50541c99275SPeter Avalos else
506*ed775ee7SAntonio Huete Jimenez ND_PRINT(" ip-proto-%u", ip_proto);
50741c99275SPeter Avalos }
508*ed775ee7SAntonio Huete Jimenez nd_pop_packet_info(ndo);
509411677aeSAaron LI return;
510411677aeSAaron LI
511411677aeSAaron LI trunc:
512*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
51341c99275SPeter Avalos }
51441c99275SPeter Avalos
51541c99275SPeter Avalos void
ipN_print(netdissect_options * ndo,const u_char * bp,u_int length)516*ed775ee7SAntonio Huete Jimenez ipN_print(netdissect_options *ndo, const u_char *bp, u_int length)
51741c99275SPeter Avalos {
518*ed775ee7SAntonio Huete Jimenez ndo->ndo_protocol = "ipn";
519411677aeSAaron LI if (length < 1) {
520*ed775ee7SAntonio Huete Jimenez ND_PRINT("truncated-ip %u", length);
521411677aeSAaron LI return;
522411677aeSAaron LI }
52341c99275SPeter Avalos
524*ed775ee7SAntonio Huete Jimenez switch (GET_U_1(bp) & 0xF0) {
525411677aeSAaron LI case 0x40:
526411677aeSAaron LI ip_print(ndo, bp, length);
527411677aeSAaron LI break;
528411677aeSAaron LI case 0x60:
529411677aeSAaron LI ip6_print(ndo, bp, length);
530411677aeSAaron LI break;
53141c99275SPeter Avalos default:
532*ed775ee7SAntonio Huete Jimenez ND_PRINT("unknown ip %u", (GET_U_1(bp) & 0xF0) >> 4);
533411677aeSAaron LI break;
53441c99275SPeter Avalos }
53541c99275SPeter Avalos }
536