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