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:
- 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. - 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 alwayssocket:[<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. :)