]> rtime.felk.cvut.cz Git - lisovros/iproute2_canprio.git/commitdiff
poll for errors after rtnl_send
authorStephen Hemminger <stephen.hemminger@vyatta.com>
Sat, 26 Jan 2008 19:09:42 +0000 (11:09 -0800)
committerStephen Hemminger <stephen.hemminger@vyatta.com>
Sat, 26 Jan 2008 19:09:42 +0000 (11:09 -0800)
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.

lib/libnetlink.c

index 7876c190b5b5f1c5b6fc187eae0311f90ea381bd..a4e91cf7c875e1a525d3ad7297b5f6132a838052 100644 (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)