massage tcpdump ip and encapsulation output

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

massage tcpdump ip and encapsulation output

David Gwynne-5
this is a significant reworking of tcpdump with a couple of goals
twisted together.

it is becoming increasingly common to encapsulate protocols, leading
to situations where you have some kind of ip packet inside another
ip packet. i am arguing our current ip printing code sucks in this
situation because some of the information about ip headers is printed
AFTER the payload. when you have a few layers of IP floating around,
it is difficult to associate these values back to the relevant header.
even if you don't have multiple IP layers, a big payload makes it
hard for my brain to backtrack. to address this, the diff moves
printing ip header properties to the front of the ip payload printing.
to give them some context, i'm prefixing the ip and ip6 printing
with IPv4 and IPv6 respectively. in practice it looks like this:

before:

dlg@v445 tcpdump$ tcpdump -nr /home/dlg/tmp/ping.pcap
16:31:18.836620 10.0.127.15 > 10.0.127.1: icmp: echo request [tos 0x20] [ttl 1]
16:31:18.837074 10.0.127.1 > 10.0.127.15: icmp: echo reply [tos 0x20]
dlg@v445 tcpdump$ tcpdump -nr /home/dlg/tmp/ping.pcap -v
16:31:18.836620 10.0.127.15 > 10.0.127.1: icmp: echo request (id:b59f seq:0) [icmp cksum ok] [tos 0x20] [ttl 1] (id 39958, len 84)
16:31:18.837074 10.0.127.1 > 10.0.127.15: icmp: echo reply (id:b59f seq:0) [icmp cksum ok] [tos 0x20] (ttl 255, id 36919, len 84)

after:

dlg@v445 tcpdump$ ./obj/tcpdump -nr /home/dlg/tmp/ping.pcap
16:31:18.836620 IPv4 ttl 1 [tos 0x20] 10.0.127.15 > 10.0.127.1: icmp: echo request
16:31:18.837074 IPv4 [tos 0x20] 10.0.127.1 > 10.0.127.15: icmp: echo reply
dlg@v445 tcpdump$ ./obj/tcpdump -nr /home/dlg/tmp/ping.pcap -v
16:31:18.836620 IPv4 ttl 1 [tos 0x20] (id 39958, len 84) 10.0.127.15 > 10.0.127.1: icmp: echo request (id:b59f seq:0) [icmp cksum ok]
16:31:18.837074 IPv4 ttl 255 [tos 0x20] (id 36919, len 84) 10.0.127.1 > 10.0.127.15: icmp: echo reply (id:b59f seq:0) [icmp cksum ok]

another part of this is wanting to print the port numbers for udp
and tcp with the addresses from the ip headers, and then do that
consistently for ipv4 and ipv6. things like ipsec (and AH in
particular) make that difficult because they kind of act as a shim
between the IP header and the TCP/UDP payloads. ipv6 goes even
further and has things like router options, fragment handling, etc,
as shims before the payload. to support this i treat those protocols
specially and recurse through the processing of them. i also disable
some length checks in the udp layer if the packet is fragmented:

so before this change:

dlg@v445 tcpdump$ tcpdump -nr /home/dlg/tmp/ipv6-udp-fragmented.pcap          
tcpdump: WARNING: snaplen raised from 116 to 65535
05:35:13.312348 2607:f010:3f9::11:0.6363 > 2607:f010:3f9::1001.6363: udp 118
05:35:13.549553 2607:f010:3f9::11:0.6363 > 2607:f010:3f9::1001.6363: udp 31
05:35:13.569339 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: frag (0xf88eb466:1448@0+) 2607:f010:3f9::1001.6363 > 2607:f010:3f9::11:0.6363:  truncated-udp - 3939 bytes missing!udp 1440 [flowlabel 0x21289]
05:35:13.569345 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: frag (0xf88eb466:1448@1448+) [flowlabel 0x21289]
05:35:13.569346 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: frag (0xf88eb466:1448@2896+) [flowlabel 0x21289]
05:35:13.569349 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: frag (0xf88eb466:1043@4344) [flowlabel 0x21289]
dlg@v445 tcpdump$ tcpdump -nr /home/dlg/tmp/ipv6-udp-fragmented.pcap -v
tcpdump: WARNING: snaplen raised from 116 to 65535
05:35:13.312348 2607:f010:3f9::11:0.6363 > 2607:f010:3f9::1001.6363: [udp sum ok] udp 118 (len 126, hlim 64)
05:35:13.549553 2607:f010:3f9::11:0.6363 > 2607:f010:3f9::1001.6363: [udp sum ok] udp 31 (len 39, hlim 64)
05:35:13.569339 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: frag (0xf88eb466:1448@0+) 2607:f010:3f9::1001.6363 > 2607:f010:3f9::11:0.6363:  truncated-udp - 3939 bytes missing![bad udp cksum 7916! -> 12e1] udp 1440 [flowlabel 0x21289] (len 1456, hlim 64)
05:35:13.569345 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: frag (0xf88eb466:1448@1448+) [flowlabel 0x21289] (len 1456, hlim 64)
05:35:13.569346 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: frag (0xf88eb466:1448@2896+) [flowlabel 0x21289] (len 1456, hlim 64)
05:35:13.569349 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: frag (0xf88eb466:1043@4344) [flowlabel 0x21289] (len 1051, hlim 64)

and after:

dlg@v445 tcpdump$ ./obj/tcpdump -nr /home/dlg/tmp/ipv6-udp-fragmented.pcap  
tcpdump: WARNING: snaplen raised from 116 to 65535
05:35:13.312348 IPv6 2607:f010:3f9::11:0.6363 > 2607:f010:3f9::1001.6363: udp 118
05:35:13.549553 IPv6 2607:f010:3f9::11:0.6363 > 2607:f010:3f9::1001.6363: udp 31
05:35:13.569339 IPv6 [flowlabel 0x21289] Fragment (0xf88eb466:1448@0+), 2607:f010:3f9::1001.6363 > 2607:f010:3f9::11:0.6363: udp 5379
05:35:13.569345 IPv6 [flowlabel 0x21289] Fragment (0xf88eb466:1448@1448+), 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: 17 fragment
05:35:13.569346 IPv6 [flowlabel 0x21289] Fragment (0xf88eb466:1448@2896+), 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: 17 fragment
05:35:13.569349 IPv6 [flowlabel 0x21289] Fragment (0xf88eb466:1043@4344), 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: 17 fragment
dlg@v445 tcpdump$ ./obj/tcpdump -nr /home/dlg/tmp/ipv6-udp-fragmented.pcap -v
tcpdump: WARNING: snaplen raised from 116 to 65535
05:35:13.312348 IPv6 hlim 64 (len 126) 2607:f010:3f9::11:0.6363 > 2607:f010:3f9::1001.6363: [udp sum ok] udp 118
05:35:13.549553 IPv6 hlim 64 (len 39) 2607:f010:3f9::11:0.6363 > 2607:f010:3f9::1001.6363: [udp sum ok] udp 31
05:35:13.569339 IPv6 hlim 64 [flowlabel 0x21289] (len 1456) Fragment (0xf88eb466:1448@0+), 2607:f010:3f9::1001.6363 > 2607:f010:3f9::11:0.6363: udp 5379
05:35:13.569345 IPv6 hlim 64 [flowlabel 0x21289] (len 1456) Fragment (0xf88eb466:1448@1448+), 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: 17 fragment
05:35:13.569346 IPv6 hlim 64 [flowlabel 0x21289] (len 1456) Fragment (0xf88eb466:1448@2896+), 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: 17 fragment
05:35:13.569349 IPv6 hlim 64 [flowlabel 0x21289] (len 1051) Fragment (0xf88eb466:1043@4344), 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: 17 fragment

note the difference in the output of the first fragment of the udp
packet.

for comparison, here's the ipv4 equivalent:

dlg@v445 tcpdump$ tcpdump -nr /home/dlg/tmp/udp-frag.pcap      
20:34:42.184788 10.0.127.15.20550 > 10.0.127.1.6363:  truncated-udp - 4528 bytes missing!udp 1472 (frag 44745:1480@0+)
20:34:42.184789 10.0.127.15 > 10.0.127.1: (frag 44745:1480@1480+)
20:34:42.184790 10.0.127.15 > 10.0.127.1: (frag 44745:1480@2960+)
20:34:42.184791 10.0.127.15 > 10.0.127.1: (frag 44745:1480@4440+)
20:34:42.184791 10.0.127.15 > 10.0.127.1: (frag 44745:88@5920)
dlg@v445 tcpdump$ ./obj/tcpdump -nr /home/dlg/tmp/udp-frag.pcap
20:34:42.184788 IPv4 (frag 44745:1480@0+) 10.0.127.15.20550 > 10.0.127.1.6363: udp 6000
20:34:42.184789 IPv4 (frag 44745:1480@1480+) 10.0.127.15 > 10.0.127.1
20:34:42.184790 IPv4 (frag 44745:1480@2960+) 10.0.127.15 > 10.0.127.1
20:34:42.184791 IPv4 (frag 44745:1480@4440+) 10.0.127.15 > 10.0.127.1
20:34:42.184791 IPv4 (frag 44745:88@5920) 10.0.127.15 > 10.0.127.1

lastly, this tweaks the output of some encapsulation protocols so
they put the encapsulated protocol on a new line when tcpdump is
run with -v. an extreme example is from
https://learningnetwork.cisco.com/docs/DOC-15614:

dlg@v445 tcpdump$ tcpdump -c2 -nr /home/dlg/tmp/gre-within-gre.pcap    
tcpdump: WARNING: snaplen raised from 116 to 65535
07:13:44.204043 72.205.54.70 > 86.106.164.150: gre 10.10.11.2 > 10.10.13.2: gre 10.10.25.1 > 192.168.1.2: icmp: echo request (DF)
07:13:44.335000 86.106.164.150 > 72.205.54.70: gre 10.10.13.2 > 10.10.11.2: gre 192.168.1.2 > 10.10.25.1: icmp: echo reply

which ip packet is that (DF) on?

dlg@v445 tcpdump$ tcpdump -c2 -nr /home/dlg/tmp/gre-within-gre.pcap -v
tcpdump: WARNING: snaplen raised from 116 to 65535
07:13:44.204043 72.205.54.70 > 86.106.164.150: gre [] 0800 10.10.11.2 > 10.10.13.2: gre [] 0800 10.10.25.1 > 192.168.1.2: icmp: echo request (id:0017 seq:7666) [icmp cksum ok] (ttl 255, id 9144, len 100) (ttl 254, id 10208, len 124) (DF) (ttl 255, id 0, len 148)
07:13:44.335000 86.106.164.150 > 72.205.54.70: gre [] 0800 10.10.13.2 > 10.10.11.2: gre [] 0800 192.168.1.2 > 10.10.25.1: icmp: echo reply (id:0017 seq:7666) [icmp cksum ok] (ttl 255, id 9144, len 100) (ttl 254, id 22814, len 124) (ttl 244, id 24206, len 148)

now it does this:

dlg@v445 tcpdump$ ./obj/tcpdump -c2 -nr /home/dlg/tmp/gre-within-gre.pcap
tcpdump: WARNING: snaplen raised from 116 to 65535
07:13:44.204043 IPv4 (DF) 72.205.54.70 > 86.106.164.150: GRE: IPv4 10.10.11.2 > 10.10.13.2: GRE: IPv4 10.10.25.1 > 192.168.1.2: icmp: echo request
07:13:44.335000 IPv4 86.106.164.150 > 72.205.54.70: GRE: IPv4 10.10.13.2 > 10.10.11.2: GRE: IPv4 192.168.1.2 > 10.10.25.1: icmp: echo reply

dlg@v445 tcpdump$ ./obj/tcpdump -c2 -nr /home/dlg/tmp/gre-within-gre.pcap -v
tcpdump: WARNING: snaplen raised from 116 to 65535
07:13:44.204043 IPv4 ttl 255 (DF) (id 0, len 148) 72.205.54.70 > 86.106.164.150: GRE []
    IPv4 ttl 254 (id 10208, len 124) 10.10.11.2 > 10.10.13.2: GRE []
    IPv4 ttl 255 (id 9144, len 100) 10.10.25.1 > 192.168.1.2: icmp: echo request (id:0017 seq:7666) [icmp cksum ok]
07:13:44.335000 IPv4 ttl 244 (id 24206, len 148) 86.106.164.150 > 72.205.54.70: GRE []
    IPv4 ttl 254 (id 22814, len 124) 10.10.13.2 > 10.10.11.2: GRE []
    IPv4 ttl 255 (id 9144, len 100) 192.168.1.2 > 10.10.25.1: icmp: echo reply (id:0017 seq:7666) [icmp cksum ok]

the new nsh support would look like this:

dlg@v445 tcpdump$ ./obj/tcpdump -c2 -nr /home/dlg/tmp/nsh.pcap    
tcpdump: WARNING: snaplen raised from 116 to 262144
09:13:40.394208 NSH spi 777 si 7 md1: IPv4 (DF) 10.0.8.3.52229 > 10.13.13.13.8000: udp 6
dlg@v445 tcpdump$ ./obj/tcpdump -c2 -nr /home/dlg/tmp/nsh.pcap -v
tcpdump: WARNING: snaplen raised from 116 to 262144
09:13:40.394208 NSH spi 777 si 7 md1
        context 00000001 00000002 00000003 00000004
    IPv4 ttl 64 (DF) (id 10308, len 34) 10.0.8.3.52229 > 10.13.13.13.8000: [no udp cksum] udp 6

and here's a bonus vxlan traffic.

before:

dlg@v445 tcpdump$ tcpdump -c4 -nr /home/dlg/tmp/vxlan.pcap      
tcpdump: WARNING: snaplen raised from 116 to 262144
01:20:32.675392 192.168.56.11.39924 > 192.168.56.12.4789: vxlan 123: arp who-has 10.0.0.2 tell 10.0.0.1 (DF)
01:20:32.675732 192.168.56.12.40908 > 192.168.56.11.4789: vxlan 123: arp reply 10.0.0.2 is-at 4a:7f:01:3b:a2:71 (DF)
tcpdump: WARNING: compensating for unaligned libpcap packets
01:20:32.676047 192.168.56.11.48134 > 192.168.56.12.4789: vxlan 123: 10.0.0.1 > 10.0.0.2: icmp: echo request (DF) (DF)
01:20:32.676385 192.168.56.12.38071 > 192.168.56.11.4789: vxlan 123: 10.0.0.2 > 10.0.0.1: icmp: echo reply (DF)
dlg@v445 tcpdump$ tcpdump -c4 -nr /home/dlg/tmp/vxlan.pcap -v
tcpdump: WARNING: snaplen raised from 116 to 262144
01:20:32.675392 192.168.56.11.39924 > 192.168.56.12.4789: [no udp cksum] vxlan 123: arp who-has 10.0.0.2 tell 10.0.0.1 (DF) (ttl 64, id 55704, len 78)
01:20:32.675732 192.168.56.12.40908 > 192.168.56.11.4789: [no udp cksum] vxlan 123: arp reply 10.0.0.2 is-at 4a:7f:01:3b:a2:71 (DF) (ttl 64, id 38782, len 78)
tcpdump: WARNING: compensating for unaligned libpcap packets
01:20:32.676047 192.168.56.11.48134 > 192.168.56.12.4789: [no udp cksum] vxlan 123: 10.0.0.1 > 10.0.0.2: icmp: echo request (id:0d3d seq:1) [icmp cksum ok] (DF) (ttl 64, id 12111, len 84) (DF) (ttl 64, id 55705, len 134)
01:20:32.676385 192.168.56.12.38071 > 192.168.56.11.4789: [no udp cksum] vxlan 123: 10.0.0.2 > 10.0.0.1: icmp: echo reply (id:0d3d seq:1) [icmp cksum ok] (ttl 64, id 36913, len 84) (DF) (ttl 64, id 38783, len 134)

after:

dlg@v445 tcpdump$ ./obj/tcpdump -c4 -nr /home/dlg/tmp/vxlan.pcap
tcpdump: WARNING: snaplen raised from 116 to 262144
01:20:32.675392 IPv4 (DF) 192.168.56.11.39924 > 192.168.56.12.4789: VXLAN vni 0: arp who-has 10.0.0.2 tell 10.0.0.1
01:20:32.675732 IPv4 (DF) 192.168.56.12.40908 > 192.168.56.11.4789: VXLAN vni 0: arp reply 10.0.0.2 is-at 4a:7f:01:3b:a2:71
tcpdump: WARNING: compensating for unaligned libpcap packets
01:20:32.676047 IPv4 (DF) 192.168.56.11.48134 > 192.168.56.12.4789: VXLAN vni 0: IPv4 (DF) 10.0.0.1 > 10.0.0.2: icmp: echo request
01:20:32.676385 IPv4 (DF) 192.168.56.12.38071 > 192.168.56.11.4789: VXLAN vni 0: IPv4 10.0.0.2 > 10.0.0.1: icmp: echo reply
dlg@v445 tcpdump$ ./obj/tcpdump -c4 -nr /home/dlg/tmp/vxlan.pcap -v
tcpdump: WARNING: snaplen raised from 116 to 262144
01:20:32.675392 IPv4 ttl 64 (DF) (id 55704, len 78) 192.168.56.11.39924 > 192.168.56.12.4789: [no udp cksum] VXLAN vni 0
    arp who-has 10.0.0.2 tell 10.0.0.1
01:20:32.675732 IPv4 ttl 64 (DF) (id 38782, len 78) 192.168.56.12.40908 > 192.168.56.11.4789: [no udp cksum] VXLAN vni 0
    arp reply 10.0.0.2 is-at 4a:7f:01:3b:a2:71
01:20:32.676047 IPv4 ttl 64 (DF) (id 55705, len 134) 192.168.56.11.48134 > 192.168.56.12.4789: [no udp cksum] VXLAN vni 0
tcpdump: WARNING: compensating for unaligned libpcap packets
    IPv4 ttl 64 (DF) (id 12111, len 84) 10.0.0.1 > 10.0.0.2: icmp: echo request (id:0d3d seq:1) [icmp cksum ok]
01:20:32.676385 IPv4 ttl 64 (DF) (id 38783, len 134) 192.168.56.12.38071 > 192.168.56.11.4789: [no udp cksum] VXLAN vni 0
    IPv4 ttl 64 (id 36913, len 84) 10.0.0.2 > 10.0.0.1: icmp: echo reply (id:0d3d seq:1) [icmp cksum ok]

thoughts? bikeshedding? or no bikeshedding please?

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 <netinet/ip6.h>
 
+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 <stdio.h>
 
 #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;
 

Reply | Threaded
Open this post in threaded view
|

Re: massage tcpdump ip and encapsulation output

Claudio Jeker
On Tue, Dec 03, 2019 at 10:00:01PM +1000, David Gwynne wrote:

> this is a significant reworking of tcpdump with a couple of goals
> twisted together.
>
> it is becoming increasingly common to encapsulate protocols, leading
> to situations where you have some kind of ip packet inside another
> ip packet. i am arguing our current ip printing code sucks in this
> situation because some of the information about ip headers is printed
> AFTER the payload. when you have a few layers of IP floating around,
> it is difficult to associate these values back to the relevant header.
> even if you don't have multiple IP layers, a big payload makes it
> hard for my brain to backtrack. to address this, the diff moves
> printing ip header properties to the front of the ip payload printing.
> to give them some context, i'm prefixing the ip and ip6 printing
> with IPv4 and IPv6 respectively. in practice it looks like this:
>
> before:
>
> dlg@v445 tcpdump$ tcpdump -nr /home/dlg/tmp/ping.pcap
> 16:31:18.836620 10.0.127.15 > 10.0.127.1: icmp: echo request [tos 0x20] [ttl 1]
> 16:31:18.837074 10.0.127.1 > 10.0.127.15: icmp: echo reply [tos 0x20]
> dlg@v445 tcpdump$ tcpdump -nr /home/dlg/tmp/ping.pcap -v
> 16:31:18.836620 10.0.127.15 > 10.0.127.1: icmp: echo request (id:b59f seq:0) [icmp cksum ok] [tos 0x20] [ttl 1] (id 39958, len 84)
> 16:31:18.837074 10.0.127.1 > 10.0.127.15: icmp: echo reply (id:b59f seq:0) [icmp cksum ok] [tos 0x20] (ttl 255, id 36919, len 84)
>
> after:
>
> dlg@v445 tcpdump$ ./obj/tcpdump -nr /home/dlg/tmp/ping.pcap
> 16:31:18.836620 IPv4 ttl 1 [tos 0x20] 10.0.127.15 > 10.0.127.1: icmp: echo request
> 16:31:18.837074 IPv4 [tos 0x20] 10.0.127.1 > 10.0.127.15: icmp: echo reply
> dlg@v445 tcpdump$ ./obj/tcpdump -nr /home/dlg/tmp/ping.pcap -v
> 16:31:18.836620 IPv4 ttl 1 [tos 0x20] (id 39958, len 84) 10.0.127.15 > 10.0.127.1: icmp: echo request (id:b59f seq:0) [icmp cksum ok]
> 16:31:18.837074 IPv4 ttl 255 [tos 0x20] (id 36919, len 84) 10.0.127.1 > 10.0.127.15: icmp: echo reply (id:b59f seq:0) [icmp cksum ok]
>

I think this is a reasonable start. I would prefer if the IP options
"ttl 255 [tos 0x20] (id 36919, len 84)" would be encoded in a somewhat
nicer fashion instead of this random collection of [] () and bare
keywords.

Similar for IPv6: "IPv6 hlim 52 [flowlabel 0x7ed4a] (len 57)" again the
line is just hard to scan.

I would suggest to just pack most of the headers into one group of ().

IPv4 ttl 1 [tos 0x20] 10.0.127.15 > 10.0.127.1
would become
IPv4 (ttl 1 tos 0x20) 10.0.127.15 > 10.0.127.1
and
IPv4 ttl 1 [tos 0x20] (id 39958, len 84) 10.0.127.15 > 10.0.127.1
would become
IPv4 (ttl 1 tos 0x20 id 39958 len 84) 10.0.127.15 > 10.0.127.1

Maybe add the commas if that is easy to do.

--
:wq Claudio

Reply | Threaded
Open this post in threaded view
|

Re: massage tcpdump ip and encapsulation output

Sebastian Benoit-3
Claudio Jeker([hidden email]) on 2019.12.05 09:53:49 +0100:

> I would suggest to just pack most of the headers into one group of ().
>
> IPv4 ttl 1 [tos 0x20] 10.0.127.15 > 10.0.127.1
> would become
> IPv4 (ttl 1 tos 0x20) 10.0.127.15 > 10.0.127.1
> and
> IPv4 ttl 1 [tos 0x20] (id 39958, len 84) 10.0.127.15 > 10.0.127.1
> would become
> IPv4 (ttl 1 tos 0x20 id 39958 len 84) 10.0.127.15 > 10.0.127.1
>
> Maybe add the commas if that is easy to do.

its more readable with commas, i think

Reply | Threaded
Open this post in threaded view
|

Re: massage tcpdump ip and encapsulation output

David Gwynne-5


> On 5 Dec 2019, at 21:14, Sebastian Benoit <[hidden email]> wrote:
>
> Claudio Jeker([hidden email]) on 2019.12.05 09:53:49 +0100:
>> I would suggest to just pack most of the headers into one group of ().
>>
>> IPv4 ttl 1 [tos 0x20] 10.0.127.15 > 10.0.127.1
>> would become
>> IPv4 (ttl 1 tos 0x20) 10.0.127.15 > 10.0.127.1
>> and
>> IPv4 ttl 1 [tos 0x20] (id 39958, len 84) 10.0.127.15 > 10.0.127.1
>> would become
>> IPv4 (ttl 1 tos 0x20 id 39958 len 84) 10.0.127.15 > 10.0.127.1
>>
>> Maybe add the commas if that is easy to do.
>
> its more readable with commas, i think

do you want me to come up with something in this space as part of the large diff, or is the large change generally ok and we can tinker with this stuff afterward?

there's some concern that what i'm proposing is too radical and will break peoples muscle memory.
Reply | Threaded
Open this post in threaded view
|

Re: massage tcpdump ip and encapsulation output

David Gwynne-5
On Fri, Dec 06, 2019 at 03:14:42PM +1000, David Gwynne wrote:

>
>
> > On 5 Dec 2019, at 21:14, Sebastian Benoit <[hidden email]> wrote:
> >
> > Claudio Jeker([hidden email]) on 2019.12.05 09:53:49 +0100:
> >> I would suggest to just pack most of the headers into one group of ().
> >>
> >> IPv4 ttl 1 [tos 0x20] 10.0.127.15 > 10.0.127.1
> >> would become
> >> IPv4 (ttl 1 tos 0x20) 10.0.127.15 > 10.0.127.1
> >> and
> >> IPv4 ttl 1 [tos 0x20] (id 39958, len 84) 10.0.127.15 > 10.0.127.1
> >> would become
> >> IPv4 (ttl 1 tos 0x20 id 39958 len 84) 10.0.127.15 > 10.0.127.1
> >>
> >> Maybe add the commas if that is easy to do.
> >
> > its more readable with commas, i think
>
> do you want me to come up with something in this space as part of the large diff, or is the large change generally ok and we can tinker with this stuff afterward?
>
> there's some concern that what i'm proposing is too radical and will break peoples muscle memory.

fyi, here's what stock (or apple tweaked) tcpdump looks like for a
similar set of packets:

dlg@fatmac Temp$ tcpdump -V
tcpdump: option requires an argument -- V
tcpdump version tcpdump version 4.9.2 -- Apple version 83.200.2
libpcap version 1.8.1 -- Apple version 79.250.1
LibreSSL 2.2.7
Usage: tcpdump [-aAbdDefhHIJKlLnNOpqStuUvxX#] [ -B size ] [ -c count ]
                [ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]
                [ -i interface ] [ -j tstamptype ] [ -M secret ] [ --number ]
                [ -Q in|out|inout ]
                [ -r file ] [ -s snaplen ] [ --time-stamp-precision precision ]
                [ --immediate-mode ] [ -T type ] [ --version ] [ -V file ]
                [ -w file ] [ -W filecount ] [ -y datalinktype ] [ -z postrotate-command ]
[ -g ] [ -k ] [ -o ] [ -P ] [ -Q met[ --time-zone-offset offset ]
                [ -Z user ] [ expression ]

dlg@fatmac Temp$ tcpdump -nr ping.pcap
reading from file ping.pcap, link-type EN10MB (Ethernet)
16:31:18.836620 IP 10.0.127.15 > 10.0.127.1: ICMP echo request, id 46495, seq 0, length 64
16:31:18.837074 IP 10.0.127.1 > 10.0.127.15: ICMP echo reply, id 46495, seq 0, length 64
dlg@fatmac Temp$ tcpdump -nr ping.pcap -v
reading from file ping.pcap, link-type EN10MB (Ethernet)
16:31:18.836620 IP (tos 0x20, ttl 1, id 39958, offset 0, flags [none], proto ICMP (1), length 84)
    10.0.127.15 > 10.0.127.1: ICMP echo request, id 46495, seq 0, length 64
16:31:18.837074 IP (tos 0x20, ttl 255, id 36919, offset 0, flags [none], proto ICMP (1), length 84)
    10.0.127.1 > 10.0.127.15: ICMP echo reply, id 46495, seq 0, length 64

dlg@fatmac Temp$ tcpdump -nr ipv6-udp-fragmented.pcap
reading from file ipv6-udp-fragmented.pcap, link-type EN10MB (Ethernet)
05:35:13.312348 IP6 2607:f010:3f9::11:0.6363 > 2607:f010:3f9::1001.6363: UDP, length 118
05:35:13.549553 IP6 2607:f010:3f9::11:0.6363 > 2607:f010:3f9::1001.6363: UDP, length 31
05:35:13.569339 IP6 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: frag (0|1448) 6363 > 6363: UDP, bad length 5379 > 1440
05:35:13.569345 IP6 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: frag (1448|1448)
05:35:13.569346 IP6 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: frag (2896|1448)
05:35:13.569349 IP6 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: frag (4344|1043)
dlg@fatmac Temp$ tcpdump -nr ipv6-udp-fragmented.pcap -v
reading from file ipv6-udp-fragmented.pcap, link-type EN10MB (Ethernet)
05:35:13.312348 IP6 (hlim 64, next-header UDP (17) payload length: 126) 2607:f010:3f9::11:0.6363 > 2607:f010:3f9::1001.6363: [udp sum ok] UDP, length 118
05:35:13.549553 IP6 (hlim 64, next-header UDP (17) payload length: 39) 2607:f010:3f9::11:0.6363 > 2607:f010:3f9::1001.6363: [udp sum ok] UDP, length 31
05:35:13.569339 IP6 (flowlabel 0x21289, hlim 64, next-header Fragment (44) payload length: 1456) 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: frag (0xf88eb466:0|1448) 6363 > 6363: UDP, bad length 5379 > 1440
05:35:13.569345 IP6 (flowlabel 0x21289, hlim 64, next-header Fragment (44) payload length: 1456) 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: frag (0xf88eb466:1448|1448)
05:35:13.569346 IP6 (flowlabel 0x21289, hlim 64, next-header Fragment (44) payload length: 1456) 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: frag (0xf88eb466:2896|1448)
05:35:13.569349 IP6 (flowlabel 0x21289, hlim 64, next-header Fragment (44) payload length: 1051) 2607:f010:3f9::1001 > 2607:f010:3f9::11:0: frag (0xf88eb466:4344|1043)


dlg@fatmac Temp$ tcpdump -nr udp-frag.pcap
reading from file udp-frag.pcap, link-type EN10MB (Ethernet)
20:34:42.184788 IP 10.0.127.15.20550 > 10.0.127.1.6363: UDP, bad length 6000 > 1472
20:34:42.184789 IP 10.0.127.15 > 10.0.127.1: ip-proto-17
20:34:42.184790 IP 10.0.127.15 > 10.0.127.1: ip-proto-17
20:34:42.184791 IP 10.0.127.15 > 10.0.127.1: ip-proto-17
20:34:42.184791 IP 10.0.127.15 > 10.0.127.1: ip-proto-17
dlg@fatmac Temp$ tcpdump -nr udp-frag.pcap -v
reading from file udp-frag.pcap, link-type EN10MB (Ethernet)
20:34:42.184788 IP (tos 0x0, ttl 64, id 44745, offset 0, flags [+], proto UDP (17), length 1500)
    10.0.127.15.20550 > 10.0.127.1.6363: UDP, bad length 6000 > 1472
20:34:42.184789 IP (tos 0x0, ttl 64, id 44745, offset 1480, flags [+], proto UDP (17), length 1500)
    10.0.127.15 > 10.0.127.1: ip-proto-17
20:34:42.184790 IP (tos 0x0, ttl 64, id 44745, offset 2960, flags [+], proto UDP (17), length 1500)
    10.0.127.15 > 10.0.127.1: ip-proto-17
20:34:42.184791 IP (tos 0x0, ttl 64, id 44745, offset 4440, flags [+], proto UDP (17), length 1500)
    10.0.127.15 > 10.0.127.1: ip-proto-17
20:34:42.184791 IP (tos 0x0, ttl 64, id 44745, offset 5920, flags [none], proto UDP (17), length 108)
    10.0.127.15 > 10.0.127.1: ip-proto-17


dlg@fatmac Temp$ tcpdump -c2 -nr gre-within-gre.pcap
reading from file gre-within-gre.pcap, link-type EN10MB (Ethernet)
07:13:44.204043 IP 72.205.54.70 > 86.106.164.150: GREv0, length 128: IP 10.10.11.2 > 10.10.13.2: GREv0, length 104: IP 10.10.25.1 > 192.168.1.2: ICMP echo request, id 23, seq 7666, length 80
07:13:44.335000 IP 86.106.164.150 > 72.205.54.70: GREv0, length 128: IP 10.10.13.2 > 10.10.11.2: GREv0, length 104: IP 192.168.1.2 > 10.10.25.1: ICMP echo reply, id 23, seq 7666, length 80
dlg@fatmac Temp$ tcpdump -c2 -nr gre-within-gre.pcap -v
reading from file gre-within-gre.pcap, link-type EN10MB (Ethernet)
07:13:44.204043 IP (tos 0x0, ttl 255, id 0, offset 0, flags [DF], proto GRE (47), length 148)
    72.205.54.70 > 86.106.164.150: GREv0, Flags [none], length 128
        IP (tos 0x0, ttl 254, id 10208, offset 0, flags [none], proto GRE (47), length 124)
    10.10.11.2 > 10.10.13.2: GREv0, Flags [none], length 104
        IP (tos 0x0, ttl 255, id 9144, offset 0, flags [none], proto ICMP (1), length 100)
    10.10.25.1 > 192.168.1.2: ICMP echo request, id 23, seq 7666, length 80
07:13:44.335000 IP (tos 0x0, ttl 244, id 24206, offset 0, flags [none], proto GRE (47), length 148)
    86.106.164.150 > 72.205.54.70: GREv0, Flags [none], length 128
        IP (tos 0x0, ttl 254, id 22814, offset 0, flags [none], proto GRE (47), length 124)
    10.10.13.2 > 10.10.11.2: GREv0, Flags [none], length 104
        IP (tos 0x0, ttl 255, id 9144, offset 0, flags [none], proto ICMP (1), length 100)
    192.168.1.2 > 10.10.25.1: ICMP echo reply, id 23, seq 7666, length 80


dlg@fatmac Temp$ tcpdump -c2 -nr nsh-over-vxlan-gpe.pcap
reading from file nsh-over-vxlan-gpe.pcap, link-type EN10MB (Ethernet)
00:19:08.994912 IP 127.0.0.1.4790 > 127.0.0.1.4790: VXLAN-GPE, flags [IP], vni 16777215: NSH, flags [OC], service-path-id 0xffffff, service-index 0xff: IP 192.168.0.1.10000 > 192.168.0.2.20000: UDP, length 4
dlg@fatmac Temp$ tcpdump -c2 -nr nsh-over-vxlan-gpe.pcap -v
reading from file nsh-over-vxlan-gpe.pcap, link-type EN10MB (Ethernet)
00:19:08.994912 IP (tos 0x0, ttl 64, id 16419, offset 0, flags [DF], proto UDP (17), length 92)
    127.0.0.1.4790 > 127.0.0.1.4790: VXLAN-GPE, flags [IP], vni 16777215
    NSH, flags [OC], service-path-id 0xffffff, service-index 0xff
    IP (tos 0x0, ttl 255, id 54321, offset 0, flags [none], proto UDP (17), length 32)
    192.168.0.1.10000 > 192.168.0.2.20000: UDP, length 4


dlg@fatmac Temp$ tcpdump -c4 -nr vxlan.pcap
reading from file vxlan.pcap, link-type EN10MB (Ethernet)
01:20:32.675392 IP 192.168.56.11.39924 > 192.168.56.12.4789: VXLAN, flags [I] (0x08), vni 123
ARP, Request who-has 10.0.0.2 tell 10.0.0.1, length 28
01:20:32.675732 IP 192.168.56.12.40908 > 192.168.56.11.4789: VXLAN, flags [I] (0x08), vni 123
ARP, Reply 10.0.0.2 is-at 4a:7f:01:3b:a2:71, length 28
01:20:32.676047 IP 192.168.56.11.48134 > 192.168.56.12.4789: VXLAN, flags [I] (0x08), vni 123
IP 10.0.0.1 > 10.0.0.2: ICMP echo request, id 3389, seq 1, length 64
01:20:32.676385 IP 192.168.56.12.38071 > 192.168.56.11.4789: VXLAN, flags [I] (0x08), vni 123
IP 10.0.0.2 > 10.0.0.1: ICMP echo reply, id 3389, seq 1, length 64
dlg@fatmac Temp$ tcpdump -c4 -nr vxlan.pcap -v
reading from file vxlan.pcap, link-type EN10MB (Ethernet)
01:20:32.675392 IP (tos 0x0, ttl 64, id 55704, offset 0, flags [DF], proto UDP (17), length 78)
    192.168.56.11.39924 > 192.168.56.12.4789: VXLAN, flags [I] (0x08), vni 123
ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 10.0.0.2 tell 10.0.0.1, length 28
01:20:32.675732 IP (tos 0x0, ttl 64, id 38782, offset 0, flags [DF], proto UDP (17), length 78)
    192.168.56.12.40908 > 192.168.56.11.4789: VXLAN, flags [I] (0x08), vni 123
ARP, Ethernet (len 6), IPv4 (len 4), Reply 10.0.0.2 is-at 4a:7f:01:3b:a2:71, length 28
01:20:32.676047 IP (tos 0x0, ttl 64, id 55705, offset 0, flags [DF], proto UDP (17), length 134)
    192.168.56.11.48134 > 192.168.56.12.4789: VXLAN, flags [I] (0x08), vni 123
IP (tos 0x0, ttl 64, id 12111, offset 0, flags [DF], proto ICMP (1), length 84)
    10.0.0.1 > 10.0.0.2: ICMP echo request, id 3389, seq 1, length 64
01:20:32.676385 IP (tos 0x0, ttl 64, id 38783, offset 0, flags [DF], proto UDP (17), length 134)
    192.168.56.12.38071 > 192.168.56.11.4789: VXLAN, flags [I] (0x08), vni 123
IP (tos 0x0, ttl 64, id 36913, offset 0, flags [none], proto ICMP (1), length 84)
    10.0.0.2 > 10.0.0.1: ICMP echo reply, id 3389, seq 1, length 64

Reply | Threaded
Open this post in threaded view
|

Re: massage tcpdump ip and encapsulation output

Stuart Henderson
In reply to this post by David Gwynne-5
On 2019/12/06 15:14, David Gwynne wrote:

>
>
> > On 5 Dec 2019, at 21:14, Sebastian Benoit <[hidden email]> wrote:
> >
> > Claudio Jeker([hidden email]) on 2019.12.05 09:53:49 +0100:
> >> I would suggest to just pack most of the headers into one group of ().
> >>
> >> IPv4 ttl 1 [tos 0x20] 10.0.127.15 > 10.0.127.1
> >> would become
> >> IPv4 (ttl 1 tos 0x20) 10.0.127.15 > 10.0.127.1
> >> and
> >> IPv4 ttl 1 [tos 0x20] (id 39958, len 84) 10.0.127.15 > 10.0.127.1
> >> would become
> >> IPv4 (ttl 1 tos 0x20 id 39958 len 84) 10.0.127.15 > 10.0.127.1
> >>
> >> Maybe add the commas if that is easy to do.
> >
> > its more readable with commas, i think
>
> do you want me to come up with something in this space as part of the large diff, or is the large change generally ok and we can tinker with this stuff afterward?
>
> there's some concern that what i'm proposing is too radical and will break peoples muscle memory.

Personally I'm OK with the general direction and think overall it's
quite an improvement. It seems to me that it would make more sense to
commit the large change and iterate on top. (for example one tiny
obvious difference in the Apple one you showed - it prints IP/IP6
instead of IPv4/IPv6, it's only 1/2 chars but this makes it feel
quite a lot more compact - but obviously it would be stupid to
re-send a modified version of the big diff with just that changed).

Reply | Threaded
Open this post in threaded view
|

Re: massage tcpdump ip and encapsulation output

Sebastian Benoit-3
In reply to this post by David Gwynne-5
David Gwynne([hidden email]) on 2019.12.06 15:14:42 +1000:

>
>
> > On 5 Dec 2019, at 21:14, Sebastian Benoit <[hidden email]> wrote:
> >
> > Claudio Jeker([hidden email]) on 2019.12.05 09:53:49 +0100:
> >> I would suggest to just pack most of the headers into one group of ().
> >>
> >> IPv4 ttl 1 [tos 0x20] 10.0.127.15 > 10.0.127.1
> >> would become
> >> IPv4 (ttl 1 tos 0x20) 10.0.127.15 > 10.0.127.1
> >> and
> >> IPv4 ttl 1 [tos 0x20] (id 39958, len 84) 10.0.127.15 > 10.0.127.1
> >> would become
> >> IPv4 (ttl 1 tos 0x20 id 39958 len 84) 10.0.127.15 > 10.0.127.1
> >>
> >> Maybe add the commas if that is easy to do.
> >
> > its more readable with commas, i think
>
> do you want me to come up with something in this space as part of the
> large diff, or is the large change generally ok and we can tinker with
> this stuff afterward?

It was just a comment on the readability of lists like that.
I like your idea, please proceed whichever way you like.

>
> there's some concern that what i'm proposing is too radical and will break
> peoples muscle memory.

Reply | Threaded
Open this post in threaded view
|

Re: massage tcpdump ip and encapsulation output

Claudio Jeker
On Fri, Dec 06, 2019 at 12:16:09PM +0100, Sebastian Benoit wrote:

> David Gwynne([hidden email]) on 2019.12.06 15:14:42 +1000:
> >
> >
> > > On 5 Dec 2019, at 21:14, Sebastian Benoit <[hidden email]> wrote:
> > >
> > > Claudio Jeker([hidden email]) on 2019.12.05 09:53:49 +0100:
> > >> I would suggest to just pack most of the headers into one group of ().
> > >>
> > >> IPv4 ttl 1 [tos 0x20] 10.0.127.15 > 10.0.127.1
> > >> would become
> > >> IPv4 (ttl 1 tos 0x20) 10.0.127.15 > 10.0.127.1
> > >> and
> > >> IPv4 ttl 1 [tos 0x20] (id 39958, len 84) 10.0.127.15 > 10.0.127.1
> > >> would become
> > >> IPv4 (ttl 1 tos 0x20 id 39958 len 84) 10.0.127.15 > 10.0.127.1
> > >>
> > >> Maybe add the commas if that is easy to do.
> > >
> > > its more readable with commas, i think
> >
> > do you want me to come up with something in this space as part of the
> > large diff, or is the large change generally ok and we can tinker with
> > this stuff afterward?
>
> It was just a comment on the readability of lists like that.
> I like your idea, please proceed whichever way you like.
>
> >
> > there's some concern that what i'm proposing is too radical and will break
> > peoples muscle memory.

The output of tcpdump depends on the version and OS it is used on.
IMO the important bits that people normally scan for are the IPs, port
numbers, some of the TCP seq numbers or similar protocol specific data.
To make this scanning easier I suggested to reduce the line noise of the
IP header by reducing the amount of different () and [] sequences giving
the eye a way to skip over that chunk quickly.

I think the new format is better and people need to retrain a bit but
again we should not make it harder den necessary.

For me your work can go in as long as the further improvements as
discussed here follow.
--
:wq Claudio

Reply | Threaded
Open this post in threaded view
|

Re: massage tcpdump ip and encapsulation output

David Gwynne-5
so this should go in and i can keep improving things in the tree?

dlg

> On 6 Dec 2019, at 9:45 pm, Claudio Jeker <[hidden email]> wrote:
>
> On Fri, Dec 06, 2019 at 12:16:09PM +0100, Sebastian Benoit wrote:
>> David Gwynne([hidden email]) on 2019.12.06 15:14:42 +1000:
>>>
>>>
>>>> On 5 Dec 2019, at 21:14, Sebastian Benoit <[hidden email]> wrote:
>>>>
>>>> Claudio Jeker([hidden email]) on 2019.12.05 09:53:49 +0100:
>>>>> I would suggest to just pack most of the headers into one group of ().
>>>>>
>>>>> IPv4 ttl 1 [tos 0x20] 10.0.127.15 > 10.0.127.1
>>>>> would become
>>>>> IPv4 (ttl 1 tos 0x20) 10.0.127.15 > 10.0.127.1
>>>>> and
>>>>> IPv4 ttl 1 [tos 0x20] (id 39958, len 84) 10.0.127.15 > 10.0.127.1
>>>>> would become
>>>>> IPv4 (ttl 1 tos 0x20 id 39958 len 84) 10.0.127.15 > 10.0.127.1
>>>>>
>>>>> Maybe add the commas if that is easy to do.
>>>>
>>>> its more readable with commas, i think
>>>
>>> do you want me to come up with something in this space as part of the
>>> large diff, or is the large change generally ok and we can tinker with
>>> this stuff afterward?
>>
>> It was just a comment on the readability of lists like that.
>> I like your idea, please proceed whichever way you like.
>>
>>>
>>> there's some concern that what i'm proposing is too radical and will break
>>> peoples muscle memory.
>
> The output of tcpdump depends on the version and OS it is used on.
> IMO the important bits that people normally scan for are the IPs, port
> numbers, some of the TCP seq numbers or similar protocol specific data.
> To make this scanning easier I suggested to reduce the line noise of the
> IP header by reducing the amount of different () and [] sequences giving
> the eye a way to skip over that chunk quickly.
>
> I think the new format is better and people need to retrain a bit but
> again we should not make it harder den necessary.
>
> For me your work can go in as long as the further improvements as
> discussed here follow.
> --
> :wq Claudio