? obj ? print-cmd.c Index: Makefile =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/Makefile,v retrieving revision 1.64 diff -u -p -r1.64 Makefile --- Makefile 3 Dec 2019 01:43:33 -0000 1.64 +++ Makefile 3 Dec 2019 11:52:08 -0000 @@ -20,10 +20,12 @@ # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. # +DEBUG=-g + PROG= tcpdump MAN= tcpdump.8 -CFLAGS+=-Wall -I${.CURDIR}/../../sbin/pfctl -I${.CURDIR}/../hostapd +CFLAGS+=-Wall -Werror -I${.CURDIR}/../../sbin/pfctl -I${.CURDIR}/../hostapd # for pcap-int.h CFLAGS+=-I${.CURDIR}/../../lib/libpcap Index: interface.h =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/interface.h,v retrieving revision 1.83 diff -u -p -r1.83 interface.h --- interface.h 3 Dec 2019 01:43:33 -0000 1.83 +++ interface.h 3 Dec 2019 11:52:08 -0000 @@ -130,6 +130,8 @@ extern int snaplen; extern const u_char *packetp; extern const u_char *snapend; +extern const char *layersep; + /* * True if "l" bytes of "var" were captured. * @@ -184,6 +186,36 @@ extern char *dnnum_string(u_short); struct pcap_pkthdr; +struct ip_hdrinfo { + const char *src; + const char *dst; + const void *hdr; + int frag; + uint8_t ttl; + + uint32_t (*pseudo_cksum)(const struct ip_hdrinfo *, + uint8_t, uint16_t); + void (*print_proto)(struct ip_hdrinfo *, int, + const u_char *, u_int); +}; + +static inline void +ip_hdrinfo_print(struct ip_hdrinfo *iph, int proto, + const u_char *bp, u_int len) +{ + (*iph->print_proto)(iph, proto, bp, len); +} + +static inline uint32_t +ip_hdrinfo_phsum(const struct ip_hdrinfo *iph, uint8_t proto, uint16_t len) +{ + return ((*iph->pseudo_cksum)(iph, proto, len)); +} + +/* common IPv4/IPv6 protocol handling */ +extern void ip_proto_print(const struct ip_hdrinfo *, int, + const u_char *, u_int); + extern int ether_encap_print(u_short, const u_char *, u_int, u_int); extern int llc_print(const u_char *, u_int, u_int, const u_char *, const u_char *); @@ -207,7 +239,7 @@ extern void pflog_old_if_print(u_char *, const u_char *); extern void pfsync_if_print(u_char *, const struct pcap_pkthdr *, const u_char *); -extern void pfsync_ip_print(const u_char *, u_int, const u_char *); +extern void pfsync_ip_print(const u_char *, u_int); extern void ether_if_print(u_char *, const struct pcap_pkthdr *, const u_char *); extern void ether_tryprint(const u_char *, u_int, int); @@ -217,13 +249,13 @@ extern void ppp_ether_if_print(u_char *, extern void gre_print(const u_char *, u_int); extern void vxlan_print(const u_char *, u_int); extern void nsh_print(const u_char *, u_int); -extern void icmp_print(const u_char *, u_int, const u_char *); +extern void icmp_print(const u_char *, u_int); extern void ieee802_11_if_print(u_char *, const struct pcap_pkthdr *, const u_char *); extern void ieee802_11_radio_if_print(u_char *, const struct pcap_pkthdr *, const u_char *); extern void iapp_print(const u_char *, u_int); -extern void igrp_print(const u_char *, u_int, const u_char *); +extern void igrp_print(const u_char *, u_int); extern void ip_print(const u_char *, u_int); extern void ipx_print(const u_char *, u_int); extern void isoclns_print(const u_char *, u_int, u_int, const u_char *, @@ -247,7 +279,7 @@ extern void ns_print(const u_char *, u_i extern void ntp_print(const u_char *, u_int); extern void loop_if_print(u_char *, const struct pcap_pkthdr *, const u_char *); extern void null_if_print(u_char *, const struct pcap_pkthdr *, const u_char *); -extern void ospf_print(const u_char *, u_int, const u_char *); +extern void ospf_print(const u_char *, u_int); extern void mobile_print(const u_char *, u_int); extern void pim_print(const u_char *, u_int); extern void ppp_if_print(u_char *, const struct pcap_pkthdr *, const u_char *); @@ -263,22 +295,22 @@ extern void sl_bsdos_if_print(u_char *, extern void snmp_print(const u_char *, u_int); extern void sunrpcrequest_print(const u_char *, u_int, const u_char *); extern void cnfp_print(const u_char *, u_int); -extern void tcp_print(const u_char *, u_int, const u_char *); +extern void tcp_print(const struct ip_hdrinfo *, const u_char *, u_int); extern void tftp_print(const u_char *, u_int); extern void timed_print(const u_char *, u_int); -extern void udp_print(const u_char *, u_int, const void *); +extern void udp_print(struct ip_hdrinfo *, const u_char *, u_int); extern void wb_print(const void *, u_int); extern void ike_print(const u_char *, u_int); -extern void udpencap_print(const u_char *, u_int, const u_char *); -extern void ah_print(const u_char *, u_int, const u_char *); -extern void esp_print(const u_char *, u_int, const u_char *); +extern void udpencap_print(struct ip_hdrinfo *, const u_char *, u_int); +extern void ah_print(struct ip_hdrinfo *, const u_char *, u_int); +extern void esp_print(struct ip_hdrinfo *, const u_char *, u_int); extern void cdp_print(const u_char *, u_int, u_int, int); extern void stp_print(const u_char *, u_int); extern void radius_print(const u_char *, u_int); extern void lwres_print(const u_char *, u_int); extern void ether_print(const u_char *, u_int); extern void etherip_print(const u_char *, u_int, u_int); -extern void ipcomp_print(const u_char *, u_int, const u_char *); +extern void ipcomp_print(const u_char *, u_int); extern void mpls_print(const u_char *, u_int); extern void lldp_print(const u_char *, u_int); extern void slow_print(const u_char *, u_int); @@ -289,13 +321,13 @@ extern void usbpcap_if_print(u_char *, c const u_char *); extern void ip6_print(const u_char *, u_int); -extern void ip6_opt_print(const u_char *, int); -extern int hbhopt_print(const u_char *); -extern int dstopt_print(const u_char *); -extern int frag6_print(const u_char *, const u_char *); -extern void icmp6_print(const u_char *, u_int, const u_char *); +extern void ip6_opt_print(const u_char *, u_int); +extern void hbhopt_print(struct ip_hdrinfo *, const u_char *, u_int); +extern void dstopt_print(struct ip_hdrinfo *, const u_char *, u_int); +extern void frag6_print(struct ip_hdrinfo *, const u_char *, u_int); +extern void icmp6_print(const struct ip_hdrinfo *, const u_char *, u_int); extern void ripng_print(const u_char *, int); -extern int rt6_print(const u_char *, const u_char *); +extern void rt6_print(struct ip_hdrinfo *iph, const u_char *, u_int); extern void ospf6_print(const u_char *, u_int); extern void dhcp6_print(const u_char *, u_int); Index: print-frag6.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/print-frag6.c,v retrieving revision 1.9 diff -u -p -r1.9 print-frag6.c --- print-frag6.c 22 Oct 2018 16:12:45 -0000 1.9 +++ print-frag6.c 3 Dec 2019 11:52:08 -0000 @@ -43,42 +43,44 @@ #include "interface.h" #include "addrtoname.h" -int -frag6_print(const u_char *bp, const u_char *bp2) +void +frag6_print(struct ip_hdrinfo *iph, const u_char *bp, u_int len) { const struct ip6_frag *dp; - const struct ip6_hdr *ip6; - const u_char *ep; + uint16_t offset; + int l = snapend - bp; -#if 0 -#define TCHECK(var) if ((u_char *)&(var) >= ep - sizeof(var)) goto trunc -#endif - - dp = (struct ip6_frag *)bp; - ip6 = (struct ip6_hdr *)bp2; - - /* 'ep' points to the end of avaible data. */ - ep = snapend; - - TCHECK(dp->ip6f_ident); - - printf("frag (0x%08x:%ld@%d%s)", - ntohl(dp->ip6f_ident), - sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen) - - (long)(bp - bp2) - sizeof(struct ip6_frag), - ntohs(dp->ip6f_offlg & IP6F_OFF_MASK), + printf("Fragment"); + + if (l < sizeof(*dp)) + goto trunc; + if (len < sizeof(*dp)) { + printf(" ip truncated"); + return; + } + + dp = (const struct ip6_frag *)bp; + bp += sizeof(*dp); + len -= sizeof(*dp); + + offset = ntohs(dp->ip6f_offlg & IP6F_OFF_MASK); + + printf(" (0x%08x:%u@%u%s)", ntohl(dp->ip6f_ident), len, offset, (dp->ip6f_offlg & IP6F_MORE_FRAG) ? "+" : ""); + printf(", "); + /* it is meaningless to decode non-first fragment */ - if (ntohs(dp->ip6f_offlg & IP6F_OFF_MASK) != 0) - return 65535; - else - { - fputs(" ", stdout); - return sizeof(struct ip6_frag); + if (offset != 0) { + printf("%s > %s: %s fragment", iph->src, iph->dst, + ipproto_string(dp->ip6f_nxt)); + return; } + + iph->frag = 1; + ip_hdrinfo_print(iph, dp->ip6f_nxt, bp, len); + return; + trunc: - fputs("[|frag]", stdout); - return 65535; -#undef TCHECK + printf(" [|frag]"); } Index: print-gre.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/print-gre.c,v retrieving revision 1.29 diff -u -p -r1.29 print-gre.c --- print-gre.c 3 Dec 2019 01:43:33 -0000 1.29 +++ print-gre.c 3 Dec 2019 11:52:08 -0000 @@ -93,16 +93,14 @@ void gre_print(const u_char *p, u_int length) { uint16_t vers; - int l; + int l = snapend - p; - l = snapend - p; + if (l < sizeof(vers)) + goto trunc; + if (length < sizeof(vers)) + goto iptrunc; - if (l < sizeof(vers)) { - printf("[|gre]"); - return; - } vers = EXTRACT_16BITS(p) & GRE_VERS; - switch (vers) { case 0: gre_print_0(p, length); @@ -114,23 +112,28 @@ gre_print(const u_char *p, u_int length) printf("gre-unknown-version=%u", vers); break; } + return; + +trunc: + printf("GRE [|gre]"); + return; +iptrunc: + printf("GRE ip truncated"); } void gre_print_0(const u_char *p, u_int length) { uint16_t flags, proto; - u_int l; + u_int l = snapend - p; - l = snapend - p; + printf("GRE"); flags = EXTRACT_16BITS(p); p += sizeof(flags); l -= sizeof(flags); length -= sizeof(flags); - printf("gre"); - if (vflag) { printf(" [%s%s%s%s%s]", (flags & GRE_CP) ? "C" : "", @@ -142,17 +145,18 @@ gre_print_0(const u_char *p, u_int lengt if (l < sizeof(proto)) goto trunc; + if (length < sizeof(proto)) + goto iptrunc; + proto = EXTRACT_16BITS(p); p += sizeof(proto); l -= sizeof(proto); length -= sizeof(proto); - if (vflag) - printf(" %04x", proto); - if ((flags & GRE_CP) | (flags & GRE_RP)) { if (l < 2) goto trunc; + if (length < 2) if ((flags & GRE_CP) && vflag) printf(" sum 0x%x", EXTRACT_16BITS(p)); p += 2; @@ -221,7 +225,7 @@ gre_print_0(const u_char *p, u_int lengt } } - printf(" "); + printf("%s", layersep); switch (packettype) { case PT_ERSPAN: @@ -295,16 +299,17 @@ gre_print_0(const u_char *p, u_int lengt return; trunc: - printf("[|gre]"); + printf(" [|gre]"); + return; +iptrunc: + printf(" ip truncated"); } void gre_print_1(const u_char *p, u_int length) { uint16_t flags, proto; - int l; - - l = snapend - p; + int l = snapend - p; flags = EXTRACT_16BITS(p); p += sizeof(flags); @@ -313,6 +318,8 @@ gre_print_1(const u_char *p, u_int lengt if (l < sizeof(proto)) goto trunc; + if (length < sizeof(proto)) + goto iptrunc; proto = EXTRACT_16BITS(p); p += sizeof(proto); @@ -328,25 +335,27 @@ gre_print_1(const u_char *p, u_int lengt gre_print_eoip(p, length, flags); break; default: - printf("unknown-gre1-proto-%04x", proto); + printf("GREv1 flags 0x%04x proto 0x%04x len %u", + flags, proto, length); break; } return; trunc: - printf("[|gre1]"); + printf("GREv1 [|gre]"); + return; +iptrunc: + printf("GREv1 ip truncated"); } void gre_print_pptp(const u_char *p, u_int length, uint16_t flags) { uint16_t len; - int l; - - l = snapend - p; + int l = snapend - p; - printf("pptp"); + printf("PPTP"); if (vflag) { printf(" [%s%s%s%s%s%s]", @@ -378,16 +387,19 @@ gre_print_pptp(const u_char *p, u_int le /* GRE_KP */ if (l < sizeof(len)) goto trunc; + if (length < sizeof(len)) + goto iptrunc; + len = EXTRACT_16BITS(p); p += sizeof(len); l -= sizeof(len); length -= sizeof(len); - if (vflag) - printf(" len %u", EXTRACT_16BITS(p)); - if (l < 2) goto trunc; + if (length < 2) + goto iptrunc; + printf(" callid %u", EXTRACT_16BITS(p)); p += 2; l -= 2; @@ -414,30 +426,33 @@ gre_print_pptp(const u_char *p, u_int le if ((flags & GRE_SP) == 0) return; - if (length < len) { - (void)printf(" truncated-pptp - %d bytes missing!", - len - length); + if (vflag) + printf(" len %u", len); + + if (length < len) { + printf(" truncated-pptp - %d bytes missing!", len - length); len = length; } - printf(": "); + printf("%s", layersep); ppp_hdlc_print(p, len); return; trunc: - printf("[|pptp]"); + printf(" [|pptp]"); + return; +iptrunc: + printf(" ip truncated"); } void gre_print_eoip(const u_char *p, u_int length, uint16_t flags) { uint16_t len, id; - int l; - - l = snapend - p; + int l = snapend - p; - printf("eoip"); + printf("EoIP"); flags &= ~GRE_VERS; if (flags != GRE_KP) { @@ -447,6 +462,8 @@ gre_print_eoip(const u_char *p, u_int le if (l < sizeof(len)) goto trunc; + if (length < sizeof(len)) + goto iptrunc; len = EXTRACT_16BITS(p); p += sizeof(len); @@ -455,34 +472,37 @@ gre_print_eoip(const u_char *p, u_int le if (l < sizeof(id)) goto trunc; + if (length < sizeof(id)) + goto iptrunc; id = EXTRACT_LE_16BITS(p); p += sizeof(id); l -= sizeof(id); length -= sizeof(id); + printf(" tunnel-id %u", id); if (vflag) - printf(" len=%u tunnel-id=%u", len, id); - else - printf(" %u", id); - - if (length < len) { - (void)printf(" truncated-eoip - %d bytes missing!", - len - length); + printf(" len %u", len); + + if (length < len) { + printf(" truncated-eoip - %d bytes missing!", len - length); len = length; } - printf(": "); - - if (len == 0) - printf("keepalive"); - else - ether_tryprint(p, len, 0); + if (len == 0) { + printf(": keepalive"); + return; + } + printf("%s", layersep); + ether_tryprint(p, len, 0); return; trunc: - printf("[|eoip]"); + printf(" [|eoip]"); + return; +iptrunc: + printf(" ip truncated"); } #define ERSPAN2_VER_SHIFT 28 @@ -748,7 +768,7 @@ vxlan_print(const u_char *p, u_int lengt return; } - printf(": "); + printf("%s", layersep); switch (proto) { case VXLAN_PROTO_RESERVED: Index: print-icmp.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/print-icmp.c,v retrieving revision 1.25 diff -u -p -r1.25 print-icmp.c --- print-icmp.c 16 Jan 2015 06:40:21 -0000 1.25 +++ print-icmp.c 3 Dec 2019 11:52:08 -0000 @@ -163,10 +163,9 @@ struct id_rdiscovery { }; void -icmp_print(const u_char *bp, u_int length, const u_char *bp2) +icmp_print(const u_char *bp, u_int length) { const struct icmp *dp; - const struct ip *ip; const char *str, *fmt; const struct ip *oip; const struct udphdr *ouh; @@ -175,12 +174,7 @@ icmp_print(const u_char *bp, u_int lengt char buf2[HOST_NAME_MAX+1+256]; dp = (struct icmp *)bp; - ip = (struct ip *)bp2; str = buf; - - (void)printf("%s > %s: ", - ipaddr_string(&ip->ip_src), - ipaddr_string(&ip->ip_dst)); TCHECK(dp->icmp_code); if (qflag) Index: print-icmp6.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/print-icmp6.c,v retrieving revision 1.22 diff -u -p -r1.22 print-icmp6.c --- print-icmp6.c 22 Oct 2018 16:12:45 -0000 1.22 +++ print-icmp6.c 3 Dec 2019 11:52:08 -0000 @@ -122,39 +122,26 @@ icmp6_cksum(const struct ip6_hdr *ip6, c } void -icmp6_print(const u_char *bp, u_int length, const u_char *bp2) +icmp6_print(const struct ip_hdrinfo *iph, const u_char *bp, u_int length) { const struct icmp6_hdr *dp; - const struct ip6_hdr *ip; const char *str; const struct ip6_hdr *oip; const struct udphdr *ouh; int hlen, dport; const u_char *ep; char buf[256]; - int icmp6len; + int icmp6len = length; -#if 0 -#define TCHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) goto trunc +#ifdef notyet + printf("ICMPv6"); #endif dp = (struct icmp6_hdr *)bp; - ip = (struct ip6_hdr *)bp2; oip = (struct ip6_hdr *)(dp + 1); str = buf; /* 'ep' points to the end of avaible data. */ ep = snapend; - if (ip->ip6_plen) - icmp6len = (ntohs(ip->ip6_plen) + sizeof(struct ip6_hdr) - - (bp - bp2)); - else /* XXX: jumbo payload case... */ - icmp6len = snapend - bp; - -#if 0 - (void)printf("%s > %s: ", - ip6addr_string(&ip->ip6_src), - ip6addr_string(&ip->ip6_dst)); -#endif TCHECK(dp->icmp6_code); switch (dp->icmp6_type) { @@ -498,7 +485,7 @@ icmp6_print(const u_char *bp, u_int leng if (vflag) { if (TTEST2(dp->icmp6_type, length)) { u_int16_t sum, icmp6_sum; - sum = icmp6_cksum(ip, dp, length); + sum = icmp6_cksum(iph->hdr, dp, length); if (sum != 0) { icmp6_sum = EXTRACT_16BITS(&dp->icmp6_cksum); printf(" [bad icmp6 cksum %x! -> %x]", icmp6_sum, Index: print-igrp.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/print-igrp.c,v retrieving revision 1.8 diff -u -p -r1.8 print-igrp.c --- print-igrp.c 16 Nov 2015 00:16:39 -0000 1.8 +++ print-igrp.c 3 Dec 2019 11:52:08 -0000 @@ -76,19 +76,16 @@ static struct tok op2str[] = { }; void -igrp_print(const u_char *bp, u_int length, const u_char *bp2) +igrp_print(const u_char *bp, u_int length) { struct igrphdr *hdr; - struct ip *ip; u_char *cp; u_int nint, nsys, next; + printf("IGRP"); + hdr = (struct igrphdr *)bp; - ip = (struct ip *)bp2; cp = (u_char *)(hdr + 1); - (void)printf("%s > %s: igrp: ", - ipaddr_string(&ip->ip_src), - ipaddr_string(&ip->ip_dst)); /* Header */ TCHECK(*hdr); @@ -129,5 +126,5 @@ igrp_print(const u_char *bp, u_int lengt if (nint == 0 && nsys == 0 && next == 0) return; trunc: - fputs("[|igrp]", stdout); + printf(" [|igrp]"); } Index: print-ip.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/print-ip.c,v retrieving revision 1.52 diff -u -p -r1.52 print-ip.c --- print-ip.c 19 Sep 2019 23:23:58 -0000 1.52 +++ print-ip.c 3 Dec 2019 11:52:08 -0000 @@ -146,15 +146,8 @@ static void print_mresp(const u_char *bp } static void -igmp_print(const u_char *bp, u_int len, const u_char *bp2) +igmp_print(const u_char *bp, u_int len) { - const struct ip *ip; - - ip = (const struct ip *)bp2; - (void)printf("%s > %s: ", - ipaddr_string(&ip->ip_src), - ipaddr_string(&ip->ip_dst)); - TCHECK2(bp[0], 8); switch (bp[0]) { case 0x11: @@ -311,27 +304,185 @@ trunc: printf("[|ip]"); } +static uint32_t +ipv4_pseudo_cksum(const struct ip_hdrinfo *iph, uint8_t proto, uint16_t len) +{ + union phu { + struct phdr { + struct in_addr src; + struct in_addr dst; + u_char mbz; + u_char proto; + uint16_t len; + } ph; + u_int16_t pa[6]; + } phu; + const struct ip *ip = iph->hdr; + const uint16_t *sp; + uint32_t sum; + + /* pseudo-header.. */ + phu.ph.src = ip->ip_src; + phu.ph.dst = ip->ip_dst; + phu.ph.len = htons(len); + phu.ph.mbz = 0; + phu.ph.proto = proto; + + sp = &phu.pa[0]; + sum = sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]; + + return (sum); +} + +static void ipv4_proto_print(struct ip_hdrinfo *, int, + const u_char *, u_int); + +static void +ipv4_print(const u_char *bp, u_int length) +{ + const struct ip *ip; + u_int hlen, len, off; + int l = snapend - bp; + + struct ip_hdrinfo iph = { + .print_proto = ipv4_proto_print, + .pseudo_cksum = ipv4_pseudo_cksum, + }; + + printf("IPv4"); + + if (l < sizeof(*ip)) + goto trunc; + if (length < sizeof(*ip)) + goto iptrunc; + + ip = (struct ip *)bp; + if (ip->ip_v != IPVERSION) { + printf(" bad-ip-version %u", ip->ip_v); + return; + } + + len = ntohs(ip->ip_len); + if (length < len) { + printf(" truncated-ip - %d bytes missing!", len - length); + len = length; + } + + hlen = ip->ip_hl * 4; + if (hlen < sizeof(struct ip) || hlen > len) { + printf(" bad-hlen %d", hlen); + return; + } + if (l < hlen) + goto trunc; + if (len < hlen) + goto iptrunc; + + bp += hlen; + len -= hlen; + + if (vflag || ip->ip_ttl <= 1) + printf(" ttl %d", (int)ip->ip_ttl); + + off = ntohs(ip->ip_off); + if (off & IP_DF) + printf(" (DF)"); + + if (ip->ip_tos) { + printf(" [tos 0x%x", (int)ip->ip_tos); + if (ip->ip_tos & (IPTOS_CE|IPTOS_ECT)) { + printf(" ("); + if (ip->ip_tos & IPTOS_ECT) { /* XXX */ + /* ECN-capable transport */ + putchar('E'); + } + if (ip->ip_tos & IPTOS_CE) { + /* _C_ongestion experienced (ECN) */ + putchar('C'); + } + printf(")"); + } + printf("]"); + } + + if (vflag) { + char *sep = ""; + + printf(" ("); + if ((off & 0x3fff) == 0) { + (void)printf("%sid %d", sep, (int)ntohs(ip->ip_id)); + sep = ", "; + } + (void)printf("%slen %u", sep, ntohs(ip->ip_len)); + sep = ", "; + if ((u_char *)ip + hlen <= snapend) { + u_int16_t sum, ip_sum; + sum = in_cksum((const u_short *)ip, hlen, 0); + if (sum != 0) { + ip_sum = EXTRACT_16BITS(&ip->ip_sum); + printf("%sbad ip cksum %x! -> %x", sep, ip_sum, + in_cksum_shouldbe(ip_sum, sum)); + sep = ", "; + } + } + if (hlen > sizeof(*ip)) { + hlen -= sizeof(*ip); + printf("%soptlen=%d", sep, hlen); + ip_optprint((u_char *)(ip + 1), hlen); + } + printf(")"); + } + + /* + * For fragmented datagrams, print id:size@offset. On all + * but the last stick a "+". + */ + if (off & 0x3fff) { + iph.frag = 1; + printf(" (frag %d:%d@%d%s)", ntohs(ip->ip_id), len, + (off & 0x1fff) * 8, (off & IP_MF)? "+" : ""); + } + + iph.src = ipaddr_string(&ip->ip_src); + iph.dst = ipaddr_string(&ip->ip_dst); + + /* + * If this is fragment zero, hand it to the next higher + * level protocol. + */ + if ((off & 0x1fff) == 0) { + iph.hdr = ip; + iph.ttl = ip->ip_ttl; + + printf(" "); + ip_hdrinfo_print(&iph, ip->ip_p, bp, len); + } else + printf(" %s > %s", iph.src, iph.dst); + return; + +trunc: + printf(" [|ip]"); + return; +iptrunc: + printf(" truncated-ip %u", length); + +} + /* * print an IP datagram. */ void ip_print(const u_char *bp, u_int length) { - const struct ip *ip; - u_int hlen, len, off; - const u_char *cp; const u_char *pktp = packetp; const u_char *send = snapend; - TCHECK2(bp[0], 1); - ip = (const struct ip *)bp; - /* * If the IP header is not aligned, copy into abuf. * This will never happen with BPF. It does happen with raw packet * dumps from -r. */ - if ((intptr_t)ip & (sizeof(u_int32_t)-1)) { + if ((intptr_t)bp & ((sizeof(u_int32_t))-1)) { static u_char *abuf = NULL; static int didwarn = 0; int clen = snapend - bp; @@ -343,10 +494,9 @@ ip_print(const u_char *bp, u_int length) if (abuf == NULL) error("ip_print: malloc"); } - memmove((char *)abuf, (char *)ip, min(length, clen)); + memmove(abuf, bp, min(length, clen)); snapend = abuf + clen; - packetp = abuf; - ip = (struct ip *)abuf; + packetp = bp = abuf; /* We really want libpcap to give us aligned packets */ if (!didwarn) { warning("compensating for unaligned libpcap packets"); @@ -354,280 +504,142 @@ ip_print(const u_char *bp, u_int length) } } - TCHECK(*ip); - if (ip->ip_v != IPVERSION) { - (void)printf("bad-ip-version %u", ip->ip_v); - goto out; - } - - len = ntohs(ip->ip_len); - if (length < len) { - (void)printf("truncated-ip - %d bytes missing!", - len - length); - len = length; - } - - hlen = ip->ip_hl * 4; - if (hlen < sizeof(struct ip) || hlen > len) { - (void)printf("bad-hlen %d", hlen); - goto out; - } - - len -= hlen; + ipv4_print(bp, length); - /* - * If this is fragment zero, hand it to the next higher - * level protocol. - */ - off = ntohs(ip->ip_off); - if ((off & 0x1fff) == 0) { - cp = (const u_char *)ip + hlen; - if (cp > snapend) - goto trunc; - switch (ip->ip_p) { + packetp = pktp; + snapend = send; + return; +} - case IPPROTO_TCP: - tcp_print(cp, len, (const u_char *)ip); - break; +static void +ipv4_proto_print(struct ip_hdrinfo *iph, int proto, + const u_char *cp, u_int len) +{ + switch (proto) { +#ifndef IPPROTO_AH +#define IPPROTO_AH 51 +#endif + case IPPROTO_AH: + ah_print(iph, cp, len); + return; - case IPPROTO_UDP: - udp_print(cp, len, (const u_char *)ip); - break; +#ifndef IPPROTO_ESP +#define IPPROTO_ESP 50 +#endif + case IPPROTO_ESP: + esp_print(iph, cp, len); + return; + + case IPPROTO_TCP: + tcp_print(iph, cp, len); + return; + case IPPROTO_UDP: + udp_print(iph, cp, len); + return; + } + + printf("%s > %s: ", iph->src, iph->dst); + + switch (proto) { + case IPPROTO_ICMP: + icmp_print(cp, len); + return; - case IPPROTO_ICMP: - icmp_print(cp, len, (const u_char *)ip); - break; +#ifndef IPPROTO_PFSYNC +#define IPPROTO_PFSYNC 240 +#endif + case IPPROTO_PFSYNC: + pfsync_ip_print(cp, len); + return; #ifndef IPPROTO_IGRP #define IPPROTO_IGRP 9 #endif - case IPPROTO_IGRP: - igrp_print(cp, len, (const u_char *)ip); - break; - - case IPPROTO_ND: - (void)printf("%s > %s:", ipaddr_string(&ip->ip_src), - ipaddr_string(&ip->ip_dst)); - (void)printf(" nd %d", len); - break; + case IPPROTO_IGRP: + igrp_print(cp, len); + return; + + case IPPROTO_ND: + printf("nd %d", len); + return; #ifndef IPPROTO_OSPF #define IPPROTO_OSPF 89 #endif - case IPPROTO_OSPF: - ospf_print(cp, len, (const u_char *)ip); - break; + case IPPROTO_OSPF: + ospf_print(cp, len); + return; #ifndef IPPROTO_IGMP #define IPPROTO_IGMP 2 #endif - case IPPROTO_IGMP: - igmp_print(cp, len, (const u_char *)ip); - break; + case IPPROTO_IGMP: + igmp_print(cp, len); + return; + +#ifndef IPPROTO_MOBILE +#define IPPROTO_MOBILE 55 +#endif + case IPPROTO_MOBILE: + mobile_print(cp, len); + return; + } + + ip_proto_print(iph, proto, cp, len); +} +void +ip_proto_print(const struct ip_hdrinfo *iph, int proto, + const u_char *cp, u_int len) +{ + switch (proto) { #ifndef IPPROTO_IPIP #define IPPROTO_IPIP 4 #endif - case IPPROTO_IPIP: - /* ip-in-ip encapsulation */ - if (vflag) - (void)printf("%s > %s: ", - ipaddr_string(&ip->ip_src), - ipaddr_string(&ip->ip_dst)); - ip_print(cp, len); - if (! vflag) { - printf(" (encap)"); - goto out; - } - break; + case IPPROTO_IPIP: + ip_print(cp, len); + return; #ifndef IPPROTO_IPV6 #define IPPROTO_IPV6 41 #endif - case IPPROTO_IPV6: - /* ip6-in-ip encapsulation */ - if (vflag) - (void)printf("%s > %s: ", - ipaddr_string(&ip->ip_src), - ipaddr_string(&ip->ip_dst)); - ip6_print(cp, len); - if (! vflag) { - printf(" (encap)"); - goto out; - } - break; - -#ifndef IPPROTO_GRE -#define IPPROTO_GRE 47 -#endif - case IPPROTO_GRE: - (void)printf("%s > %s: ", - ipaddr_string(&ip->ip_src), - ipaddr_string(&ip->ip_dst)); - /* do it */ - gre_print(cp, len); - break; - -#ifndef IPPROTO_ESP -#define IPPROTO_ESP 50 -#endif - case IPPROTO_ESP: - (void)printf("%s > %s: ", - ipaddr_string(&ip->ip_src), - ipaddr_string(&ip->ip_dst)); - esp_print(cp, len, (const u_char *)ip); - break; - -#ifndef IPPROTO_AH -#define IPPROTO_AH 51 -#endif - case IPPROTO_AH: - ah_print(cp, len, (const u_char *)ip); - break; - -#ifndef IPPROTO_MOBILE -#define IPPROTO_MOBILE 55 -#endif - case IPPROTO_MOBILE: - if (vflag) - (void)printf("mobile %s > %s: ", - ipaddr_string(&ip->ip_src), - ipaddr_string(&ip->ip_dst)); - mobile_print(cp, len); - if (! vflag) { - printf(" (mobile encap)"); - goto out; - } - break; + case IPPROTO_IPV6: + /* ip6-in-ip encapsulation */ + ip6_print(cp, len); + return; #ifndef IPPROTO_ETHERIP #define IPPROTO_ETHERIP 97 #endif - case IPPROTO_ETHERIP: - (void)printf("%s > %s: ", - ipaddr_string(&ip->ip_src), - ipaddr_string(&ip->ip_dst)); - etherip_print(cp, snapend - cp, len); - break; + case IPPROTO_ETHERIP: + etherip_print(cp, snapend - cp, len); + return; + +#ifndef IPPROTO_GRE +#define IPPROTO_GRE 47 +#endif + case IPPROTO_GRE: + gre_print(cp, len); + return; #ifndef IPPROTO_IPCOMP #define IPPROTO_IPCOMP 108 #endif - case IPPROTO_IPCOMP: - ipcomp_print(cp, len, (const u_char *)ip); - break; + case IPPROTO_IPCOMP: + ipcomp_print(cp, len); + return; #ifndef IPPROTO_CARP #define IPPROTO_CARP 112 #endif - case IPPROTO_CARP: - if (packettype == PT_VRRP) { - if (vflag) - (void)printf("vrrp %s > %s: ", - ipaddr_string(&ip->ip_src), - ipaddr_string(&ip->ip_dst)); - vrrp_print(cp, len, ip->ip_ttl); - } else { - if (vflag) - (void)printf("carp %s > %s: ", - ipaddr_string(&ip->ip_src), - ipaddr_string(&ip->ip_dst)); - carp_print(cp, len, ip->ip_ttl); - } - break; - -#ifndef IPPROTO_PFSYNC -#define IPPROTO_PFSYNC 240 -#endif - case IPPROTO_PFSYNC: - pfsync_ip_print(cp, - (int)(snapend - (u_char *)ip) - hlen, - (const u_char *)ip); - break; - - default: - (void)printf("%s > %s:", ipaddr_string(&ip->ip_src), - ipaddr_string(&ip->ip_dst)); - (void)printf(" ip-proto-%d %d", ip->ip_p, len); - break; + case IPPROTO_CARP: + if (packettype == PT_VRRP) { + vrrp_print(cp, len, iph->ttl); + } else { + carp_print(cp, len, iph->ttl); } + return; } - /* - * for fragmented datagrams, print id:size@offset. On all - * but the last stick a "+". For unfragmented datagrams, note - * the don't fragment flag. - */ - if (off & 0x3fff) { - /* - * if this isn't the first frag, we're missing the - * next level protocol header. print the ip addr. - */ - if (off & 0x1fff) - (void)printf("%s > %s:", ipaddr_string(&ip->ip_src), - ipaddr_string(&ip->ip_dst)); - (void)printf(" (frag %d:%d@%d%s)", ntohs(ip->ip_id), len, - (off & 0x1fff) * 8, - (off & IP_MF)? "+" : ""); - } - if (off & IP_DF) - (void)printf(" (DF)"); - if (ip->ip_tos) { - (void)printf(" [tos 0x%x", (int)ip->ip_tos); - if (ip->ip_tos & (IPTOS_CE|IPTOS_ECT)) { - (void)printf(" ("); - if (ip->ip_tos & IPTOS_ECT) { - /* ECN-capable transport */ - putchar('E'); - } - if (ip->ip_tos & IPTOS_CE) { - /* _C_ongestion experienced (ECN) */ - putchar('C'); - } - (void)printf(")"); - } - (void)printf("]"); - } - - if (ip->ip_ttl <= 1) - (void)printf(" [ttl %d]", (int)ip->ip_ttl); - - if (vflag) { - char *sep = ""; - - printf(" ("); - if (ip->ip_ttl > 1) { - (void)printf("%sttl %d", sep, (int)ip->ip_ttl); - sep = ", "; - } - if ((off & 0x3fff) == 0) { - (void)printf("%sid %d", sep, (int)ntohs(ip->ip_id)); - sep = ", "; - } - (void)printf("%slen %u", sep, ntohs(ip->ip_len)); - sep = ", "; - if ((u_char *)ip + hlen <= snapend) { - u_int16_t sum, ip_sum; - sum = in_cksum((const u_short *)ip, hlen, 0); - if (sum != 0) { - ip_sum = EXTRACT_16BITS(&ip->ip_sum); - (void)printf("%sbad ip cksum %x! -> %x", sep, ip_sum, - in_cksum_shouldbe(ip_sum, sum)); - sep = ", "; - } - } - if (hlen > sizeof(struct ip)) { - hlen -= sizeof(struct ip); - (void)printf("%soptlen=%d", sep, hlen); - ip_optprint((u_char *)(ip + 1), hlen); - } - printf(")"); - } -out: - packetp = pktp; - snapend = send; - return; - -trunc: - printf("[|ip]"); + printf("ip-proto-%d %u", proto, len); } Index: print-ip6.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/print-ip6.c,v retrieving revision 1.29 diff -u -p -r1.29 print-ip6.c --- print-ip6.c 19 Sep 2019 23:23:58 -0000 1.29 +++ print-ip6.c 3 Dec 2019 11:52:08 -0000 @@ -43,48 +43,128 @@ #include +static uint32_t +ipv6_pseudo_cksum(const struct ip_hdrinfo *iph, uint8_t proto, uint16_t len) +{ + union { + struct { + struct in6_addr ph_src; + struct in6_addr ph_dst; + u_int32_t ph_len; + u_int8_t ph_zero[3]; + u_int8_t ph_nxt; + } ph; + u_int16_t pa[20]; + } phu; + const struct ip6_hdr *ip6 = iph->hdr; + size_t i; + u_int32_t sum = 0; + + /* pseudo-header */ + memset(&phu, 0, sizeof(phu)); + phu.ph.ph_src = ip6->ip6_src; + phu.ph.ph_dst = ip6->ip6_dst; + phu.ph.ph_len = htonl(len); + phu.ph.ph_nxt = proto; + + for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++) + sum += phu.pa[i]; + + return (sum); +} + +static void +ipv6_proto_print(struct ip_hdrinfo *, int, const u_char *, u_int); + /* * print an IP6 datagram. */ void -ip6_print(const u_char *bp, u_int length) +ipv6_print(const u_char *bp, u_int length) { const struct ip6_hdr *ip6; - int hlen; - int len; - const u_char *cp; - const u_char *pktp = packetp; - const u_char *send = snapend; - int nh; + u_int len; u_int flow; + int l = snapend - bp; + + struct ip_hdrinfo iph = { + .print_proto = ipv6_proto_print, + .pseudo_cksum = ipv6_pseudo_cksum, + }; + + printf("IPv6"); + + if (l < sizeof(*ip6)) { + printf(" [|ip6]"); + return; + } + if (length < sizeof(*ip6)) { + printf(" truncated-ip6 %d", length); + return; + } ip6 = (const struct ip6_hdr *)bp; - if ((u_char *)(ip6 + 1) > snapend) { - printf("[|ip6]"); + bp += sizeof(*ip6); + length -= sizeof(*ip6); + + if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { + printf(" bad-ip6-version %u", ip6->ip6_vfc >> 4); return; } + len = ntohs(ip6->ip6_plen); + if (length < len) { + printf(" truncated-ip6 - %d bytes missing!", len - length); + len = length; + } + + if (vflag || ip6->ip6_hlim <= 1) + printf(" hlim %d", (int)ip6->ip6_hlim); + + flow = ntohl(ip6->ip6_flow); + if (flow & 0x0ff00000) + printf(" [class 0x%x]", (flow & 0x0ff00000) >> 20); + if (flow & 0x000fffff) + printf(" [flowlabel 0x%x]", flow & 0x000fffff); + + if (vflag) + printf(" (len %u)", len); + + iph.src = ip6addr_string(&ip6->ip6_src); + iph.dst = ip6addr_string(&ip6->ip6_dst); + iph.hdr = ip6; + iph.ttl = ip6->ip6_hlim; + + printf(" "); + ip_hdrinfo_print(&iph, ip6->ip6_nxt, bp, len); +} + +void +ip6_print(const u_char *bp, u_int length) +{ + const u_char *pktp = packetp; + const u_char *send = snapend; + /* - * The IP header is not word aligned, so copy into abuf. - * This will never happen with BPF. It does happen with - * raw packet dumps from -r. + * If the IP header is not aligned, copy into abuf. + * This will never happen with BPF. It does happen with raw packet + * dumps from -r. */ - if ((intptr_t)ip6 & (sizeof(u_int32_t)-1)) { + if ((intptr_t)bp & ((sizeof(u_int32_t))-1)) { static u_char *abuf = NULL; static int didwarn = 0; int clen = snapend - bp; + if (clen > snaplen) clen = snaplen; - if (abuf == NULL) { abuf = malloc(snaplen); if (abuf == NULL) error("ip6_print: malloc"); } - memmove((char *)abuf, (char *)ip6, min(length, clen)); + memmove(abuf, bp, min(length, clen)); snapend = abuf + clen; packetp = bp = abuf; - ip6 = (struct ip6_hdr *)abuf; /* We really want libpcap to give us aligned packets */ if (!didwarn) { warning("compensating for unaligned libpcap packets"); @@ -92,153 +172,61 @@ ip6_print(const u_char *bp, u_int length } } - if (length < sizeof (struct ip6_hdr)) { - (void)printf("truncated-ip6 %d", length); - goto out; - } - if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { - (void)printf("bad-ip6-version %u", ip6->ip6_vfc >> 4); - goto out; - } - hlen = sizeof(struct ip6_hdr); + ipv6_print(bp, length); - len = ntohs(ip6->ip6_plen); - if (length < len + hlen) - (void)printf("truncated-ip6 - %d bytes missing!", - len + hlen - length); - - cp = (const u_char *)ip6; - nh = ip6->ip6_nxt; - while (cp + hlen <= snapend) { - cp += hlen; - -#ifndef IPPROTO_IPV4 -#define IPPROTO_IPV4 4 -#endif - if (cp == (u_char *)(ip6 + 1) && - nh != IPPROTO_TCP && nh != IPPROTO_UDP && - nh != IPPROTO_AH && - (vflag || (nh != IPPROTO_IPV4 && nh != IPPROTO_IPV6))) { - (void)printf("%s > %s: ", ip6addr_string(&ip6->ip6_src), - ip6addr_string(&ip6->ip6_dst)); - } - - switch (nh) { - case IPPROTO_HOPOPTS: - hlen = hbhopt_print(cp); - nh = *cp; - break; - case IPPROTO_DSTOPTS: - hlen = dstopt_print(cp); - nh = *cp; - break; - case IPPROTO_FRAGMENT: - hlen = frag6_print(cp, (const u_char *)ip6); - if (snapend < cp + hlen) - goto end; - nh = *cp; - break; - case IPPROTO_ROUTING: - hlen = rt6_print(cp, (const u_char *)ip6); - nh = *cp; - break; - case IPPROTO_TCP: - tcp_print(cp, len + sizeof(struct ip6_hdr) - (cp - bp), - (const u_char *)ip6); - goto end; - case IPPROTO_UDP: - udp_print(cp, len + sizeof(struct ip6_hdr) - (cp - bp), - (const u_char *)ip6); - goto end; - case IPPROTO_ESP: - esp_print(cp, len + sizeof(struct ip6_hdr) - (cp - bp), - (const u_char *)ip6); - goto end; - case IPPROTO_AH: - ah_print(cp, len + sizeof(struct ip6_hdr) - (cp - bp), - (const u_char *)ip6); - goto end; - case IPPROTO_ICMPV6: - icmp6_print(cp, len + sizeof(struct ip6_hdr) - (cp - bp), - (const u_char *)ip6); - goto end; - case IPPROTO_PIM: - (void)printf("PIM"); - pim_print(cp, len); - goto end; -#ifndef IPPROTO_OSPF -#define IPPROTO_OSPF 89 -#endif - case IPPROTO_OSPF: - ospf6_print(cp, len); - goto end; - case IPPROTO_IPV6: - ip6_print(cp, len); - if (! vflag) - printf(" (encap)"); - goto end; - case IPPROTO_IPV4: - ip_print(cp, len); - if (! vflag) - printf(" (encap)"); - goto end; - -#ifndef IPPROTO_GRE -#define IPPROTO_GRE 47 -#endif - case IPPROTO_GRE: - gre_print(cp, len); - goto end; - - case IPPROTO_NONE: - (void)printf("no next header"); - goto end; + packetp = pktp; + snapend = send; + return; +} -#ifndef IPPROTO_ETHERIP -#define IPPROTO_ETHERIP 97 -#endif - case IPPROTO_ETHERIP: - etherip_print(cp, snapend - cp, len); - goto end; +static void +ipv6_proto_print(struct ip_hdrinfo *iph, int proto, + const u_char *cp, u_int length) +{ + switch (proto) { + case IPPROTO_TCP: + tcp_print(iph, cp, length); + return; + case IPPROTO_UDP: + udp_print(iph, cp, length); + return; + case IPPROTO_ESP: + esp_print(iph, cp, length); + return; + case IPPROTO_AH: + ah_print(iph, cp, length); + return; -#ifndef IPPROTO_CARP -#define IPPROTO_CARP 112 -#endif - case IPPROTO_CARP: - if (packettype == PT_VRRP) - vrrp_print(cp, len, ip6->ip6_hlim); - else - carp_print(cp, len, ip6->ip6_hlim); - break; - - default: - (void)printf("ip-proto-%d %d", ip6->ip6_nxt, len); - goto end; - } - if (hlen == 0) - break; + case IPPROTO_HOPOPTS: + hbhopt_print(iph, cp, length); + return; + case IPPROTO_DSTOPTS: + dstopt_print(iph, cp, length); + return; + case IPPROTO_FRAGMENT: + frag6_print(iph, cp, length); + return; + case IPPROTO_ROUTING: + rt6_print(iph, cp, length); + return; } - end: - - flow = ntohl(ip6->ip6_flow); - if (flow & 0x0ff00000) - (void)printf(" [class 0x%x]", (flow & 0x0ff00000) >> 20); - if (flow & 0x000fffff) - (void)printf(" [flowlabel 0x%x]", flow & 0x000fffff); - - if (ip6->ip6_hlim <= 1) - (void)printf(" [hlim %d]", (int)ip6->ip6_hlim); + printf("%s > %s: ", iph->src, iph->dst); - if (vflag) { - printf(" ("); - (void)printf("len %d", len); - if (ip6->ip6_hlim > 1) - (void)printf(", hlim %d", (int)ip6->ip6_hlim); - printf(")"); + switch (proto) { + case IPPROTO_ICMPV6: + icmp6_print(iph, cp, length); + return; +#ifndef IPPROTO_OSPF +#define IPPROTO_OSPF 89 +#endif + case IPPROTO_OSPF: + ospf6_print(cp, length); + return; + case IPPROTO_NONE: + printf("none"); + return; } - out: - packetp = pktp; - snapend = send; + ip_proto_print(iph, proto, cp, length); } Index: print-ip6opts.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/print-ip6opts.c,v retrieving revision 1.6 diff -u -p -r1.6 print-ip6opts.c --- print-ip6opts.c 22 Oct 2018 16:12:45 -0000 1.6 +++ print-ip6opts.c 3 Dec 2019 11:52:08 -0000 @@ -42,111 +42,133 @@ #include "addrtoname.h" void -ip6_opt_print(const u_char *bp, int len) +ip6_opt_print(const u_char *bp, u_int len) { - int i; - int optlen; + u_int i; + u_int optlen; - for (i = 0; i < len; i += optlen) { - switch (bp[i]) { - case IP6OPT_PAD1: - optlen = 1; - break; - case IP6OPT_PADN: - if (len - i < IP6OPT_MINLEN) { - printf("(padn: trunc)"); - goto trunc; - } - optlen = bp[i + 1] + 2; - break; - case IP6OPT_ROUTER_ALERT: - if (len - i < IP6OPT_RTALERT_LEN) { - printf("(rtalert: trunc)"); - goto trunc; - } - if (bp[i + 1] != IP6OPT_RTALERT_LEN - 2) { - printf("(rtalert: invalid len %d)", bp[i + 1]); - goto trunc; - } - printf("(rtalert: 0x%04x) ", ntohs(*(u_short *)&bp[i + 2])); - optlen = IP6OPT_RTALERT_LEN; - break; - case IP6OPT_JUMBO: - if (len - i < IP6OPT_JUMBO_LEN) { - printf("(jumbo: trunc)"); - goto trunc; - } - if (bp[i + 1] != IP6OPT_JUMBO_LEN - 2) { - printf("(jumbo: invalid len %d)", bp[i + 1]); - goto trunc; - } - printf("(jumbo: %u) ", (u_int32_t)ntohl(*(u_int *)&bp[i + 2])); - optlen = IP6OPT_JUMBO_LEN; - break; - default: - if (len - i < IP6OPT_MINLEN) { - printf("(type %d: trunc)", bp[i]); + for (i = 0; i < len; i += optlen) { + switch (bp[i]) { + case IP6OPT_PAD1: + optlen = 1; + break; + case IP6OPT_PADN: + if (len - i < IP6OPT_MINLEN) { + printf(" (padn: trunc)"); + return; + } + optlen = bp[i + 1] + 2; + break; + case IP6OPT_ROUTER_ALERT: + if (len - i < IP6OPT_RTALERT_LEN) { + printf(" (rtalert: trunc)"); + return; + } + if (bp[i + 1] != IP6OPT_RTALERT_LEN - 2) { + printf(" (rtalert: invalid len %d)", bp[i + 1]); + return; + } + printf(" (rtalert: 0x%04x)", + ntohs(*(u_short *)&bp[i + 2])); + optlen = IP6OPT_RTALERT_LEN; + break; + case IP6OPT_JUMBO: + if (len - i < IP6OPT_JUMBO_LEN) { + printf(" (jumbo: trunc)"); + return; + } + if (bp[i + 1] != IP6OPT_JUMBO_LEN - 2) { + printf(" (jumbo: invalid len %d)", bp[i + 1]); + return; + } + printf(" (jumbo: %u)", + (u_int32_t)ntohl(*(u_int *)&bp[i + 2])); + optlen = IP6OPT_JUMBO_LEN; + break; + default: + if (len - i < IP6OPT_MINLEN) { + printf(" (type %d: trunc)", bp[i]); + return; + } + printf(" (type 0x%02x: len=%d)", bp[i], bp[i + 1]); + optlen = bp[i + 1] + 2; + break; + } + } +} + +void +hbhopt_print(struct ip_hdrinfo *iph, const u_char *bp, u_int len) +{ + const struct ip6_hbh *dp; + u_int hbhlen; + int l = snapend - bp; + + printf("HBH"); + + if (l < sizeof(*dp)) goto trunc; - } - printf("(type 0x%02x: len=%d) ", bp[i], bp[i + 1]); - optlen = bp[i + 1] + 2; - break; + if (len < sizeof(*dp)) { + printf(" ip truncated"); + return; + } + + dp = (const struct ip6_hbh *)bp; + hbhlen = (dp->ip6h_len + 1) << 3; + if (vflag) + printf(" len %u", hbhlen); + if (l < sizeof(hbhlen)) + goto trunc; + if (len < sizeof(hbhlen)) { + printf(" ip truncated"); + return; } - } + if (vflag) + ip6_opt_print(bp + sizeof(*dp), hbhlen - sizeof(*dp)); -#if 0 -end: -#endif - return; + printf(", "); + + bp += hbhlen; + len -= hbhlen; + + ip_hdrinfo_print(iph, dp->ip6h_nxt, bp, len); + return; trunc: - printf("[trunc] "); + printf(" [|hbh]"); } -int -hbhopt_print(const u_char *bp) +void +dstopt_print(struct ip_hdrinfo *iph, const u_char *bp, u_int len) { - const struct ip6_hbh *dp = (struct ip6_hbh *)bp; - const u_char *ep; - int hbhlen = 0; - - /* 'ep' points to the end of avaible data. */ - ep = snapend; - TCHECK(dp->ip6h_len); - hbhlen = (int)((dp->ip6h_len + 1) << 3); - TCHECK2(*dp, hbhlen); - printf("HBH "); - if (vflag) - ip6_opt_print((const u_char *)dp + sizeof(*dp), hbhlen - sizeof(*dp)); - - return(hbhlen); - - trunc: - fputs("[|HBH]", stdout); - return(hbhlen); -} + const struct ip6_dest *dp; + u_int dstoptlen = 0; + int l = snapend - bp; -int -dstopt_print(const u_char *bp) -{ - const struct ip6_dest *dp = (struct ip6_dest *)bp; - const u_char *ep; - int dstoptlen = 0; - - /* 'ep' points to the end of avaible data. */ - ep = snapend; - TCHECK(dp->ip6d_len); - dstoptlen = (int)((dp->ip6d_len + 1) << 3); - TCHECK2(*dp, dstoptlen); - printf("DSTOPT "); - if (vflag) { - ip6_opt_print((const u_char *)dp + sizeof(*dp), - dstoptlen - sizeof(*dp)); - } - - return(dstoptlen); - - trunc: - fputs("[|DSTOPT]", stdout); - return(dstoptlen); + printf("DSTOPT"); + + if (l < sizeof(*dp)) + goto trunc; + if (l < len) { + printf(" ip truncated"); + return; + } + + dp = (const struct ip6_dest *)bp; + dstoptlen = (dp->ip6d_len + 1) << 3; + if (vflag) + printf(" len %u", dstoptlen); + if (vflag) + ip6_opt_print(bp + sizeof(*dp), dstoptlen - sizeof(*dp)); + + printf(", "); + + bp += dstoptlen; + len -= dstoptlen; + + ip_hdrinfo_print(iph, dp->ip6d_nxt, bp, len); + return; + +trunc: + printf("[|dstopt]"); } Index: print-ipsec.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/print-ipsec.c,v retrieving revision 1.25 diff -u -p -r1.25 print-ipsec.c --- print-ipsec.c 22 Oct 2018 16:12:45 -0000 1.25 +++ print-ipsec.c 3 Dec 2019 11:52:08 -0000 @@ -62,7 +62,7 @@ static int espauthlen = 12; static EVP_CIPHER_CTX ctx; int -esp_init (char *espspec) +esp_init(char *espspec) { const EVP_CIPHER *evp; char *p, *espkey, s[3], name[1024]; @@ -115,32 +115,29 @@ esp_init (char *espspec) return (0); } -void -esp_decrypt (const u_char *bp, u_int len, const u_char *bp2) +static int +esp_decrypt(struct ip_hdrinfo *iph, const const u_char *bp, u_int len) { - const struct ip *ip; u_char *data, pad, nh; int blocksz; - - ip = (const struct ip *)bp2; + int l = snapend - bp; blocksz = EVP_CIPHER_CTX_block_size(&ctx); - /* Skip fragments and short packets */ - if (ntohs(ip->ip_off) & 0x3fff) - return; - if (snapend - bp < len) { - printf(" [|esp]"); - return; + /* Skip short packets */ + if (l < len) { + printf("esp decrypt truncated, "); + return (-1); } + /* * Skip ESP header and ignore authentication trailer. * For decryption we need at least 2 blocks: IV and * one cipher block. */ if (len < sizeof(struct esp_hdr) + espauthlen + 2 * blocksz) { - printf(" [|esp]"); - return; + printf("esp decrypt short, "); + return (-1); } data = (char *)bp; @@ -161,56 +158,47 @@ esp_decrypt (const u_char *bp, u_int len /* verify padding */ if (pad + 2 > len) - return; + return (-1); if (data[len - 3] != pad) - return; - if (vflag > 1) - printf(" pad %d", pad); + return (-1); len -= (pad + 2); - printf(": "); - switch (nh) { - case IPPROTO_TCP: - tcp_print(data, len, bp2); - break; - case IPPROTO_UDP: - udp_print(data, len, bp2); - break; - case IPPROTO_IPV6: - ip6_print(data, len); - break; - case IPPROTO_IPV4: - ip_print(data, len); - break; - case IPPROTO_ICMP: - icmp_print(data, len, bp2); - break; - case IPPROTO_ICMPV6: - icmp6_print(data, len, bp2); - break; - default: - printf("ip-proto-%d %d", nh, len); - break; - } - if (vflag) - printf(" (esp)"); + + ip_hdrinfo_print(iph, nh, data, len); + return (0); } void -esp_print (const u_char *bp, u_int len, const u_char *bp2) +esp_print(struct ip_hdrinfo *iph, const u_char *bp, u_int len) { const struct esp_hdr *esp; + int l = snapend - bp; + + printf("ESP"); - if (len < sizeof(struct esp_hdr)) { - printf("[|esp]"); + if (l < sizeof(*esp)) { + if (iph != NULL) + printf(", %s > %s:", iph->src, iph->dst); + goto trunc; + } + if (len < sizeof(*esp)) { + if (iph != NULL) + printf(", %s > %s:", iph->src, iph->dst); + printf(" ip len %u too short (<%zu)", len, sizeof(*esp)); return; } esp = (const struct esp_hdr *)bp; - printf("esp spi 0x%08x seq %u len %d", + printf(" spi 0x%08x seq %u len %d, ", ntohl(esp->esp_spi), ntohl(esp->esp_seq), len); - if (espinit) - esp_decrypt(bp, len, bp2); + if (!iph->frag && espinit && esp_decrypt(iph, bp, len) == 0) + return; + + if (iph != NULL) + printf("%s > %s", iph->src, iph->dst); + return; +trunc: + printf(" [|esp]"); } /* @@ -225,87 +213,46 @@ struct ah_hdr { }; void -ah_print (const u_char *bp, u_int len, const u_char *bp2) +ah_print(struct ip_hdrinfo *iph, const u_char *bp, u_int len) { - const struct ip *ip; const struct ah_hdr *ah; - u_int pl_len = len; - const struct ip6_hdr *ip6; - - ip = (const struct ip *)bp2; - if (ip->ip_v == 6) { - ip6 = (const struct ip6_hdr *)bp2; - printf("ah %s > %s", ip6addr_string(&ip6->ip6_src), - ip6addr_string(&ip6->ip6_dst)); - } else - printf("ah %s > %s", - ipaddr_string(&ip->ip_src), ipaddr_string(&ip->ip_dst)); + u_int plen; + int l = snapend - bp; - if (pl_len < sizeof(struct ah_hdr)) { - printf("[|ah]"); + printf("AH"); + if (l < sizeof(*ah)) + goto trunc; + if (len < sizeof(*ah)) { + printf(" ip len %u too short (<%zu)", len, sizeof(*ah)); return; } + ah = (const struct ah_hdr *)bp; + printf(" spi 0x%08x seq %u", ntohl(ah->ah_spi), ntohl(ah->ah_seq)); - printf(" spi 0x%08x seq %u len %d", - ntohl(ah->ah_spi), ntohl(ah->ah_seq), len); + plen = (ah->ah_pl_len + 2) << 2; /* RFC2402, sec 2.2 */ + if (l < plen) + goto trunc; + if (len < plen) { + printf(" ip len %u too short (payload len %u)", len, plen); + return; + } - if (vflag) { - (void)printf(" [ "); + bp += plen; + len -= plen; - pl_len = (ah->ah_pl_len + 2) << 2; /* RFC2402, sec 2.2 */ - - if (len <= pl_len) { - (void)printf("truncated"); - goto out; - } - - switch (ah->ah_nxt_hdr) { - - case IPPROTO_IPIP: /* Tunnel Mode, IP-in-IP */ - ip_print(bp + pl_len, len - pl_len); - break; - - case IPPROTO_ICMP: /* From here and down; Transport mode */ - icmp_print(bp + pl_len, len - pl_len, - (const u_char *) ip); - break; - - case IPPROTO_ICMPV6: - icmp6_print(bp + pl_len, len - pl_len, - (const u_char *) ip); - break; - - case IPPROTO_TCP: - tcp_print(bp + pl_len, len - pl_len, - (const u_char *) ip); - break; - - case IPPROTO_UDP: - udp_print(bp + pl_len, len - pl_len, - (const u_char *) ip); - break; - - case IPPROTO_ESP: - esp_print(bp + pl_len, len - pl_len, - (const u_char *) ip); - break; - - case IPPROTO_AH: - ah_print(bp + pl_len, len - pl_len, - (const u_char *) ip); - break; - - default: - (void)printf("ip-proto-%d len %d", ah->ah_nxt_hdr, - len - pl_len); - } -out: - (void)printf(" ]"); - } + printf(", "); + ip_hdrinfo_print(iph, ah->ah_nxt_hdr, bp, len); + return; +trunc: + printf(" [|ah]"); } +/* + * IPComp + */ + struct ipcomp_hdr { u_char ipcomp_nxt_hdr; u_char ipcomp_flags; @@ -313,23 +260,24 @@ struct ipcomp_hdr { }; void -ipcomp_print (const u_char *bp, u_int len, const u_char *bp2) +ipcomp_print(const u_char *bp, u_int len) { - const struct ip *ip; const struct ipcomp_hdr *ipc; - u_int plen = len; - - ip = (const struct ip *)bp2; + int l = snapend - bp; - printf("ipcomp %s > %s", - ipaddr_string(&ip->ip_src), ipaddr_string(&ip->ip_dst)); + printf("IPComp "); - if (plen < sizeof(struct ipcomp_hdr)) { - printf("[|ipcomp]"); + if (l < sizeof(*ipc)) + goto trunc; + if (len < sizeof(*ipc)) { + printf(" ip len %u too short (<%zu)", len, sizeof(*ipc)); return; } - ipc = (const struct ipcomp_hdr *)bp; - printf(" cpi 0x%04X flags %x next %x", + ipc = (const struct ipcomp_hdr *)bp; + printf("cpi 0x%04X flags %x next %u", ntohs(ipc->ipcomp_cpi), ipc->ipcomp_flags, ipc->ipcomp_nxt_hdr); + return; +trunc: + printf(" [|ipcomp]"); } Index: print-ospf.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/print-ospf.c,v retrieving revision 1.21 diff -u -p -r1.21 print-ospf.c --- print-ospf.c 14 Apr 2019 00:37:31 -0000 1.21 +++ print-ospf.c 3 Dec 2019 11:52:08 -0000 @@ -491,19 +491,13 @@ trunc: } void -ospf_print(const u_char *bp, u_int length, const u_char *bp2) +ospf_print(const u_char *bp, u_int length) { const struct ospfhdr *op; - const struct ip *ip; const u_char *dataend; const char *cp; op = (struct ospfhdr *)bp; - ip = (struct ip *)bp2; - /* Print the source and destination address */ - (void) printf("%s > %s:", - ipaddr_string(&ip->ip_src), - ipaddr_string(&ip->ip_dst)); /* XXX Before we do anything else, strip off the MD5 trailer */ TCHECK(op->ospf_authtype); @@ -516,7 +510,7 @@ ospf_print(const u_char *bp, u_int lengt /* value. If it's not valid, say so and return */ TCHECK(op->ospf_type); cp = tok2str(type2str, "type%d", op->ospf_type); - printf(" OSPFv%d-%s ", op->ospf_version, cp); + printf("OSPFv%d-%s ", op->ospf_version, cp); if (*cp == 't') return; Index: print-pfsync.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/print-pfsync.c,v retrieving revision 1.43 diff -u -p -r1.43 print-pfsync.c --- print-pfsync.c 20 Jan 2017 09:36:42 -0000 1.43 +++ print-pfsync.c 3 Dec 2019 11:52:08 -0000 @@ -82,22 +82,25 @@ out: } void -pfsync_ip_print(const u_char *bp, u_int len, const u_char *bp2) +pfsync_ip_print(const u_char *bp, u_int len) { - struct pfsync_header *hdr = (struct pfsync_header *)bp; - struct ip *ip = (struct ip *)bp2; + struct pfsync_header *hdr; + int l = snapend - bp; - if (vflag) - printf("%s > %s: ", ipaddr_string(&ip->ip_src), - ipaddr_string(&ip->ip_dst)); - else - printf("%s: ", ipaddr_string(&ip->ip_src)); + if (l < sizeof(*hdr)) { + printf(" [|pfsync]"); + return; + } + if (len < PFSYNC_HDRLEN) { + printf(" ip truncated"); + return; + } - if (len < PFSYNC_HDRLEN) - printf("[|pfsync]"); - else - pfsync_print(hdr, bp + sizeof(struct pfsync_header), - len - sizeof(struct pfsync_header)); + bp += sizeof(*hdr); + len -= sizeof(*hdr); + + hdr = (struct pfsync_header *)bp; + pfsync_print(hdr, bp, len); putchar('\n'); } Index: print-rt6.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/print-rt6.c,v retrieving revision 1.7 diff -u -p -r1.7 print-rt6.c --- print-rt6.c 22 Oct 2018 16:12:45 -0000 1.7 +++ print-rt6.c 3 Dec 2019 11:52:08 -0000 @@ -44,66 +44,92 @@ #include "interface.h" #include "addrtoname.h" -int -rt6_print(const u_char *bp, const u_char *bp2) +static void +rthdr0_print(const u_char *bp, u_int len) { - const struct ip6_rthdr *dp; const struct ip6_rthdr0 *dp0; - const struct ip6_hdr *ip; - const u_char *ep; - int i, len; + const struct in6_addr *addr; + u_int hlen; + u_int i = 1; + int l = snapend - bp; + + if (l < sizeof(*dp0)) + return; + if (len < sizeof(*dp0)) + return; + + dp0 = (const struct ip6_rthdr0 *)bp; + hlen = (dp0->ip6r0_len + 1) << 3; + if (vflag || dp0->ip6r0_reserved) + printf(" rsv=0x%0x", ntohl(dp0->ip6r0_reserved)); + + bp += sizeof(*dp0); + len -= sizeof(*dp0); + hlen -= sizeof(*dp0); + + while (hlen >= sizeof(*addr)) { + if (l < sizeof(*addr)) + return; + if (len < sizeof(*addr)) + return; + + addr = (const struct in6_addr *)bp; + printf(" [%u]%s]", i++, ip6addr_string(addr)); + + bp += sizeof(*addr); + len -= sizeof(*addr); + hlen -= sizeof(*addr); + } + if (hlen != 0) + printf(" rthdr0-extra-bytes-%u", hlen); +} - dp = (struct ip6_rthdr *)bp; - ip = (struct ip6_hdr *)bp2; - len = dp->ip6r_len; +void +rt6_print(struct ip_hdrinfo *iph, const u_char *bp, u_int len) +{ + const struct ip6_rthdr *dp; + u_int hlen; + int l = snapend - bp; + + printf("Routing Header"); - /* 'ep' points to the end of avaible data. */ - ep = snapend; + if (l < sizeof(*dp)) + goto trunc; + if (len < sizeof(*dp)) { + printf(" ip truncated"); + return; + } -#if 0 - printf("%s > %s: ", - ip6addr_string(&ip->ip6_src), - ip6addr_string(&ip->ip6_dst)); -#endif - - TCHECK(dp->ip6r_segleft); - - printf("srcrt (len=%d, ", dp->ip6r_len); - printf("type=%d, ", dp->ip6r_type); - printf("segleft=%d", dp->ip6r_segleft); + dp = (struct ip6_rthdr *)bp; + hlen = (dp->ip6r_len + 1) << 3; + + printf(" Type %u", dp->ip6r_type); + if (vflag) + printf(" len %u", len); + printf(" segleft %u", dp->ip6r_segleft); switch (dp->ip6r_type) { case IPV6_RTHDR_TYPE_0: - dp0 = (struct ip6_rthdr0 *)dp; - - TCHECK(dp0->ip6r0_reserved); - if (dp0->ip6r0_reserved || vflag) { - printf(", rsv=0x%0x", - (u_int32_t)ntohl(dp0->ip6r0_reserved)); - } - - if (len % 2 == 1) - goto trunc; - len >>= 1; - for (i = 0; i < len; i++) { - struct in6_addr *addr; - - addr = ((struct in6_addr *)(dp0 + 1)) + i; - if ((u_char *)addr > ep - sizeof(*addr)) - goto trunc; - - printf(", [%d]%s", i, ip6addr_string((u_char *)addr)); - } - printf(")"); - return((dp0->ip6r0_len + 1) << 3); + rthdr0_print(bp, len); + /* FALLTHROUGH for remaining hlen */ default: - if (bp + ((dp->ip6r_len + 1) << 3) > ep) - goto trunc; - printf(")"); - return((dp->ip6r_len + 1) << 3); + break; + } + + if (hlen < l) + goto trunc; + if (hlen < len) { + printf(" ip truncated"); + return; } + bp += hlen; + len -= hlen; + + ip_hdrinfo_print(iph, dp->ip6r_nxt, bp, len); + + return; + trunc: - fputs(", [|srcrt]", stdout); - return 65535; /* XXX */ + printf(" [|rthdr]"); } Index: print-tcp.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/print-tcp.c,v retrieving revision 1.38 diff -u -p -r1.38 print-tcp.c --- print-tcp.c 22 Oct 2018 16:12:45 -0000 1.38 +++ print-tcp.c 3 Dec 2019 11:52:08 -0000 @@ -119,65 +119,8 @@ static struct tcp_seq_hash tcp_seq_hash[ #define OLD_OFP_PORT 6633 #define OFP_PORT 6653 -static int tcp_cksum(const struct ip *ip, const struct tcphdr *tp, int len) -{ - union phu { - struct phdr { - u_int32_t src; - u_int32_t dst; - u_char mbz; - u_char proto; - u_int16_t len; - } ph; - u_int16_t pa[6]; - } phu; - const u_int16_t *sp; - u_int32_t sum; - - /* pseudo-header.. */ - phu.ph.len = htons((u_int16_t)len); - phu.ph.mbz = 0; - phu.ph.proto = IPPROTO_TCP; - memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t)); - memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t)); - - sp = &phu.pa[0]; - sum = sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]; - - return in_cksum((u_short *)tp, len, sum); -} - -static int tcp6_cksum(const struct ip6_hdr *ip6, const struct tcphdr *tp, - u_int len) -{ - union { - struct { - struct in6_addr ph_src; - struct in6_addr ph_dst; - u_int32_t ph_len; - u_int8_t ph_zero[3]; - u_int8_t ph_nxt; - } ph; - u_int16_t pa[20]; - } phu; - size_t i; - u_int32_t sum = 0; - - /* pseudo-header */ - memset(&phu, 0, sizeof(phu)); - phu.ph.ph_src = ip6->ip6_src; - phu.ph.ph_dst = ip6->ip6_dst; - phu.ph.ph_len = htonl(len); - phu.ph.ph_nxt = IPPROTO_TCP; - - for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++) - sum += phu.pa[i]; - - return in_cksum((u_short *)tp, len, sum); -} - void -tcp_print(const u_char *bp, u_int length, const u_char *bp2) +tcp_print(const struct ip_hdrinfo *iph, const u_char *bp, u_int length) { const struct tcphdr *tp; const struct ip *ip; @@ -188,17 +131,17 @@ tcp_print(const u_char *bp, u_int length int rev = 0; u_int16_t sport, dport, win, urp; tcp_seq seq, ack; + int l = snapend - bp; const struct ip6_hdr *ip6; - tp = (struct tcphdr *)bp; - switch (((struct ip *)bp2)->ip_v) { + switch (((const struct ip *)iph->hdr)->ip_v) { case 4: - ip = (struct ip *)bp2; + ip = iph->hdr; ip6 = NULL; break; case 6: ip = NULL; - ip6 = (struct ip6_hdr *)bp2; + ip6 = iph->hdr; break; default: (void)printf("invalid ip version"); @@ -206,50 +149,23 @@ tcp_print(const u_char *bp, u_int length } ch = '\0'; - if (length < sizeof(*tp)) { - (void)printf("truncated-tcp %u", length); + if (l < sizeof(*tp)) { + printf("%s > %s: [|tcp]", iph->src, iph->dst); return; } - - if (!TTEST(tp->th_dport)) { - if (ip6) { - (void)printf("%s > %s: [|tcp]", - ip6addr_string(&ip6->ip6_src), - ip6addr_string(&ip6->ip6_dst)); - } else { - (void)printf("%s > %s: [|tcp]", - ipaddr_string(&ip->ip_src), - ipaddr_string(&ip->ip_dst)); - } + if (length < sizeof(*tp)) { + printf("%s > %s: ip len %u too short (<%zu)", + iph->src, iph->dst, length, sizeof(*tp)); return; } + tp = (struct tcphdr *)bp; sport = ntohs(tp->th_sport); dport = ntohs(tp->th_dport); - if (ip6) { - if (ip6->ip6_nxt == IPPROTO_TCP) { - (void)printf("%s.%s > %s.%s: ", - ip6addr_string(&ip6->ip6_src), - tcpport_string(sport), - ip6addr_string(&ip6->ip6_dst), - tcpport_string(dport)); - } else { - (void)printf("%s > %s: ", - tcpport_string(sport), tcpport_string(dport)); - } - } else { - if (ip->ip_p == IPPROTO_TCP) { - (void)printf("%s.%s > %s.%s: ", - ipaddr_string(&ip->ip_src), - tcpport_string(sport), - ipaddr_string(&ip->ip_dst), - tcpport_string(dport)); - } else { - (void)printf("%s > %s: ", - tcpport_string(sport), tcpport_string(dport)); - } - } + printf("%s.%s > %s.%s: ", + iph->src, tcpport_string(sport), + iph->dst, tcpport_string(dport)); if (!qflag && TTEST(tp->th_seq) && !TTEST(tp->th_ack)) (void)printf("%u ", ntohl(tp->th_seq)); @@ -274,11 +190,11 @@ tcp_print(const u_char *bp, u_int length u_int len = length - hlen; if ((u_char *)tp + 4 + sizeof(struct rpc_msg) <= snapend && dport == NFS_PORT) { - nfsreq_print((u_char *)tp + hlen + 4, len, bp2); + nfsreq_print((u_char *)tp + hlen + 4, len, iph->hdr); return; } else if ((u_char *)tp + 4 + sizeof(struct rpc_msg) <= snapend && sport == NFS_PORT) { - nfsreply_print((u_char *)tp + hlen + 4, len, bp2); + nfsreply_print((u_char *)tp + hlen + 4, len, iph->hdr); return; } } @@ -380,22 +296,12 @@ tcp_print(const u_char *bp, u_int length return; } - if (ip && ip->ip_v == 4 && vflag) { - if (TTEST2(tp->th_sport, length)) { - u_int16_t sum, tcp_sum; - sum = tcp_cksum(ip, tp, length); - if (sum != 0) { - tcp_sum = EXTRACT_16BITS(&tp->th_sum); - (void)printf(" [bad tcp cksum %x! -> %x]", tcp_sum, - in_cksum_shouldbe(tcp_sum, sum)); - } else - (void)printf(" [tcp sum ok]"); - } - } - if (ip6 && ip6->ip6_plen && vflag) { + if (vflag) { if (TTEST2(tp->th_sport, length)) { + uint32_t phsum = ip_hdrinfo_phsum(iph, + IPPROTO_TCP, length); u_int16_t sum, tcp_sum; - sum = tcp6_cksum(ip6, tp, length); + sum = in_cksum((u_short *)tp, length, phsum); if (sum != 0) { tcp_sum = EXTRACT_16BITS(&tp->th_sum); (void)printf(" [bad tcp cksum %x! -> %x]", tcp_sum, Index: print-udp.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/print-udp.c,v retrieving revision 1.53 diff -u -p -r1.53 print-udp.c --- print-udp.c 2 Dec 2019 22:32:01 -0000 1.53 +++ print-udp.c 3 Dec 2019 11:52:08 -0000 @@ -312,7 +312,7 @@ rtcp_print(const u_char *hdr, const u_ch #define UDPENCAP_PORT 4500 /*XXX*/ #define GRE_PORT 4754 #define VXLAN_PORT 4789 -#define VXLAN_GPE_PORT 4790 +#define VXLAN_GPE_PORT 4790 /* draft-ietf-nvo3-vxlan-gpe */ #define MULTICASTDNS_PORT 5353 #define MPLS_PORT 6635 @@ -321,114 +321,60 @@ rtcp_print(const u_char *hdr, const u_ch #define DHCP6_PORT2 547 /*XXX*/ void -udp_print(const u_char *bp, u_int length, const void *iph) +udp_print(struct ip_hdrinfo *iph, const u_char *bp, u_int length) { const struct udphdr *up; const u_char *cp; - const u_char *ep = bp + length; u_int16_t sport, dport, ulen; - const char *ipsrc = NULL, *ipdst = NULL; - unsigned int ipv = 0; - uint32_t cksum = 0; - - if (ep > snapend) - ep = snapend; - - if (iph != NULL) { - const struct ip *ip = iph; - ipv = ip->ip_v; - - switch (ipv) { - case 6: { - const struct ip6_hdr *ip6 = iph; - - ipsrc = ip6addr_string(&ip6->ip6_src); - ipdst = ip6addr_string(&ip6->ip6_dst); - - cksum = in_cksum_add(&ip6->ip6_src, - sizeof(ip6->ip6_src), cksum); - cksum = in_cksum_add(&ip6->ip6_dst, - sizeof(ip6->ip6_dst), cksum); - break; - } - case 4: - ipsrc = ipaddr_string(&ip->ip_src); - ipdst = ipaddr_string(&ip->ip_dst); - - cksum = in_cksum_add(&ip->ip_src, - sizeof(ip->ip_src), cksum); - cksum = in_cksum_add(&ip->ip_dst, - sizeof(ip->ip_dst), cksum); - break; - } - } - - up = (const struct udphdr *)bp; - cp = (const u_char *)(up + 1); + int l = snapend - bp; /* check if the udp header was captured */ - if (cp > snapend) { - if (ipv) - printf("%s > %s: ", ipsrc, ipdst); - + if (l < sizeof(*up)) { + printf("%s > %s: ", iph->src, iph->dst); printf("[|udp]"); return; } /* check if the packet payload is long enough */ if (length < sizeof(*up)) { - if (ipv) - printf("%s > %s: ", ipsrc, ipdst); - + printf("%s > %s: ", iph->src, iph->dst); printf("truncated-udp %u", length); return; } + up = (const struct udphdr *)bp; sport = ntohs(up->uh_sport); dport = ntohs(up->uh_dport); - if (ipv) { - printf("%s.%s > %s.%s", - ipsrc, udpport_string(sport), - ipdst, udpport_string(dport)); - } else { - printf("udp %s > %s", - udpport_string(sport), - udpport_string(dport)); - } - - printf(": "); - - cksum += htons(length); + printf("%s.%s > %s.%s: ", + iph->src, udpport_string(sport), + iph->dst, udpport_string(dport)); ulen = ntohs(up->uh_ulen); - if (length < ulen) - printf(" truncated-udp - %u bytes missing!", ulen - length); + if (!iph->frag && length < ulen) + printf("truncated-udp - %u bytes missing! ", ulen - length); - length -= sizeof(*up); + cp = bp + sizeof(*up); + length = ulen - sizeof(*up); /* XXX */ - if (vflag && ipv && TTEST2(cp[0], length)) { + if (vflag && ulen <= l) { uint16_t sum, usum = up->uh_sum; if (usum == 0) { - if (ipv == 4) - printf("[no udp cksum] "); - else - printf("[invalid udp cksum 0] "); + printf("[no udp cksum] "); } else { - cksum += htons(IPPROTO_UDP); + uint32_t cksum = ip_hdrinfo_phsum(iph, + IPPROTO_UDP, ulen); cksum += up->uh_sport; cksum += up->uh_dport; cksum += up->uh_ulen; sum = in_cksum(cp, length, cksum); - - if (sum == usum) - printf("[udp sum ok] "); - else { + if (sum != usum) { printf("[bad udp cksum %04x! -> %04x] ", usum, sum); - } + } else + printf("[udp sum ok] "); } } @@ -449,9 +395,9 @@ udp_print(const u_char *bp, u_int length rp = (struct rpc_msg *)cp; direction = (enum msg_type)ntohl(rp->rm_direction); if (direction == CALL) - sunrpcrequest_print(cp, length, iph); + sunrpcrequest_print(cp, length, iph->hdr); else - nfsreply_print(cp, length, iph); + nfsreply_print(cp, length, iph->hdr); break; case PT_RTP: @@ -459,8 +405,8 @@ udp_print(const u_char *bp, u_int length break; case PT_RTCP: - while (cp < ep) - cp = rtcp_print(cp, ep); + while (cp < snapend) + cp = rtcp_print(cp, snapend); break; case PT_CNFP: cnfp_print(cp, length); @@ -489,16 +435,16 @@ udp_print(const u_char *bp, u_int length if (TTEST(rp->rm_direction)) { direction = (enum msg_type)ntohl(rp->rm_direction); if (dport == NFS_PORT && direction == CALL) { - nfsreq_print(cp, length, iph); + nfsreq_print(cp, length, iph->hdr); return; } if (sport == NFS_PORT && direction == REPLY) { - nfsreply_print(cp, length, iph); + nfsreply_print(cp, length, iph->hdr); return; } #ifdef notdef if (dport == SUNRPC_PORT && direction == CALL) { - sunrpcrequest_print(cp, length, iph); + sunrpcrequest_print(cp, length, iph->hdr); return; } #endif @@ -538,7 +484,7 @@ udp_print(const u_char *bp, u_int length else if (ISPORT(L2TP_PORT)) l2tp_print(cp, length); else if (ISPORT(UDPENCAP_PORT)) - udpencap_print(cp, length, iph); + udpencap_print(iph, cp, length); else if (ISPORT(ISAKMP_PORT)) ike_print(cp, length); #if 0 Index: print-udpencap.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/print-udpencap.c,v retrieving revision 1.6 diff -u -p -r1.6 print-udpencap.c --- print-udpencap.c 6 Jul 2018 05:47:22 -0000 1.6 +++ print-udpencap.c 3 Dec 2019 11:52:08 -0000 @@ -28,26 +28,44 @@ #include #include "interface.h" +#include "extract.h" void -udpencap_print(const u_char *bp, u_int len, const u_char *bp2) +udpencap_print(struct ip_hdrinfo *iph, const u_char *bp, u_int len) { - u_int32_t *spi; + uint32_t spi; + int l = snapend - bp; + + printf("udpencap"); /* Recognize NAT-T Keepalive msgs. (draft-ietf-ipsec-udp-encaps-nn) */ - if (len == 1 && *bp == 0xFF) { - fputs("NAT-T Keepalive", stdout); - return; + if (len == 1) { + if (l < 1) + goto trunc; + if (len < 1) + goto iptrunc; + if (*bp == 0xFF) { + printf(" NAT-T Keepalive"); + return; + } } - if (len < sizeof(u_int32_t)) { - fputs("[|udpencap]", stdout); - return; - } - fputs("udpencap: ", stdout); - spi = (u_int32_t *)(bp); - if (*spi == 0) - ike_print(bp + sizeof(u_int32_t), len - sizeof(u_int32_t)); + if (l < sizeof(spi)) + goto trunc; + if (len < sizeof(spi)) + goto iptrunc; + spi = EXTRACT_32BITS(bp); + + printf(": "); + if (spi == 0) + ike_print(bp + sizeof(spi), len - sizeof(spi)); else - esp_print(bp, len, bp2); + esp_print(iph, bp, len); + + return; +trunc: + printf(" [|udpencap]"); + return; +iptrunc: + printf(" ip truncated"); } Index: tcpdump.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/tcpdump.c,v retrieving revision 1.91 diff -u -p -r1.91 tcpdump.c --- tcpdump.c 28 Jun 2019 13:32:51 -0000 1.91 +++ tcpdump.c 3 Dec 2019 11:52:08 -0000 @@ -100,6 +100,9 @@ extern __dead void usage(void); /* Length of saved portion of packet. */ int snaplen = 0; +/* Separator between protocol encapsulations */ +const char *layersep = ": "; + struct printer { pcap_handler f; int type; @@ -382,6 +385,7 @@ main(int argc, char **argv) break; case 'v': + layersep = "\n "; ++vflag; break;