Using libproc to get ports used by processes on macos

I am trying to get ports used by processes. It can be done via lsof on macOS, i am trying to do it via libproc.

#include <iostream>
#include <libproc.h>

int main(int argc, const char * argv[]) {
    pid_t pids[3072];
    int count = proc_listpids(PROC_ALL_PIDS, 0, pids, sizeof(pids));
    for (int i = 0; i < count; i++) {
        char buffer[1024];
        for (int j = 1; j < 50000; j++) { //port range
            int ret = proc_pidfileportinfo(pids[i], j, PROC_PIDFILEPORTVNODEPATHINFO, buffer, sizeof(buffer));
            if(ret != 0) {
                printf("proc_pidfileportinfo returned %d bytes of data\n", ret);
                printf("%s\n", name);
            }
        }
        
    }
    return 0;
}

proc_pidfileportinfo function is not working for any port, i tried iterating till 50K. What i am doing wrong with proc_pidfileportinfo? how to properly use proc_pidfileportinfo?

Add a Comment

Accepted Reply

OK.

By far the easiest way to do this is to sublaunch lsof. Normally I don’t recommend such shenanigans but in this case lsof has specific affordance for it. See the Output for Other Programs section of the lsof man page.

If you don’t want to do that then, yes, libproc is the right answer. However, you’re barking up the wrong tree with the fileport stuff. A fileport is a Mach port that holds a file descriptor [1]. There is no fileport API per se, but you can see hints of it with other APIs. For example, it’s the mechanism that allows XPC to transfer file descriptors in an XPC message (XPC_TYPE_FD).

Rather that work with fileports you want to work with file descriptors directly. Call proc_pidinfo with PROC_PIDLISTFDS and then call proc_pidfdinfo with proc_pidfdinfo with PROC_PIDFDSOCKETINFO. And if you get stuck, check out the lsof source code in Darwin.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Well, not actually the file descriptor but the node that the file descriptor references.

Replies

I am trying to get ports used by processes.

What do you mean by ports? Mach ports? TCP ports? UDP ports? Or something else?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

  • @eskimo it is port used for network communication over the internet such as TCP, UDP etc

Add a Comment

@eskimo it is port used for network communication over the internet such as TCP, UDP etc

OK.

By far the easiest way to do this is to sublaunch lsof. Normally I don’t recommend such shenanigans but in this case lsof has specific affordance for it. See the Output for Other Programs section of the lsof man page.

If you don’t want to do that then, yes, libproc is the right answer. However, you’re barking up the wrong tree with the fileport stuff. A fileport is a Mach port that holds a file descriptor [1]. There is no fileport API per se, but you can see hints of it with other APIs. For example, it’s the mechanism that allows XPC to transfer file descriptors in an XPC message (XPC_TYPE_FD).

Rather that work with fileports you want to work with file descriptors directly. Call proc_pidinfo with PROC_PIDLISTFDS and then call proc_pidfdinfo with proc_pidfdinfo with PROC_PIDFDSOCKETINFO. And if you get stuck, check out the lsof source code in Darwin.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Well, not actually the file descriptor but the node that the file descriptor references.

Thanks a ton @eskimo

lsof doesn't works in sandboxed enviroment.
i wanted to use lsof -i:port. i.e lsof -i:443 and grab Name(TCP 172.20.10.3:62323->52.98.87.66:https (ESTABLISHED)) as you can see last part in below command output.

faisalikwal@TTWPXM6W4Y ~ % lsof -i:443                                                                                                                                                                         
COMMAND     PID        USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
CalendarA   757 faisalikwal   82u  IPv4 0x9b970081ec8283e5      0t0  TCP 172.20.10.3:62323->52.98.87.66:https (ESTABLISHED)
exchanges   758 faisalikwal    8u  IPv4 0x9b970081ec8303e5      0t0  TCP 172.20.10.3:62241->40.99.34.226:https (ESTABLISHED)
Notes       867 faisalikwal   28u  IPv4 0x9b970081ec001915      0t0  TCP localhost:62472->52.98.86.162:https (CLOSED)
Mail        868 faisalikwal   83u  IPv4 0x9b970081ec7d0e7d      0t0  TCP 172.20.10.3:62488->40.99.34.242:https (ESTABLISHED)
Google      942 faisalikwal   22u  IPv4 0x9b970081ec02794d      0t0  TCP 172.20.10.3:62512->okapi-services-apse1.apple.com:https (ESTABLISHED)

My ultimate goal is to identify process belong to NEPacket received by packet tunnel provider since apple doesn't exposes metadata in packet tunnel(except perapp cases).
I will have a look at lsof code to check how they do it.

  • @faisalIkwal did you end up getting it working? If so I'd be very grateful if you'd post the working code.

Add a Comment

By far the easiest way to do this is to sublaunch lsof.

In my experience, this has been frustratingly unreliable.

My app runs local servers (nginx, apache, etc etc) and I'm simply trying to ascertain whether the ports they require (eg 127.0.0.1:443) are already in use, as a quick "sanity check" before launching them.

Prior to discovering -F (thanks for your suggestion above, I'll rewrite my lsof parsing code at some point) I was calling it like this:

lsof -i +c 0 -P -n -R -sTCP:LISTEN

which works 99% of the time, but that 1% where it times out is super annoying. I think it's due to deadlocks — eg I sometimes noticed lsof was spawning a second lsof, which is mentioned in the man page as one of its deadlock-breaking strategies.

Would you recommend I add -b to my lsof calls to "avoid kernel functions that might block"?

Would you recommend I add -b to my lsof calls to "avoid kernel functions that might block"?

No idea )-:

To dig into this you’d need to look at a spin dump to see why it’s blocking.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi @eskimo I am able to get process path associated with packet read in Packet tunnel. I am facing below problem with Safari:

For Safari or any other apps which uses WKWebview having same process path: /Library/Apple/System/Library/StagedFrameworks/Safari/WebKit.framework/Versions/A/XPCServices/com.apple.WebKit.Networking.xpc/Contents/MacOS/com.apple.WebKit.Networking

Any ways to distinguish wether it is safari or other wkwebview apps?

Related Problem: https://developer.apple.com/forums/thread/693528 In this thread, app proxy can help but in packet tunnel no such options exposed.

Any ways to distinguish wether it is safari or other wkwebview apps?

This is a very different question from the focus on this thread (which is about mapping between ports and processes). Please put your question in a new thread. Tag it with Network Extension so that I see it.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"