From f2699b76c89a5be1ef6411f29a57b4cccc59fa17 Mon Sep 17 00:00:00 2001 From: Googler Date: Fri, 3 May 2019 13:29:20 -0700 Subject: Support IPv4 fragmentation in netstack Testing: Unit tests and also large ping in Fuchsia OS PiperOrigin-RevId: 246563592 Change-Id: Ia12ab619f64f4be2c8d346ce81341a91724aef95 --- pkg/tcpip/link/sniffer/sniffer.go | 108 +++++++++++++++++++++----------------- 1 file changed, 59 insertions(+), 49 deletions(-) (limited to 'pkg/tcpip/link/sniffer/sniffer.go') diff --git a/pkg/tcpip/link/sniffer/sniffer.go b/pkg/tcpip/link/sniffer/sniffer.go index e87ae07d7..fccabd554 100644 --- a/pkg/tcpip/link/sniffer/sniffer.go +++ b/pkg/tcpip/link/sniffer/sniffer.go @@ -247,9 +247,13 @@ func logPacket(prefix string, protocol tcpip.NetworkProtocolNumber, b buffer.Vie dst := tcpip.Address("unknown") id := 0 size := uint16(0) + var fragmentOffset uint16 + var moreFragments bool switch protocol { case header.IPv4ProtocolNumber: ipv4 := header.IPv4(b) + fragmentOffset = ipv4.FragmentOffset() + moreFragments = ipv4.Flags()&header.IPv4FlagMoreFragments == header.IPv4FlagMoreFragments src = ipv4.SourceAddress() dst = ipv4.DestinationAddress() transProto = ipv4.Protocol() @@ -290,29 +294,31 @@ func logPacket(prefix string, protocol tcpip.NetworkProtocolNumber, b buffer.Vie transName = "icmp" icmp := header.ICMPv4(b) icmpType := "unknown" - switch icmp.Type() { - case header.ICMPv4EchoReply: - icmpType = "echo reply" - case header.ICMPv4DstUnreachable: - icmpType = "destination unreachable" - case header.ICMPv4SrcQuench: - icmpType = "source quench" - case header.ICMPv4Redirect: - icmpType = "redirect" - case header.ICMPv4Echo: - icmpType = "echo" - case header.ICMPv4TimeExceeded: - icmpType = "time exceeded" - case header.ICMPv4ParamProblem: - icmpType = "param problem" - case header.ICMPv4Timestamp: - icmpType = "timestamp" - case header.ICMPv4TimestampReply: - icmpType = "timestamp reply" - case header.ICMPv4InfoRequest: - icmpType = "info request" - case header.ICMPv4InfoReply: - icmpType = "info reply" + if fragmentOffset == 0 { + switch icmp.Type() { + case header.ICMPv4EchoReply: + icmpType = "echo reply" + case header.ICMPv4DstUnreachable: + icmpType = "destination unreachable" + case header.ICMPv4SrcQuench: + icmpType = "source quench" + case header.ICMPv4Redirect: + icmpType = "redirect" + case header.ICMPv4Echo: + icmpType = "echo" + case header.ICMPv4TimeExceeded: + icmpType = "time exceeded" + case header.ICMPv4ParamProblem: + icmpType = "param problem" + case header.ICMPv4Timestamp: + icmpType = "timestamp" + case header.ICMPv4TimestampReply: + icmpType = "timestamp reply" + case header.ICMPv4InfoRequest: + icmpType = "info request" + case header.ICMPv4InfoReply: + icmpType = "info reply" + } } log.Infof("%s %s %v -> %v %s len:%d id:%04x code:%d", prefix, transName, src, dst, icmpType, size, id, icmp.Code()) return @@ -351,8 +357,10 @@ func logPacket(prefix string, protocol tcpip.NetworkProtocolNumber, b buffer.Vie case header.UDPProtocolNumber: transName = "udp" udp := header.UDP(b) - srcPort = udp.SourcePort() - dstPort = udp.DestinationPort() + if fragmentOffset == 0 && len(udp) >= header.UDPMinimumSize { + srcPort = udp.SourcePort() + dstPort = udp.DestinationPort() + } size -= header.UDPMinimumSize details = fmt.Sprintf("xsum: 0x%x", udp.Checksum()) @@ -360,33 +368,35 @@ func logPacket(prefix string, protocol tcpip.NetworkProtocolNumber, b buffer.Vie case header.TCPProtocolNumber: transName = "tcp" tcp := header.TCP(b) - offset := int(tcp.DataOffset()) - if offset < header.TCPMinimumSize { - details += fmt.Sprintf("invalid packet: tcp data offset too small %d", offset) - break - } - if offset > len(tcp) { - details += fmt.Sprintf("invalid packet: tcp data offset %d larger than packet buffer length %d", offset, len(tcp)) - break - } + if fragmentOffset == 0 && len(tcp) >= header.TCPMinimumSize { + offset := int(tcp.DataOffset()) + if offset < header.TCPMinimumSize { + details += fmt.Sprintf("invalid packet: tcp data offset too small %d", offset) + break + } + if offset > len(tcp) && !moreFragments { + details += fmt.Sprintf("invalid packet: tcp data offset %d larger than packet buffer length %d", offset, len(tcp)) + break + } - srcPort = tcp.SourcePort() - dstPort = tcp.DestinationPort() - size -= uint16(offset) + srcPort = tcp.SourcePort() + dstPort = tcp.DestinationPort() + size -= uint16(offset) - // Initialize the TCP flags. - flags := tcp.Flags() - flagsStr := []byte("FSRPAU") - for i := range flagsStr { - if flags&(1<