func (tcp *Tcp) getStream(pkt *protos.Packet) (stream TcpStream, created bool) { if conn := tcp.findStream(pkt.Tuple.Hashable()); conn != nil { return TcpStream{conn: conn, dir: TcpDirectionOriginal}, false } if conn := tcp.findStream(pkt.Tuple.RevHashable()); conn != nil { return TcpStream{conn: conn, dir: TcpDirectionReverse}, false } protocol := tcp.decideProtocol(&pkt.Tuple) if protocol == protos.UnknownProtocol { // don't follow return TcpStream{}, false } var timeout time.Duration mod := tcp.protocols.GetTcp(protocol) if mod != nil { timeout = mod.ConnectionTimeout() } if isDebug { t := pkt.Tuple debugf("Connection src[%s:%d] dst[%s:%d] doesn't exist, creating new", t.Src_ip.String(), t.Src_port, t.Dst_ip.String(), t.Dst_port) } conn := &TcpConnection{ id: tcp.getId(), tuple: &pkt.Tuple, protocol: protocol, tcp: tcp} conn.tcptuple = common.TcpTupleFromIpPort(conn.tuple, conn.id) tcp.streams.PutWithTimeout(pkt.Tuple.Hashable(), conn, timeout) return TcpStream{conn: conn, dir: TcpDirectionOriginal}, true }
func (tcp *Tcp) Process(tcphdr *layers.TCP, pkt *protos.Packet) { // This Recover should catch all exceptions in // protocol modules. defer logp.Recover("Process tcp exception") stream := tcp.getStream(pkt.Tuple.Hashable()) var original_dir uint8 = TcpDirectionOriginal created := false if stream == nil { stream = tcp.getStream(pkt.Tuple.RevHashable()) if stream == nil { protocol := tcp.decideProtocol(&pkt.Tuple) if protocol == protos.UnknownProtocol { // don't follow return } timeout := time.Duration(0) mod := tcp.protocols.GetTcp(protocol) if mod != nil { timeout = mod.ConnectionTimeout() } logp.Debug("tcp", "Stream doesn't exist, creating new") // create stream = &TcpStream{id: tcp.getId(), tuple: &pkt.Tuple, protocol: protocol, tcp: tcp} stream.tcptuple = common.TcpTupleFromIpPort(stream.tuple, stream.id) tcp.streams.PutWithTimeout(pkt.Tuple.Hashable(), stream, timeout) created = true } else { original_dir = TcpDirectionReverse } } tcp_start_seq := tcphdr.Seq tcp_seq := tcp_start_seq + uint32(len(pkt.Payload)) logp.Debug("tcp", "pkt.start_seq=%v pkt.last_seq=%v stream.last_seq=%v (len=%d)", tcp_start_seq, tcp_seq, stream.lastSeq[original_dir], len(pkt.Payload)) if len(pkt.Payload) > 0 && stream.lastSeq[original_dir] != 0 { if tcpSeqBeforeEq(tcp_seq, stream.lastSeq[original_dir]) { logp.Debug("tcp", "Ignoring what looks like a retransmitted segment. pkt.seq=%v len=%v stream.seq=%v", tcphdr.Seq, len(pkt.Payload), stream.lastSeq[original_dir]) return } if tcpSeqBefore(stream.lastSeq[original_dir], tcp_start_seq) { if !created { logp.Debug("tcp", "Gap in tcp stream. last_seq: %d, seq: %d", stream.lastSeq[original_dir], tcp_start_seq) drop := stream.gapInStream(original_dir, int(tcp_start_seq-stream.lastSeq[original_dir])) if drop { logp.Debug("tcp", "Dropping stream because of gap") tcp.streams.Delete(stream.tuple.Hashable()) } } } } stream.lastSeq[original_dir] = tcp_seq stream.addPacket(pkt, tcphdr, original_dir) }