Reputation: 920
In MacOS, other than launching lsof
command, is there way to get the process id of a socket's peer from within a TCP server that is bound to localhost? If there isn't, is lsof
guaranteed to be present in all OSX versions starting from 10.11 (El Capitan)?
EDIT: The server process is running within the current user context (it does not have elevated privileges). And the connecting process is also expected to be running at the same privilege level.
TIA.
Upvotes: 0
Views: 1131
Reputation: 402
This is surprisingly easy, despite the apparent ignorance around the Internet of this solution. LOCAL_PEERPID
is your friend here.
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <stdio.h>
pid_t pid = -1;
socklen_t len = sizeof(pid);
if (getsockopt(sockfd, SOL_LOCAL, LOCAL_PEERPID, &pid, &len) == -1) {
printf("failed: %d\n", errno);
} else {
printf("pid: %d\n", pid);
}
where sockfd
is the socket file descriptor you need to input.
The rest of the LOCAL_PEER*
family of options could also be of interest, depending on which exact piece of information is required:
// Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/Mac0SX.sdk/usr/include/sys/un.h
#define LOCAL_PEERCRED 0x001 /* retrieve peer credentials */
#define LOCAL_PEERPID 0x002 /* retrieve peer pid */
#define LOCAL_PEEREPID 0x003 /* retrieve eff. peer pid */
#define LOCAL_PEERUUID 0x004 /* retrieve peer UUID */
#define LOCAL_PEEREUUID 0x005 /* retrieve eff. peer UUID */
#define LOCAL_PEERTOKEN 0x006 /* retrieve peer audit token */
Higher-level abstractions around the API exist in other languages:
UnixStream::peer_cred
or Tokio's equivalent;NetworkChannel#getOption
with ExtendedSocketOptions.SO_PEERCRED
;syscall.GetsockoptUcred
;socket.getsockopt
;Upvotes: 0
Reputation: 7907
There is, but it's very proprietary and won't work outside Darwin. You can use the com.apple.network.statistics PF_SYSTEM socket to effectively do what netstat(1) and the Darwin-specific nettop(1) do, and get all socket activity (including updated in real time).
The private NetworkStatistics.framework even contains wrappers for this and (so far) it doesn't need entitlements or root privileges. Check the code sample in Listing 16-26 at http://newosxbook.com/bonus/vol1ch16.html for exact details, and couple that with getpeername(2).
FYI, this still isn't a good idea, because any process can easily spoof its name. If you're already in macOS and you are dealing with code signed processes, a much better option is, once you have the PID in hand, to use the csops(2) system call to obtain the code signing identity, which can't be spoofed.
Upvotes: 3