1

I've seen so many things that can be poll()'ed on that I'm wondering whether that would include the detection of another process binding and then listening to a port.

poll() is most often used on a set of sockets to know when they gets new content (read) or have space in its output buffer (write).

Now we have:

  • signalfd() to convert a Unix signal to a file descriptor and poll() on that.
  • pipe() to listen to inter-process pipes (very similar to sockets)
  • timerfd_create() to create a timer that will wake you up through your poll()
  • eventfd() to create an event notification file descriptor (for example, to send events between threads)
  • special socket to listen to the kernel creating new processes (fork()) and killing processes (exit())

    struct sockaddr_nl sa_nl;
    int s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
    
    sa_nl.nl_family = AF_NETLINK;
    sa_nl.nl_groups = CN_IDX_PROC;
    sa_nl.nl_pid = getpid();
    bind(nl_sock, (struct sockaddr *) &sa_nl, sizeof(sa_nl));
    ...
    

Now... Is there a way to know when a process calls the listen() function?

In other words, know as soon as a new bound address and port appear in the output of netstat with the LISTEN keyword attached to it such as:

Proto   Local Address         Foreign Address       State
tcp     0.0.0.0:25            0.0.0.0:*             LISTEN

Obviously, I know that the connection will appear in /proc/net/tcp which I can scan (just like netstat does,) but that would require polling (opposed to sleeping with a call to poll()) with an interval timer. I know how to do that, but I would prefer to be able to know that the port is open without having to read a file over and over again...

frogatto
  • 28,539
  • 11
  • 83
  • 129
Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
  • Do you mean when _any_ process opens a listening socket? You'd likely need some cooperation from the kernel. [This question](http://stackoverflow.com/q/18541517) might be relevant, but using NETLINK_INET_DIAG still requires polling AFAICT. Presumably getting something that works continuously would require some modification of the kernel. – Hasturkun Sep 06 '16 at 07:25
  • You could always interpose the listen syscall (using e.g. `LD_PRELOAD` environment variable to load the interposing library when the target binary is executed), or even modify the C library `listen()` function, to report the action via e.g. an Unix domain datagram socket. At the kernel level, you could use the Linux kernel audit subsystem (and a suitable audit rule) to generate a record of the interesting syscalls. No `poll()` -based mechanisms exist, as far as I know. – Nominal Animal Sep 06 '16 at 11:57
  • is it possible that `inotify()` would work on the `/proc/net/tcp` directory? – J Earls Sep 06 '16 at 17:06
  • @Hasturkun, yes. At this point it would be to know when port 9042 (Cassandra) gets opened. That way I know Cassandra is ready just then. i see that `NETLINK_INET_DIAG` is poorly documented, but it may still be faster than parsing `/proc/net/tcp`... – Alexis Wilke Sep 06 '16 at 21:28
  • @NominalAnimal, I was hoping something was already in place rather than hacking the OS or kernel... It's probably way cleaner to poll at this point, especially for long term support. – Alexis Wilke Sep 06 '16 at 21:30
  • @JEarls, if it works, I do not think that would be useful. The data is probably "immediate" as you read it and things present in that file change nearly all the time on a server... so the `poll()` would anyway constantly return. – Alexis Wilke Sep 06 '16 at 23:03
  • You'll find a bit more information re: `NETLINK_INET_DIAG` [here](https://github.com/kristrev/inet-diag-example) and [its associated blog post](http://kristrev.github.io/2013/07/26/passive-monitoring-of-sockets-on-linux), but yes, documentation seems nonexistent. – Hasturkun Sep 07 '16 at 09:45
  • @Hasturkun, actually, with the filtering it looks like you can really minimize the transfer to just the one or two entries you are interested in, so it look very promising compared to reading a file with possibly hundreds of lines. – Alexis Wilke Sep 07 '16 at 18:17
  • @AlexisWilke: The audit subsystem is enabled in most Linux distros, many also install an audit daemon by default. If there is no audit daemon, you could write your own. However, `NETLINK_INET_DIAG` looks like it might be a better route. You might wish to also take a look at [libnl-idiag](https://www.infradead.org/~tgr/libnl/doc/api/group__idiag.html) module of [libnl](https://www.infradead.org/~tgr/libnl/doc/api/index.html); some of the authors are Linux kernel developers implementing the features on the kernel side. You might even find you can rely on `libnl` directly; that's what I would do. – Nominal Animal Sep 07 '16 at 20:01

0 Answers0