]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
ss: Use rtnl_dump_filter in handle_netlink_request
authorvadimk <vadim4j@gmail.com>
Thu, 4 Dec 2014 10:32:58 +0000 (12:32 +0200)
committerStephen Hemminger <shemming@brocade.com>
Sat, 20 Dec 2014 20:17:02 +0000 (12:17 -0800)
Replaced handling netlink messages by rtnl_dump_filter
from lib/libnetlink.c, also:

    - removed unused dump_fp arg;
    - added MAGIC_SEQ #define for 123456 seq id;
    - silently exit if ENOENT errno is caused for NETLINK_SOCK_DIAG proto
        in lib/libnetlink.c: rtnl_duml_filter_l(...) function. This fix
        was added in a3fd8e58c1787af186f5c4b234ff974544f840b6 by Eric
        for misc/ss.c

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

index fe7d5d386264494a09e9e928430055fe3e4d7af5..3794ef1b28afeadb5b25fd44da8f1e1d354bd007 100644 (file)
@@ -18,6 +18,7 @@ struct rtnl_handle
        struct sockaddr_nl      peer;
        __u32                   seq;
        __u32                   dump;
+       int                     proto;
 };
 
 extern int rcvbuf;
index 8d504a9e769bd5eb29e9d97754acfec6fa7ecca2..e3b7862c32a25ef4325321b0886793f77034e3ba 100644 (file)
@@ -43,6 +43,7 @@ int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions,
 
        memset(rth, 0, sizeof(*rth));
 
+       rth->proto = protocol;
        rth->fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, protocol);
        if (rth->fd < 0) {
                perror("Cannot open netlink socket");
@@ -245,6 +246,10 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth,
                                                        "ERROR truncated\n");
                                        } else {
                                                errno = -err->error;
+                                               if (rth->proto == NETLINK_SOCK_DIAG &&
+                                                   errno == ENOENT)
+                                                       return -1;
+
                                                perror("RTNETLINK answers");
                                        }
                                        return -1;
index e9927a50df0ba09129adef07ff0a21049784ba48..15fa2bc526ceb48b30770c0712d049e28fe0483e 100644 (file)
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -41,6 +41,8 @@
 #include <linux/packet_diag.h>
 #include <linux/netlink_diag.h>
 
+#define MAGIC_SEQ 123456
+
 #define DIAG_REQUEST(_req, _r)                                             \
        struct {                                                            \
                struct nlmsghdr nlh;                                        \
@@ -49,7 +51,7 @@
                .nlh = {                                                    \
                        .nlmsg_type = SOCK_DIAG_BY_FAMILY,                  \
                        .nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST,\
-                       .nlmsg_seq = 123456,                                \
+                       .nlmsg_seq = MAGIC_SEQ,                             \
                        .nlmsg_len = sizeof(_req),                          \
                },                                                          \
        }
@@ -1767,7 +1769,7 @@ static int tcpdiag_send(int fd, int protocol, struct filter *f)
                req.nlh.nlmsg_type = DCCPDIAG_GETSOCK;
        req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
        req.nlh.nlmsg_pid = 0;
-       req.nlh.nlmsg_seq = 123456;
+       req.nlh.nlmsg_seq = MAGIC_SEQ;
        memset(&req.r, 0, sizeof(req.r));
        req.r.idiag_family = AF_INET;
        req.r.idiag_states = f->states;
@@ -1927,7 +1929,7 @@ again:
                        struct inet_diag_msg *r = NLMSG_DATA(h);
 
                        if (/*h->nlmsg_pid != rth->local.nl_pid ||*/
-                           h->nlmsg_seq != 123456)
+                           h->nlmsg_seq != MAGIC_SEQ)
                                goto skip_it;
 
                        if (h->nlmsg_type == NLMSG_DONE)
@@ -2412,8 +2414,10 @@ static void unix_list_print(struct unixstat *list, struct filter *f)
        }
 }
 
-static int unix_show_sock(struct nlmsghdr *nlh, struct filter *f)
+static int unix_show_sock(const struct sockaddr_nl *addr, struct nlmsghdr *nlh,
+               void *arg)
 {
+       struct filter *f = (struct filter *)arg;
        struct unix_diag_msg *r = NLMSG_DATA(nlh);
        struct rtattr *tb[UNIX_DIAG_MAX+1];
        char name[128];
@@ -2502,90 +2506,30 @@ static int unix_show_sock(struct nlmsghdr *nlh, struct filter *f)
        return 0;
 }
 
-static int handle_netlink_request(struct filter *f, FILE *dump_fp,
-                                 struct nlmsghdr *req, size_t size,
-                                 int (* show_one_sock)(struct nlmsghdr *nlh, struct filter *f))
+static int handle_netlink_request(struct filter *f, struct nlmsghdr *req,
+               size_t size, rtnl_filter_t show_one_sock)
 {
-       int fd;
-       char    buf[16384];
+       int ret = -1;
+       struct rtnl_handle rth;
 
-       if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG)) < 0)
+       if (rtnl_open_byproto(&rth, 0, NETLINK_SOCK_DIAG))
                return -1;
 
-       if (send(fd, req, size, 0) < 0) {
-               close(fd);
-               return -1;
-       }
+       rth.dump = MAGIC_SEQ;
 
-       while (1) {
-               ssize_t status;
-               struct nlmsghdr *h;
-               struct sockaddr_nl nladdr;
-               socklen_t slen = sizeof(nladdr);
+       if (rtnl_send(&rth, req, size) < 0)
+               goto Exit;
 
-               status = recvfrom(fd, buf, sizeof(buf), 0,
-                                 (struct sockaddr *) &nladdr, &slen);
-               if (status < 0) {
-                       if (errno == EINTR)
-                               continue;
-                       perror("OVERRUN");
-                       continue;
-               }
-               if (status == 0) {
-                       fprintf(stderr, "EOF on netlink\n");
-                       goto close_it;
-               }
-
-               if (dump_fp)
-                       fwrite(buf, 1, NLMSG_ALIGN(status), dump_fp);
-
-               h = (struct nlmsghdr*)buf;
-               while (NLMSG_OK(h, status)) {
-                       int err;
+       if (rtnl_dump_filter(&rth, show_one_sock, f))
+               goto Exit;
 
-                       if (/*h->nlmsg_pid != rth->local.nl_pid ||*/
-                           h->nlmsg_seq != 123456)
-                               goto skip_it;
-
-                       if (h->nlmsg_type == NLMSG_DONE)
-                               goto close_it;
-
-                       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;
-                                       if (errno != ENOENT)
-                                               fprintf(stderr, "DIAG answers %d\n", errno);
-                               }
-                               close(fd);
-                               return -1;
-                       }
-                       if (!dump_fp) {
-                               err = show_one_sock(h, f);
-                               if (err < 0) {
-                                       close(fd);
-                                       return err;
-                               }
-                       }
-
-skip_it:
-                       h = NLMSG_NEXT(h, status);
-               }
-
-               if (status) {
-                       fprintf(stderr, "!!!Remnant of size %zd\n", status);
-                       exit(1);
-               }
-       }
-
-close_it:
-       close(fd);
-       return 0;
+       ret = 0;
+Exit:
+       rtnl_close(&rth);
+       return ret;
 }
 
-static int unix_show_netlink(struct filter *f, FILE *dump_fp)
+static int unix_show_netlink(struct filter *f)
 {
        DIAG_REQUEST(req, struct unix_diag_req r);
 
@@ -2595,8 +2539,7 @@ static int unix_show_netlink(struct filter *f, FILE *dump_fp)
        if (show_mem)
                req.r.udiag_show |= UDIAG_SHOW_MEMINFO;
 
-       return handle_netlink_request(f, dump_fp, &req.nlh,
-                                       sizeof(req), unix_show_sock);
+       return handle_netlink_request(f, &req.nlh, sizeof(req), unix_show_sock);
 }
 
 static int unix_show(struct filter *f)
@@ -2609,7 +2552,7 @@ static int unix_show(struct filter *f)
        struct unixstat *list = NULL;
 
        if (!getenv("PROC_NET_UNIX") && !getenv("PROC_ROOT")
-           && unix_show_netlink(f, NULL) == 0)
+           && unix_show_netlink(f) == 0)
                return 0;
 
        if ((fp = net_unix_open()) == NULL)
@@ -2683,7 +2626,8 @@ static int unix_show(struct filter *f)
        return 0;
 }
 
-static int packet_show_sock(struct nlmsghdr *nlh, struct filter *f)
+static int packet_show_sock(const struct sockaddr_nl *addr,
+               struct nlmsghdr *nlh, void *arg)
 {
        struct packet_diag_msg *r = NLMSG_DATA(nlh);
        struct rtattr *tb[PACKET_DIAG_MAX+1];
@@ -2776,15 +2720,14 @@ static int packet_show_sock(struct nlmsghdr *nlh, struct filter *f)
        return 0;
 }
 
-static int packet_show_netlink(struct filter *f, FILE *dump_fp)
+static int packet_show_netlink(struct filter *f)
 {
        DIAG_REQUEST(req, struct packet_diag_req r);
 
        req.r.sdiag_family = AF_PACKET;
        req.r.pdiag_show = PACKET_SHOW_INFO | PACKET_SHOW_MEMINFO | PACKET_SHOW_FILTER;
 
-       return handle_netlink_request(f, dump_fp, &req.nlh, sizeof(req),
-                       packet_show_sock);
+       return handle_netlink_request(f, &req.nlh, sizeof(req), packet_show_sock);
 }
 
 
@@ -2801,7 +2744,7 @@ static int packet_show(struct filter *f)
        int ino;
        unsigned long long sk;
 
-       if (packet_show_netlink(f, NULL) == 0)
+       if (packet_show_netlink(f) == 0)
                return 0;
 
        if ((fp = net_packet_open()) == NULL)
@@ -2973,8 +2916,10 @@ static void netlink_show_one(struct filter *f,
        return;
 }
 
-static int netlink_show_sock(struct nlmsghdr *nlh, struct filter *f)
+static int netlink_show_sock(const struct sockaddr_nl *addr,
+               struct nlmsghdr *nlh, void *arg)
 {
+       struct filter *f = (struct filter *)arg;
        struct netlink_diag_msg *r = NLMSG_DATA(nlh);
        struct rtattr *tb[NETLINK_DIAG_MAX+1];
        int rq = 0, wq = 0;
@@ -3007,7 +2952,7 @@ static int netlink_show_sock(struct nlmsghdr *nlh, struct filter *f)
        return 0;
 }
 
-static int netlink_show_netlink(struct filter *f, FILE *dump_fp)
+static int netlink_show_netlink(struct filter *f)
 {
        DIAG_REQUEST(req, struct netlink_diag_req r);
 
@@ -3015,8 +2960,7 @@ static int netlink_show_netlink(struct filter *f, FILE *dump_fp)
        req.r.sdiag_protocol = NDIAG_PROTO_ALL;
        req.r.ndiag_show = NDIAG_SHOW_GROUPS | NDIAG_SHOW_MEMINFO;
 
-       return handle_netlink_request(f, dump_fp, &req.nlh,
-                                       sizeof(req), netlink_show_sock);
+       return handle_netlink_request(f, &req.nlh, sizeof(req), netlink_show_sock);
 }
 
 static int netlink_show(struct filter *f)
@@ -3029,7 +2973,7 @@ static int netlink_show(struct filter *f)
        unsigned long long sk, cb;
 
        if (!getenv("PROC_NET_NETLINK") && !getenv("PROC_ROOT") &&
-               netlink_show_netlink(f, NULL) == 0)
+               netlink_show_netlink(f) == 0)
                return 0;
 
        if ((fp = net_netlink_open()) == NULL)