OLD | NEW |
1 #include <errno.h> | 1 #include <errno.h> |
2 #include <string.h> | 2 #include <string.h> |
3 #include <syscall.h> | 3 #include <syscall.h> |
4 #include <sys/socket.h> | 4 #include <sys/socket.h> |
5 #include "netlink.h" | 5 #include "netlink.h" |
6 | 6 |
7 static int __netlink_enumerate(int fd, unsigned int seq, int type, int af, | 7 static int __netlink_enumerate(int fd, |
8 » int (*cb)(void *ctx, struct nlmsghdr *h), void *ctx) | 8 unsigned int seq, |
9 { | 9 int type, |
10 » struct nlmsghdr *h; | 10 int af, |
11 » union { | 11 int (*cb)(void* ctx, struct nlmsghdr* h), |
12 » » uint8_t buf[8192]; | 12 void* ctx) { |
13 » » struct { | 13 struct nlmsghdr* h; |
14 » » » struct nlmsghdr nlh; | 14 union { |
15 » » » struct rtgenmsg g; | 15 uint8_t buf[8192]; |
16 » » } req; | 16 struct { |
17 » » struct nlmsghdr reply; | 17 struct nlmsghdr nlh; |
18 » } u; | 18 struct rtgenmsg g; |
19 » int r, ret; | 19 } req; |
| 20 struct nlmsghdr reply; |
| 21 } u; |
| 22 int r, ret; |
20 | 23 |
21 » memset(&u.req, 0, sizeof(u.req)); | 24 memset(&u.req, 0, sizeof(u.req)); |
22 » u.req.nlh.nlmsg_len = sizeof(u.req); | 25 u.req.nlh.nlmsg_len = sizeof(u.req); |
23 » u.req.nlh.nlmsg_type = type; | 26 u.req.nlh.nlmsg_type = type; |
24 » u.req.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; | 27 u.req.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; |
25 » u.req.nlh.nlmsg_seq = seq; | 28 u.req.nlh.nlmsg_seq = seq; |
26 » u.req.g.rtgen_family = af; | 29 u.req.g.rtgen_family = af; |
27 » r = send(fd, &u.req, sizeof(u.req), 0); | 30 r = send(fd, &u.req, sizeof(u.req), 0); |
28 » if (r < 0) return r; | 31 if (r < 0) |
| 32 return r; |
29 | 33 |
30 » while (1) { | 34 while (1) { |
31 » » r = recv(fd, u.buf, sizeof(u.buf), MSG_DONTWAIT); | 35 r = recv(fd, u.buf, sizeof(u.buf), MSG_DONTWAIT); |
32 » » if (r <= 0) return -1; | 36 if (r <= 0) |
33 » » for (h = &u.reply; NLMSG_OK(h, (void*)&u.buf[r]); h = NLMSG_NEXT
(h)) { | 37 return -1; |
34 » » » if (h->nlmsg_type == NLMSG_DONE) return 0; | 38 for (h = &u.reply; NLMSG_OK(h, (void*)&u.buf[r]); h = NLMSG_NEXT(h)) { |
35 » » » if (h->nlmsg_type == NLMSG_ERROR) return -1; | 39 if (h->nlmsg_type == NLMSG_DONE) |
36 » » » ret = cb(ctx, h); | 40 return 0; |
37 » » » if (ret) return ret; | 41 if (h->nlmsg_type == NLMSG_ERROR) |
38 » » } | 42 return -1; |
39 » } | 43 ret = cb(ctx, h); |
| 44 if (ret) |
| 45 return ret; |
| 46 } |
| 47 } |
40 } | 48 } |
41 | 49 |
42 int __rtnetlink_enumerate(int link_af, int addr_af, int (*cb)(void *ctx, struct
nlmsghdr *h), void *ctx) | 50 int __rtnetlink_enumerate(int link_af, |
43 { | 51 int addr_af, |
44 » int fd, r; | 52 int (*cb)(void* ctx, struct nlmsghdr* h), |
| 53 void* ctx) { |
| 54 int fd, r; |
45 | 55 |
46 » fd = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE); | 56 fd = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE); |
47 » if (fd < 0) return -1; | 57 if (fd < 0) |
48 » r = __netlink_enumerate(fd, 1, RTM_GETLINK, link_af, cb, ctx); | 58 return -1; |
49 » if (!r) r = __netlink_enumerate(fd, 2, RTM_GETADDR, addr_af, cb, ctx); | 59 r = __netlink_enumerate(fd, 1, RTM_GETLINK, link_af, cb, ctx); |
50 » __syscall(SYS_close,fd); | 60 if (!r) |
51 » return r; | 61 r = __netlink_enumerate(fd, 2, RTM_GETADDR, addr_af, cb, ctx); |
| 62 __syscall(SYS_close, fd); |
| 63 return r; |
52 } | 64 } |
OLD | NEW |