Get the right port number form the proc file

On Linux, the proc file (/proc/<pid>/net/tcp) contains not only the ports for the given process, as this is the same as the /proc/net/tcp file.
We can obtain the right port by the inode number which is also in the proc file and with the file descriptor of the process (/proc/<pid>/fd).
This commit is contained in:
tabi.katalin
2018-12-19 10:17:25 +01:00
committed by Baldur Karlsson
parent 8934da6dc3
commit e59fc15369
+38 -4
View File
@@ -23,6 +23,7 @@
******************************************************************************/
#include <unistd.h>
#include <algorithm>
#include "os/os_specific.h"
extern char **environ;
@@ -35,6 +36,31 @@ char **GetCurrentEnvironment()
return environ;
}
std::vector<int> getSockets(pid_t childPid)
{
std::vector<int> sockets;
string dirPath = StringFormat::Fmt("/proc/%d/fd", (int)childPid);
std::vector<PathEntry> files = FileIO::GetFilesInDirectory(dirPath.c_str());
if(files.empty())
return sockets;
for(const PathEntry &file : files)
{
string target = StringFormat::Fmt("%s/%s", dirPath.c_str(), file.filename.c_str());
char linkname[1024];
ssize_t length = readlink(target.c_str(), linkname, 1023);
if(length == -1)
continue;
linkname[length] = '\0';
uint32_t inode = 0;
int num = sscanf(linkname, "socket:[%u]", &inode);
if(num == 1)
sockets.push_back(inode);
}
return sockets;
}
int GetIdentPort(pid_t childPid)
{
int ret = 0;
@@ -59,6 +85,8 @@ int GetIdentPort(pid_t childPid)
continue;
}
std::vector<int> sockets = getSockets(childPid);
// read through the proc file to check for an open listen socket
while(ret == 0 && !feof(f))
{
@@ -67,12 +95,18 @@ int GetIdentPort(pid_t childPid)
line[sz - 1] = 0;
fgets(line, sz - 1, f);
int socketnum = 0, hexip = 0, hexport = 0;
int num = sscanf(line, " %d: %x:%x", &socketnum, &hexip, &hexport);
// an example for a line:
// sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
// 0: 00000000:9808 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1000 0 109747
int socketnum = 0, hexip = 0, hexport = 0, inode = 0;
int num = sscanf(line, " %d: %x:%x %*x:%*x %*x %*x:%*x %*x:%*x %*x %*d %*d %d", &socketnum,
&hexip, &hexport, &inode);
// find open listen socket on 0.0.0.0:port
if(num == 3 && hexip == 0 && hexport >= RenderDoc_FirstTargetControlPort &&
hexport <= RenderDoc_LastTargetControlPort)
if(num == 4 && hexip == 0 && hexport >= RenderDoc_FirstTargetControlPort &&
hexport <= RenderDoc_LastTargetControlPort &&
std::find(sockets.begin(), sockets.end(), inode) != sockets.end())
{
ret = hexport;
}