Home > other >  How do I find the process ID that listens to SOCK_SEQPACKET in C/C program
How do I find the process ID that listens to SOCK_SEQPACKET in C/C program

Time:02-03

There is a server that starts and listens to a SOCK_SEQPACKET. I think a SOCK_SEQPACKET has a name, say, @Foo. It's per user, so initiated by each Linux user account, and there is only one service per user.

The goal is to make an external tool that forcefully kill the service when something goes wrong. The language is C .

When I have to kill that service, I use netstat:

$ netstat -lnp | egrep Foo

I would not like to have a dependency on the net-tools package, though. I would like to do this with minimal dependencies on external tools and/or even libraries.

I've tried Google search, and could not find how. I guess I could perhaps read netstat source code to see how they do; I would like to defer that to the last resort, though. I have learned how I could kill the service, using netstat, which gives me dependency on net-tools. The service somehow runs as /proc/self or so. I could visit every process ID in /proc, and see if that looks like the service: see the executable name, etc. However, that is not necessarily sufficient indication to narrow down to that one single process, which uses the @Foo SOCK_SEQPACKET. Now, as non-expert in socket/network programming, I am running out of ideas about how I should proceed.

CodePudding user response:

As @user253751 says, that's not actually a socket type but more of a socket behavior type. As they suggested, it is probably a unix domain socket. Given the '@' sign in it, it is almost certainly using the unix domain socket's "abstract" namespace (which means the socket doesn't have an endpoint directly visible in the filesystem). At the system call level, such endpoints are created with a null byte as the first character (the @ is commonly substituted in command line utilities or wherever the socket is surfaced to user space for user convenience). See the unix(7) man page for more details.

Since the socket doesn't appear in the filesystem anywhere, it can be difficult to find the association of process to socket. One way you can find that is through use of the lsof utility -- but that is probably little improvement over the netstat utility.

It appears that the abstract namespace sockets do show up in the /proc/net/unix pseudo-file. In association with that, there is an inode column (second to the last). In conjunction with looking at each process's /proc/<pid>/fd directory, I think you can make the association.

For example, I created a small python program that creates a Unix domain SOCK_SEQPACKET socket and binds it to '@Foo'. That program is here:

import socket, time

sock = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
sock.bind('\0Foo')  # Note the \0 for the initial null byte
time.sleep(10000)   # Just hang around while we do other stuff

In a separate terminal window:

gh $ grep '@Foo' /proc/net/unix
0000000000000000: 00000002 00000000 00000000 0005 01 7733102 @Foo

gh $ sudo bash -c 'for proc in /proc/[0-9]*; do ls -l $proc/fd | grep 7733102 && echo $proc; done'
lrwx------ 1 gh gh 64 Feb  2 17:13 3 -> socket:[7733102]
/proc/339264    

gh $ ps -fp 339264
UID   PID    PPID  C STIME TTY          TIME CMD
gh   339264   22444  0 17:11 pts/3    00:00:00 python3

gh $ ls -l /proc/339264/fd
total 0
lrwx------ 1 gh gh 64 Feb  2 17:13 0 -> /dev/pts/3
lrwx------ 1 gh gh 64 Feb  2 17:13 1 -> /dev/pts/3
lrwx------ 1 gh gh 64 Feb  2 17:13 2 -> /dev/pts/3
lrwx------ 1 gh gh 64 Feb  2 17:13 3 -> 'socket:[7733102]'

Explaining:

  1. First, we do a grep on /proc/net/unix for the '@Foo' socket. That gives us the inode number 7733102 (second to last column). The inode number is unique to every socket on the system.
  2. Next, as root, we do an ls -l /proc/<pid>/fd for each process on the system and grep for the inode number we found in the previous step. When found, we printed out the /proc/<pid> entry. (On linux, that pseudo-directory shows a symlink to a representation of what each file descriptor open in the process is. For sockets, that representation is always socket:[<inode>].) Here we found the process ID is 339264.

The remaining two steps are just confirming that that is in fact, our python process, and you can see its four open files (the first three [stdin, stdout, stderr] all pointing to its terminal's pseudo-tty, the fourth to the socket).

To make this into a more foolproof program, you'd need to account for the fact that the inode number you found in step 1 could be a substring of some other socket's inode number but that is left as an exercise for the reader. :)

  • Related