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;
}

_______________________________________________
Dng mailing list
Dng@lists.dyne.org
https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng

Reply via email to