summaryrefslogtreecommitdiffstats
path: root/src/getifn.c
blob: 74dfc727cf450e04b22aeacdd1aa6d0ef676cefc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <string.h>
#include <stdio.h>

#include "getifn.h"
#include "nlrequest.h"

struct getifn_info {
    char ifname[IFNAMSIZ+1];
    int idx;
};

int getifn_callback(struct nlmsghdr *n, void *u) {
    struct rtattr *a = NULL;
    int l;
    struct getifn_info *gi = (struct getifn_info*) u;
    struct ifinfomsg *i;

    if (n->nlmsg_type != RTM_NEWLINK) {
        fprintf(stderr, "NETLINK: Got response for wrong request.\n");
        return -1;
    }

    i = NLMSG_DATA(n);
    l = NLMSG_PAYLOAD(n, sizeof(struct ifinfomsg));
    a = IFLA_RTA(i);
    
    while(RTA_OK(a, l)) {
        
        switch(a->rta_type) {
            case IFLA_IFNAME:
                if (strncmp(RTA_DATA(a), gi->ifname, IFNAMSIZ) == 0)  {
                    gi->idx = i->ifi_index;
                    return 0;
                }
        }
        a = RTA_NEXT(a, l);
    }
    
    return 0;
}

int getifn(int s, char *iface) {
    struct getifn_info gi;
    
    struct {
        struct nlmsghdr n;
        struct ifinfomsg i;
        char a[1024];
    } req;
    
    memset(&req, 0, sizeof(req));
    req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
    req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_MATCH;
    req.n.nlmsg_type = RTM_GETLINK;
    
    req.i.ifi_family = AF_UNSPEC;
    req.i.ifi_change = -1;

    memset(&gi, 0, sizeof(gi));
    strncpy(gi.ifname, iface, IFNAMSIZ);
    gi.idx = -1;

    if (addattr_l(&req.n, sizeof(req), IFLA_IFNAME, gi.ifname, IFNAMSIZ+1) < 0) {
        fprintf(stderr, "Failed to add attribute to netlink message\n");
        return -1;
    }
    
    if (netlink_request(s, (struct nlmsghdr*) &req, getifn_callback, &gi) < 0)
        return -1;

    if (gi.idx < 0) {
        fprintf(stderr, "Interface '%s' not existent.\n", iface);
        return -1;
    }
    
    return gi.idx;
}