aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2019-05-22 13:54:46 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2019-05-22 13:54:46 +0200
commit028c5aa18b5273c029f0278232d922ee1a164de6 (patch)
treef57dbcb9445ce4878f74789872ed123491f705c2
parent84fc645605827d53aa3e749dfff309978b1bc73d (diff)
downloadbusybox-w32-028c5aa18b5273c029f0278232d922ee1a164de6.tar.gz
busybox-w32-028c5aa18b5273c029f0278232d922ee1a164de6.tar.bz2
busybox-w32-028c5aa18b5273c029f0278232d922ee1a164de6.zip
ip: use rtnl_send_check() on flush commands, closes 6962
function old new delta rtnl_send_check - 160 +160 xrtnl_wilddump_request 64 66 +2 ipneigh_list_or_flush 714 706 -8 rtnl_send 69 - -69 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 1/1 up/down: 162/-77) Total: 85 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/libiproute/ipaddress.c6
-rw-r--r--networking/libiproute/ipneigh.c9
-rw-r--r--networking/libiproute/iproute.c5
-rw-r--r--networking/libiproute/libnetlink.c43
-rw-r--r--networking/libiproute/libnetlink.h19
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
24struct filter_t { 24struct 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
202static int flush_update(void) 205static 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
46static int flush_update(void) 49static 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
27struct filter_t { 27struct 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
54static int flush_update(void) 57static 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
37int FAST_FUNC xrtnl_wilddump_request(struct rtnl_handle *rth, int family, int type) 37void 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.
55int FAST_FUNC rtnl_send(struct rtnl_handle *rth, char *buf, int len) 55 * Try: setuidgid 1:1 ip addr flush dev eth0
56 */
57int 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
65int FAST_FUNC rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) 92int 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
21extern void xrtnl_open(struct rtnl_handle *rth) FAST_FUNC; 21extern 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))
23extern int xrtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type) FAST_FUNC; 23extern void xrtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type) FAST_FUNC;
24extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) FAST_FUNC; 24extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) FAST_FUNC;
25extern int xrtnl_dump_filter(struct rtnl_handle *rth, 25extern 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
37extern int rtnl_send(struct rtnl_handle *rth, char *buf, int) FAST_FUNC; 37int rtnl_send_check(struct rtnl_handle *rth, const void *buf, int len) FAST_FUNC;
38//TODO: pass rth->fd instead of full rth?
39static 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
40extern int addattr32(struct nlmsghdr *n, int maxlen, int type, uint32_t data) FAST_FUNC; 55extern int addattr32(struct nlmsghdr *n, int maxlen, int type, uint32_t data) FAST_FUNC;
41extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen) FAST_FUNC; 56extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen) FAST_FUNC;