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