0

I'm working on POSIX platform (PSE51 to be exact). I want to get notified when the default network interface goes up/down (via a callback or through continuous poll). The challenge is that I could find a linux specific way to get the default interface here and found a linux specific way to find the network is up or down here but not able figure out a POSIX way to get notified when default network interface goes up or down in C/C++. Please suggest.

samy
  • 5
  • 4
  • 1
    Welcome to Stack Overflow. Please read [the help pages](http://stackoverflow.com/help), take the SO [tour], read [ask], as well as [this question checklist](https://codeblog.jonskeet.uk/2012/11/24/stack-overflow-question-checklist/). Lastly please don't use the term "C/C++". There is no such language, only the two separate and very different languages C and C++. – Some programmer dude Jun 03 '20 at 09:03
  • 1
    I don't think that feature is in POSIX at all. – molbdnilo Jun 03 '20 at 09:12
  • @molbdnilo, thanks for your comment. Do we have any way at least to detect if the interface is up or down in case we provide the interface name? – samy Jun 04 '20 at 03:54

1 Answers1

2

POSIX does not provide such an interface.

Many POSIXy systems – Linux, BSDs, many Unixes – do provide a C function getifaddrs(), which provides a pointer to a linked list of struct ifaddrs structures. If the list contains an entry whose ->if_name matches your interface name and ->if_addr->sa_family matches your address family (usually AF_INET and AF_INET6), then the interface is up. Otherwise the interface is down.

Consider the following example:

#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <string.h>
#include <errno.h>

enum {
    IFACE_IPv4 = (1<<0),
    IFACE_IPv6 = (1<<1),
    IFACE_IP   = (1<<0) | (1<<1),
};

int iface_check(const char *name)
{
    struct ifaddrs *curr, *list = NULL;
    int             result = 0;

    if (!name || !(*name)) {
        errno = EINVAL;
        return 0;
    }

    if (getifaddrs(&list) == -1)
        return 0;

    for (curr = list; curr != NULL; curr = curr->ifa_next) {
        if (!strcmp(name, curr->ifa_name)) {
            if (curr->ifa_addr->sa_family == AF_INET)
                result |= IFACE_IPv4;
            if (curr->ifa_addr->sa_family == AF_INET6)
                result |= IFACE_IPv6;  
        }
    }

    freeifaddrs(list);

    errno = 0;
    return result;
}

If the getifaddrs() and freeifaddrs() functions are supported on your system (they are widely available), calling ifa_check(name) with name containing the interface name, should return 0 if the interface is down, and a combination of IFACE_IPv4 and IFACE_IPv6 if up (depending on which address families are supported on it).

For ease of use, the above function always sets errno to zero if no errors occurred. This way you can just use the return value (nonzero if "up" in the IP/IPv6 sense). If it returns zero, you can check errno if there was an error. (It will be zero if there was no error; the interface just wasn't listed with IPv4/IPv6.)

samy
  • 5
  • 4
None
  • 46
  • 2
  • Thanks for the solution. I've few of POSIX complaint platforms, I'll check if they support these APIs. BTW, I checked this code on Linux and it works fine. Just I had to fix couple of compiler errors. – samy Jun 04 '20 at 10:36
  • @samy: Thanks for fixing the typos! Yes, it works on Linux (which is what I use), but also should work on Mac OS, FreeBSD, and OpenBSD, too. – None Jun 04 '20 at 13:01