From 88efa359d533b54f823c11fec7f746aae0ac19c0 Mon Sep 17 00:00:00 2001 From: Lucas Manning Date: Tue, 9 Jan 2024 14:25:18 -0800 Subject: [PATCH] Handle PCAP logging in non XDP case and update sniffer to print GSO opts. PiperOrigin-RevId: 597044663 --- pkg/tcpip/link/sniffer/sniffer.go | 30 +++++++++++++++--------------- runsc/boot/network.go | 16 +++++++++++++++- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/pkg/tcpip/link/sniffer/sniffer.go b/pkg/tcpip/link/sniffer/sniffer.go index c3a186741..542509c76 100644 --- a/pkg/tcpip/link/sniffer/sniffer.go +++ b/pkg/tcpip/link/sniffer/sniffer.go @@ -190,15 +190,15 @@ func LogPacket(prefix string, dir Direction, protocol tcpip.NetworkProtocolNumbe panic(fmt.Sprintf("unrecognized direction: %d", dir)) } - pkt = trimmedClone(pkt) - defer pkt.DecRef() + clone := trimmedClone(pkt) + defer clone.DecRef() switch protocol { case header.IPv4ProtocolNumber: - if ok := parse.IPv4(pkt); !ok { + if ok := parse.IPv4(clone); !ok { return } - ipv4 := header.IPv4(pkt.NetworkHeader().Slice()) + ipv4 := header.IPv4(clone.NetworkHeader().Slice()) fragmentOffset = ipv4.FragmentOffset() moreFragments = ipv4.Flags()&header.IPv4FlagMoreFragments == header.IPv4FlagMoreFragments src = ipv4.SourceAddress() @@ -208,12 +208,12 @@ func LogPacket(prefix string, dir Direction, protocol tcpip.NetworkProtocolNumbe id = uint32(ipv4.ID()) case header.IPv6ProtocolNumber: - proto, fragID, fragOffset, fragMore, ok := parse.IPv6(pkt) + proto, fragID, fragOffset, fragMore, ok := parse.IPv6(clone) if !ok { return } - ipv6 := header.IPv6(pkt.NetworkHeader().Slice()) + ipv6 := header.IPv6(clone.NetworkHeader().Slice()) src = ipv6.SourceAddress() dst = ipv6.DestinationAddress() transProto = uint8(proto) @@ -223,11 +223,11 @@ func LogPacket(prefix string, dir Direction, protocol tcpip.NetworkProtocolNumbe fragmentOffset = fragOffset case header.ARPProtocolNumber: - if !parse.ARP(pkt) { + if !parse.ARP(clone) { return } - arp := header.ARP(pkt.NetworkHeader().Slice()) + arp := header.ARP(clone.NetworkHeader().Slice()) log.Infof( "%s%s arp %s (%s) -> %s (%s) valid:%t", prefix, @@ -250,7 +250,7 @@ func LogPacket(prefix string, dir Direction, protocol tcpip.NetworkProtocolNumbe switch tcpip.TransportProtocolNumber(transProto) { case header.ICMPv4ProtocolNumber: transName = "icmp" - hdr, ok := pkt.Data().PullUp(header.ICMPv4MinimumSize) + hdr, ok := clone.Data().PullUp(header.ICMPv4MinimumSize) if !ok { break } @@ -287,7 +287,7 @@ func LogPacket(prefix string, dir Direction, protocol tcpip.NetworkProtocolNumbe case header.ICMPv6ProtocolNumber: transName = "icmp" - hdr, ok := pkt.Data().PullUp(header.ICMPv6MinimumSize) + hdr, ok := clone.Data().PullUp(header.ICMPv6MinimumSize) if !ok { break } @@ -322,11 +322,11 @@ func LogPacket(prefix string, dir Direction, protocol tcpip.NetworkProtocolNumbe case header.UDPProtocolNumber: transName = "udp" - if ok := parse.UDP(pkt); !ok { + if ok := parse.UDP(clone); !ok { break } - udp := header.UDP(pkt.TransportHeader().Slice()) + udp := header.UDP(clone.TransportHeader().Slice()) if fragmentOffset == 0 { srcPort = udp.SourcePort() dstPort = udp.DestinationPort() @@ -336,18 +336,18 @@ func LogPacket(prefix string, dir Direction, protocol tcpip.NetworkProtocolNumbe case header.TCPProtocolNumber: transName = "tcp" - if ok := parse.TCP(pkt); !ok { + if ok := parse.TCP(clone); !ok { break } - tcp := header.TCP(pkt.TransportHeader().Slice()) + tcp := header.TCP(clone.TransportHeader().Slice()) if fragmentOffset == 0 { offset := int(tcp.DataOffset()) if offset < header.TCPMinimumSize { details += fmt.Sprintf("invalid packet: tcp data offset too small %d", offset) break } - if size := pkt.Data().Size() + len(tcp); offset > size && !moreFragments { + if size := clone.Data().Size() + len(tcp); offset > size && !moreFragments { details += fmt.Sprintf("invalid packet: tcp data offset %d larger than tcp packet length %d", offset, size) break } diff --git a/runsc/boot/network.go b/runsc/boot/network.go index c1d98126f..3506aa382 100644 --- a/runsc/boot/network.go +++ b/runsc/boot/network.go @@ -320,7 +320,21 @@ func (n *Network) CreateLinksAndRoutes(args *CreateLinksAndRoutesArgs, _ *struct } // Wrap linkEP in a sniffer to enable packet logging. - sniffEP := sniffer.New(packetsocket.New(linkEP)) + var sniffEP stack.LinkEndpoint + if args.PCAP { + newFD, err := unix.Dup(int(args.FilePayload.Files[fdOffset].Fd())) + if err != nil { + return fmt.Errorf("failed to dup pcap FD: %v", err) + } + const packetTruncateSize = 4096 + sniffEP, err = sniffer.NewWithWriter(packetsocket.New(linkEP), os.NewFile(uintptr(newFD), "pcap-file"), packetTruncateSize) + if err != nil { + return fmt.Errorf("failed to create PCAP logger: %v", err) + } + fdOffset++ + } else { + sniffEP = sniffer.New(packetsocket.New(linkEP)) + } var qDisc stack.QueueingDiscipline switch link.QDisc {