Commit 486ccd99 authored by Vadim Kochan's avatar Vadim Kochan Committed by Stephen Hemminger

ss: Use rtnl_dump_filter for inet_show_netlink

Just another refactoring for ss to use rtnl API from lib
Signed-off-by: default avatarVadim Kochan <vadim4j@gmail.com>
parent 417b2180
...@@ -19,6 +19,7 @@ struct rtnl_handle ...@@ -19,6 +19,7 @@ struct rtnl_handle
__u32 seq; __u32 seq;
__u32 dump; __u32 dump;
int proto; int proto;
FILE *dump_fp;
}; };
extern int rcvbuf; extern int rcvbuf;
......
...@@ -220,12 +220,15 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth, ...@@ -220,12 +220,15 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth,
return -1; return -1;
} }
if (rth->dump_fp)
fwrite(buf, 1, NLMSG_ALIGN(status), rth->dump_fp);
for (a = arg; a->filter; a++) { for (a = arg; a->filter; a++) {
struct nlmsghdr *h = (struct nlmsghdr*)buf; struct nlmsghdr *h = (struct nlmsghdr*)buf;
msglen = status; msglen = status;
while (NLMSG_OK(h, msglen)) { while (NLMSG_OK(h, msglen)) {
int err; int err = 0;
if (nladdr.nl_pid != 0 || if (nladdr.nl_pid != 0 ||
h->nlmsg_pid != rth->local.nl_pid || h->nlmsg_pid != rth->local.nl_pid ||
...@@ -247,16 +250,20 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth, ...@@ -247,16 +250,20 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth,
} else { } else {
errno = -err->error; errno = -err->error;
if (rth->proto == NETLINK_SOCK_DIAG && if (rth->proto == NETLINK_SOCK_DIAG &&
errno == ENOENT) (errno == ENOENT ||
errno == EOPNOTSUPP))
return -1; return -1;
perror("RTNETLINK answers"); perror("RTNETLINK answers");
} }
return -1; return -1;
} }
err = a->filter(&nladdr, h, a->arg1);
if (err < 0) if (!rth->dump_fp) {
return err; err = a->filter(&nladdr, h, a->arg1);
if (err < 0)
return err;
}
skip_it: skip_it:
h = NLMSG_NEXT(h, msglen); h = NLMSG_NEXT(h, msglen);
......
...@@ -1871,122 +1871,57 @@ static int sockdiag_send(int family, int fd, int protocol, struct filter *f) ...@@ -1871,122 +1871,57 @@ static int sockdiag_send(int family, int fd, int protocol, struct filter *f)
return 0; return 0;
} }
static int inet_show_netlink(struct filter *f, FILE *dump_fp, int protocol) struct inet_diag_arg {
{ struct filter *f;
int fd, family; int protocol;
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);
h = (struct nlmsghdr*)buf; static int show_one_inet_sock(const struct sockaddr_nl *addr,
while (NLMSG_OK(h, status)) { struct nlmsghdr *h, void *arg)
int err; {
struct inet_diag_msg *r = NLMSG_DATA(h); 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 ||*/ if (!(diag_arg->f->families & (1 << r->idiag_family)))
h->nlmsg_seq != MAGIC_SEQ) return 0;
goto skip_it; if ((err = inet_show_sock(h, NULL, diag_arg->protocol)) < 0)
return err;
if (h->nlmsg_type == NLMSG_DONE) return 0;
goto done; }
if (h->nlmsg_type == NLMSG_ERROR) { static int inet_show_netlink(struct filter *f, FILE *dump_fp, int protocol)
struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); {
if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) { int err = 0;
fprintf(stderr, "ERROR truncated\n"); struct rtnl_handle rth;
} else { int family = PF_INET;
if (family != PF_UNSPEC) { struct inet_diag_arg arg = { .f = f, .protocol = protocol };
family = PF_UNSPEC;
goto again;
}
errno = -err->error; if (rtnl_open_byproto(&rth, 0, NETLINK_SOCK_DIAG))
if (errno == EOPNOTSUPP) { return -1;
close(fd); rth.dump = MAGIC_SEQ;
return -1; rth.dump_fp = dump_fp;
}
perror("TCPDIAG answers");
}
goto done; again:
} if ((err = sockdiag_send(family, rth.fd, protocol, f)))
if (!dump_fp) { goto Exit;
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;
}
}
skip_it: if ((err = rtnl_dump_filter(&rth, show_one_inet_sock, &arg))) {
h = NLMSG_NEXT(h, status); if (family != PF_UNSPEC) {
} family = PF_UNSPEC;
if (msg.msg_flags & MSG_TRUNC) { goto again;
fprintf(stderr, "Message truncated\n");
continue;
}
if (status) {
fprintf(stderr, "!!!Remnant of size %d\n", status);
exit(1);
} }
goto Exit;
} }
done:
if (family == PF_INET) { if (family == PF_INET) {
family = PF_INET6; family = PF_INET6;
goto again; goto again;
} }
close(fd); Exit:
return 0; rtnl_close(&rth);
return err;
} }
static int tcp_show_netlink_file(struct filter *f) static int tcp_show_netlink_file(struct filter *f)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment