Esempio n. 1
0
func (i *Sniffer) decodePackets() {
	var eth layers.Ethernet
	var ip layers.IPv4
	var tcp layers.TCP
	var payload gopacket.Payload

	parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, &eth, &ip, &tcp, &payload)
	decoded := make([]gopacket.LayerType, 0, 4)

	for {
		select {
		case <-i.stopDecodeChan:
			return
		case timedRawPacket := <-i.decodePacketChan:
			newPayload := new(gopacket.Payload)
			payload = *newPayload
			err := parser.DecodeLayers(timedRawPacket.RawPacket, &decoded)
			if err != nil {
				continue
			}
			flow := types.NewTcpIpFlowFromFlows(ip.NetworkFlow(), tcp.TransportFlow())
			packetManifest := types.PacketManifest{
				Timestamp: timedRawPacket.Timestamp,
				Flow:      flow,
				RawPacket: timedRawPacket.RawPacket,
				IP:        ip,
				TCP:       tcp,
				Payload:   payload,
			}
			i.dispatcher.ReceivePacket(&packetManifest)
		}
	}
}
func TestPcapLogger(t *testing.T) {
	ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5)))
	tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2)))
	flow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow)

	pcapLogger := NewPcapLogger("fake-dir", flow)
	testWriter := NewTestPcapWriter()
	pcapLogger.fileWriter = testWriter

	pcapLogger.Start()

	// test pcap header
	want := []byte("\xd4\xc3\xb2\xa1\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00")
	if !bytes.Equal(testWriter.lastWrite, want) {
		t.Errorf("pcap header is wrong")
		t.Fail()
	}

	// test pcap packet
	rawPacket := makeTestPacket()
	testWriter.lastWrite = make([]byte, 0)
	pcapLogger.WritePacket(rawPacket, time.Now())

	if !bytes.Equal(testWriter.lastWrite, rawPacket) {
		t.Errorf("pcap packet is wrong")
		t.Fail()
	}

	pcapLogger.Stop()
}
func TestGetOverlapRingsWithZeroRings(t *testing.T) {
	ip := layers.IPv4{
		SrcIP:    net.IP{1, 2, 3, 4},
		DstIP:    net.IP{2, 3, 4, 5},
		Version:  4,
		TTL:      64,
		Protocol: layers.IPProtocolTCP,
	}
	tcp := layers.TCP{
		SYN:     true,
		SrcPort: 1,
		DstPort: 2,
	}
	tcp.SetNetworkLayerForChecksum(&ip)
	payload := gopacket.Payload([]byte{1, 2, 3, 4})
	p := types.PacketManifest{
		IP:      ip,
		TCP:     tcp,
		Payload: payload,
	}
	options := ConnectionOptions{
		MaxBufferedPagesTotal:         0,
		MaxBufferedPagesPerConnection: 0,
		MaxRingPackets:                40,
		PageCache:                     nil,
		LogDir:                        "fake-log-dir",
	}

	f := &DefaultConnFactory{}
	conn := f.Build(options).(*Connection)

	ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5)))
	tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2)))
	serverFlow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow)
	clientFlow := serverFlow.Reverse()
	conn.serverFlow = serverFlow
	conn.clientFlow = clientFlow

	head, tail := getOverlapRings(&p, serverFlow, conn.ClientStreamRing)
	if head == nil || tail == nil {
		return
	} else {
		t.Fail()
	}
	return
}
func TestOrderedCoalesceUsedPages(t *testing.T) {
	maxBufferedPagesTotal := 1024
	maxBufferedPagesPerFlow := 1024
	streamRing := types.NewRing(40)
	PageCache := newPageCache()

	ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5)))
	tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2)))
	flow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow)

	var nextSeq types.Sequence = types.Sequence(1)

	coalesce := NewOrderedCoalesce(nil, flow, PageCache, streamRing, maxBufferedPagesTotal, maxBufferedPagesPerFlow, false)

	ip := layers.IPv4{
		SrcIP:    net.IP{1, 2, 3, 4},
		DstIP:    net.IP{2, 3, 4, 5},
		Version:  4,
		TTL:      64,
		Protocol: layers.IPProtocolTCP,
	}
	tcp := layers.TCP{
		Seq:     3,
		SYN:     false,
		SrcPort: 1,
		DstPort: 2,
	}
	p := types.PacketManifest{
		Timestamp: time.Now(),
		Flow:      flow,
		IP:        ip,
		TCP:       tcp,
		Payload:   []byte{1, 2, 3, 4, 5, 6, 7},
	}

	coalesce.insert(&p, nextSeq)

	if coalesce.PageCache.used != 1 {
		t.Errorf("coalesce.pager.Used() not equal to 1\n")
		t.Fail()
	}

	coalesce.Close()
}
Esempio n. 5
0
func TestTCPHijack(t *testing.T) {
	attackLogger := NewDummyAttackLogger()
	options := ConnectionOptions{
		MaxBufferedPagesTotal:         0,
		MaxBufferedPagesPerConnection: 0,
		MaxRingPackets:                40,
		PageCache:                     nil,
		LogDir:                        "fake-log-dir",
		DetectHijack:                  true,
	}

	f := &DefaultConnFactory{}
	conn := f.Build(options).(*Connection)
	conn.AttackLogger = attackLogger

	ip := layers.IPv4{
		SrcIP:    net.IP{1, 2, 3, 4},
		DstIP:    net.IP{2, 3, 4, 5},
		Version:  4,
		TTL:      64,
		Protocol: layers.IPProtocolTCP,
	}
	tcp := layers.TCP{
		Seq:     3,
		SYN:     true,
		ACK:     false,
		SrcPort: 1,
		DstPort: 2,
	}

	ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5)))
	tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2)))
	flow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow)

	p := types.PacketManifest{
		Timestamp: time.Now(),
		Flow:      flow,
		IP:        ip,
		TCP:       tcp,
		Payload:   []byte{},
	}
	tcp.SetNetworkLayerForChecksum(&ip)
	flowReversed := flow.Reverse()

	conn.clientFlow = flow
	conn.serverFlow = flowReversed

	conn.ReceivePacket(&p)

	if conn.state != TCP_CONNECTION_REQUEST {
		t.Error("invalid state transition\n")
		t.Fail()
	}

	// next state transition test
	ip = layers.IPv4{
		SrcIP:    net.IP{2, 3, 4, 5},
		DstIP:    net.IP{1, 2, 3, 4},
		Version:  4,
		TTL:      64,
		Protocol: layers.IPProtocolTCP,
	}
	tcp = layers.TCP{
		Seq:     9,
		SYN:     true,
		ACK:     true,
		Ack:     4,
		SrcPort: 2,
		DstPort: 1,
	}
	p = types.PacketManifest{
		Timestamp: time.Now(),
		Flow:      flowReversed,
		IP:        ip,
		TCP:       tcp,
		Payload:   []byte{},
	}
	conn.ReceivePacket(&p)

	if conn.state != TCP_CONNECTION_ESTABLISHED {
		t.Errorf("invalid state transition: current state %d\n", conn.state)
		t.Fail()
	}

	// test hijack in TCP_CONNECTION_ESTABLISHED state
	ip = layers.IPv4{
		SrcIP:    net.IP{2, 3, 4, 5},
		DstIP:    net.IP{1, 2, 3, 4},
		Version:  4,
		TTL:      64,
		Protocol: layers.IPProtocolTCP,
	}
	tcp = layers.TCP{
		Seq:     6699,
		SYN:     true,
		ACK:     true,
		Ack:     4,
		SrcPort: 2,
		DstPort: 1,
	}
	p = types.PacketManifest{
		Timestamp: time.Now(),
		Flow:      flowReversed,
		IP:        ip,
		TCP:       tcp,
		Payload:   []byte{},
	}
	conn.ReceivePacket(&p)

	if attackLogger.Count != 1 {
		t.Error("hijack detection fail")
		t.Fail()
	}

	// next state transition test
	ip = layers.IPv4{
		SrcIP:    net.IP{1, 2, 3, 4},
		DstIP:    net.IP{2, 3, 4, 5},
		Version:  4,
		TTL:      64,
		Protocol: layers.IPProtocolTCP,
	}
	tcp = layers.TCP{
		Seq:     4,
		SYN:     false,
		ACK:     true,
		Ack:     10,
		SrcPort: 1,
		DstPort: 2,
	}
	p = types.PacketManifest{
		Timestamp: time.Now(),
		Flow:      flow,
		IP:        ip,
		TCP:       tcp,
		Payload:   []byte{},
	}
	conn.ReceivePacket(&p)

	if conn.state != TCP_DATA_TRANSFER {
		t.Errorf("invalid state transition; state is %d\n", conn.state)
		t.Fail()
	}

	// test hijack in TCP_DATA_TRANSFER state
	ip = layers.IPv4{
		SrcIP:    net.IP{2, 3, 4, 5},
		DstIP:    net.IP{1, 2, 3, 4},
		Version:  4,
		TTL:      64,
		Protocol: layers.IPProtocolTCP,
	}
	tcp = layers.TCP{
		Seq:     7711,
		SYN:     true,
		ACK:     true,
		Ack:     4,
		SrcPort: 2,
		DstPort: 1,
	}
	p = types.PacketManifest{
		Timestamp: time.Now(),
		Flow:      flowReversed,
		IP:        ip,
		TCP:       tcp,
		Payload:   []byte{},
	}
	conn.ReceivePacket(&p)

	if attackLogger.Count != 2 {
		t.Error("hijack detection fail")
		t.Fail()
	}

}
Esempio n. 6
0
func HelperTestThreeWayClose(isClient bool, t *testing.T) {
	PageCache := newPageCache()

	var closerState, remoteState *uint8
	attackLogger := NewDummyAttackLogger()
	options := ConnectionOptions{
		MaxBufferedPagesTotal:         0,
		MaxBufferedPagesPerConnection: 0,
		MaxRingPackets:                40,
		PageCache:                     PageCache,
		LogDir:                        "fake-log-dir",
	}

	f := &DefaultConnFactory{}
	conn := f.Build(options).(*Connection)
	conn.AttackLogger = attackLogger

	conn.state = TCP_DATA_TRANSFER
	conn.serverNextSeq = 4666
	conn.clientNextSeq = 9666

	if isClient {
		closerState = &conn.clientState
		remoteState = &conn.serverState
	} else {
		closerState = &conn.serverState
		remoteState = &conn.clientState
	}

	ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5)))
	tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2)))

	ip := layers.IPv4{
		SrcIP:    net.IP{1, 2, 3, 4},
		DstIP:    net.IP{2, 3, 4, 5},
		Version:  4,
		TTL:      64,
		Protocol: layers.IPProtocolTCP,
	}

	tcp := layers.TCP{
		Seq:     9666,
		Ack:     4111,
		FIN:     true,
		SYN:     false,
		ACK:     true,
		SrcPort: 1,
		DstPort: 2,
	}

	flow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow)
	p := types.PacketManifest{
		Timestamp: time.Now(),
		Flow:      flow,
		IP:        ip,
		TCP:       tcp,
		Payload:   []byte{},
	}

	conn.clientFlow = flow
	conn.serverFlow = flow.Reverse()

	conn.ReceivePacket(&p)
	log.Print("meow1")

	if conn.state != TCP_CONNECTION_CLOSING {
		t.Error("connection state must transition to TCP_CONNECTION_CLOSING\n")
		t.Fail()
	}
	if *closerState != TCP_FIN_WAIT1 {
		t.Error("closer state must be in TCP_FINE_WAIT1\n")
		t.Fail()
	}
	if *remoteState != TCP_CLOSE_WAIT {
		t.Error("remote state must be in TCP_CLOSE_WAIT\n")
		t.Fail()
	}

	// next state transition
	ip = layers.IPv4{
		SrcIP:    net.IP{2, 3, 4, 5},
		DstIP:    net.IP{1, 2, 3, 4},
		Version:  4,
		TTL:      64,
		Protocol: layers.IPProtocolTCP,
	}
	tcp = layers.TCP{
		Seq:     4111,
		SYN:     false,
		FIN:     true,
		ACK:     true,
		Ack:     9667,
		SrcPort: 2,
		DstPort: 1,
	}

	flow2 := flow.Reverse()

	p = types.PacketManifest{
		Timestamp: time.Now(),
		Flow:      flow2,
		IP:        ip,
		TCP:       tcp,
		Payload:   []byte{},
	}

	conn.ReceivePacket(&p)
	log.Print("meow2")

	if conn.state != TCP_CONNECTION_CLOSING {
		t.Error("connection state must transition to TCP_CONNECTION_CLOSING\n")
		t.Fail()
	}

	// next state transition
	ip = layers.IPv4{
		SrcIP:    net.IP{1, 2, 3, 4},
		DstIP:    net.IP{2, 3, 4, 5},
		Version:  4,
		TTL:      64,
		Protocol: layers.IPProtocolTCP,
	}
	tcp = layers.TCP{
		Seq:     9667,
		SYN:     false,
		FIN:     false,
		ACK:     true,
		Ack:     4112,
		SrcPort: 1,
		DstPort: 2,
	}
	p = types.PacketManifest{
		Timestamp: time.Now(),
		Flow:      flow,
		IP:        ip,
		TCP:       tcp,
		Payload:   []byte{},
	}

	conn.ReceivePacket(&p)
	log.Print("freeing page cache")
}
func TestGetOverlapRings(t *testing.T) {
	overlapTests := []struct {
		in   reassemblyInput
		want []*types.Reassembly
	}{
		{
			reassemblyInput{7, []byte{1, 2}}, []*types.Reassembly{
				{
					Seq: 5,
				},
				{
					Seq: 5,
				},
			},
		},
		{
			reassemblyInput{7, []byte{6, 7}}, []*types.Reassembly{
				{
					Seq: 5,
				},
				{
					Seq: 5,
				},
			},
		},
		{
			reassemblyInput{5, []byte{1, 2, 3, 4, 5}}, []*types.Reassembly{
				{
					Seq: 5,
				},
				{
					Seq: 5,
				},
			},
		},
		{
			reassemblyInput{5, []byte{1, 2, 3, 4, 5, 6}}, []*types.Reassembly{
				{
					Seq: 5,
				},
				{
					Seq: 10,
				},
			},
		},
		{
			reassemblyInput{6, []byte{1, 2, 3, 4, 5}}, []*types.Reassembly{
				{
					Seq: 5,
				},
				{
					Seq: 10,
				},
			},
		},
		{
			reassemblyInput{7, []byte{1, 2, 3, 4, 5}}, []*types.Reassembly{
				{
					Seq: 5,
				},
				{
					Seq: 10,
				},
			},
		},
		{
			reassemblyInput{32, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}, []*types.Reassembly{
				{
					Seq: 30,
				},
				{
					Seq: 35,
				},
			},
		},
		{
			reassemblyInput{0, []byte{1, 2, 3}}, []*types.Reassembly{
				nil,
				nil,
			},
		},
		{
			reassemblyInput{0, []byte{1, 2, 3, 4, 5, 6, 7, 8}}, []*types.Reassembly{
				{
					Seq: 5,
				},
				{
					Seq: 5,
				},
			},
		},
		{
			reassemblyInput{0, []byte{1, 2, 3, 4, 5, 6}}, []*types.Reassembly{
				{
					Seq: 5,
				},
				{
					Seq: 5,
				},
			},
		},
		{
			reassemblyInput{0, []byte{1, 2, 3}}, []*types.Reassembly{
				nil,
				nil,
			},
		},
		{
			reassemblyInput{0, []byte{1, 2, 3, 4, 5}}, []*types.Reassembly{
				nil,
				nil,
			},
		},
		{
			reassemblyInput{0, []byte{1, 2, 3, 4, 5, 6}}, []*types.Reassembly{
				{
					Seq: 5,
				},
				{
					Seq: 5,
				},
			},
		},
		{
			reassemblyInput{40, []byte{1}}, []*types.Reassembly{
				nil,
				nil,
			},
		},
		{
			reassemblyInput{42, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}, []*types.Reassembly{
				nil,
				nil,
			},
		},
		{
			reassemblyInput{38, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}}, []*types.Reassembly{
				{
					Seq: 35,
				},
				{
					Seq: 35,
				},
			},
		},
	}

	ip := layers.IPv4{
		SrcIP:    net.IP{1, 2, 3, 4},
		DstIP:    net.IP{2, 3, 4, 5},
		Version:  4,
		TTL:      64,
		Protocol: layers.IPProtocolTCP,
	}

	options := ConnectionOptions{
		MaxBufferedPagesTotal:         0,
		MaxBufferedPagesPerConnection: 0,
		MaxRingPackets:                40,
		PageCache:                     nil,
		LogDir:                        "fake-log-dir",
	}

	f := &DefaultConnFactory{}
	conn := f.Build(options).(*Connection)

	for j := 5; j < 40; j += 5 {
		reassembly := types.Reassembly{
			Skip:  0,
			Seq:   types.Sequence(j),
			Bytes: []byte{1, 2, 3, 4, 5},
		}
		conn.ClientStreamRing.Reassembly = &reassembly
		conn.ClientStreamRing = conn.ClientStreamRing.Next()
	}

	for i := 0; i < len(overlapTests); i++ {
		log.Printf("test # %d", i)
		tcp := layers.TCP{
			Seq:     overlapTests[i].in.Seq,
			SYN:     false,
			SrcPort: 1,
			DstPort: 2,
		}
		p := types.PacketManifest{
			IP:      ip,
			TCP:     tcp,
			Payload: overlapTests[i].in.Payload,
		}

		ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5)))
		tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2)))
		serverFlow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow)
		clientFlow := serverFlow.Reverse()
		conn.serverFlow = serverFlow
		conn.clientFlow = clientFlow

		head, tail := getOverlapRings(&p, serverFlow, conn.ClientStreamRing)

		log.Printf("head %v tail %v", head, tail)

		log.Printf("want %v", overlapTests[i].want[0])

		if overlapTests[i].want[0] == nil {
			log.Print("want nil results")

			if head != nil {
				t.Error("getOverlapRings did not return a nil ring segment head\n")
				t.Fail()
			}
			if tail != nil {
				t.Error("getOverlapRings did not return a nil ring segment tail\n")
				t.Fail()
			}
		} else {
			if overlapTests[i].want[0] != nil {
				if head == nil || tail == nil {
					t.Error("head or tail is nil\n")
					t.Fail()
				}
			}
			if overlapTests[i].want[0] != nil {
				if head.Reassembly.Seq.Difference(overlapTests[i].want[0].Seq) != 0 {
					t.Errorf("test %d: reassembly.Seq %d != want.Seq %d\n", i, head.Reassembly.Seq, overlapTests[i].want[0].Seq)
					t.Fail()
				}
			}
			if overlapTests[i].want[1] != nil {
				if tail.Reassembly.Seq.Difference(overlapTests[i].want[1].Seq) != 0 {
					t.Errorf("test num %d in.Seq %d != want.Seq %d\n", i, head.Reassembly.Seq, overlapTests[i].want[1].Seq)
					t.Fail()
				}
			}
		}
	}
	return
}
func TestInjectionDetector(t *testing.T) {
	log.Print("TestInjectionDetector")
	attackLogger := NewDummyAttackLogger()
	options := ConnectionOptions{
		MaxBufferedPagesTotal:         0,
		MaxBufferedPagesPerConnection: 0,
		MaxRingPackets:                40,
		PageCache:                     nil,
		LogDir:                        "fake-log-dir",
		AttackLogger:                  attackLogger,
	}

	f := &DefaultConnFactory{}
	conn := f.Build(options).(*Connection)
	reassembly := types.Reassembly{
		Seq:   types.Sequence(5),
		Bytes: []byte{1, 2, 3, 4, 5},
	}
	conn.ClientStreamRing.Reassembly = &reassembly
	conn.ClientStreamRing = conn.ClientStreamRing.Next()

	p := types.PacketManifest{
		IP: layers.IPv4{
			SrcIP:    net.IP{1, 2, 3, 4},
			DstIP:    net.IP{2, 3, 4, 5},
			Version:  4,
			TTL:      64,
			Protocol: layers.IPProtocolTCP,
		},
		TCP: layers.TCP{
			Seq:     7,
			SrcPort: 1,
			DstPort: 2,
		},
		Payload: []byte{1, 2, 3, 4, 5, 6, 7},
	}

	ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5)))
	tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2)))
	serverFlow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow)
	conn.serverFlow = serverFlow
	clientFlow := serverFlow.Reverse()
	conn.clientFlow = clientFlow
	conn.detectInjection(&p, serverFlow)

	if attackLogger.Count != 1 {
		t.Errorf("detectInjection failed; count == %d\n", attackLogger.Count)
		t.Fail()
	}

	// next test case
	p.TCP = layers.TCP{
		Seq:     7,
		SrcPort: 1,
		DstPort: 2,
	}
	p.Payload = []byte{3, 4, 5}
	conn.detectInjection(&p, serverFlow)
	if attackLogger.Count == 0 {
		t.Error("failed to detect injection\n")
		t.Fail()
	}

	// next test case
	attackLogger.Count = 0
	p.TCP = layers.TCP{
		Seq:     1,
		SrcPort: 1,
		DstPort: 2,
	}
	p.Payload = []byte{1, 2, 3, 4, 5, 6}
	conn.detectInjection(&p, serverFlow)
	if attackLogger.Count == 0 {
		t.Error("failed to detect injection\n")
		t.Fail()
	}

	// next test case
	attackLogger.Count = 0
	p.TCP = layers.TCP{
		Seq:     1,
		SrcPort: 1,
		DstPort: 2,
	}
	p.Payload = []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17}
	conn.detectInjection(&p, serverFlow)
	if attackLogger.Count != 1 {
		t.Error("injection detection failure\n")
		t.Fail()
	}
}
func TestGetOverlapBytes(t *testing.T) {
	overlapBytesTests := []struct {
		in   reassemblyInput
		want TestOverlapBytesWant
	}{
		{ //0
			reassemblyInput{3, []byte{2, 3, 4}}, TestOverlapBytesWant{
				bytes:       []byte{6},
				startOffset: 2,
				endOffset:   3,
			},
		},
		{ //1
			reassemblyInput{4, []byte{2, 3, 4}}, TestOverlapBytesWant{
				bytes:       []byte{6, 7},
				startOffset: 1,
				endOffset:   3,
			},
		},
		{ //2
			reassemblyInput{5, []byte{2, 3, 4}}, TestOverlapBytesWant{
				bytes:       []byte{6, 7, 8},
				startOffset: 0,
				endOffset:   3,
			},
		},
		{ //3
			reassemblyInput{6, []byte{1, 2, 3}}, TestOverlapBytesWant{
				bytes:       []byte{7, 8, 9},
				startOffset: 0,
				endOffset:   3,
			},
		},
		{ //4
			reassemblyInput{4, []byte{91, 92, 93, 94, 95, 96, 97}}, TestOverlapBytesWant{
				bytes:       []byte{6, 7, 8, 9, 10, 11},
				startOffset: 1,
				endOffset:   7,
			},
		},
		{
			reassemblyInput{4, []byte{91, 92, 93, 94, 95, 96, 97, 98}}, TestOverlapBytesWant{
				bytes:       []byte{6, 7, 8, 9, 10, 11, 12},
				startOffset: 1,
				endOffset:   8,
			},
		},
		{
			reassemblyInput{4, []byte{91, 92, 93, 94, 95, 96, 97, 98, 99}}, TestOverlapBytesWant{
				bytes:       []byte{6, 7, 8, 9, 10, 11, 12, 13},
				startOffset: 1,
				endOffset:   9,
			},
		},
		{
			reassemblyInput{3, []byte{1, 2, 3, 4, 5, 6, 7}}, TestOverlapBytesWant{
				bytes:       []byte{6, 7, 8, 9, 10},
				startOffset: 2,
				endOffset:   7,
			},
		},
		{
			reassemblyInput{34, []byte{1, 2, 3, 4, 5, 6, 7}}, TestOverlapBytesWant{
				bytes:       []byte{35, 36, 37, 38, 39, 40},
				startOffset: 0,
				endOffset:   6,
			},
		},
		{
			reassemblyInput{34, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}}, TestOverlapBytesWant{
				bytes:       []byte{35, 36, 37, 38, 39, 40},
				startOffset: 0,
				endOffset:   6,
			},
		},
		{
			reassemblyInput{5, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}, TestOverlapBytesWant{
				bytes:       []byte{6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40},
				startOffset: 0,
				endOffset:   35,
			},
		},

		{
			reassemblyInput{5, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}, TestOverlapBytesWant{
				bytes:       []byte{6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40},
				startOffset: 0,
				endOffset:   35,
			},
		},

		{
			reassemblyInput{5, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}}, TestOverlapBytesWant{
				bytes:       []byte{6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40},
				startOffset: 0,
				endOffset:   35,
			},
		},

		{
			reassemblyInput{4, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}, TestOverlapBytesWant{
				bytes:       []byte{6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40},
				startOffset: 1,
				endOffset:   36,
			},
		},

		{
			reassemblyInput{3, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}, TestOverlapBytesWant{
				bytes:       []byte{6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40},
				startOffset: 2,
				endOffset:   37,
			},
		},

		{
			reassemblyInput{4, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}, TestOverlapBytesWant{
				bytes:       []byte{6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40},
				startOffset: 1,
				endOffset:   36,
			},
		},
	}

	options := ConnectionOptions{
		MaxBufferedPagesTotal:         0,
		MaxBufferedPagesPerConnection: 0,
		MaxRingPackets:                40,
		PageCache:                     nil,
		LogDir:                        "fake-log-dir",
	}

	f := &DefaultConnFactory{}
	conn := f.Build(options).(*Connection)

	for j := 5; j < 40; j += 5 {
		reassembly := types.Reassembly{
			Seq:   types.Sequence(j),
			Bytes: []byte{byte(j + 1), byte(j + 2), byte(j + 3), byte(j + 4), byte(j + 5)},
		}
		conn.ClientStreamRing.Reassembly = &reassembly
		conn.ClientStreamRing = conn.ClientStreamRing.Next()
	}
	for i := 0; i < len(overlapBytesTests); i++ {
		var startSeq uint32 = overlapBytesTests[i].in.Seq
		start := types.Sequence(startSeq)
		end := start.Add(len(overlapBytesTests[i].in.Payload) - 1)
		p := types.PacketManifest{
			IP: layers.IPv4{
				SrcIP:    net.IP{1, 2, 3, 4},
				DstIP:    net.IP{2, 3, 4, 5},
				Version:  4,
				TTL:      64,
				Protocol: layers.IPProtocolTCP,
			},
			TCP: layers.TCP{
				Seq:     startSeq,
				SrcPort: 1,
				DstPort: 2,
			},
			Payload: overlapBytesTests[i].in.Payload,
		}

		ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5)))
		tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2)))
		serverFlow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow)
		clientFlow := serverFlow.Reverse()
		conn.serverFlow = serverFlow
		conn.clientFlow = clientFlow

		head, tail := getOverlapRings(&p, serverFlow, conn.ClientStreamRing)
		if head == nil || tail == nil {
			t.Errorf("%d getOverlapRings returned a nil\n", i)
			t.Fail()
			continue
		}

		log.Printf("test #%d", i)
		overlapBytes, startOffset, endOffset := getOverlapBytes(head, tail, start, end)

		if startOffset != overlapBytesTests[i].want.startOffset {
			t.Errorf("test %d startOffset %d does not match want.startOffset %d\n", i, startOffset, overlapBytesTests[i].want.startOffset)
			t.Fail()
		}
		if endOffset != overlapBytesTests[i].want.endOffset {
			t.Errorf("test %d endOffset %d does not match want.endOffset %d\n", i, endOffset, overlapBytesTests[i].want.endOffset)
			t.Fail()
		}
		if len(overlapBytes) != len(overlapBytesTests[i].want.bytes) {
			t.Errorf("test %d overlapBytes len %d not equal to want.bytes len %d\n", i, len(overlapBytes), len(overlapBytesTests[i].want.bytes))
			t.Fail()
		}
		if !bytes.Equal(overlapBytes, overlapBytesTests[i].want.bytes) {
			t.Errorf("test %d overlapBytes %x not equal to want.bytes %x\n", i, overlapBytes, overlapBytesTests[i].want.bytes)
			t.Fail()
		}
	}
}
func TestGetRingSlice(t *testing.T) {
	options := ConnectionOptions{
		MaxBufferedPagesTotal:         0,
		MaxBufferedPagesPerConnection: 0,
		MaxRingPackets:                40,
		PageCache:                     nil,
		LogDir:                        "fake-log-dir",
	}

	f := &DefaultConnFactory{}
	conn := f.Build(options).(*Connection)
	for j := 5; j < 40; j += 5 {
		reassembly := types.Reassembly{
			Seq:   types.Sequence(j),
			Bytes: []byte{1, 2, 3, 4, 5},
		}

		conn.ClientStreamRing.Reassembly = &reassembly
		conn.ClientStreamRing = conn.ClientStreamRing.Next()
	}
	var startSeq uint32 = 5
	p := types.PacketManifest{
		IP: layers.IPv4{
			SrcIP:    net.IP{1, 2, 3, 4},
			DstIP:    net.IP{2, 3, 4, 5},
			Version:  4,
			TTL:      64,
			Protocol: layers.IPProtocolTCP,
		},
		TCP: layers.TCP{
			Seq:     startSeq,
			SrcPort: 1,
			DstPort: 2,
		},
		Payload: []byte{1, 2, 3, 4, 5, 6, 7},
	}

	ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5)))
	tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2)))
	serverFlow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow)
	clientFlow := serverFlow.Reverse()
	conn.serverFlow = serverFlow
	conn.clientFlow = clientFlow

	head, tail := getOverlapRings(&p, serverFlow, conn.ClientStreamRing)

	if head == nil {
		t.Fatal()
	}
	if tail == nil {
		t.Fatal()
	}

	ringSlice := getRingSlice(head, tail, 0, 1)
	if !bytes.Equal(ringSlice, []byte{1, 2, 3, 4, 5, 1}) {
		t.Error("byte comparison failed")
		t.Fail()
	}

	ringSlice = getRingSlice(head, tail, 0, 3)
	if !bytes.Equal(ringSlice, []byte{1, 2, 3, 4, 5, 1, 2, 3}) {
		t.Error("byte comparison failed")
		t.Fail()
	}

	ringSlice = getRingSlice(head, tail, 0, 1)
	if !bytes.Equal(ringSlice, []byte{1, 2, 3, 4, 5, 1}) {
		t.Error("byte comparison failed")
		t.Fail()
	}

	ringSlice = getRingSlice(head, tail, 1, 0)
	if !bytes.Equal(ringSlice, []byte{2, 3, 4, 5}) {
		t.Error("byte comparison failed")
		t.Fail()
	}

	ringSlice = getRingSlice(head, tail, 1, 1)
	if !bytes.Equal(ringSlice, []byte{2, 3, 4, 5, 1}) {
		t.Error("byte comparison failed")
		t.Fail()
	}

	ringSlice = getRingSlice(head, tail, 2, 0)
	if !bytes.Equal(ringSlice, []byte{3, 4, 5}) {
		t.Error("byte comparison failed")
		t.Fail()
	}
	ringSlice = getRingSlice(head, tail, 2, 3)
	if !bytes.Equal(ringSlice, []byte{3, 4, 5, 1, 2, 3}) {
		t.Error("byte comparison failed")
		t.Fail()
	}

	startSeq = 1
	p = types.PacketManifest{
		IP: layers.IPv4{
			SrcIP:    net.IP{1, 2, 3, 4},
			DstIP:    net.IP{2, 3, 4, 5},
			Version:  4,
			TTL:      64,
			Protocol: layers.IPProtocolTCP,
		},
		TCP: layers.TCP{
			Seq:     startSeq,
			SrcPort: 1,
			DstPort: 2,
		},
		Payload: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
	}

	head, tail = getOverlapRings(&p, serverFlow, conn.ClientStreamRing)

	log.Printf("sequence of head %d", head.Reassembly.Seq)
	log.Printf("and tail %d", tail.Reassembly.Seq)

	ringSlice = getRingSlice(head, tail, 0, 2)

	if !bytes.Equal(ringSlice, []byte{1, 2, 3, 4, 5, 1, 2}) {
		t.Errorf("ringSlice is %x\n", ringSlice)
		t.Fail()
	}

	ringSlice = getRingSlice(head, tail, 2, 4)
	if !bytes.Equal(ringSlice, []byte{3, 4, 5, 1, 2, 3, 4}) {
		t.Errorf("ringSlice is %x\n", ringSlice) //XXX
		t.Fail()
	}
}