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
78
79
80
| | #define _GNU_SOURCE
#include <net/if.h>
#include <sys/socket.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "__netlink.h"
struct ifnamemap {
unsigned int index;
unsigned char namelen;
char name[IFNAMSIZ];
};
struct ifnameindexctx {
unsigned int num;
unsigned int str_bytes;
struct ifnamemap *list;
};
static int __handle_link(void *pctx, struct nlmsghdr *h)
{
struct ifnameindexctx *ctx = pctx;
struct ifinfomsg *ifim = NLMSG_DATA(h);
struct rtattr *rta;
struct ifnamemap *e;
for (rta = NLMSG_RTA(h, sizeof(*ifim)); NLMSG_RTAOK(rta, h); rta = RTA_NEXT(rta)) {
if (rta->rta_type != IFLA_IFNAME) continue;
if (RTA_DATALEN(rta) > IFNAMSIZ) return -ENOBUFS;
ctx->num++;
ctx->str_bytes += RTA_DATALEN(rta) + 1;
e = realloc(ctx->list, sizeof(struct ifnamemap[ctx->num]));
if (e == 0) return -ENOMEM;
ctx->list = e;
e = &ctx->list[ctx->num-1];
e->index = ifim->ifi_index;
e->namelen = RTA_DATALEN(rta);
memcpy(e->name, RTA_DATA(rta), IFNAMSIZ);
}
return 0;
}
struct if_nameindex *if_nameindex()
{
struct ifnameindexctx _ctx, *ctx = &_ctx;
struct if_nameindex *ifs = NULL;
struct __netlink_handle *nh;
int r, i;
char *p;
nh = __netlink_open(NETLINK_ROUTE);
if (!nh) goto err;
memset(ctx, 0, sizeof(*ctx));
r = __netlink_enumerate(nh, RTM_GETLINK, __handle_link, ctx);
__netlink_close(nh);
if (r < 0) goto err;
ifs = malloc(sizeof(struct if_nameindex[ctx->num+1]) + ctx->str_bytes);
if (ifs == 0) goto err;
p = (char*)ifs + sizeof(struct if_nameindex[ctx->num+1]);
for (i = 0; i < ctx->num; i++) {
ifs[i].if_index = ctx->list[i].index;
ifs[i].if_name = p;
memcpy(p, ctx->list[i].name, ctx->list[i].namelen);
p += ctx->list[i].namelen;
*p++ = 0;
}
ifs[i].if_index = 0;
ifs[i].if_name = 0;
err:
free(ctx->list);
if (ifs == NULL) errno = ENOBUFS;
return ifs;
}
|