All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pavel Emelyanov <xemul@parallels.com>
To: Stephen Hemminger <shemminger@vyatta.com>,
	Linux Netdev List <netdev@vger.kernel.org>
Subject: [PATCH 3/5] ss: Support sock-diag
Date: Thu, 25 Oct 2012 17:23:36 +0400	[thread overview]
Message-ID: <50893D58.3030808@parallels.com> (raw)
In-Reply-To: <50893BAF.7030500@parallels.com>

That is -- write the code, that sends diag request in new format. It's
mostly copied from tcp-diag code. Plus, sock-diag differentiates sockets
by families, thus we have to send two requests sequentially.

If we fail to submit new sock-diag request, try to fall-back and submit
the legacy tcp-diag one.

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>

---
 misc/ss.c |   95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 87 insertions(+), 8 deletions(-)

diff --git a/misc/ss.c b/misc/ss.c
index 27feeb8..1ceb026 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -1561,9 +1561,76 @@ static int tcpdiag_send(int fd, int protocol, struct filter *f)
 	return 0;
 }
 
+static int sockdiag_send(int family, int fd, int protocol, struct filter *f)
+{
+	struct sockaddr_nl nladdr;
+	struct {
+		struct nlmsghdr nlh;
+		struct inet_diag_req_v2 r;
+	} req;
+	char    *bc = NULL;
+	int	bclen;
+	struct msghdr msg;
+	struct rtattr rta;
+	struct iovec iov[3];
+
+	if (family == PF_UNSPEC)
+		return tcpdiag_send(fd, protocol, f);
+
+	memset(&nladdr, 0, sizeof(nladdr));
+	nladdr.nl_family = AF_NETLINK;
+
+	req.nlh.nlmsg_len = sizeof(req);
+	req.nlh.nlmsg_type = SOCK_DIAG_BY_FAMILY;
+	req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
+	req.nlh.nlmsg_pid = 0;
+	req.nlh.nlmsg_seq = 123456;
+	memset(&req.r, 0, sizeof(req.r));
+	req.r.sdiag_family = family;
+	req.r.sdiag_protocol = protocol;
+	req.r.idiag_states = f->states;
+	if (show_mem) {
+		req.r.idiag_ext |= (1<<(INET_DIAG_MEMINFO-1));
+		req.r.idiag_ext |= (1<<(INET_DIAG_SKMEMINFO-1));
+	}
+
+	if (show_tcpinfo) {
+		req.r.idiag_ext |= (1<<(INET_DIAG_INFO-1));
+		req.r.idiag_ext |= (1<<(INET_DIAG_VEGASINFO-1));
+		req.r.idiag_ext |= (1<<(INET_DIAG_CONG-1));
+	}
+
+	iov[0] = (struct iovec){
+		.iov_base = &req,
+		.iov_len = sizeof(req)
+	};
+	if (f->f) {
+		bclen = ssfilter_bytecompile(f->f, &bc);
+		rta.rta_type = INET_DIAG_REQ_BYTECODE;
+		rta.rta_len = RTA_LENGTH(bclen);
+		iov[1] = (struct iovec){ &rta, sizeof(rta) };
+		iov[2] = (struct iovec){ bc, bclen };
+		req.nlh.nlmsg_len += RTA_LENGTH(bclen);
+	}
+
+	msg = (struct msghdr) {
+		.msg_name = (void*)&nladdr,
+		.msg_namelen = sizeof(nladdr),
+		.msg_iov = iov,
+		.msg_iovlen = f->f ? 3 : 1,
+	};
+
+	if (sendmsg(fd, &msg, 0) < 0) {
+		close(fd);
+		return -1;
+	}
+
+	return 0;
+}
+
 static int inet_show_netlink(struct filter *f, FILE *dump_fp, int protocol)
 {
-	int fd;
+	int fd, family;
 	struct sockaddr_nl nladdr;
 	struct msghdr msg;
 	char	buf[8192];
@@ -1572,7 +1639,9 @@ static int inet_show_netlink(struct filter *f, FILE *dump_fp, int protocol)
 	if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG)) < 0)
 		return -1;
 
-	if (tcpdiag_send(fd, protocol, f))
+	family = PF_INET;
+again:
+	if (sockdiag_send(family, fd, protocol, f))
 		return -1;
 
 	memset(&nladdr, 0, sizeof(nladdr));
@@ -1620,15 +1689,19 @@ static int inet_show_netlink(struct filter *f, FILE *dump_fp, int protocol)
 			    h->nlmsg_seq != 123456)
 				goto skip_it;
 
-			if (h->nlmsg_type == NLMSG_DONE) {
-				close(fd);
-				return 0;
-			}
+			if (h->nlmsg_type == NLMSG_DONE)
+				goto done;
+
 			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;
+					}
+
 					errno = -err->error;
 					if (errno == EOPNOTSUPP) {
 						close(fd);
@@ -1636,8 +1709,8 @@ static int inet_show_netlink(struct filter *f, FILE *dump_fp, int protocol)
 					}
 					perror("TCPDIAG answers");
 				}
-				close(fd);
-				return 0;
+
+				goto done;
 			}
 			if (!dump_fp) {
 				if (!(f->families & (1<<r->idiag_family))) {
@@ -1663,6 +1736,12 @@ skip_it:
 			exit(1);
 		}
 	}
+done:
+	if (family == PF_INET) {
+		family = PF_INET6;
+		goto again;
+	}
+
 	close(fd);
 	return 0;
 }
-- 
1.7.1

  parent reply	other threads:[~2012-10-25 13:23 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-10-25 13:16 [PATCH iproute2 0/5] Teach ss to show sockets' shutdown state Pavel Emelyanov
2012-10-25 13:18 ` [PATCH 1/5] ss: Rename some tcp- names into inet- Pavel Emelyanov
2012-10-25 13:21 ` [PATCH 2/5] ss: Split inet_show_netlink into parts Pavel Emelyanov
2012-10-25 13:23 ` Pavel Emelyanov [this message]
2012-10-25 13:24 ` [PATCH 4/5] ss: Get udp sockets info via sock-diag Pavel Emelyanov
2012-10-27  0:51   ` Stephen Hemminger
2012-10-25 13:26 ` [PATCH 5/5] ss: Show inet and unix sockets' shutdown state Pavel Emelyanov
2012-10-25 15:52   ` Stephen Hemminger
2012-10-25 16:53     ` Eric Dumazet
2012-10-25 17:09       ` Stephen Hemminger
2012-10-25 18:00         ` Eric Dumazet
2012-10-25 23:01           ` Stephen Hemminger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=50893D58.3030808@parallels.com \
    --to=xemul@parallels.com \
    --cc=netdev@vger.kernel.org \
    --cc=shemminger@vyatta.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.