Reputation: 23501
Given an inode number (an opened socket), I want to find the process that opened the socket, is that possible?
Is there any function I could use?
Upvotes: 3
Views: 5563
Reputation: 20730
I looked at the ss
tool implementation to see how they get the information when we use the -p
command line option.
The fact is that they read the user entries with the following function and generate a corresponding map. Then when displaying the list of sockets, they check the map to see whether they can find the inode, if so, they have the PID.
Note that the following function needs the user to be root to find all the inode. It detects files which name are of the form socket:[<inode>]
(the files under /proc/<pid>/fd/<number>
are softlinks, try listing them with ls -l ...
to see the special socket & FIFO entries).
static void user_ent_hash_build(void)
{
const char *root = getenv("PROC_ROOT") ? : "/proc/";
struct dirent *d;
char name[1024];
int nameoff;
DIR *dir;
char *pid_context;
char *sock_context;
const char *no_ctx = "unavailable";
static int user_ent_hash_build_init;
/* If show_users & show_proc_ctx set only do this once */
if (user_ent_hash_build_init != 0)
return;
user_ent_hash_build_init = 1;
strlcpy(name, root, sizeof(name));
if (strlen(name) == 0 || name[strlen(name)-1] != '/')
strcat(name, "/");
nameoff = strlen(name);
dir = opendir(name);
if (!dir)
return;
while ((d = readdir(dir)) != NULL) {
struct dirent *d1;
char process[16];
char *p;
int pid, pos;
DIR *dir1;
char crap;
if (sscanf(d->d_name, "%d%c", &pid, &crap) != 1)
continue;
if (getpidcon(pid, &pid_context) != 0)
pid_context = strdup(no_ctx);
snprintf(name + nameoff, sizeof(name) - nameoff, "%d/fd/", pid);
pos = strlen(name);
if ((dir1 = opendir(name)) == NULL) {
free(pid_context);
continue;
}
process[0] = '\0';
p = process;
while ((d1 = readdir(dir1)) != NULL) {
const char *pattern = "socket:[";
unsigned int ino;
char lnk[64];
int fd;
ssize_t link_len;
char tmp[1024];
if (sscanf(d1->d_name, "%d%c", &fd, &crap) != 1)
continue;
snprintf(name+pos, sizeof(name) - pos, "%d", fd);
link_len = readlink(name, lnk, sizeof(lnk)-1);
if (link_len == -1)
continue;
lnk[link_len] = '\0';
if (strncmp(lnk, pattern, strlen(pattern)))
continue;
sscanf(lnk, "socket:[%u]", &ino);
snprintf(tmp, sizeof(tmp), "%s/%d/fd/%s",
root, pid, d1->d_name);
if (getfilecon(tmp, &sock_context) <= 0)
sock_context = strdup(no_ctx);
if (*p == '\0') {
FILE *fp;
snprintf(tmp, sizeof(tmp), "%s/%d/stat",
root, pid);
if ((fp = fopen(tmp, "r")) != NULL) {
if (fscanf(fp, "%*d (%[^)])", p) < 1)
; /* ignore */
fclose(fp);
}
}
user_ent_add(ino, p, pid, fd,
pid_context, sock_context);
free(sock_context);
}
free(pid_context);
closedir(dir1);
}
closedir(dir);
}
So, in other words, the fact is that there doesn't seem to be an inode to PID function in the kernel (or it's not made accessible to the end users).
Upvotes: 0
Reputation: 12658
Two ways looking at /proc
which you can find it but you need to grep with the inode you want to know. In the below case check the last column for th inode's.
$ cat /proc/net/tcp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
The value specified in the square brackets is inode again.
$ls -l /proc/5267/fd/10
lrwx------ 1 esunboj egi 64 Feb 18 12:07 /proc/5267/fd/10 -> socket:[19950]
Upvotes: 1
Reputation: 1410
There is the lsof tool which does this, you can also see this using the /proc/ filsystem as answered here. How to use lsof(List Opened Files) in a C/C++ application?
Upvotes: 1