inet.c 2.23 KB
#include <netdb.h>
#include <string.h>
#include <ifaddrs.h>

#include "inet.h"

static struct sockaddr *find_address_of(char *name, struct ifaddrs *from)
{
    struct ifaddrs *ifa;
    int n;
    for (ifa = from, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
        if (strcmp(ifa->ifa_name, name)) {
            continue;
        }

        if (ifa->ifa_addr == NULL) {
            continue;
        }

        int family = ifa->ifa_addr->sa_family;
        if (family == AF_INET || family == AF_INET6) {
            return ifa->ifa_addr;
        }
    }

    return NULL;
}

static struct sockaddr *find_netmask_of(char *name, struct ifaddrs *from)
{
    struct ifaddrs *ifa;
    int n;
    for (ifa = from, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
        if (strcmp(ifa->ifa_name, name)) {
            continue;
        }

        if (ifa->ifa_netmask == NULL) {
            continue;
        }

        int family = ifa->ifa_netmask->sa_family;
        if (family == AF_INET || family == AF_INET6) {
            return ifa->ifa_netmask;
        }
    }

    return NULL;
}

static int address_to_string(struct sockaddr *addr, char *buffer, int size)
{
    return getnameinfo(addr,
        (addr->sa_family == AF_INET)
            ? sizeof(struct sockaddr_in)
            : sizeof(struct sockaddr_in6),
        buffer, size,
        NULL, 0,
        NI_NUMERICHOST);
}

int get_ip_addr(char *p_ip, int sz_ip)
{
    struct ifaddrs *ifaddr;
    if (getifaddrs(&ifaddr) == -1) {
        return -1;
    }

    struct sockaddr *address = find_address_of(IFNAME, ifaddr);
    if (address == NULL) {
        goto ERROR;
    }

    int ret = address_to_string(address, p_ip, sz_ip);
    if (ret != 0) {
        goto ERROR;
    }

    freeifaddrs(ifaddr);
    return 0;

ERROR:
    freeifaddrs(ifaddr);
    return -1;
}

int get_netmask(char *p_netmask, int sz_netmask)
{
    struct ifaddrs *ifaddr;
    if (getifaddrs(&ifaddr) == -1) {
        return -1;
    }

    struct sockaddr *netmask = find_netmask_of(IFNAME, ifaddr);
    if (netmask == NULL) {
        goto ERROR;
    }

    int ret = address_to_string(netmask, p_netmask, sz_netmask);
    if (ret != 0) {
        goto ERROR;
    }

    freeifaddrs(ifaddr);
    return 0;

ERROR:
    freeifaddrs(ifaddr);
    return -1;
}