]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
ss: Use rtnl_dump_filter for inet_show_netlink
authorVadim Kochan <vadim4j@gmail.com>
Fri, 26 Dec 2014 02:26:27 +0000 (04:26 +0200)
committerStephen Hemminger <shemming@brocade.com>
Sat, 27 Dec 2014 18:21:10 +0000 (10:21 -0800)
Just another refactoring for ss to use rtnl API from lib

Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
include/libnetlink.h
lib/libnetlink.c
misc/ss.c

index 3794ef1b28afeadb5b25fd44da8f1e1d354bd007..db0496945177206b45f99cf7504814576994ba58 100644 (file)
@@ -19,6 +19,7 @@ struct rtnl_handle
        __u32                   seq;
        __u32                   dump;
        int                     proto;
+       FILE                   *dump_fp;
 };
 
 extern int rcvbuf;
index e3b7862c32a25ef4325321b0886793f77034e3ba..45ff90a07aa869123555381e94d01fed6e34c528 100644 (file)
@@ -220,12 +220,15 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth,
                        return -1;
                }
 
+               if (rth->dump_fp)
+                       fwrite(buf, 1, NLMSG_ALIGN(status), rth->dump_fp);
+
                for (a = arg; a->filter; a++) {
                        struct nlmsghdr *h = (struct nlmsghdr*)buf;
                        msglen = status;
 
                        while (NLMSG_OK(h, msglen)) {
-                               int err;
+                               int err = 0;
 
                                if (nladdr.nl_pid != 0 ||
                                    h->nlmsg_pid != rth->local.nl_pid ||
@@ -247,16 +250,20 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth,
                                        } else {
                                                errno = -err->error;
                                                if (rth->proto == NETLINK_SOCK_DIAG &&
-                                                   errno == ENOENT)
+                                                   (errno == ENOENT ||
+                                                    errno == EOPNOTSUPP))
                                                        return -1;
 
                                                perror("RTNETLINK answers");
                                        }
                                        return -1;
                                }
-                               err = a->filter(&nladdr, h, a->arg1);
-                               if (err < 0)
-                                       return err;
+
+                               if (!rth->dump_fp) {
+                                       err = a->filter(&nladdr, h, a->arg1);
+                                       if (err < 0)
+                                               return err;
+                               }
 
 skip_it:
                                h = NLMSG_NEXT(h, msglen);
index 706b5bada85b89213572ef7169a884cf3db4f645..f0c7b345b67e4f2a5aac3a2feecbd2dbd3a6e0fe 100644 (file)
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -1871,122 +1871,57 @@ static int sockdiag_send(int family, int fd, int protocol, struct filter *f)
        return 0;
 }
 
-static int inet_show_netlink(struct filter *f, FILE *dump_fp, int protocol)
-{
-       int fd, family;
-       struct sockaddr_nl nladdr;
-       struct msghdr msg;
-       char    buf[16384];
-       struct iovec iov[3];
-
-       if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG)) < 0)
-               return -1;
-
-       family = PF_INET;
-again:
-       if (sockdiag_send(family, fd, protocol, f))
-               return -1;
-
-       memset(&nladdr, 0, sizeof(nladdr));
-       nladdr.nl_family = AF_NETLINK;
-
-       iov[0] = (struct iovec){
-               .iov_base = buf,
-               .iov_len = sizeof(buf)
-       };
-
-       while (1) {
-               int status;
-               struct nlmsghdr *h;
-
-               msg = (struct msghdr) {
-                       (void*)&nladdr, sizeof(nladdr),
-                       iov,    1,
-                       NULL,   0,
-                       0
-               };
-
-               status = recvmsg(fd, &msg, 0);
-
-               if (status < 0) {
-                       if (errno == EINTR)
-                               continue;
-                       perror("OVERRUN");
-                       continue;
-               }
-               if (status == 0) {
-                       fprintf(stderr, "EOF on netlink\n");
-                       close(fd);
-                       return 0;
-               }
-
-               if (dump_fp)
-                       fwrite(buf, 1, NLMSG_ALIGN(status), dump_fp);
+struct inet_diag_arg {
+       struct filter *f;
+       int protocol;
+};
 
-               h = (struct nlmsghdr*)buf;
-               while (NLMSG_OK(h, status)) {
-                       int err;
-                       struct inet_diag_msg *r = NLMSG_DATA(h);
+static int show_one_inet_sock(const struct sockaddr_nl *addr,
+               struct nlmsghdr *h, void *arg)
+{
+       int err;
+       struct inet_diag_arg *diag_arg = arg;
+       struct inet_diag_msg *r = NLMSG_DATA(h);
 
-                       if (/*h->nlmsg_pid != rth->local.nl_pid ||*/
-                           h->nlmsg_seq != MAGIC_SEQ)
-                               goto skip_it;
+       if (!(diag_arg->f->families & (1 << r->idiag_family)))
+               return 0;
+       if ((err = inet_show_sock(h, NULL, diag_arg->protocol)) < 0)
+               return err;
 
-                       if (h->nlmsg_type == NLMSG_DONE)
-                               goto done;
+       return 0;
+}
 
-                       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 {
-                                       if (family != PF_UNSPEC) {
-                                               family = PF_UNSPEC;
-                                               goto again;
-                                       }
+static int inet_show_netlink(struct filter *f, FILE *dump_fp, int protocol)
+{
+       int err = 0;
+       struct rtnl_handle rth;
+       int family = PF_INET;
+       struct inet_diag_arg arg = { .f = f, .protocol = protocol };
 
-                                       errno = -err->error;
-                                       if (errno == EOPNOTSUPP) {
-                                               close(fd);
-                                               return -1;
-                                       }
-                                       perror("TCPDIAG answers");
-                               }
+       if (rtnl_open_byproto(&rth, 0, NETLINK_SOCK_DIAG))
+               return -1;
+       rth.dump = MAGIC_SEQ;
+       rth.dump_fp = dump_fp;
 
-                               goto done;
-                       }
-                       if (!dump_fp) {
-                               if (!(f->families & (1<<r->idiag_family))) {
-                                       h = NLMSG_NEXT(h, status);
-                                       continue;
-                               }
-                               err = inet_show_sock(h, NULL, protocol);
-                               if (err < 0) {
-                                       close(fd);
-                                       return err;
-                               }
-                       }
+again:
+       if ((err = sockdiag_send(family, rth.fd, protocol, f)))
+               goto Exit;
 
-skip_it:
-                       h = NLMSG_NEXT(h, status);
-               }
-               if (msg.msg_flags & MSG_TRUNC) {
-                       fprintf(stderr, "Message truncated\n");
-                       continue;
-               }
-               if (status) {
-                       fprintf(stderr, "!!!Remnant of size %d\n", status);
-                       exit(1);
+       if ((err = rtnl_dump_filter(&rth, show_one_inet_sock, &arg))) {
+               if (family != PF_UNSPEC) {
+                       family = PF_UNSPEC;
+                       goto again;
                }
+               goto Exit;
        }
-done:
        if (family == PF_INET) {
                family = PF_INET6;
                goto again;
        }
 
-       close(fd);
-       return 0;
+Exit:
+       rtnl_close(&rth);
+       return err;
 }
 
 static int tcp_show_netlink_file(struct filter *f)