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>
This commit is contained in:
Denys Vlasenko
2019-05-22 13:54:46 +02:00
parent 84fc645605
commit 028c5aa18b
5 changed files with 65 additions and 17 deletions

View File

@ -34,7 +34,7 @@ void FAST_FUNC xrtnl_open(struct rtnl_handle *rth/*, unsigned subscriptions*/)
rth->seq = time(NULL);
}
int FAST_FUNC xrtnl_wilddump_request(struct rtnl_handle *rth, int family, int type)
void FAST_FUNC xrtnl_wilddump_request(struct rtnl_handle *rth, int family, int type)
{
struct {
struct nlmsghdr nlh;
@ -48,18 +48,45 @@ int FAST_FUNC xrtnl_wilddump_request(struct rtnl_handle *rth, int family, int ty
req.nlh.nlmsg_seq = rth->dump = ++rth->seq;
req.g.rtgen_family = family;
return rtnl_send(rth, (void*)&req, sizeof(req));
rtnl_send(rth, (void*)&req, sizeof(req));
}
//TODO: pass rth->fd instead of full rth?
int FAST_FUNC rtnl_send(struct rtnl_handle *rth, char *buf, int len)
/* A version which checks for e.g. EPERM errors.
* Try: setuidgid 1:1 ip addr flush dev eth0
*/
int FAST_FUNC rtnl_send_check(struct rtnl_handle *rth, const void *buf, int len)
{
struct sockaddr_nl nladdr;
struct nlmsghdr *h;
int status;
char resp[1024];
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
status = write(rth->fd, buf, len);
if (status < 0)
return status;
return xsendto(rth->fd, buf, len, (struct sockaddr*)&nladdr, sizeof(nladdr));
/* Check for immediate errors */
status = recv(rth->fd, resp, sizeof(resp), MSG_DONTWAIT|MSG_PEEK);
if (status < 0) {
if (errno == EAGAIN) /* if no error, this happens */
return 0;
return -1;
}
for (h = (struct nlmsghdr *)resp;
NLMSG_OK(h, status);
h = NLMSG_NEXT(h, status)
) {
if (h->nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
bb_error_msg("ERROR truncated");
else
errno = -err->error;
return -1;
}
}
return 0;
}
int FAST_FUNC rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len)