From: vadimk Date: Thu, 4 Dec 2014 10:32:58 +0000 (+0200) Subject: ss: Use rtnl_dump_filter in handle_netlink_request X-Git-Tag: v3.18.0~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8a4025f6a4e182f0f33763238314ff1d96c580db;p=thirdparty%2Fiproute2.git ss: Use rtnl_dump_filter in handle_netlink_request 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 --- diff --git a/include/libnetlink.h b/include/libnetlink.h index fe7d5d386..3794ef1b2 100644 --- a/include/libnetlink.h +++ b/include/libnetlink.h @@ -18,6 +18,7 @@ struct rtnl_handle struct sockaddr_nl peer; __u32 seq; __u32 dump; + int proto; }; extern int rcvbuf; diff --git a/lib/libnetlink.c b/lib/libnetlink.c index 8d504a9e7..e3b7862c3 100644 --- a/lib/libnetlink.c +++ b/lib/libnetlink.c @@ -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; diff --git a/misc/ss.c b/misc/ss.c index e9927a50d..15fa2bc52 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -41,6 +41,8 @@ #include #include +#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)