How to tie a network connection to a PID without using lsof or netstat? [closed]
Asked Answered
B

5

9

Is there a way to tie a network connection to a PID (process ID) without forking to lsof or netstat?

Currently lsof is being used to poll what connections belong which process ID. However lsof or netstat can be quite expensive on a busy host and would like to avoid having to fork to these tools.

Is there someplace similar to /proc/$pid where one can look to find this information? I know what the network connections are by examining /proc/net but can't figure out how to tie this back to a pid. Over in /proc/$pid, there doesn't seem to be any network information.

The target hosts are Linux 2.4 and Solaris 8 to 10. If possible, a solution in Perl, but am willing to do C/C++.

additional notes:

I would like to emphasize the goal here is to tie a network connection to a PID. Getting one or the other is trivial, but putting the two together in a low cost manner appears to be difficult. Thanks for the answers to so far!

Beata answered 8/5, 2009 at 5:8 Comment(0)
K
7

I don't know how often you need to poll, or what you mean with "expensive", but with the right options both netstat and lsof run a lot faster than in the default configuration.
Examples:

netstat -ltn

shows only listening tcp sockets, and omits the (slow) name resolution that is on by default.

lsof -b -n -i4tcp:80

omits all blocking operations, name resolution, and limits the selection to IPv4 tcp sockets on port 80.

Kimberliekimberlin answered 8/5, 2009 at 6:11 Comment(1)
On Linux 'netstat -tnp' gives me what I want. The 'p' gives me the pid and indeed it is quite quick. But I was hoping to avoid forking to netstat to get this information. Same with 'lsof' where I've gotten it to work very quickly but want to avoid forking.Beata
C
6

On Solaris you can use pfiles(1) to do this:

# ps -fp 308 
     UID   PID  PPID   C    STIME TTY         TIME CMD
    root   308   255   0 22:44:07 ?           0:00 /usr/lib/ssh/sshd
# pfiles 308 | egrep 'S_IFSOCK|sockname: '
   6: S_IFSOCK mode:0666 dev:326,0 ino:3255 uid:0 gid:0 size:0
        sockname: AF_INET 192.168.1.30  port: 22

For Linux, this is more complex (gruesome):

# pgrep sshd
3155
# ls -l /proc/3155/fd | fgrep socket
lrwx------ 1 root root 64 May 22 23:04 3 -> socket:[7529]
# fgrep 7529 /proc/3155/net/tcp 
   6: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 7529 1 f5baa8a0 300 0 0 2 -1            

00000000:0016 is 0.0.0.0:22. Here's the equivalent output from netstat -a:

tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
Cenesthesia answered 22/5, 2009 at 21:47 Comment(0)
W
2

For Linux, have a look at the /proc/net directory (for example, cat /proc/net/tcp lists your tcp connections). Not sure about Solaris.

Some more information here.

I guess netstat basically uses this exact same information so i don't know if you will be able to speed it up a whole lot. Be sure to try the netstat '-an' flags to NOT resolve ip-adresses to hostnames realtime (as this can take a lot of time due to dns queries).

Washable answered 8/5, 2009 at 5:56 Comment(1)
We found a round about way of figuring out the pid by looking at /proc/net/tcp. From 'tcp', get the uid and the socket. Then traverse the /proc/* where the owner is uid and the 'fd' contains the same socket. This doesn't work in Solaris unfortunately. Also I was hoping for a solution where a search through the /proc file system wasn't necessary.Beata
C
1

The easiest thing to do is

strace -f netstat -na

On Linux (I don't know about Solaris). This will give you a log of all of the system calls made. It's a lot of output, some of which will be relevant. Take a look at the files in the /proc file system that it's opening. This should lead you to how netstat does it. Indecently, ltrace will allow you to do the same thing through the c library. Not useful for you in this instance, but it can be useful in other circumstances.

If it's not clear from that, then take a look at the source.

Cetane answered 8/5, 2009 at 6:4 Comment(0)
B
0

alternative for netstat or lsof is fuser

$ fuser 22/tcp 22/tcp: 547 825 842 896 898

or if you like to know how it works (for ipv4 tcp) and do it on your own:

$ ls -l /proc//fd/ | grep $(PORT=22 grep printf ":%04x" $PORT /proc/net/tcp | awk '{printf(" -e %s",$10); }') | awk -F/ '{print $3 }'

Bilberry answered 8/3 at 16:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.