package common import ( "fmt" "net" ) // In order for the IpPortTuple and the TcpTuple to be used as // hashtable keys, they need to have a fixed size. This means the // net.IP is problematic because it's internally represented as a slice. // We're introducing the HashableIpPortTuple and the HashableTcpTuple // types which are internally simple byte arrays. const MaxIPPortTupleRawSize = 16 + 16 + 2 + 2 type HashableIPPortTuple [MaxIPPortTupleRawSize]byte type IPPortTuple struct { IPLength int SrcIP, DstIP net.IP SrcPort, DstPort uint16 raw HashableIPPortTuple // Src_ip:Src_port:Dst_ip:Dst_port revRaw HashableIPPortTuple // Dst_ip:Dst_port:Src_ip:Src_port } func NewIPPortTuple(ipLength int, srcIP net.IP, srcPort uint16, dstIP net.IP, dstPort uint16) IPPortTuple { tuple := IPPortTuple{ IPLength: ipLength, SrcIP: srcIP, DstIP: dstIP, SrcPort: srcPort, DstPort: dstPort, } tuple.ComputeHashebles() return tuple } func (t *IPPortTuple) ComputeHashebles() { copy(t.raw[0:16], t.SrcIP) copy(t.raw[16:18], []byte{byte(t.SrcPort >> 8), byte(t.SrcPort)}) copy(t.raw[18:34], t.DstIP) copy(t.raw[34:36], []byte{byte(t.DstPort >> 8), byte(t.DstPort)}) copy(t.revRaw[0:16], t.DstIP) copy(t.revRaw[16:18], []byte{byte(t.DstPort >> 8), byte(t.DstPort)}) copy(t.revRaw[18:34], t.SrcIP) copy(t.revRaw[34:36], []byte{byte(t.SrcPort >> 8), byte(t.SrcPort)}) } func (t *IPPortTuple) String() string { return fmt.Sprintf("IpPortTuple src[%s:%d] dst[%s:%d]", t.SrcIP.String(), t.SrcPort, t.DstIP.String(), t.DstPort) } // Hashable returns a hashable value that uniquely identifies // the IP-port tuple. func (t *IPPortTuple) Hashable() HashableIPPortTuple { return t.raw } // Hashable returns a hashable value that uniquely identifies // the IP-port tuple after swapping the source and destination. func (t *IPPortTuple) RevHashable() HashableIPPortTuple { return t.revRaw } const MaxTCPTupleRawSize = 16 + 16 + 2 + 2 + 4 type HashableTCPTuple [MaxTCPTupleRawSize]byte type TCPTuple struct { IPLength int SrcIP, DstIP net.IP SrcPort, DstPort uint16 StreamID uint32 raw HashableTCPTuple // Src_ip:Src_port:Dst_ip:Dst_port:stream_id } func TCPTupleFromIPPort(t *IPPortTuple, streamID uint32) TCPTuple { tuple := TCPTuple{ IPLength: t.IPLength, SrcIP: t.SrcIP, DstIP: t.DstIP, SrcPort: t.SrcPort, DstPort: t.DstPort, StreamID: streamID, } tuple.ComputeHashebles() return tuple } func (t *TCPTuple) ComputeHashebles() { copy(t.raw[0:16], t.SrcIP) copy(t.raw[16:18], []byte{byte(t.SrcPort >> 8), byte(t.SrcPort)}) copy(t.raw[18:34], t.DstIP) copy(t.raw[34:36], []byte{byte(t.DstPort >> 8), byte(t.DstPort)}) copy(t.raw[36:40], []byte{byte(t.StreamID >> 24), byte(t.StreamID >> 16), byte(t.StreamID >> 8), byte(t.StreamID)}) } func (t TCPTuple) String() string { return fmt.Sprintf("TcpTuple src[%s:%d] dst[%s:%d] stream_id[%d]", t.SrcIP.String(), t.SrcPort, t.DstIP.String(), t.DstPort, t.StreamID) } // Returns a pointer to the equivalent IpPortTuple. func (t TCPTuple) IPPort() *IPPortTuple { ipport := NewIPPortTuple(t.IPLength, t.SrcIP, t.SrcPort, t.DstIP, t.DstPort) return &ipport } // Hashable() returns a hashable value that uniquely identifies // the TCP tuple. func (t *TCPTuple) Hashable() HashableTCPTuple { return t.raw } // Source and destination process names, as found by the proc module. type CmdlineTuple struct { Src, Dst []byte }