Example #1
0
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()
	}
}
Example #2
0
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)
}
Example #3
0
// 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(&eth, &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")
		}
	}
}