diff --git a/probe/endpoint/procspy/procnet.go b/probe/endpoint/procspy/procnet.go index 3eabd2838..3073ad2c3 100644 --- a/probe/endpoint/procspy/procnet.go +++ b/probe/endpoint/procspy/procnet.go @@ -5,22 +5,23 @@ import ( "net" ) +// Used to check whether we are parsing a header line +var slHeader = []byte("sl") + // ProcNet is an iterator to parse /proc/net/tcp{,6} files. type ProcNet struct { b []byte c Connection - wantedState uint bytesLocal, bytesRemote [16]byte seen map[uint64]struct{} } // NewProcNet gives a new ProcNet parser. -func NewProcNet(b []byte, wantedState uint) *ProcNet { +func NewProcNet(b []byte) *ProcNet { return &ProcNet{ - b: b, - c: Connection{}, - wantedState: wantedState, - seen: map[uint64]struct{}{}, + b: b, + c: Connection{}, + seen: map[uint64]struct{}{}, } } @@ -33,20 +34,23 @@ again: } b := p.b - if p.b[2] == 's' { + var ( + sl, local, remote, state, inode []byte + ) + + sl, b = nextField(b) // 'sl' column + if bytes.Equal(sl, slHeader) { // Skip header p.b = nextLine(b) goto again } - - var ( - local, remote, state, inode []byte - ) - _, b = nextField(b) // 'sl' column local, b = nextField(b) remote, b = nextField(b) state, b = nextField(b) - if parseHex(state) != p.wantedState { + switch parseHex(state) { + // Only process established or half-closed connections + case tcpEstablished, tcpFinWait1, tcpFinWait2, tcpCloseWait: + default: p.b = nextLine(b) goto again } diff --git a/probe/endpoint/procspy/procnet_internal_test.go b/probe/endpoint/procspy/procnet_internal_test.go index 1dd7d7f45..876282678 100644 --- a/probe/endpoint/procspy/procnet_internal_test.go +++ b/probe/endpoint/procspy/procnet_internal_test.go @@ -13,7 +13,7 @@ func TestProcNet(t *testing.T) { 2: 0100007F:0019 00000000:0000 01 00000000:00000000 00:00000000 00000000 0 0 10550 1 ffff8800a729b780 100 0 0 10 0 3: A12CF62E:E4D7 57FC1EC0:01BB 01 00000000:00000000 02:000006FA 00000000 1000 0 639474 2 ffff88007e75a740 48 4 26 10 -1 ` - p := NewProcNet([]byte(testString), tcpEstablished) + p := NewProcNet([]byte(testString)) expected := []Connection{ { LocalAddress: net.IP([]byte{0, 0, 0, 0}), @@ -59,12 +59,12 @@ func TestProcNet(t *testing.T) { func TestTransport6(t *testing.T) { // Abridged copy of my /proc/net/tcp6 - testString := ` sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout Inode + testString := ` sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout Inode 0: 00000000000000000000000000000000:19C8 00000000000000000000000000000000:0000 01 00000000:00000000 00:00000000 00000000 0 0 23661201 1 ffff880103fb4800 100 0 0 10 -1 8: 4500032000BE692B8AE31EBD919D9D10:D61C 5014002A080805400000000015100000:01BB 01 00000000:00000000 02:00000045 00000000 1000 0 36856710 2 ffff88010b796080 22 4 30 8 7 ` - p := NewProcNet([]byte(testString), tcpEstablished) + p := NewProcNet([]byte(testString)) expected := []Connection{ { // state: 10, @@ -114,7 +114,7 @@ func TestTransportNonsense(t *testing.T) { 0: 00000000:A6C0 00000000:0000 01 000000 broken line ` - p := NewProcNet([]byte(testString), tcpEstablished) + p := NewProcNet([]byte(testString)) expected := []Connection{ { LocalAddress: net.IP([]byte{0, 0, 0, 0}), @@ -142,7 +142,7 @@ func TestProcNetFiltersDuplicates(t *testing.T) { 0: 00000000:A6C0 00000000:0000 01 00000000:00000000 00:00000000 00000000 105 0 5107 1 ffff8800a6aaf040 100 0 0 10 0 1: 00000000:A6C0 00000000:0000 01 00000000:00000000 00:00000000 00000000 105 0 5107 1 ffff8800a6aaf040 100 0 0 10 0 ` - p := NewProcNet([]byte(testString), tcpEstablished) + p := NewProcNet([]byte(testString)) expected := Connection{ LocalAddress: net.IP([]byte{0, 0, 0, 0}), LocalPort: 0xa6c0, diff --git a/probe/endpoint/procspy/spy.go b/probe/endpoint/procspy/spy.go index d59de62b4..7620e208a 100644 --- a/probe/endpoint/procspy/spy.go +++ b/probe/endpoint/procspy/spy.go @@ -8,7 +8,11 @@ import ( ) const ( - tcpEstablished = 1 // according to /include/net/tcp_states.h + // according to /include/net/tcp_states.h + tcpEstablished = 1 + tcpFinWait1 = 4 + tcpFinWait2 = 5 + tcpCloseWait = 8 ) // Connection is a (TCP) connection. The Proc struct might not be filled in. diff --git a/probe/endpoint/procspy/spy_linux.go b/probe/endpoint/procspy/spy_linux.go index 61f189881..6966f852f 100644 --- a/probe/endpoint/procspy/spy_linux.go +++ b/probe/endpoint/procspy/spy_linux.go @@ -61,7 +61,7 @@ func (s *linuxScanner) Connections(processes bool) (ConnIter, error) { } return &pnConnIter{ - pn: NewProcNet(buf.Bytes(), tcpEstablished), + pn: NewProcNet(buf.Bytes()), buf: buf, procs: procs, }, nil