| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // +build !build_with_native_toolchain |
| |
| package filter |
| |
| import ( |
| "testing" |
| |
| "gvisor.dev/gvisor/pkg/tcpip" |
| "gvisor.dev/gvisor/pkg/tcpip/buffer" |
| "gvisor.dev/gvisor/pkg/tcpip/header" |
| ) |
| |
| const ( |
| testStateLocalAddrV4 = "\x0a\x00\x00\x00" |
| testStateLocalPort = 100 |
| testStateRemoteAddrV4 = "\x0a\x00\x00\x02" |
| testStateRemotePort = 200 |
| ) |
| |
| type stateTest struct { |
| dir Direction |
| netProto tcpip.NetworkProtocolNumber |
| packet func() (buffer.View, buffer.VectorisedView) |
| localState endpointState |
| remoteState endpointState |
| } |
| |
| func TestFindStateICMPv4(t *testing.T) { |
| var seq1 = []stateTest{ |
| { |
| Outgoing, |
| header.IPv4ProtocolNumber, |
| func() (buffer.View, buffer.VectorisedView) { |
| return icmpV4Packet([]byte("payload"), &icmpV4Params{ |
| srcAddr: testStateLocalAddrV4, |
| dstAddr: testStateRemoteAddrV4, |
| icmpV4Type: header.ICMPv4EchoReply, |
| code: 0, |
| }) |
| }, |
| ICMPFirstPacket, |
| ICMPFirstPacket, |
| }, |
| } |
| |
| var tests = [][]stateTest{ |
| seq1, |
| } |
| |
| for _, seq := range tests { |
| ss := NewStates() |
| |
| for _, test := range seq { |
| hdr, payload := test.packet() |
| ipv4 := header.IPv4(hdr) |
| if !ipv4.IsValid(len(hdr) + payload.Size()) { |
| t.Fatalf("ipv4 packet is not valid: %v", ipv4) |
| } |
| transportHeader := ipv4[ipv4.HeaderLength():] |
| |
| srcAddr := ipv4.SourceAddress() |
| dstAddr := ipv4.DestinationAddress() |
| payloadLength := ipv4.PayloadLength() |
| |
| s, err := ss.findStateICMPv4( |
| test.dir, |
| header.IPv4ProtocolNumber, |
| header.ICMPv4ProtocolNumber, |
| srcAddr, |
| dstAddr, |
| payloadLength, |
| transportHeader, |
| buffer.VectorisedView{}, |
| ) |
| if err != nil { |
| t.Fatalf("err: %v", err) |
| } |
| if s == nil { |
| s = ss.createState( |
| test.dir, |
| 0, // nic |
| header.ICMPv4ProtocolNumber, |
| srcAddr, |
| 0, // srcPort |
| dstAddr, |
| 0, // dstPort |
| "", // origAddr |
| 0, // origPort |
| "", // rsvdAddr |
| 0, // rsvdPort |
| false, // isNAT |
| false, // isRDR |
| payloadLength, |
| hdr, |
| transportHeader, |
| buffer.VectorisedView{}, |
| ) |
| } |
| if s == nil { |
| t.Fatal("createState failed") |
| } |
| if got, want := s.srcEp.state, test.localState; got != want { |
| t.Errorf("localState=%s, want=%s", got, want) |
| } |
| if got, want := s.dstEp.state, test.remoteState; got != want { |
| t.Errorf("remoteState=%s, want=%s", got, want) |
| } |
| } |
| } |
| } |
| |
| func TestFindStateUDP(t *testing.T) { |
| var seq1 = []stateTest{ |
| { |
| Outgoing, |
| header.IPv4ProtocolNumber, |
| func() (buffer.View, buffer.VectorisedView) { |
| return udpV4Packet([]byte("payload"), &udpParams{ |
| srcAddr: testStateLocalAddrV4, |
| srcPort: testStateLocalPort, |
| dstAddr: testStateRemoteAddrV4, |
| dstPort: testStateRemotePort, |
| }) |
| }, |
| UDPSingle, |
| UDPFirstPacket, |
| }, |
| { |
| Incoming, |
| header.IPv4ProtocolNumber, |
| func() (buffer.View, buffer.VectorisedView) { |
| return udpV4Packet([]byte("payload"), &udpParams{ |
| srcAddr: testStateRemoteAddrV4, |
| srcPort: testStateRemotePort, |
| dstAddr: testStateLocalAddrV4, |
| dstPort: testStateLocalPort, |
| }) |
| }, |
| UDPMultiple, |
| UDPSingle, |
| }, |
| { |
| Outgoing, |
| header.IPv4ProtocolNumber, |
| func() (buffer.View, buffer.VectorisedView) { |
| return udpV4Packet([]byte("payload"), &udpParams{ |
| srcAddr: testStateLocalAddrV4, |
| srcPort: testStateLocalPort, |
| dstAddr: testStateRemoteAddrV4, |
| dstPort: testStateRemotePort, |
| }) |
| }, |
| UDPMultiple, |
| UDPMultiple, |
| }, |
| } |
| |
| var tests = [][]stateTest{ |
| seq1, |
| } |
| |
| for _, seq := range tests { |
| ss := NewStates() |
| |
| for _, test := range seq { |
| hdr, payload := test.packet() |
| ipv4 := header.IPv4(hdr) |
| if !ipv4.IsValid(len(hdr) + payload.Size()) { |
| t.Fatalf("ipv4 packet is not valid: %v", ipv4) |
| } |
| transportHeader := ipv4[ipv4.HeaderLength():] |
| udp := header.UDP(transportHeader) |
| |
| srcAddr := ipv4.SourceAddress() |
| srcPort := udp.SourcePort() |
| dstAddr := ipv4.DestinationAddress() |
| dstPort := udp.DestinationPort() |
| payloadLength := ipv4.PayloadLength() |
| |
| s, err := ss.findStateUDP( |
| test.dir, |
| header.IPv4ProtocolNumber, |
| header.UDPProtocolNumber, |
| srcAddr, |
| srcPort, |
| dstAddr, |
| dstPort, |
| payloadLength, |
| transportHeader, |
| ) |
| if err != nil { |
| t.Fatalf("err: %v", err) |
| } |
| if s == nil { |
| s = ss.createState( |
| test.dir, |
| 0, // nic |
| header.UDPProtocolNumber, |
| srcAddr, |
| srcPort, |
| dstAddr, |
| dstPort, |
| "", // origAddr |
| 0, // origPort |
| "", // rsvdAddr |
| 0, // rsvdPort |
| false, // isNAT |
| false, // isRDR |
| payloadLength, |
| hdr, |
| transportHeader, |
| buffer.VectorisedView{}, |
| ) |
| } |
| if s == nil { |
| t.Fatal("createState failed") |
| } |
| if got, want := s.srcEp.state, test.localState; got != want { |
| t.Errorf("localState=%s, want=%s", got, want) |
| } |
| if got, want := s.dstEp.state, test.remoteState; got != want { |
| t.Errorf("remoteState=%s, want=%s", got, want) |
| } |
| } |
| } |
| } |
| |
| func TestFindStateTCPv4(t *testing.T) { |
| var seq1 = []stateTest{ |
| { |
| Outgoing, |
| header.IPv4ProtocolNumber, |
| func() (buffer.View, buffer.VectorisedView) { |
| return tcpV4Packet(nil, &tcpParams{ |
| srcAddr: testStateLocalAddrV4, |
| srcPort: testStateLocalPort, |
| dstAddr: testStateRemoteAddrV4, |
| dstPort: testStateRemotePort, |
| seqNum: 0, |
| ackNum: 0, |
| flags: header.TCPFlagSyn, |
| rcvWnd: 65535, |
| }) |
| }, |
| TCPOpening, |
| TCPFirstPacket, |
| }, |
| { |
| Incoming, |
| header.IPv4ProtocolNumber, |
| func() (buffer.View, buffer.VectorisedView) { |
| return tcpV4Packet(nil, &tcpParams{ |
| srcAddr: testStateRemoteAddrV4, |
| srcPort: testStateRemotePort, |
| dstAddr: testStateLocalAddrV4, |
| dstPort: testStateLocalPort, |
| seqNum: 0, |
| ackNum: 1, |
| flags: header.TCPFlagSyn | header.TCPFlagAck, |
| rcvWnd: 65535, |
| }) |
| }, |
| TCPEstablished, |
| TCPOpening, |
| }, |
| { |
| Outgoing, |
| header.IPv4ProtocolNumber, |
| func() (buffer.View, buffer.VectorisedView) { |
| return tcpV4Packet(nil, &tcpParams{ |
| srcAddr: testStateLocalAddrV4, |
| srcPort: testStateLocalPort, |
| dstAddr: testStateRemoteAddrV4, |
| dstPort: testStateRemotePort, |
| seqNum: 1, |
| ackNum: 1, |
| flags: header.TCPFlagAck, |
| rcvWnd: 53248, |
| }) |
| }, |
| TCPEstablished, |
| TCPEstablished, |
| }, |
| { |
| Outgoing, |
| header.IPv4ProtocolNumber, |
| func() (buffer.View, buffer.VectorisedView) { |
| return tcpV4Packet([]byte("payload"), &tcpParams{ |
| srcAddr: testStateLocalAddrV4, |
| srcPort: testStateLocalPort, |
| dstAddr: testStateRemoteAddrV4, |
| dstPort: testStateRemotePort, |
| seqNum: 1, |
| ackNum: 1, |
| flags: header.TCPFlagAck, |
| rcvWnd: 53248, |
| }) |
| }, |
| TCPEstablished, |
| TCPEstablished, |
| }, |
| { |
| Incoming, |
| header.IPv4ProtocolNumber, |
| func() (buffer.View, buffer.VectorisedView) { |
| return tcpV4Packet(nil, &tcpParams{ |
| srcAddr: testStateRemoteAddrV4, |
| srcPort: testStateRemotePort, |
| dstAddr: testStateLocalAddrV4, |
| dstPort: testStateLocalPort, |
| seqNum: 1, |
| ackNum: 8, |
| flags: header.TCPFlagAck, |
| rcvWnd: 65535, |
| }) |
| }, |
| TCPEstablished, |
| TCPEstablished, |
| }, |
| { |
| Incoming, |
| header.IPv4ProtocolNumber, |
| func() (buffer.View, buffer.VectorisedView) { |
| return tcpV4Packet(nil, &tcpParams{ |
| srcAddr: testStateRemoteAddrV4, |
| srcPort: testStateRemotePort, |
| dstAddr: testStateLocalAddrV4, |
| dstPort: testStateLocalPort, |
| seqNum: 1, |
| ackNum: 8, |
| flags: header.TCPFlagFin | header.TCPFlagAck, |
| rcvWnd: 65535, |
| }) |
| }, |
| TCPEstablished, |
| TCPClosing, |
| }, |
| { |
| Outgoing, |
| header.IPv4ProtocolNumber, |
| func() (buffer.View, buffer.VectorisedView) { |
| return tcpV4Packet(nil, &tcpParams{ |
| srcAddr: testStateLocalAddrV4, |
| srcPort: testStateLocalPort, |
| dstAddr: testStateRemoteAddrV4, |
| dstPort: testStateRemotePort, |
| seqNum: 8, |
| ackNum: 2, |
| flags: header.TCPFlagAck, |
| rcvWnd: 53248, |
| }) |
| }, |
| TCPEstablished, |
| TCPFinWait, |
| }, |
| { |
| Outgoing, |
| header.IPv4ProtocolNumber, |
| func() (buffer.View, buffer.VectorisedView) { |
| return tcpV4Packet(nil, &tcpParams{ |
| srcAddr: testStateLocalAddrV4, |
| srcPort: testStateLocalPort, |
| dstAddr: testStateRemoteAddrV4, |
| dstPort: testStateRemotePort, |
| seqNum: 8, |
| ackNum: 2, |
| flags: header.TCPFlagFin | header.TCPFlagAck, |
| rcvWnd: 53248, |
| }) |
| }, |
| TCPClosing, |
| TCPFinWait, |
| }, |
| { |
| Incoming, |
| header.IPv4ProtocolNumber, |
| func() (buffer.View, buffer.VectorisedView) { |
| return tcpV4Packet(nil, &tcpParams{ |
| srcAddr: testStateRemoteAddrV4, |
| srcPort: testStateRemotePort, |
| dstAddr: testStateLocalAddrV4, |
| dstPort: testStateLocalPort, |
| seqNum: 2, |
| ackNum: 9, |
| flags: header.TCPFlagAck, |
| rcvWnd: 65535, |
| }) |
| }, |
| TCPFinWait, |
| TCPFinWait, |
| }, |
| } |
| |
| var seq2 = []stateTest{ |
| { |
| Outgoing, |
| header.IPv4ProtocolNumber, |
| func() (buffer.View, buffer.VectorisedView) { |
| return tcpV4Packet(nil, &tcpParams{ |
| srcAddr: testStateLocalAddrV4, |
| srcPort: testStateLocalPort, |
| dstAddr: testStateRemoteAddrV4, |
| dstPort: testStateRemotePort, |
| seqNum: 0, |
| ackNum: 0, |
| flags: header.TCPFlagSyn, |
| tcpOpts: []byte{ // WS: 2 |
| header.TCPOptionWS, 3, 2, header.TCPOptionNOP, |
| }, |
| rcvWnd: 65535, |
| }) |
| }, |
| TCPOpening, |
| TCPFirstPacket, |
| }, |
| { |
| Incoming, |
| header.IPv4ProtocolNumber, |
| func() (buffer.View, buffer.VectorisedView) { |
| return tcpV4Packet(nil, &tcpParams{ |
| srcAddr: testStateRemoteAddrV4, |
| srcPort: testStateRemotePort, |
| dstAddr: testStateLocalAddrV4, |
| dstPort: testStateLocalPort, |
| seqNum: 0, |
| ackNum: 1, |
| flags: header.TCPFlagSyn | header.TCPFlagAck, |
| tcpOpts: []byte{ // WS: 5 |
| header.TCPOptionWS, 3, 5, header.TCPOptionNOP, |
| }, |
| rcvWnd: 65535, |
| }) |
| }, |
| TCPEstablished, |
| TCPOpening, |
| }, |
| { |
| Outgoing, |
| header.IPv4ProtocolNumber, |
| func() (buffer.View, buffer.VectorisedView) { |
| return tcpV4Packet(nil, &tcpParams{ |
| srcAddr: testStateLocalAddrV4, |
| srcPort: testStateLocalPort, |
| dstAddr: testStateRemoteAddrV4, |
| dstPort: testStateRemotePort, |
| seqNum: 1, |
| ackNum: 1, |
| flags: header.TCPFlagAck, |
| rcvWnd: 53248, |
| }) |
| }, |
| TCPEstablished, |
| TCPEstablished, |
| }, |
| { |
| Outgoing, |
| header.IPv4ProtocolNumber, |
| func() (buffer.View, buffer.VectorisedView) { |
| return tcpV4Packet([]byte("payload"), &tcpParams{ |
| srcAddr: testStateLocalAddrV4, |
| srcPort: testStateLocalPort, |
| dstAddr: testStateRemoteAddrV4, |
| dstPort: testStateRemotePort, |
| seqNum: 1, |
| ackNum: 1, |
| flags: header.TCPFlagAck, |
| rcvWnd: 53248, |
| }) |
| }, |
| TCPEstablished, |
| TCPEstablished, |
| }, |
| { |
| Incoming, |
| header.IPv4ProtocolNumber, |
| func() (buffer.View, buffer.VectorisedView) { |
| return tcpV4Packet(nil, &tcpParams{ |
| srcAddr: testStateRemoteAddrV4, |
| srcPort: testStateRemotePort, |
| dstAddr: testStateLocalAddrV4, |
| dstPort: testStateLocalPort, |
| seqNum: 1, |
| ackNum: 8, |
| flags: header.TCPFlagAck, |
| rcvWnd: 4122, |
| }) |
| }, |
| TCPEstablished, |
| TCPEstablished, |
| }, |
| } |
| |
| var tests = [][]stateTest{ |
| seq1, |
| seq2, |
| } |
| |
| for _, seq := range tests { |
| ss := NewStates() |
| |
| for _, test := range seq { |
| hdr, payload := test.packet() |
| ipv4 := header.IPv4(hdr) |
| if !ipv4.IsValid(len(hdr) + payload.Size()) { |
| t.Fatalf("ipv4 packet is not valid: %v", ipv4) |
| } |
| transportHeader := ipv4[ipv4.HeaderLength():] |
| tcp := header.TCP(transportHeader) |
| |
| srcAddr := ipv4.SourceAddress() |
| srcPort := tcp.SourcePort() |
| dstAddr := ipv4.DestinationAddress() |
| dstPort := tcp.DestinationPort() |
| payloadLength := ipv4.PayloadLength() |
| |
| s, err := ss.findStateTCP( |
| test.dir, |
| header.IPv4ProtocolNumber, |
| header.TCPProtocolNumber, |
| srcAddr, |
| srcPort, |
| dstAddr, |
| dstPort, |
| payloadLength, |
| transportHeader, |
| ) |
| if err != nil { |
| t.Fatalf("err: %v", err) |
| } |
| if s == nil { |
| s = ss.createState( |
| test.dir, |
| 0, // nic |
| header.TCPProtocolNumber, |
| srcAddr, |
| srcPort, |
| dstAddr, |
| dstPort, |
| "", // origAddr |
| 0, // origPort |
| "", // rsvdAddr |
| 0, // rsvdPort |
| false, // isNAT |
| false, // isRDR |
| payloadLength, |
| hdr, |
| transportHeader, |
| buffer.VectorisedView{}, |
| ) |
| } |
| if s == nil { |
| t.Fatal("createState failed") |
| } |
| if got, want := s.srcEp.state, test.localState; got != want { |
| t.Errorf("localState=%s, want=%s", got, want) |
| } |
| if got, want := s.dstEp.state, test.remoteState; got != want { |
| t.Errorf("remoteState=%s, want=%s", got, want) |
| } |
| t.Logf("s: %s", s) |
| } |
| } |
| } |