From cf4bb56fc66b37ef00c1e3684c28d1b696ae282e Mon Sep 17 00:00:00 2001 From: Kevin Krakauer Date: Wed, 11 Sep 2024 16:25:11 -0700 Subject: [PATCH] netstack: gvisor2pcap ipv6 support PiperOrigin-RevId: 673580199 --- tools/gvisor2pcap/BUILD | 1 + tools/gvisor2pcap/gvisor2pcap_test.go | 21 +++++++++--- tools/gvisor2pcap/main.go | 46 +++++++++++++++++---------- tools/gvisor2pcap/wget6.log | 46 +++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 21 deletions(-) create mode 100644 tools/gvisor2pcap/wget6.log diff --git a/tools/gvisor2pcap/BUILD b/tools/gvisor2pcap/BUILD index 1c4d27062..bba039e39 100644 --- a/tools/gvisor2pcap/BUILD +++ b/tools/gvisor2pcap/BUILD @@ -26,6 +26,7 @@ go_test( srcs = ["gvisor2pcap_test.go"], data = [ "wget.log", + "wget6.log", ":gvisor2pcap", ], deps = [ diff --git a/tools/gvisor2pcap/gvisor2pcap_test.go b/tools/gvisor2pcap/gvisor2pcap_test.go index c46082f57..e7dc52e4c 100644 --- a/tools/gvisor2pcap/gvisor2pcap_test.go +++ b/tools/gvisor2pcap/gvisor2pcap_test.go @@ -152,11 +152,24 @@ func TestGolden(t *testing.T) { testBinary(t, packetLogFile, tempDir) } +// TestGolden6 runs against the packet logs from `wget -6`. This is a larger, +// more realistic log than we could reasonably generate ourselves. +// +// One way to generate a new golden is via docker configured to run `runsc` +// with `--log-packets`. Build an image with wget and run +// `docker run --runtime runsc wget-image wget -6 google.com` +func TestGolden6(t *testing.T) { + tempDir := t.TempDir() + packetLogFile, err := testutil.FindFile("tools/gvisor2pcap/wget6.log") + if err != nil { + t.Fatalf("couldn't get log path: %v", err) + } + + testBinary(t, packetLogFile, tempDir) +} + // allowedErrors matches output for packets that are known to be unhandled. -var allowedErrors = regexp.MustCompile(strings.Join([]string{ - "unhandled protocol (udp|arp|icmp)", - "IPv6 packet", -}, "|")) +var allowedErrors = regexp.MustCompile("unhandled protocol (udp|arp|icmp)") // testBinary runs gvisor2pcap with an input and checks that packets are either // handled or in the set of known unhandled packet types. diff --git a/tools/gvisor2pcap/main.go b/tools/gvisor2pcap/main.go index 447df9185..a79965f3d 100644 --- a/tools/gvisor2pcap/main.go +++ b/tools/gvisor2pcap/main.go @@ -168,10 +168,6 @@ func processLine(ep *sniffer.Endpoint, scanner *bufio.Scanner) error { return fmt.Errorf("bad source: %w", err) } - if srcIP.Is6() || dstIP.Is6() { - return fmt.Errorf("IPv6 packet") - } - // Packet length is of the form "len:200". It describes the // payload length not including headers. length, err := consumeFieldUint[uint16](&tokens, "len") @@ -438,21 +434,37 @@ func processLine(ep *sniffer.Endpoint, scanner *bufio.Scanner) error { WindowSize: window, }) copy(tcpHdr[header.TCPMinimumSize:], optsBuf) + length += uint16(len(tcpHdr)) // Build IP header. - length += header.IPv4MinimumSize + uint16(len(tcpHdr)) - ipHdr := header.IPv4(make([]byte, header.IPv4MinimumSize)) - ipHdr.Encode(&header.IPv4Fields{ - TotalLength: length, - ID: id, - TTL: 10, // Made up. - TOS: 0, // Made up. - Protocol: uint8(transProto), - Checksum: csum, - SrcAddr: tcpip.AddrFrom4(srcIP.As4()), - DstAddr: tcpip.AddrFrom4(dstIP.As4()), - Options: nil, - }) + var ipHdr []byte + if srcIP.Is4() { + length += header.IPv4MinimumSize + hdr := make(header.IPv4, header.IPv4MinimumSize) + hdr.Encode(&header.IPv4Fields{ + TotalLength: length, + ID: id, + TTL: 10, // Made up. + TOS: 0, // Made up. + Protocol: uint8(transProto), + Checksum: csum, + SrcAddr: tcpip.AddrFrom4(srcIP.As4()), + DstAddr: tcpip.AddrFrom4(dstIP.As4()), + Options: nil, + }) + ipHdr = hdr + } else { + length += header.IPv6MinimumSize + hdr := make(header.IPv6, header.IPv6MinimumSize) + hdr.Encode(&header.IPv6Fields{ + PayloadLength: uint16(len(tcpHdr)), + TransportProtocol: transProto, + SrcAddr: tcpip.AddrFrom16(srcIP.As16()), + DstAddr: tcpip.AddrFrom16(dstIP.As16()), + ExtensionHeaders: header.IPv6ExtHdrSerializer{}, + }) + ipHdr = hdr + } // Build PacketBuffer. data := make([]byte, length) diff --git a/tools/gvisor2pcap/wget6.log b/tools/gvisor2pcap/wget6.log new file mode 100644 index 000000000..48178945d --- /dev/null +++ b/tools/gvisor2pcap/wget6.log @@ -0,0 +1,46 @@ +I0904 10:33:33.685134 1 sniffer.go:330] recv icmp :: -> ff02::16 unknown len:36 id:0000 code:0 +I0904 10:33:33.786062 1 sniffer.go:241] send arp 192.168.9.2 (02:42:c0:a8:09:02) -> 192.168.9.1 (00:00:00:00:00:00) valid:true +I0904 10:33:33.785972 1 strace.go:576] [ 1: 1] wget E sendto(0x3 socket:[3], 0x7edfafc17140, 0x27, 0x4000, null, 0x0) +I0904 10:33:33.786137 1 sniffer.go:241] recv arp 192.168.9.1 (02:42:29:bf:13:2b) -> 192.168.9.2 (02:42:c0:a8:09:02) valid:true +I0904 10:33:33.786181 1 sniffer.go:388] send udp 192.168.9.2:16271 -> 8.8.8.8:53 len:39 id:0x9931 xsum: 0x7fa2 +I0904 10:33:33.803439 1 sniffer.go:388] recv udp 8.8.8.8:53 -> 192.168.9.2:16271 len:67 id:0x9ffb xsum: 0x66d8 +I0904 10:33:33.804019 1 sniffer.go:330] send icmp 2001:db8:1::242:c0a8:902 -> ff02::1:ff00:1 neighbor solicit len:32 id:0000 code:0 +I0904 10:33:33.804105 1 sniffer.go:330] recv icmp 2001:db8:1::1 -> 2001:db8:1::242:c0a8:902 neighbor advert len:32 id:0000 code:0 +I0904 10:33:33.804175 1 sniffer.go:388] send tcp 2001:db8:1::242:c0a8:902:30827 -> 2607:f8b0:4005:802::200e:80 len:0 id:0x0000 flags: S seqnum:1137993137 ack:0 win:28800 xsum:0x5212 options:{MSS:1440 WS:7 TS:true TSVal:1369608490 TSEcr:0 SACKPermitted:true Flags: } +I0904 10:33:33.805764 1 sniffer.go:388] recv tcp 2607:f8b0:4005:802::200e:80 -> 2001:db8:1::242:c0a8:902:30827 len:0 id:0x0000 flags: S A seqnum:4111371323 ack:1137993138 win:65535 xsum:0x8878 options:{MSS:1440 WS:8 TS:true TSVal:2053717588 TSEcr:1369608490 SACKPermitted:true Flags: } +I0904 10:33:33.805859 1 sniffer.go:388] send tcp 2001:db8:1::242:c0a8:902:30827 -> 2607:f8b0:4005:802::200e:80 len:0 id:0x0000 flags: A seqnum:1137993138 ack:4111371324 win:225 xsum:0x809a options:{TS:true TSVal:1369608492 TSEcr:2053717588 SACKBlocks:[]} gso:stack.GSO{Type:2, NeedsCsum:true, CsumOffset:0x10, MSS:0x578, L3HdrLen:0x28, MaxSize:0x10000} +I0904 10:33:33.785972 1 strace.go:576] [ 1: 1] wget E sendto(0x3 socket:[3], 0x7edfafc17140, 0x27, 0x4000, null, 0x0) +I0904 10:33:33.806189 1 sniffer.go:388] send tcp 2001:db8:1::242:c0a8:902:30827 -> 2607:f8b0:4005:802::200e:80 len:125 id:0x0000 flags: PA seqnum:1137993138 ack:4111371324 win:4096 xsum:0x8117 options:{TS:true TSVal:1369608492 TSEcr:2053717588 SACKBlocks:[]} gso:stack.GSO{Type:2, NeedsCsum:true, CsumOffset:0x10, MSS:0x578, L3HdrLen:0x28, MaxSize:0x10000} +I0904 10:33:33.807771 1 sniffer.go:388] recv tcp 2607:f8b0:4005:802::200e:80 -> 2001:db8:1::242:c0a8:902:30827 len:0 id:0x0000 flags: A seqnum:4111371324 ack:1137993263 win:256 xsum:0xb5b0 options:{TS:true TSVal:2053717590 TSEcr:1369608492 SACKBlocks:[]} +I0904 10:33:33.825143 1 sniffer.go:388] recv tcp 2607:f8b0:4005:802::200e:80 -> 2001:db8:1::242:c0a8:902:30827 len:2158 id:0x0000 flags: PA seqnum:4111371324 ack:1137993263 win:256 xsum:0x8908 options:{TS:true TSVal:2053717608 TSEcr:1369608492 SACKBlocks:[]} +I0904 10:33:33.825190 1 sniffer.go:388] send tcp 2001:db8:1::242:c0a8:902:30827 -> 2607:f8b0:4005:802::200e:80 len:0 id:0x0000 flags: A seqnum:1137993263 ack:4111373482 win:4079 xsum:0x809a options:{TS:true TSVal:1369608511 TSEcr:2053717608 SACKBlocks:[]} gso:stack.GSO{Type:2, NeedsCsum:true, CsumOffset:0x10, MSS:0x578, L3HdrLen:0x28, MaxSize:0x10000} +I0904 10:33:33.826259 1 sniffer.go:388] send udp 192.168.9.2:33562 -> 8.8.8.8:53 len:43 id:0x9774 xsum: 0x81a5 +I0904 10:33:33.836946 1 sniffer.go:330] recv icmp fe80::1 -> ff02::16 unknown len:116 id:0000 code:0 +I0904 10:33:33.785972 1 strace.go:576] [ 1: 1] wget E sendto(0x3 socket:[3], 0x7edfafc17140, 0x27, 0x4000, null, 0x0) +I0904 10:33:33.785972 1 strace.go:576] [ 1: 1] wget E sendto(0x3 socket:[3], 0x7edfafc17140, 0x27, 0x4000, null, 0x0) +I0904 10:33:33.842379 1 sniffer.go:388] recv udp 8.8.8.8:53 -> 192.168.9.2:33562 len:71 id:0x99d2 xsum: 0x68db +I0904 10:33:33.842720 1 sniffer.go:388] send tcp 2001:db8:1::242:c0a8:902:56814 -> 2607:f8b0:4005:80c::2004:80 len:0 id:0x0000 flags: S seqnum:2405414926 ack:0 win:28800 xsum:0x1aae options:{MSS:1440 WS:7 TS:true TSVal:158600529 TSEcr:0 SACKPermitted:true Flags: } +I0904 10:33:33.843973 1 sniffer.go:388] recv tcp 2607:f8b0:4005:80c::2004:80 -> 2001:db8:1::242:c0a8:902:56814 len:0 id:0x0000 flags: S A seqnum:597967621 ack:2405414927 win:65535 xsum:0x8d3a options:{MSS:1440 WS:8 TS:true TSVal:743205612 TSEcr:158600529 SACKPermitted:true Flags: } +I0904 10:33:33.844041 1 sniffer.go:388] send tcp 2001:db8:1::242:c0a8:902:56814 -> 2607:f8b0:4005:80c::2004:80 len:0 id:0x0000 flags: A seqnum:2405414927 ack:597967622 win:225 xsum:0x809a options:{TS:true TSVal:158600530 TSEcr:743205612 SACKBlocks:[]} gso:stack.GSO{Type:2, NeedsCsum:true, CsumOffset:0x10, MSS:0x578, L3HdrLen:0x28, MaxSize:0x10000} +I0904 10:33:33.844197 1 sniffer.go:388] send tcp 2001:db8:1::242:c0a8:902:56814 -> 2607:f8b0:4005:80c::2004:80 len:129 id:0x0000 flags: PA seqnum:2405414927 ack:597967622 win:4096 xsum:0x811b options:{TS:true TSVal:158600530 TSEcr:743205612 SACKBlocks:[]} gso:stack.GSO{Type:2, NeedsCsum:true, CsumOffset:0x10, MSS:0x578, L3HdrLen:0x28, MaxSize:0x10000} +I0904 10:33:33.845429 1 sniffer.go:388] recv tcp 2607:f8b0:4005:80c::2004:80 -> 2001:db8:1::242:c0a8:902:56814 len:0 id:0x0000 flags: A seqnum:597967622 ack:2405415056 win:261 xsum:0xba6b options:{TS:true TSVal:743205613 TSEcr:158600530 SACKBlocks:[]} +I0904 10:33:33.785972 1 strace.go:576] [ 1: 1] wget E sendto(0x3 socket:[3], 0x7edfafc17140, 0x27, 0x4000, null, 0x0) +I0904 10:33:33.891752 1 sniffer.go:388] recv tcp 2607:f8b0:4005:80c::2004:80 -> 2001:db8:1::242:c0a8:902:56814 len:6040 id:0x0000 flags: PA seqnum:597967622 ack:2405415056 win:261 xsum:0x9832 options:{TS:true TSVal:743205659 TSEcr:158600530 SACKBlocks:[]} +I0904 10:33:33.785972 1 strace.go:576] [ 1: 1] wget E sendto(0x3 socket:[3], 0x7edfafc17140, 0x27, 0x4000, null, 0x0) +I0904 10:33:33.785972 1 strace.go:576] [ 1: 1] wget E sendto(0x3 socket:[3], 0x7edfafc17140, 0x27, 0x4000, null, 0x0) +I0904 10:33:33.891780 1 sniffer.go:388] recv tcp 2607:f8b0:4005:80c::2004:80 -> 2001:db8:1::242:c0a8:902:56814 len:6040 id:0x0000 flags: PA seqnum:597973662 ack:2405415056 win:261 xsum:0x9832 options:{TS:true TSVal:743205659 TSEcr:158600530 SACKBlocks:[]} +I0904 10:33:33.891812 1 sniffer.go:388] send tcp 2001:db8:1::242:c0a8:902:56814 -> 2607:f8b0:4005:80c::2004:80 len:0 id:0x0000 flags: A seqnum:2405415056 ack:597979702 win:4001 xsum:0x809a options:{TS:true TSVal:158600578 TSEcr:743205659 SACKBlocks:[]} gso:stack.GSO{Type:2, NeedsCsum:true, CsumOffset:0x10, MSS:0x578, L3HdrLen:0x28, MaxSize:0x10000} +I0904 10:33:33.893202 1 sniffer.go:388] recv tcp 2607:f8b0:4005:80c::2004:80 -> 2001:db8:1::242:c0a8:902:56814 len:12080 id:0x0000 flags: PA seqnum:597979702 ack:2405415056 win:261 xsum:0xafca options:{TS:true TSVal:743205661 TSEcr:158600578 SACKBlocks:[]} +I0904 10:33:33.893275 1 sniffer.go:388] send tcp 2001:db8:1::242:c0a8:902:56814 -> 2607:f8b0:4005:80c::2004:80 len:0 id:0x0000 flags: A seqnum:2405415056 ack:597991782 win:3994 xsum:0x809a options:{TS:true TSVal:158600579 TSEcr:743205661 SACKBlocks:[]} gso:stack.GSO{Type:2, NeedsCsum:true, CsumOffset:0x10, MSS:0x578, L3HdrLen:0x28, MaxSize:0x10000} +I0904 10:33:33.893354 1 sniffer.go:388] send tcp 2001:db8:1::242:c0a8:902:30827 -> 2607:f8b0:4005:802::200e:80 len:0 id:0x0000 flags:F A seqnum:1137993263 ack:4111373482 win:4096 xsum:0x809a options:{TS:true TSVal:1369608579 TSEcr:2053717608 SACKBlocks:[]} gso:stack.GSO{Type:2, NeedsCsum:true, CsumOffset:0x10, MSS:0x578, L3HdrLen:0x28, MaxSize:0x10000} +I0904 10:33:33.893384 1 sniffer.go:388] recv tcp 2607:f8b0:4005:80c::2004:80 -> 2001:db8:1::242:c0a8:902:56814 len:7921 id:0x0000 flags: PA seqnum:597991782 ack:2405415056 win:261 xsum:0x9f8b options:{TS:true TSVal:743205661 TSEcr:158600578 SACKBlocks:[]} +I0904 10:33:33.893414 1 sniffer.go:388] send tcp 2001:db8:1::242:c0a8:902:56814 -> 2607:f8b0:4005:80c::2004:80 len:0 id:0x0000 flags: A seqnum:2405415056 ack:597999703 win:3932 xsum:0x809a options:{TS:true TSVal:158600580 TSEcr:743205661 SACKBlocks:[]} gso:stack.GSO{Type:2, NeedsCsum:true, CsumOffset:0x10, MSS:0x578, L3HdrLen:0x28, MaxSize:0x10000} +I0904 10:33:33.785972 1 strace.go:576] [ 1: 1] wget E sendto(0x3 socket:[3], 0x7edfafc17140, 0x27, 0x4000, null, 0x0) +I0904 10:33:33.785972 1 strace.go:576] [ 1: 1] wget E sendto(0x3 socket:[3], 0x7edfafc17140, 0x27, 0x4000, null, 0x0) +I0904 10:33:33.785972 1 strace.go:576] [ 1: 1] wget E sendto(0x3 socket:[3], 0x7edfafc17140, 0x27, 0x4000, null, 0x0) +I0904 10:33:33.895413 1 sniffer.go:388] recv tcp 2607:f8b0:4005:802::200e:80 -> 2001:db8:1::242:c0a8:902:30827 len:0 id:0x0000 flags:F A seqnum:4111373482 ack:1137993264 win:256 xsum:0xac91 options:{TS:true TSVal:2053717678 TSEcr:1369608579 SACKBlocks:[]} +I0904 10:33:33.895502 1 sniffer.go:388] send tcp 2001:db8:1::242:c0a8:902:30827 -> 2607:f8b0:4005:802::200e:80 len:0 id:0x0000 flags: A seqnum:1137993264 ack:4111373483 win:4095 xsum:0x809a options:{TS:true TSVal:1369608582 TSEcr:2053717608 SACKBlocks:[]} gso:stack.GSO{Type:2, NeedsCsum:true, CsumOffset:0x10, MSS:0x578, L3HdrLen:0x28, MaxSize:0x10000} +I0904 10:33:33.895854 1 sniffer.go:388] send tcp 2001:db8:1::242:c0a8:902:56814 -> 2607:f8b0:4005:80c::2004:80 len:0 id:0x0000 flags:F A seqnum:2405415056 ack:597999703 win:4096 xsum:0x809a options:{TS:true TSVal:158600582 TSEcr:743205661 SACKBlocks:[]} gso:stack.GSO{Type:2, NeedsCsum:true, CsumOffset:0x10, MSS:0x578, L3HdrLen:0x28, MaxSize:0x10000} +I0904 10:33:33.785972 1 strace.go:576] [ 1: 1] wget E sendto(0x3 socket:[3], 0x7edfafc17140, 0x27, 0x4000, null, 0x0) +I0904 10:33:33.896544 1 sniffer.go:388] send tcp 2001:db8:1::242:c0a8:902:56814 -> 2607:f8b0:4005:80c::2004:80 len:0 id:0x0000 flags: R A seqnum:2405415057 ack:597999703 win:0 xsum:0x809a options:{TS:true TSVal:158600583 TSEcr:743205661 SACKBlocks:[]} gso:stack.GSO{Type:2, NeedsCsum:true, CsumOffset:0x10, MSS:0x578, L3HdrLen:0x28, MaxSize:0x10000} +I0904 10:33:33.785972 1 strace.go:576] [ 1: 1] wget E sendto(0x3 socket:[3], 0x7edfafc17140, 0x27, 0x4000, null, 0x0)