diff options
author | Googler <noreply@google.com> | 2019-05-03 13:29:20 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2019-05-03 13:30:35 -0700 |
commit | f2699b76c89a5be1ef6411f29a57b4cccc59fa17 (patch) | |
tree | 6e5ec5a4520b98fee3551d0baa16f59db69bc42e /pkg/tcpip/link | |
parent | 264d012d81d210c6d949554667c6fbf8e330587a (diff) |
Support IPv4 fragmentation in netstack
Testing:
Unit tests and also large ping in Fuchsia OS
PiperOrigin-RevId: 246563592
Change-Id: Ia12ab619f64f4be2c8d346ce81341a91724aef95
Diffstat (limited to 'pkg/tcpip/link')
-rw-r--r-- | pkg/tcpip/link/sniffer/sniffer.go | 108 |
1 files changed, 59 insertions, 49 deletions
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<<uint(i)) == 0 { - flagsStr[i] = ' ' + // Initialize the TCP flags. + flags := tcp.Flags() + flagsStr := []byte("FSRPAU") + for i := range flagsStr { + if flags&(1<<uint(i)) == 0 { + flagsStr[i] = ' ' + } + } + details = fmt.Sprintf("flags:0x%02x (%v) seqnum: %v ack: %v win: %v xsum:0x%x", flags, string(flagsStr), tcp.SequenceNumber(), tcp.AckNumber(), tcp.WindowSize(), tcp.Checksum()) + if flags&header.TCPFlagSyn != 0 { + details += fmt.Sprintf(" options: %+v", header.ParseSynOptions(tcp.Options(), flags&header.TCPFlagAck != 0)) + } else { + details += fmt.Sprintf(" options: %+v", tcp.ParsedOptions()) } - } - details = fmt.Sprintf("flags:0x%02x (%v) seqnum: %v ack: %v win: %v xsum:0x%x", flags, string(flagsStr), tcp.SequenceNumber(), tcp.AckNumber(), tcp.WindowSize(), tcp.Checksum()) - if flags&header.TCPFlagSyn != 0 { - details += fmt.Sprintf(" options: %+v", header.ParseSynOptions(tcp.Options(), flags&header.TCPFlagAck != 0)) - } else { - details += fmt.Sprintf(" options: %+v", tcp.ParsedOptions()) } default: |