Tuesday, October 14, 2008

Network interface link status

Hi all,

Rahool wanted to check link status of his network interface, i.e. whether the network cable is unplugged or not. 'ifconfig' just gives list of all configured interfaces. It does not show current status of the link. After some Google-ing, we came across a tool called 'ethtool'.

vinitd@pe-lt271:~/prog$ sudo ethtool eth0 | grep Link
Link detected: yes
vinitd@pe-lt271:~/prog$

But he wanted the code for the same. So I did strace of above tool and browsed some of its code. Here I found a new (to me ofcourse!!) ioctl SIOCETHTOOL. We can give different command to this ioctl using data that is passed to it. I have tried ETHTOOL_GLINK command to get above output.
Code:
#include <stdio.h>
#include <sys/types.h>
#include <linux/types.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <net/if.h>
#include <linux/ethtool.h>
#include <linux/sockios.h>
#define IFACE                   "eth0"

static int do_it(int fd, struct ifreq *ifr)
{

        int err;
        struct ethtool_value edata;
        int allfail = 1;
        edata.cmd = ETHTOOL_GLINK;
        ifr->ifr_data = (caddr_t)&edata;
        err = ioctl(fd, SIOCETHTOOL, ifr);
        if (err == 0) {
                fprintf(stdout, "       Link detected: %s\n",
                        edata.data ? "yes":"no");
                allfail = 0;
        } else if (errno != EOPNOTSUPP) {
                perror("Cannot get link status");
        }

        if (allfail) {
                fprintf(stdout, "No data available\n");
                return 75;
        }
        return 0;
}
int main()
{
        struct ifreq ifr;
        int fd;
        memset(&ifr, 0, sizeof(ifr));
        strcpy(ifr.ifr_name, IFACE);
        fd = socket(AF_INET, SOCK_DGRAM, 0);
        if (fd < 0) {
                perror("Cannot get control socket");
                return 70;
        }

        do_it(fd, &ifr);
        return 0;
}


Output:
vinitd@pe-lt271:~/prog$ gcc ethtool.c -Wall -o ethtool
vinitd@pe-lt271:~/prog$ sudo ./ethtool
Link detected: yes
vinitd@pe-lt271:~/prog$