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