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)"));
442 /* ip6-in-ip encapsulation */
443 ip6_print(ndo, ipds->cp, ipds->len);
447 rsvp_print(ndo, ipds->cp, ipds->len);
452 gre_print(ndo, ipds->cp, ipds->len);
456 mobile_print(ndo, ipds->cp, ipds->len);
460 vec[0].ptr = ipds->cp;
461 vec[0].len = ipds->len;
462 pim_print(ndo, ipds->cp, ipds->len, in_cksum(vec, 1));
466 if (ndo->ndo_packettype == PT_CARP) {
468 ND_PRINT((ndo, "carp %s > %s: ",
469 ipaddr_string(ndo, &ipds->ip->ip_src),
470 ipaddr_string(ndo, &ipds->ip->ip_dst)));
471 carp_print(ndo, ipds->cp, ipds->len, ipds->ip->ip_ttl);
474 ND_PRINT((ndo, "vrrp %s > %s: ",
475 ipaddr_string(ndo, &ipds->ip->ip_src),
476 ipaddr_string(ndo, &ipds->ip->ip_dst)));
477 vrrp_print(ndo, ipds->cp, ipds->len,
478 (const u_char *)ipds->ip, ipds->ip->ip_ttl);
483 pgm_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip);
486 #if defined(HAVE_NET_PFVAR_H)
488 pfsync_ip_print(ndo, ipds->cp, ipds->len);
493 if (ndo->ndo_nflag==0 && (proto = getprotobynumber(ipds->nh)) != NULL)
494 ND_PRINT((ndo, " %s", proto->p_name));
496 ND_PRINT((ndo, " ip-proto-%d", ipds->nh));
497 ND_PRINT((ndo, " %d", ipds->len));
503 ip_print_inner(netdissect_options *ndo,
505 u_int length, u_int nh,
508 struct ip_print_demux_state ipd;
510 ipd.ip = (const struct ip *)bp2;
517 ip_print_demux(ndo, &ipd);
522 * print an IP datagram.
525 ip_print(netdissect_options *ndo,
529 struct ip_print_demux_state ipd;
530 struct ip_print_demux_state *ipds=&ipd;
533 struct cksum_vec vec[1];
534 uint16_t sum, ip_sum;
535 struct protoent *proto;
537 ipds->ip = (const struct ip *)bp;
538 ND_TCHECK(ipds->ip->ip_vhl);
539 if (IP_V(ipds->ip) != 4) { /* print version if != 4 */
540 if (IP_V(ipds->ip) == 6)
541 ND_PRINT((ndo, "IP6, wrong link-layer encapsulation "));
543 ND_PRINT((ndo, "IP%u ", IP_V(ipds->ip)));
545 else if (!ndo->ndo_eflag)
546 ND_PRINT((ndo, "IP "));
548 ND_TCHECK(*ipds->ip);
549 if (length < sizeof (struct ip)) {
550 ND_PRINT((ndo, "truncated-ip %u", length));
553 hlen = IP_HL(ipds->ip) * 4;
554 if (hlen < sizeof (struct ip)) {
555 ND_PRINT((ndo, "bad-hlen %u", hlen));
559 ipds->len = EXTRACT_16BITS(&ipds->ip->ip_len);
560 if (length < ipds->len)
561 ND_PRINT((ndo, "truncated-ip - %u bytes missing! ",
562 ipds->len - length));
563 if (ipds->len < hlen) {
566 ND_PRINT((ndo, "bad-len %u", ipds->len));
570 /* we guess that it is a TSO send */
574 ND_PRINT((ndo, "bad-len %u", ipds->len));
576 #endif /* GUESS_TSO */
580 * Cut off the snapshot length to the end of the IP payload.
582 ipend = bp + ipds->len;
583 if (ipend < ndo->ndo_snapend)
584 ndo->ndo_snapend = ipend;
588 ipds->off = EXTRACT_16BITS(&ipds->ip->ip_off);
590 if (ndo->ndo_vflag) {
591 ND_PRINT((ndo, "(tos 0x%x", (int)ipds->ip->ip_tos));
593 if (ipds->ip->ip_tos & 0x03) {
594 switch (ipds->ip->ip_tos & 0x03) {
596 ND_PRINT((ndo, ",ECT(1)"));
599 ND_PRINT((ndo, ",ECT(0)"));
602 ND_PRINT((ndo, ",CE"));
606 if (ipds->ip->ip_ttl >= 1)
607 ND_PRINT((ndo, ", ttl %u", ipds->ip->ip_ttl));
610 * for the firewall guys, print id, offset.
611 * On all but the last stick a "+" in the flags portion.
612 * For unfragmented datagrams, note the don't fragment flag.
615 ND_PRINT((ndo, ", id %u, offset %u, flags [%s], proto %s (%u)",
616 EXTRACT_16BITS(&ipds->ip->ip_id),
617 (ipds->off & 0x1fff) * 8,
618 bittok2str(ip_frag_values, "none", ipds->off&0xe000),
619 tok2str(ipproto_values,"unknown",ipds->ip->ip_p),
622 ND_PRINT((ndo, ", length %u", EXTRACT_16BITS(&ipds->ip->ip_len)));
624 if ((hlen - sizeof(struct ip)) > 0) {
625 ND_PRINT((ndo, ", options ("));
626 ip_optprint(ndo, (u_char *)(ipds->ip + 1), hlen - sizeof(struct ip));
627 ND_PRINT((ndo, ")"));
630 if (!ndo->ndo_Kflag && (u_char *)ipds->ip + hlen <= ndo->ndo_snapend) {
631 vec[0].ptr = (const uint8_t *)(void *)ipds->ip;
633 sum = in_cksum(vec, 1);
635 ip_sum = EXTRACT_16BITS(&ipds->ip->ip_sum);
636 ND_PRINT((ndo, ", bad cksum %x (->%x)!", ip_sum,
637 in_cksum_shouldbe(ip_sum, sum)));
641 ND_PRINT((ndo, ")\n "));
645 * If this is fragment zero, hand it to the next higher
648 if ((ipds->off & 0x1fff) == 0) {
649 ipds->cp = (const u_char *)ipds->ip + hlen;
650 ipds->nh = ipds->ip->ip_p;
652 if (ipds->nh != IPPROTO_TCP && ipds->nh != IPPROTO_UDP &&
653 ipds->nh != IPPROTO_SCTP && ipds->nh != IPPROTO_DCCP) {
654 ND_PRINT((ndo, "%s > %s: ",
655 ipaddr_string(ndo, &ipds->ip->ip_src),
656 ipaddr_string(ndo, &ipds->ip->ip_dst)));
658 ip_print_demux(ndo, ipds);
660 /* Ultra quiet now means that all this stuff should be suppressed */
661 if (ndo->ndo_qflag > 1) return;
664 * if this isn't the first frag, we're missing the
665 * next level protocol header. print the ip addr
668 if (ipds->off & 0x1fff) {
669 ND_PRINT((ndo, "%s > %s:", ipaddr_string(ndo, &ipds->ip->ip_src),
670 ipaddr_string(ndo, &ipds->ip->ip_dst)));
671 if (!ndo->ndo_nflag && (proto = getprotobynumber(ipds->ip->ip_p)) != NULL)
672 ND_PRINT((ndo, " %s", proto->p_name));
674 ND_PRINT((ndo, " ip-proto-%d", ipds->ip->ip_p));
680 ND_PRINT((ndo, "%s", tstr));
685 ipN_print(netdissect_options *ndo, register const u_char *bp, register u_int length)
690 ND_PRINT((ndo, "truncated-ip %d", length));
693 memcpy (&hdr, bp, 4);
694 switch (IP_V(&hdr)) {
696 ip_print (ndo, bp, length);
699 ip6_print (ndo, bp, length);
702 ND_PRINT((ndo, "unknown ip %d", IP_V(&hdr)));
709 * c-style: whitesmith