I know lsof and ss provide metadata about connections. Where do they get it from?

For example, this represents a connection:

ls -al /proc/102922/fd/98
lrwx------ 1 me me 64 dic 21 06:06 /proc/102922/fd/74 -> 'socket:[3803248]'

With ss I can see more info:

tcp   ESTAB      0      0        users:(("chrome",pid=102922,fd=98)) cubic wscale:9,7 rto:296 rtt:92.785/24.455 ato:40 mss:1448 pmtu:1500 rcvmss:536 advmss:1448 cwnd:10 bytes_sent:1463 bytes_acked:1464 bytes_received:336 segs_out:11 segs_in:7 data_segs_out:6 data_segs_in:2 send 1.25Mbps lastsnd:71284 lastrcv:71292 lastack:26068 pacing_rate 2.5Mbps delivery_rate 271kbps delivered:7 app_limited busy:308ms rcv_space:14480 rcv_ssthresh:64088 minrtt:86.996     

But, assume the system my app is running on does not have ss for some reason. How can I go from socket:[3803248] to the tcp stats that ss provides? I don't intend to fully rewrite ss :) but I'm curious about what exists in the filesystem.

  • 1
    See also the old API at /proc/net/tcp, /proc/net/unix, /proc/net/udp... Dec 22, 2021 at 14:30

1 Answer 1


trick: such things can often be figured out with a run of strace -o logfile.txt programname; in your case, you'd find out that ss creates an AF_NETLINK socket, and sends and receives messages via that.

Netlink is an logical interface of the kernel designed to give access to internals of the networking stack.

Using ldd $(which ss) you can find out that ss seems to use the libmnl library – which makes generating, sending, receiving and parsing these messages feasible. You could theoretically certainly craft such messages from hand, but you'd just be reimplementing libmnl in parts (and quite likely worse), sou you'd want to use that - it's by the same folks who invented the kernel side of this, so it kind of makes sense to use it.

  • Thank you, that's helpful.
    – user717847
    Dec 23, 2021 at 10:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .