func BenchmarkFlow(b *testing.B) { p := gopacket.NewPacket(testSimpleTCPPacket, LinkTypeEthernet, gopacket.DecodeOptions{Lazy: true, NoCopy: true}) net := p.NetworkLayer() for i := 0; i < b.N; i++ { net.NetworkFlow() } }
func TestDecodeSimpleTCPPacket(t *testing.T) { equal := func(desc, want string, got fmt.Stringer) { if want != got.String() { t.Errorf("%s: got %q want %q", desc, got.String(), want) } } p := gopacket.NewPacket(testSimpleTCPPacket, LinkTypeEthernet, gopacket.DecodeOptions{Lazy: true, NoCopy: true}) if eth := p.LinkLayer(); eth == nil { t.Error("No ethernet layer found") } else { equal("Eth Src", "bc:30:5b:e8:d3:49", eth.LinkFlow().Src()) equal("Eth Dst", "00:00:0c:9f:f0:20", eth.LinkFlow().Dst()) } if net := p.NetworkLayer(); net == nil { t.Error("No net layer found") } else if ip, ok := net.(*IPv4); !ok { t.Error("Net layer is not IP layer") } else { equal("IP Src", "172.17.81.73", net.NetworkFlow().Src()) equal("IP Dst", "173.222.254.225", net.NetworkFlow().Dst()) want := &IPv4{ BaseLayer: BaseLayer{testSimpleTCPPacket[14:34], testSimpleTCPPacket[34:]}, Version: 4, IHL: 5, TOS: 0, Length: 420, Id: 14815, Flags: 0x02, FragOffset: 0, TTL: 64, Protocol: 6, Checksum: 0x555A, SrcIP: []byte{172, 17, 81, 73}, DstIP: []byte{173, 222, 254, 225}, } if !reflect.DeepEqual(ip, want) { t.Errorf("IP layer mismatch, \ngot %#v\nwant %#v\n", ip, want) } } if trans := p.TransportLayer(); trans == nil { t.Error("No transport layer found") } else if tcp, ok := trans.(*TCP); !ok { t.Error("Transport layer is not TCP layer") } else { equal("TCP Src", "50679", trans.TransportFlow().Src()) equal("TCP Dst", "80", trans.TransportFlow().Dst()) want := &TCP{ BaseLayer: BaseLayer{testSimpleTCPPacket[34:66], testSimpleTCPPacket[66:]}, SrcPort: 50679, DstPort: 80, Seq: 0xc57e0e48, Ack: 0x49074232, DataOffset: 8, ACK: true, PSH: true, Window: 0x73, Checksum: 0x9a8f, Urgent: 0, sPort: []byte{0xc5, 0xf7}, dPort: []byte{0x0, 0x50}, Options: []TCPOption{ TCPOption{ OptionType: 0x1, OptionLength: 0x1, }, TCPOption{ OptionType: 0x1, OptionLength: 0x1, }, TCPOption{ OptionType: 0x8, OptionLength: 0xa, OptionData: []byte{0x3, 0x77, 0x37, 0x9c, 0x42, 0x77, 0x5e, 0x3a}, }, }, opts: [4]TCPOption{ TCPOption{ OptionType: 0x1, OptionLength: 0x1, }, TCPOption{ OptionType: 0x1, OptionLength: 0x1, }, TCPOption{ OptionType: 0x8, OptionLength: 0xa, OptionData: []byte{0x3, 0x77, 0x37, 0x9c, 0x42, 0x77, 0x5e, 0x3a}, }, TCPOption{}, }, } if !reflect.DeepEqual(tcp, want) { t.Errorf("TCP layer mismatch\ngot %#v\nwant %#v", tcp, want) } } if payload, ok := p.Layer(gopacket.LayerTypePayload).(*gopacket.Payload); payload == nil || !ok { t.Error("No payload layer found") } else { if string(payload.Payload()) != "GET / HTTP/1.1\r\nHost: www.fish.com\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Encoding: gzip,deflate,sdch\r\nAccept-Language: en-US,en;q=0.8\r\nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3\r\n\r\n" { t.Error("--- Payload STRING ---\n", string(payload.Payload()), "\n--- Payload BYTES ---\n", payload.Payload()) } } // Test re-serialization. testSerialization(t, p, testSimpleTCPPacket) }
// scan scans the dst IP address of this scanner. func (s *scanner) scan() error { // First off, get the MAC address we should be sending packets to. hwaddr, err := s.getHwAddr() if err != nil { return err } // Construct all the network layers we need. eth := layers.Ethernet{ SrcMAC: s.iface.HardwareAddr, DstMAC: hwaddr, EthernetType: layers.EthernetTypeIPv4, } ip4 := layers.IPv4{ SrcIP: s.src, DstIP: s.dst, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp := layers.TCP{ SrcPort: 54321, DstPort: 0, // will be incremented during the scan SYN: true, } tcp.SetNetworkLayerForChecksum(&ip4) // Create the flow we expect returning packets to have, so we can check // against it and discard useless packets. ipFlow := gopacket.NewFlow(layers.EndpointIPv4, s.dst, s.src) start := time.Now() for { // Send one packet per loop iteration until we've sent packets // to all of ports [1, 65535]. if tcp.DstPort < 65535 { start = time.Now() tcp.DstPort++ if err := s.send(ð, &ip4, &tcp); err != nil { log.Printf("error sending to port %v: %v", tcp.DstPort, err) } } // Time out 5 seconds after the last packet we sent. if time.Since(start) > time.Second*5 { log.Printf("timed out for %v, assuming we've seen all we can", s.dst) return nil } // Read in the next packet. data, _, err := s.handle.ReadPacketData() if err == pcap.NextErrorTimeoutExpired { continue } else if err != nil { log.Printf("error reading packet: %v", err) continue } // Parse the packet. We'd use DecodingLayerParser here if we // wanted to be really fast. packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy) // Find the packets we care about, and print out logging // information about them. All others are ignored. if net := packet.NetworkLayer(); net == nil { // log.Printf("packet has no network layer") } else if net.NetworkFlow() != ipFlow { // log.Printf("packet does not match our ip src/dst") } else if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer == nil { // log.Printf("packet has not tcp layer") } else if tcp, ok := tcpLayer.(*layers.TCP); !ok { // We panic here because this is guaranteed to never // happen. panic("tcp layer is not tcp layer :-/") } else if tcp.DstPort != 54321 { // log.Printf("dst port %v does not match", tcp.DstPort) } else if tcp.RST { log.Printf(" port %v closed", tcp.SrcPort) } else if tcp.SYN && tcp.ACK { log.Printf(" port %v open", tcp.SrcPort) } else { // log.Printf("ignoring useless packet") } } }