summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/link
diff options
context:
space:
mode:
authorGoogler <noreply@google.com>2019-05-03 13:29:20 -0700
committerShentubot <shentubot@google.com>2019-05-03 13:30:35 -0700
commitf2699b76c89a5be1ef6411f29a57b4cccc59fa17 (patch)
tree6e5ec5a4520b98fee3551d0baa16f59db69bc42e /pkg/tcpip/link
parent264d012d81d210c6d949554667c6fbf8e330587a (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.go108
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: