2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
24 #define NETDISSECT_REWORKED
29 #include <tcpdump-stdinc.h>
33 #include "interface.h"
34 #include "addrtoname.h"
35 #include "extract.h" /* must come after interface.h */
40 static const char tstr[] = "[|ip]";
42 static const struct tok ip_option_values[] = {
45 { IPOPT_TS, "timestamp" },
46 { IPOPT_SECURITY, "security" },
48 { IPOPT_SSRR, "SSRR" },
49 { IPOPT_LSRR, "LSRR" },
51 { IPOPT_RFC1393, "traceroute" },
56 * print the recorded route in an IP RR, LSRR or SSRR option.
59 ip_printroute(netdissect_options *ndo,
60 register const u_char *cp, u_int length)
66 ND_PRINT((ndo, " [bad length %u]", length));
70 ND_PRINT((ndo, " [bad length %u]", length));
72 if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
73 ND_PRINT((ndo, " [bad ptr %u]", cp[2]));
75 for (len = 3; len < length; len += 4) {
76 ND_PRINT((ndo, " %s", ipaddr_string(ndo, &cp[len])));
83 * If source-routing is present and valid, return the final destination.
84 * Otherwise, return IP destination.
86 * This is used for UDP and TCP pseudo-header in the checksum
90 ip_finddst(netdissect_options *ndo,
98 cp = (const u_char *)(ip + 1);
99 length = (IP_HL(ip) << 2) - sizeof(struct ip);
101 for (; length > 0; cp += len, length -= len) {
108 else if (tt == IPOPT_NOP)
116 ND_TCHECK2(*cp, len);
123 UNALIGNED_MEMCPY(&retval, cp + len - 4, 4);
128 UNALIGNED_MEMCPY(&retval, &ip->ip_dst.s_addr, sizeof(uint32_t));
133 * Compute a V4-style checksum by building a pseudoheader.
136 nextproto4_cksum(netdissect_options *ndo,
137 const struct ip *ip, const uint8_t *data,
138 u_int len, u_int covlen, u_int next_proto)
147 struct cksum_vec vec[2];
149 /* pseudo-header.. */
150 ph.len = htons((uint16_t)len);
152 ph.proto = next_proto;
153 UNALIGNED_MEMCPY(&ph.src, &ip->ip_src.s_addr, sizeof(uint32_t));
155 UNALIGNED_MEMCPY(&ph.dst, &ip->ip_dst.s_addr, sizeof(uint32_t));
157 ph.dst = ip_finddst(ndo, ip);
159 vec[0].ptr = (const uint8_t *)(void *)&ph;
160 vec[0].len = sizeof(ph);
163 return (in_cksum(vec, 2));
167 ip_printts(netdissect_options *ndo,
168 register const u_char *cp, u_int length)
176 ND_PRINT((ndo, "[bad length %u]", length));
179 ND_PRINT((ndo, " TS{"));
180 hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
181 if ((length - 4) & (hoplen-1))
182 ND_PRINT((ndo, "[bad length %u]", length));
185 if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
186 ND_PRINT((ndo, "[bad ptr %u]", cp[2]));
188 case IPOPT_TS_TSONLY:
189 ND_PRINT((ndo, "TSONLY"));
191 case IPOPT_TS_TSANDADDR:
192 ND_PRINT((ndo, "TS+ADDR"));
195 * prespecified should really be 3, but some ones might send 2
196 * instead, and the IPOPT_TS_PRESPEC constant can apparently
197 * have both values, so we have to hard-code it here.
201 ND_PRINT((ndo, "PRESPEC2.0"));
203 case 3: /* IPOPT_TS_PRESPEC */
204 ND_PRINT((ndo, "PRESPEC"));
207 ND_PRINT((ndo, "[bad ts type %d]", cp[3]&0xF));
212 for (len = 4; len < length; len += hoplen) {
215 ND_PRINT((ndo, "%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]),
216 hoplen!=8 ? "" : ipaddr_string(ndo, &cp[len])));
221 ND_PRINT((ndo, "%s", ptr == len ? " ^ " : ""));
224 ND_PRINT((ndo, " [%d hops not recorded]} ", cp[3]>>4));
226 ND_PRINT((ndo, "}"));
233 ip_optprint(netdissect_options *ndo,
234 register const u_char *cp, u_int length)
236 register u_int option_len;
237 const char *sep = "";
239 for (; length > 0; cp += option_len, length -= option_len) {
242 ND_PRINT((ndo, "%s", sep));
249 tok2str(ip_option_values,"unknown %u",option_code)));
251 if (option_code == IPOPT_NOP ||
252 option_code == IPOPT_EOL)
258 if (option_len < 2) {
259 ND_PRINT((ndo, " [bad length %u]", option_len));
264 if (option_len > length) {
265 ND_PRINT((ndo, " [bad length %u]", option_len));
269 ND_TCHECK2(*cp, option_len);
271 switch (option_code) {
276 ip_printts(ndo, cp, option_len);
279 case IPOPT_RR: /* fall through */
282 ip_printroute(ndo, cp, option_len);
286 if (option_len < 4) {
287 ND_PRINT((ndo, " [bad length %u]", option_len));
291 if (EXTRACT_16BITS(&cp[2]) != 0)
292 ND_PRINT((ndo, " value %u", EXTRACT_16BITS(&cp[2])));
295 case IPOPT_NOP: /* nothing to print - fall through */
304 ND_PRINT((ndo, "%s", tstr));
307 #define IP_RES 0x8000
309 static const struct tok ip_frag_values[] = {
312 { IP_RES, "rsvd" }, /* The RFC3514 evil ;-) bit */
316 struct ip_print_demux_state {
325 ip_print_demux(netdissect_options *ndo,
326 struct ip_print_demux_state *ipds)
328 struct protoent *proto;
329 struct cksum_vec vec[1];
335 ipds->nh = *ipds->cp;
336 ipds->advance = ah_print(ndo, ipds->cp);
337 if (ipds->advance <= 0)
339 ipds->cp += ipds->advance;
340 ipds->len -= ipds->advance;
346 ipds->advance = esp_print(ndo, ipds->cp, ipds->len,
347 (const u_char *)ipds->ip,
349 if (ipds->advance <= 0)
351 ipds->cp += ipds->advance;
352 ipds->len -= ipds->advance + padlen;
353 ipds->nh = enh & 0xff;
360 ipds->advance = ipcomp_print(ndo, ipds->cp, &enh);
361 if (ipds->advance <= 0)
363 ipds->cp += ipds->advance;
364 ipds->len -= ipds->advance;
365 ipds->nh = enh & 0xff;
370 sctp_print(ndo, ipds->cp, (const u_char *)ipds->ip, ipds->len);
374 dccp_print(ndo, ipds->cp, (const u_char *)ipds->ip, ipds->len);
378 /* pass on the MF bit plus the offset to detect fragments */
379 tcp_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip,
380 ipds->off & (IP_MF|IP_OFFMASK));
384 /* pass on the MF bit plus the offset to detect fragments */
385 udp_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip,
386 ipds->off & (IP_MF|IP_OFFMASK));
390 /* pass on the MF bit plus the offset to detect fragments */
391 icmp_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip,
392 ipds->off & (IP_MF|IP_OFFMASK));
397 * XXX - the current IANA protocol number assignments
398 * page lists 9 as "any private interior gateway
399 * (used by Cisco for their IGRP)" and 88 as
400 * "EIGRP" from Cisco.
402 * Recent BSD <netinet/in.h> headers define
403 * IP_PROTO_PIGP as 9 and IP_PROTO_IGRP as 88.
404 * We define IP_PROTO_PIGP as 9 and
405 * IP_PROTO_EIGRP as 88; those names better
406 * match was the current protocol number
409 igrp_print(ndo, ipds->cp, ipds->len);
413 eigrp_print(ndo, ipds->cp, ipds->len);
417 ND_PRINT((ndo, " nd %d", ipds->len));
421 egp_print(ndo, ipds->cp, ipds->len);
425 ospf_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip);
429 igmp_print(ndo, ipds->cp, ipds->len);
433 /* DVMRP multicast tunnel (ip-in-ip encapsulation) */
434 ip_print(ndo, ipds->cp, ipds->len);
435 if (! ndo->ndo_vflag) {
436 ND_PRINT((ndo, " (ipip-proto-4)"));
443 /* ip6-in-ip encapsulation */
444 ip6_print(ndo, ipds->cp, ipds->len);
449 rsvp_print(ndo, ipds->cp, ipds->len);
454 gre_print(ndo, ipds->cp, ipds->len);
458 mobile_print(ndo, ipds->cp, ipds->len);
462 vec[0].ptr = ipds->cp;
463 vec[0].len = ipds->len;
464 pim_print(ndo, ipds->cp, ipds->len, in_cksum(vec, 1));
468 if (ndo->ndo_packettype == PT_CARP) {
470 ND_PRINT((ndo, "carp %s > %s: ",
471 ipaddr_string(ndo, &ipds->ip->ip_src),
472 ipaddr_string(ndo, &ipds->ip->ip_dst)));
473 carp_print(ndo, ipds->cp, ipds->len, ipds->ip->ip_ttl);
476 ND_PRINT((ndo, "vrrp %s > %s: ",
477 ipaddr_string(ndo, &ipds->ip->ip_src),
478 ipaddr_string(ndo, &ipds->ip->ip_dst)));
479 vrrp_print(ndo, ipds->cp, ipds->len,
480 (const u_char *)ipds->ip, ipds->ip->ip_ttl);
485 pgm_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip);
488 #if defined(HAVE_NET_PFVAR_H)
490 pfsync_ip_print(ipds->cp, ipds->len);
495 if (ndo->ndo_nflag==0 && (proto = getprotobynumber(ipds->nh)) != NULL)
496 ND_PRINT((ndo, " %s", proto->p_name));
498 ND_PRINT((ndo, " ip-proto-%d", ipds->nh));
499 ND_PRINT((ndo, " %d", ipds->len));
505 ip_print_inner(netdissect_options *ndo,
507 u_int length, u_int nh,
510 struct ip_print_demux_state ipd;
512 ipd.ip = (const struct ip *)bp2;
519 ip_print_demux(ndo, &ipd);
524 * print an IP datagram.
527 ip_print(netdissect_options *ndo,
531 struct ip_print_demux_state ipd;
532 struct ip_print_demux_state *ipds=&ipd;
535 struct cksum_vec vec[1];
536 uint16_t sum, ip_sum;
537 struct protoent *proto;
539 ipds->ip = (const struct ip *)bp;
540 ND_TCHECK(ipds->ip->ip_vhl);
541 if (IP_V(ipds->ip) != 4) { /* print version if != 4 */
542 ND_PRINT((ndo, "IP%u ", IP_V(ipds->ip)));
543 if (IP_V(ipds->ip) == 6)
544 ND_PRINT((ndo, ", wrong link-layer encapsulation"));
546 else if (!ndo->ndo_eflag)
547 ND_PRINT((ndo, "IP "));
549 ND_TCHECK(*ipds->ip);
550 if (length < sizeof (struct ip)) {
551 ND_PRINT((ndo, "truncated-ip %u", length));
554 hlen = IP_HL(ipds->ip) * 4;
555 if (hlen < sizeof (struct ip)) {
556 ND_PRINT((ndo, "bad-hlen %u", hlen));
560 ipds->len = EXTRACT_16BITS(&ipds->ip->ip_len);
561 if (length < ipds->len)
562 ND_PRINT((ndo, "truncated-ip - %u bytes missing! ",
563 ipds->len - length));
564 if (ipds->len < hlen) {
567 ND_PRINT((ndo, "bad-len %u", ipds->len));
571 /* we guess that it is a TSO send */
575 ND_PRINT((ndo, "bad-len %u", ipds->len));
577 #endif /* GUESS_TSO */
581 * Cut off the snapshot length to the end of the IP payload.
583 ipend = bp + ipds->len;
584 if (ipend < ndo->ndo_snapend)
585 ndo->ndo_snapend = ipend;
589 ipds->off = EXTRACT_16BITS(&ipds->ip->ip_off);
591 if (ndo->ndo_vflag) {
592 ND_PRINT((ndo, "(tos 0x%x", (int)ipds->ip->ip_tos));
594 if (ipds->ip->ip_tos & 0x03) {
595 switch (ipds->ip->ip_tos & 0x03) {
597 ND_PRINT((ndo, ",ECT(1)"));
600 ND_PRINT((ndo, ",ECT(0)"));
603 ND_PRINT((ndo, ",CE"));
607 if (ipds->ip->ip_ttl >= 1)
608 ND_PRINT((ndo, ", ttl %u", ipds->ip->ip_ttl));
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.
616 ND_PRINT((ndo, ", 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),
623 ND_PRINT((ndo, ", length %u", EXTRACT_16BITS(&ipds->ip->ip_len)));
625 if ((hlen - sizeof(struct ip)) > 0) {
626 ND_PRINT((ndo, ", options ("));
627 ip_optprint(ndo, (u_char *)(ipds->ip + 1), hlen - sizeof(struct ip));
628 ND_PRINT((ndo, ")"));
631 if (!ndo->ndo_Kflag && (u_char *)ipds->ip + hlen <= ndo->ndo_snapend) {
632 vec[0].ptr = (const uint8_t *)(void *)ipds->ip;
634 sum = in_cksum(vec, 1);
636 ip_sum = EXTRACT_16BITS(&ipds->ip->ip_sum);
637 ND_PRINT((ndo, ", bad cksum %x (->%x)!", ip_sum,
638 in_cksum_shouldbe(ip_sum, sum)));
642 ND_PRINT((ndo, ")\n "));
646 * If this is fragment zero, hand it to the next higher
649 if ((ipds->off & 0x1fff) == 0) {
650 ipds->cp = (const u_char *)ipds->ip + hlen;
651 ipds->nh = ipds->ip->ip_p;
653 if (ipds->nh != IPPROTO_TCP && ipds->nh != IPPROTO_UDP &&
654 ipds->nh != IPPROTO_SCTP && ipds->nh != IPPROTO_DCCP) {
655 ND_PRINT((ndo, "%s > %s: ",
656 ipaddr_string(ndo, &ipds->ip->ip_src),
657 ipaddr_string(ndo, &ipds->ip->ip_dst)));
659 ip_print_demux(ndo, ipds);
661 /* Ultra quiet now means that all this stuff should be suppressed */
662 if (ndo->ndo_qflag > 1) return;
665 * if this isn't the first frag, we're missing the
666 * next level protocol header. print the ip addr
669 if (ipds->off & 0x1fff) {
670 ND_PRINT((ndo, "%s > %s:", ipaddr_string(ndo, &ipds->ip->ip_src),
671 ipaddr_string(ndo, &ipds->ip->ip_dst)));
672 if (!ndo->ndo_nflag && (proto = getprotobynumber(ipds->ip->ip_p)) != NULL)
673 ND_PRINT((ndo, " %s", proto->p_name));
675 ND_PRINT((ndo, " ip-proto-%d", ipds->ip->ip_p));
681 ND_PRINT((ndo, "%s", tstr));
686 ipN_print(netdissect_options *ndo, register const u_char *bp, register u_int length)
691 ND_PRINT((ndo, "truncated-ip %d", length));
694 memcpy (&hdr, bp, 4);
695 switch (IP_V(&hdr)) {
697 ip_print (ndo, bp, length);
701 ip6_print (ndo, bp, length);
705 ND_PRINT((ndo, "unknown ip %d", IP_V(&hdr)));
712 * c-style: whitesmith