ifname of network interface and ifndex query of interface index under linux

Posted by amithn12 on Fri, 10 May 2019 23:58:15 +0200

Relevant function interface information:

#include <net/if.h>

unsigned if_nametoindex(const char *ifname);
char *if_indextoname(unsigned ifindex, char *ifname);
struct if_nameindex *if_nameindex(void);
void if_freenameindex(struct if_nameindex *ptr);
if_nametoindex(): Specifies the network interface name string as a parameter; if the interface exists, returns the corresponding index, otherwise returns 0.

if_indextoname(): Specifies a network interface index and a memory area of at least IF_NAMESIZE(16) bytes in length as parameters; if the corresponding network interface exists in the memory area, returns the name string of the interface, otherwise returns NULL, and sets errno to the corresponding value.

If_name index(): Returns the dynamically allocated struct if_name index structure array, each element in the array corresponds to a local network interface; if_index field of struct if_name index structure is the interface index, if_name field is the interface name string; index 0 and name string is NULL to represent the end of the structure array; when invoking an error, returns NULL and sets errno Set to the corresponding value

if_freenameindex(): After the interface name and index are obtained by if_nameindex(), the function is called to release the dynamically allocated memory area.

The four functions mentioned above can be viewed in the man document of the system, and all of them are supported by POSIX standard. The Linux kernel may not implement these functions, or have been implemented but are different from POSIX standard. The prototype declarations and definitions of these functions do not appear in the customized kernel 2.6.32-573.26.1.el6.x86_64 and the original kernel 2.6.32.5 of CentOS 6.7, but are implemented by glibc-2.12 of the system: in the glibc-2.12.2 source tree, the prototype declarations of functions are located in sysdeps/gnu/net/if.h and sysdeps/generic/net/if.h, and the definitions of functions are located in sysds/unix/sysepv/linux/if.c, essentially. It encapsulates IOCGIFNAME, SIOCGIFCONF, SIOCGIFINDEX and netlink sockets of ioctl(2).

Sample program:

1.if_name_index.c example:

int main(void)
{
    struct if_nameindex *head, *ifni;
    ifni = if_nameindex();
    head = ifni;
    
    if (head == NULL) {
        perror("if_nameindex()");
        exit(EXIT_FAILURE);
    }   
    
    while (ifni->if_index != 0) {
        printf("Interfece %d : %s\n", ifni->if_index, ifni->if_name);
        ifni++;
    }   
    
    if_freenameindex(head);
    head = NULL;
    ifni = NULL;
    
    exit(EXIT_SUCCESS);
}

Compile and run:

[lilei@gw ~]$ gcc if_name_index.c -o if_name_index                 
if_name_index.c
[lilei@gw ~]$ gcc if_name_index.c -o if_name_index
[lilei@gw ~]$ ls -l if_name_index
-rwxrwxr-x 1 lilei lilei 7153 5 Month 111:19 if_name_index
[lilei@gw ~]$ ./if_name_index 
Interfece 1 : lo
Interfece 2 : eth0
Interfece 3 : eth2
Interfece 4 : eth1
[lilei@gw ~]$ 

2.if_index_to_name.c example:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <net/if.h>

int main(int argc, char *argv[])
{
    if (argc != 2) {
        fprintf(stderr, "Usage: %s [interface index]\n", argv[0]);
        exit(EXIT_FAILURE);
    }   

    int saved_errno = errno;
    char if_name[IFNAMSIZ] = {'\0'};
    unsigned int if_index = (unsigned int )atoi(argv[1]);

    char *name = if_indextoname(if_index, if_name);
    if (name == NULL && errno == ENXIO) {
        fprintf(stderr, "Index %d : No such device\n", if_index);
        exit(EXIT_FAILURE); 
    } 
    
    errno = saved_errno;  

    printf("Index %d : %s\n", if_index, if_name);

    exit(EXIT_SUCCESS);
}

Compile and run:

[lilei@gw ~]$ gcc if_index_to_name.c -o if_index_to_name
[lilei@gw ~]$ ./if_index_to_name 
Usage: ./if_index_to_name [interface index]
[lilei@gw ~]$ ./if_index_to_name 0
Index 0 : No such device
[lilei@gw ~]$ ./if_index_to_name 1
Index 1 : lo
[lilei@gw ~]$ ./if_index_to_name 2
Index 2 : eth0
[lilei@gw ~]$ ./if_index_to_name 3
Index 3 : eth2
[lilei@gw ~]$ ./if_index_to_name 4
Index 4 : eth1
[lilei@gw ~]$ ./if_index_to_name 5
Index 5 : No such device
[lilei@gw ~]$ 

3.if_name_to_index.c example:

#include <stdio.h>
#include <stdlib.h>
#include <net/if.h>

int main(int argc, char *argv[])
{
    if (argc != 2) {
        fprintf(stderr, "Usage: %s [interface name]\n", argv[0]);
        exit(EXIT_FAILURE);
    }   

    unsigned int if_index;
    if_index = if_nametoindex(argv[1]);
    if (if_index == 0) {
        fprintf(stderr, "Interface %s : No such device\n", argv[1]);
        exit(EXIT_FAILURE);
    }   

    printf("Interface %s : %d\n", argv[1], if_index);   

    exit(EXIT_SUCCESS);
}

Compile and run:

[lilei@gw ~]$ gcc if_name_to_index.c -o if_name_to_index
[lilei@gw ~]$ ./if_name_to_index eth0
Interface eth0 : 2
[lilei@gw ~]$ ./if_name_to_index eth1
Interface eth1 : 4
[lilei@gw ~]$ ./if_name_to_index eth2
Interface eth2 : 3
[lilei@gw ~]$ ./if_name_to_index eth3
Interface eth3 : No such device
[lilei@gw ~]$ 

Links to the original text: https://www.jianshu.com/p/389a8870a51d

Topics: network Linux glibc CentOS