Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I programmatically find the IP address/netmask/gateway configured for a specific network device in Linux?

I would like to write a piece of code which checks, for each network device (e.g. eth0, lo, master devices) some statistics and configuration data about that device.
I could find the statistics data (and most of the configuration data) in /sys/class/net/..., however, I couldn't find any C/C++ API or any entry in procfs/sysfs listing the inet addr, netmask and gateway.

Some alternatives I checked:

  • parsing the output from ifconfig/route/some other utilities: I don't want to start a subprocess every time I need to do the inspection.
  • parsing /etc/sysconfig/network-scripts/: will give me only the start-up configuration, and not the current state.

Also, since this code is intended for a product in my workplace, where every external library is inspected thoroughly (meaning it will take me forever to add any external library) I prefer solutions which rely on Linux native API and not external libraries.

Thanks!

like image 283
Oren S Avatar asked Jun 07 '10 12:06

Oren S


1 Answers

There sure is using a struct of ifreq and ioctl() calls you can grab all interface information:

Man page is here Ifreq manpage

/* local interface info */
    typedef struct{
        char *iface;
        struct ether_addr hwa;
        struct in_addr ipa;
        struct in_addr bcast;
        struct in_addr nmask;
        u_short mtu;
    } ifcfg_t; 
    /*
     * Grabs local network interface information and stores in a ifcfg_t 
     * defined in network.h, returns 0 on success -1 on failure
    */
    int get_local_info(int rsock, ifcfg_t *ifcfg)
    {
        struct ifreq ifr;

        memset(&ifr, 0, sizeof(ifr));
        strncpy(ifr.ifr_name, ifcfg->iface, IF_NAMESIZE);
        if((ioctl(rsock, SIOCGIFHWADDR, &ifr)) == -1){
            perror("ioctl():");
            return -1;
        }
        memcpy(&(ifcfg->hwa), &ifr.ifr_hwaddr.sa_data, 6);

        memset(&ifr, 0, sizeof(ifr));
        strncpy(ifr.ifr_name, ifcfg->iface, IF_NAMESIZE);
        if((ioctl(rsock, SIOCGIFADDR, &ifr)) == -1){
            perror("ioctl():");
            return -1;
        }
        memcpy(&ifcfg->ipa, &(*(struct sockaddr_in *)&ifr.ifr_addr).sin_addr, 4);

        memset(&ifr, 0, sizeof(ifr));
        strncpy(ifr.ifr_name, ifcfg->iface, IF_NAMESIZE);
        if((ioctl(rsock, SIOCGIFBRDADDR, &ifr)) == -1){
            perror("ioctl():");
            return -1;
        }
        memcpy(&ifcfg->bcast, &(*(struct sockaddr_in *)&ifr.ifr_broadaddr).sin_addr, 4);

        memset(&ifr, 0, sizeof(ifr));
        strncpy(ifr.ifr_name, ifcfg->iface, IF_NAMESIZE);
        if((ioctl(rsock, SIOCGIFNETMASK, &ifr)) == -1){
            perror("ioctl():");
            return -1;
        }
        memcpy(&ifcfg->nmask.s_addr, &(*(struct sockaddr_in *)&ifr.ifr_netmask).sin_addr, 4);

        memset(&ifr, 0, sizeof(ifr));
        strncpy(ifr.ifr_name, ifcfg->iface, IF_NAMESIZE);
        if((ioctl(rsock, SIOCGIFMTU, &ifr)) == -1){
            perror("ioctl():");
            return -1;
        }
        ifcfg->mtu = ifr.ifr_mtu;

        return 0;
    }

Quick edit, this function requires that the interface has been assigned before it is called, like so:

strcpy(if_cfg->iface, iface)

Ensuring you have allocated the memory first, then call like so

if((get_local_info(sock, if_cfg)) != 0){
    printf("Unable to get network device info\n");
    return -1;
}
like image 161
Bella Avatar answered Oct 26 '22 13:10

Bella