diff options
-rw-r--r-- | networking/libiproute/ipaddress.c | 6 | ||||
-rw-r--r-- | networking/libiproute/ipneigh.c | 9 | ||||
-rw-r--r-- | networking/libiproute/iproute.c | 5 | ||||
-rw-r--r-- | networking/libiproute/libnetlink.c | 43 | ||||
-rw-r--r-- | networking/libiproute/libnetlink.h | 19 |
5 files changed, 65 insertions, 17 deletions
diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c index fc6a4fb77..7b7e0154b 100644 --- a/networking/libiproute/ipaddress.c +++ b/networking/libiproute/ipaddress.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | struct filter_t { | 24 | struct filter_t { |
25 | char *label; | 25 | char *label; |
26 | /* Flush cmd buf. If !NULL, print_addrinfo() constructs flush commands in it */ | ||
26 | char *flushb; | 27 | char *flushb; |
27 | struct rtnl_handle *rth; | 28 | struct rtnl_handle *rth; |
28 | int scope, scopemask; | 29 | int scope, scopemask; |
@@ -34,6 +35,8 @@ struct filter_t { | |||
34 | smallint showqueue; | 35 | smallint showqueue; |
35 | smallint oneline; | 36 | smallint oneline; |
36 | smallint up; | 37 | smallint up; |
38 | /* Misnomer. Does not mean "flushed something" */ | ||
39 | /* More like "flush commands were constructed by print_addrinfo()" */ | ||
37 | smallint flushed; | 40 | smallint flushed; |
38 | inet_prefix pfx; | 41 | inet_prefix pfx; |
39 | } FIX_ALIASING; | 42 | } FIX_ALIASING; |
@@ -201,7 +204,7 @@ static NOINLINE int print_linkinfo(const struct nlmsghdr *n) | |||
201 | 204 | ||
202 | static int flush_update(void) | 205 | static int flush_update(void) |
203 | { | 206 | { |
204 | if (rtnl_send(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) { | 207 | if (rtnl_send_check(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) { |
205 | bb_perror_msg("can't send flush request"); | 208 | bb_perror_msg("can't send flush request"); |
206 | return -1; | 209 | return -1; |
207 | } | 210 | } |
@@ -510,7 +513,6 @@ int FAST_FUNC ipaddr_list_or_flush(char **argv, int flush) | |||
510 | xrtnl_dump_filter(&rth, store_nlmsg, &ainfo); | 513 | xrtnl_dump_filter(&rth, store_nlmsg, &ainfo); |
511 | } | 514 | } |
512 | 515 | ||
513 | |||
514 | if (G_filter.family && G_filter.family != AF_PACKET) { | 516 | if (G_filter.family && G_filter.family != AF_PACKET) { |
515 | struct nlmsg_list **lp; | 517 | struct nlmsg_list **lp; |
516 | lp = &linfo; | 518 | lp = &linfo; |
diff --git a/networking/libiproute/ipneigh.c b/networking/libiproute/ipneigh.c index f572414e9..984dd4bdd 100644 --- a/networking/libiproute/ipneigh.c +++ b/networking/libiproute/ipneigh.c | |||
@@ -32,7 +32,10 @@ struct filter_t { | |||
32 | int state; | 32 | int state; |
33 | int unused_only; | 33 | int unused_only; |
34 | inet_prefix pfx; | 34 | inet_prefix pfx; |
35 | /* Misnomer. Does not mean "flushed N something" */ | ||
36 | /* More like "no_of_flush_commands_constructed_by_print_neigh()" */ | ||
35 | int flushed; | 37 | int flushed; |
38 | /* Flush cmd buf. If !NULL, print_neigh() constructs flush commands in it */ | ||
36 | char *flushb; | 39 | char *flushb; |
37 | int flushp; | 40 | int flushp; |
38 | int flushe; | 41 | int flushe; |
@@ -45,7 +48,7 @@ typedef struct filter_t filter_t; | |||
45 | 48 | ||
46 | static int flush_update(void) | 49 | static int flush_update(void) |
47 | { | 50 | { |
48 | if (rtnl_send(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) { | 51 | if (rtnl_send_check(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) { |
49 | bb_perror_msg("can't send flush request"); | 52 | bb_perror_msg("can't send flush request"); |
50 | return -1; | 53 | return -1; |
51 | } | 54 | } |
@@ -299,9 +302,7 @@ static int FAST_FUNC ipneigh_list_or_flush(char **argv, int flush) | |||
299 | G_filter.rth = &rth; | 302 | G_filter.rth = &rth; |
300 | 303 | ||
301 | while (round < MAX_ROUNDS) { | 304 | while (round < MAX_ROUNDS) { |
302 | if (xrtnl_wilddump_request(&rth, G_filter.family, RTM_GETNEIGH) < 0) { | 305 | xrtnl_wilddump_request(&rth, G_filter.family, RTM_GETNEIGH); |
303 | bb_perror_msg_and_die("can't send dump request"); | ||
304 | } | ||
305 | G_filter.flushed = 0; | 306 | G_filter.flushed = 0; |
306 | if (xrtnl_dump_filter(&rth, print_neigh, NULL) < 0) { | 307 | if (xrtnl_dump_filter(&rth, print_neigh, NULL) < 0) { |
307 | bb_perror_msg_and_die("flush terminated"); | 308 | bb_perror_msg_and_die("flush terminated"); |
diff --git a/networking/libiproute/iproute.c b/networking/libiproute/iproute.c index 2a8610ea6..b11078ed5 100644 --- a/networking/libiproute/iproute.c +++ b/networking/libiproute/iproute.c | |||
@@ -26,7 +26,10 @@ | |||
26 | 26 | ||
27 | struct filter_t { | 27 | struct filter_t { |
28 | int tb; | 28 | int tb; |
29 | /* Misnomer. Does not mean "flushed something" */ | ||
30 | /* More like "flush commands were constructed by print_route()" */ | ||
29 | smallint flushed; | 31 | smallint flushed; |
32 | /* Flush cmd buf. If !NULL, print_route() constructs flush commands in it */ | ||
30 | char *flushb; | 33 | char *flushb; |
31 | int flushp; | 34 | int flushp; |
32 | int flushe; | 35 | int flushe; |
@@ -53,7 +56,7 @@ typedef struct filter_t filter_t; | |||
53 | 56 | ||
54 | static int flush_update(void) | 57 | static int flush_update(void) |
55 | { | 58 | { |
56 | if (rtnl_send(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) { | 59 | if (rtnl_send_check(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) { |
57 | bb_perror_msg("can't send flush request"); | 60 | bb_perror_msg("can't send flush request"); |
58 | return -1; | 61 | return -1; |
59 | } | 62 | } |
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) |
diff --git a/networking/libiproute/libnetlink.h b/networking/libiproute/libnetlink.h index 51bee2d67..1b082e019 100644 --- a/networking/libiproute/libnetlink.h +++ b/networking/libiproute/libnetlink.h | |||
@@ -20,7 +20,7 @@ struct rtnl_handle { | |||
20 | 20 | ||
21 | extern void xrtnl_open(struct rtnl_handle *rth) FAST_FUNC; | 21 | extern void xrtnl_open(struct rtnl_handle *rth) FAST_FUNC; |
22 | #define rtnl_close(rth) (close((rth)->fd)) | 22 | #define rtnl_close(rth) (close((rth)->fd)) |
23 | extern int xrtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type) FAST_FUNC; | 23 | extern void xrtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type) FAST_FUNC; |
24 | extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) FAST_FUNC; | 24 | extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) FAST_FUNC; |
25 | extern int xrtnl_dump_filter(struct rtnl_handle *rth, | 25 | extern int xrtnl_dump_filter(struct rtnl_handle *rth, |
26 | int (*filter)(const struct sockaddr_nl*, struct nlmsghdr *n, void*) FAST_FUNC, | 26 | int (*filter)(const struct sockaddr_nl*, struct nlmsghdr *n, void*) FAST_FUNC, |
@@ -34,8 +34,23 @@ extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, | |||
34 | int (*junk)(struct sockaddr_nl *,struct nlmsghdr *n, void *), | 34 | int (*junk)(struct sockaddr_nl *,struct nlmsghdr *n, void *), |
35 | void *jarg) FAST_FUNC; | 35 | void *jarg) FAST_FUNC; |
36 | 36 | ||
37 | extern int rtnl_send(struct rtnl_handle *rth, char *buf, int) FAST_FUNC; | 37 | int rtnl_send_check(struct rtnl_handle *rth, const void *buf, int len) FAST_FUNC; |
38 | //TODO: pass rth->fd instead of full rth? | ||
39 | static ALWAYS_INLINE void rtnl_send(struct rtnl_handle *rth, const void *buf, int len) | ||
40 | { | ||
41 | // Used to be: | ||
42 | //struct sockaddr_nl nladdr; | ||
43 | //memset(&nladdr, 0, sizeof(nladdr)); | ||
44 | //nladdr.nl_family = AF_NETLINK; | ||
45 | //return xsendto(rth->fd, buf, len, (struct sockaddr*)&nladdr, sizeof(nladdr)); | ||
38 | 46 | ||
47 | // iproute2-4.2.0 simplified the above to: | ||
48 | //return send(rth->fd, buf, len, 0); | ||
49 | |||
50 | // We are using even shorter: | ||
51 | xwrite(rth->fd, buf, len); | ||
52 | // and convert to void, inline. | ||
53 | } | ||
39 | 54 | ||
40 | extern int addattr32(struct nlmsghdr *n, int maxlen, int type, uint32_t data) FAST_FUNC; | 55 | extern int addattr32(struct nlmsghdr *n, int maxlen, int type, uint32_t data) FAST_FUNC; |
41 | extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen) FAST_FUNC; | 56 | extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen) FAST_FUNC; |