poll for errors after rtnl_send

This fixes the problem where a bulk operation (like ip flush)
is performed as non-root user.  The kernel will only send a response
if there is an error, so check for it.
This commit is contained in:
Stephen Hemminger 2008-01-26 11:09:42 -08:00
parent 1fb0a998e1
commit 54bb35c69c

View File

@ -114,11 +114,39 @@ int rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type)
int rtnl_send(struct rtnl_handle *rth, const char *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;
return sendto(rth->fd, buf, len, 0, (struct sockaddr*)&nladdr, sizeof(nladdr));
status = sendto(rth->fd, buf, len, 0,
(struct sockaddr*)&nladdr, sizeof(nladdr));
if (status < 0)
return status;
/* Check for errors */
status = recv(rth->fd, resp, sizeof(resp), MSG_DONTWAIT);
if (status < 0) {
if (errno == EAGAIN)
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)))
fprintf(stderr, "ERROR truncated\n");
else
errno = -err->error;
}
return -1;
}
return 0;
}
int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len)