diff options
Diffstat (limited to 'networking/libiproute/libnetlink.c')
-rw-r--r-- | networking/libiproute/libnetlink.c | 43 |
1 files changed, 35 insertions, 8 deletions
diff --git a/networking/libiproute/libnetlink.c b/networking/libiproute/libnetlink.c index 40955fcae..b0d4166ac 100644 --- a/networking/libiproute/libnetlink.c +++ b/networking/libiproute/libnetlink.c | |||
@@ -34,7 +34,7 @@ void FAST_FUNC xrtnl_open(struct rtnl_handle *rth/*, unsigned subscriptions*/) | |||
34 | rth->seq = time(NULL); | 34 | rth->seq = time(NULL); |
35 | } | 35 | } |
36 | 36 | ||
37 | int FAST_FUNC xrtnl_wilddump_request(struct rtnl_handle *rth, int family, int type) | 37 | void FAST_FUNC xrtnl_wilddump_request(struct rtnl_handle *rth, int family, int type) |
38 | { | 38 | { |
39 | struct { | 39 | struct { |
40 | struct nlmsghdr nlh; | 40 | struct nlmsghdr nlh; |
@@ -48,18 +48,45 @@ int FAST_FUNC xrtnl_wilddump_request(struct rtnl_handle *rth, int family, int ty | |||
48 | req.nlh.nlmsg_seq = rth->dump = ++rth->seq; | 48 | req.nlh.nlmsg_seq = rth->dump = ++rth->seq; |
49 | req.g.rtgen_family = family; | 49 | req.g.rtgen_family = family; |
50 | 50 | ||
51 | return rtnl_send(rth, (void*)&req, sizeof(req)); | 51 | rtnl_send(rth, (void*)&req, sizeof(req)); |
52 | } | 52 | } |
53 | 53 | ||
54 | //TODO: pass rth->fd instead of full rth? | 54 | /* A version which checks for e.g. EPERM errors. |
55 | int FAST_FUNC rtnl_send(struct rtnl_handle *rth, char *buf, int len) | 55 | * Try: setuidgid 1:1 ip addr flush dev eth0 |
56 | */ | ||
57 | int FAST_FUNC rtnl_send_check(struct rtnl_handle *rth, const void *buf, int len) | ||
56 | { | 58 | { |
57 | struct sockaddr_nl nladdr; | 59 | struct nlmsghdr *h; |
60 | int status; | ||
61 | char resp[1024]; | ||
58 | 62 | ||
59 | memset(&nladdr, 0, sizeof(nladdr)); | 63 | status = write(rth->fd, buf, len); |
60 | nladdr.nl_family = AF_NETLINK; | 64 | if (status < 0) |
65 | return status; | ||
66 | |||
67 | /* Check for immediate errors */ | ||
68 | status = recv(rth->fd, resp, sizeof(resp), MSG_DONTWAIT|MSG_PEEK); | ||
69 | if (status < 0) { | ||
70 | if (errno == EAGAIN) /* if no error, this happens */ | ||
71 | return 0; | ||
72 | return -1; | ||
73 | } | ||
61 | 74 | ||
62 | return xsendto(rth->fd, buf, len, (struct sockaddr*)&nladdr, sizeof(nladdr)); | 75 | for (h = (struct nlmsghdr *)resp; |
76 | NLMSG_OK(h, status); | ||
77 | h = NLMSG_NEXT(h, status) | ||
78 | ) { | ||
79 | if (h->nlmsg_type == NLMSG_ERROR) { | ||
80 | struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); | ||
81 | if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) | ||
82 | bb_error_msg("ERROR truncated"); | ||
83 | else | ||
84 | errno = -err->error; | ||
85 | return -1; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | return 0; | ||
63 | } | 90 | } |
64 | 91 | ||
65 | int FAST_FUNC rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) | 92 | int FAST_FUNC rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) |