:: Re: [DNG] netman GIT project
Top Page
Delete this message
Reply to this message
Author: tilt!
Date:  
To: dng
Subject: Re: [DNG] netman GIT project
On 08/26/2015 01:36 PM, Irrwahn wrote:
> [...]
> Or, even better, you could easily pass the IF name as an additional
> parameter to the backend (and possily even use it as additional component
> to construct the interface file names).


An easy way to obtain a list of interface names on Linux is:

awk 'NR>2{gsub(/:/,"");print $1}' /proc/net/dev

For doing this in pure C, by the "rtnetlink" method, please see
attached file, which is based on .

Kind regards,
Tilman.


/* ifnames - On Linux, list available network interfaces, one by line.

gcc -g -o ifnames ifnames.c
./ifnames

Based on "nprocnetdev.c":
https://gist.github.com/javiermon/43a0b9e1c07abd4b13df
(javiermon. "nprocnetdev.c: print proc/net/dev via netlink sockets")

Originally based on:
http://www.iijlab.net/~jean/iflist.c
Reference:
http://iijean.blogspot.com/2010/03/howto-get-list-of-network-interfaces-in.html
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <signal.h>
#include <errno.h>

#define IFLIST_REPLY_BUFFER 8192 // FIXME: is this defined somewhere?

typedef struct nl_req_s nl_req_t;

struct nl_req_s {
    struct nlmsghdr hdr;
    struct rtgenmsg gen;
};


void rtnl_print_link(struct nlmsghdr *h) {
    struct ifinfomsg *iface;
    struct rtattr *attribute;


    int len;


    iface = NLMSG_DATA(h);
    len = h->nlmsg_len - NLMSG_LENGTH(sizeof(*iface));


    for(
        attribute = IFLA_RTA(iface); 
        RTA_OK(attribute, len); 
        attribute = RTA_NEXT(attribute, len)
    ) {
        switch(attribute->rta_type) {
            case IFLA_IFNAME:
                printf("%s\n", (char *) RTA_DATA(attribute));
                break;
            default:
                break;
        }
    }
}


int main(void) {
    int fd;
    struct sockaddr_nl local;
    struct sockaddr_nl kernel;


    struct msghdr rtnl_msg;
    struct iovec io;


    nl_req_t req;
    char reply[IFLIST_REPLY_BUFFER]; 


    pid_t pid = getpid();
    unsigned int sleep_sec = 0;


    fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);


    if(-1 == fd) {
        fprintf(stderr, "ERROR: socket(): %s\n", strerror(errno));


        return -1;
    }


    memset(&local, 0, sizeof(local));


    local.nl_family = AF_NETLINK;
    local.nl_pid = pid;
    local.nl_groups = 0;


    if(0 > bind(fd, (struct sockaddr *) &local, sizeof(local))) {
        fprintf(stderr, "ERROR: bind(): %s\n", strerror(errno));


        return -1;
    }


    int msg_done = 0;


    memset(&rtnl_msg, 0, sizeof(rtnl_msg));
    memset(&kernel, 0, sizeof(kernel));
    memset(&req, 0, sizeof(req));


    kernel.nl_family = AF_NETLINK;


    req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
    req.hdr.nlmsg_type = RTM_GETLINK;
    req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
    req.hdr.nlmsg_seq = 1;
    req.hdr.nlmsg_pid = pid;
    req.gen.rtgen_family = AF_PACKET;


    io.iov_base = &req;
    io.iov_len = req.hdr.nlmsg_len;
    rtnl_msg.msg_iov = &io;
    rtnl_msg.msg_iovlen = 1;
    rtnl_msg.msg_name = &kernel;
    rtnl_msg.msg_namelen = sizeof(kernel);


    if(sendmsg(fd, (struct msghdr *) &rtnl_msg, 0) < 0)
        fprintf(stderr, "ERROR: sendmsg(): %s",  strerror(errno));


    while (!msg_done) {
        int len;
        struct nlmsghdr *msg_ptr;
        struct msghdr rtnl_reply;
        struct iovec io_reply;


        memset(&io_reply, 0, sizeof(io_reply));
        memset(&rtnl_reply, 0, sizeof(rtnl_reply));


        io.iov_base = reply;
        io.iov_len = IFLIST_REPLY_BUFFER;
        rtnl_reply.msg_iov = &io;
        rtnl_reply.msg_iovlen = 1;
        rtnl_reply.msg_name = &kernel;
        rtnl_reply.msg_namelen = sizeof(kernel);


        if ((len = recvmsg(fd, &rtnl_reply, 0)) != 0) {
            for (
                msg_ptr = (struct nlmsghdr *) reply; 
                NLMSG_OK(msg_ptr, len); 
                msg_ptr = NLMSG_NEXT(msg_ptr, len)
            ) {
                switch(msg_ptr->nlmsg_type) {
                    case NLMSG_DONE:
                        msg_done = 1;
                        break;
                    case RTM_NEWLINK:
                        rtnl_print_link(msg_ptr);
                        break;
                    default:
                        break;
                }
            }
        }
    }


    close(fd);


    return 0;
}