1 - from http://www.ducksong.com/misc/netstat-netlink-diag-patch.txt
4 ===================================================================
5 RCS file: /cvsroot/net-tools/net-tools/netstat.c,v
6 retrieving revision 1.55
7 diff -c -d -u -r1.55 netstat.c
8 --- netstat.c 1 Dec 2007 19:00:40 -0000 1.55
9 +++ netstat.c 20 Feb 2008 23:04:29 -0000
15 +#include <asm/types.h>
16 +#include <linux/netlink.h>
17 +#include <linux/inet_diag.h>
21 #define PROGNAME_WIDTH 20
23 #if !defined(s6_addr32) && defined(in6a_words)
24 @@ -828,11 +835,194 @@
33 + /* a newer alternative to /proc/net/tcp[6] - using NETLINK DIAG
34 + runs much faster with large number of entries
35 + essentially just a bridge - converts from DIAG to /proc/net/tcp format
36 + largely taken directly from ss of iproute package
38 + returns -1 if NETLINK isn't available, in which case the old /proc/net/tcp code is run
42 + struct sockaddr_nl nladdr;
44 + struct nlmsghdr nlh;
45 + struct inet_diag_req r;
52 + struct inet_diag_msg *r;
55 + if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG)) < 0)
58 + memset(&nladdr, 0, sizeof(nladdr));
59 + nladdr.nl_family = AF_NETLINK;
61 + req.nlh.nlmsg_len = sizeof(req);
62 + req.nlh.nlmsg_type = TCPDIAG_GETSOCK;
63 + req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
64 + req.nlh.nlmsg_pid = 0;
65 + req.nlh.nlmsg_seq = 123456;
66 + memset(&req.r, 0, sizeof(req.r));
67 + req.r.idiag_family = AF_INET;
68 + req.r.idiag_states = 0xfff;
69 + req.r.idiag_ext = 0;
71 + iov.iov_base = &req;
72 + iov.iov_len = sizeof(req);
74 + msg = (struct msghdr) {
75 + .msg_name = (void*)&nladdr,
76 + .msg_namelen = sizeof(nladdr),
81 + if (sendmsg(fd, &msg, 0) < 0)
88 + iov.iov_len = sizeof(buf);
95 + msg = (struct msghdr) {
96 + (void*)&nladdr, sizeof(nladdr),
102 + status = recvmsg(fd, &msg, 0);
106 + if (errno == EINTR)
119 + h = (struct nlmsghdr*)buf;
120 + while (NLMSG_OK(h, status))
122 + if (h->nlmsg_seq == 123456)
124 + if (h->nlmsg_type == NLMSG_DONE)
130 + if (h->nlmsg_type == NLMSG_ERROR)
138 + if (r->idiag_family == AF_INET)
140 + snprintf (linebuf,8192,
141 + "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08X %08X %5d %8d %d",
143 + r->id.idiag_src[0],
144 + ntohs(r->id.idiag_sport),
145 + r->id.idiag_dst[0],
146 + ntohs(r->id.idiag_dport),
148 + r->idiag_wqueue, r->idiag_rqueue,
150 + r->idiag_expires/10, // (diag reports as miliseconds, /proc interface stuck at centiseconds)
158 + snprintf (linebuf,8192,
159 + "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X %02X %08X:%08X %02X:%08X %08X %5d %8d %d",
161 + r->id.idiag_src[0],
162 + r->id.idiag_src[1],
163 + r->id.idiag_src[2],
164 + r->id.idiag_src[3],
165 + ntohs(r->id.idiag_sport),
166 + r->id.idiag_dst[0],
167 + r->id.idiag_dst[1],
168 + r->id.idiag_dst[2],
169 + r->id.idiag_dst[3],
170 + ntohs(r->id.idiag_dport),
172 + r->idiag_wqueue, r->idiag_rqueue,
174 + r->idiag_expires/10, // (diag reports as miliseconds, /proc interface stuck at centiseconds)
181 + tcp_do_one (++lnr, linebuf, r->idiag_family == AF_INET ? "tcp" : "tcp6");
183 + h = NLMSG_NEXT(h, status);
196 static int tcp_info(void)
198 - INFO_GUTS6(_PATH_PROCNET_TCP, _PATH_PROCNET_TCP6, "AF INET (tcp)",
199 - tcp_do_one, "tcp", "tcp6");
203 + rv = tcp_netlink();
208 + // netlink is not available - so parse /proc/net/tcp
209 + INFO_GUTS6(_PATH_PROCNET_TCP, _PATH_PROCNET_TCP6, "AF INET (tcp)",
210 + tcp_do_one, "tcp", "tcp6");
219 static void udp_do_one(int lnr, const char *line,const char *prot)
221 --- config.in~ 2009-03-10 04:37:40.000000000 +0200
222 +++ config.in 2009-03-10 04:38:14.092903210 +0200
224 bool 'Build iptunnel and ipmaddr' HAVE_IP_TOOLS n
225 bool 'Build mii-tool' HAVE_MII n
226 bool 'SELinux support' HAVE_SELINUX n
227 +bool 'Use Netlink Diag' HAVE_NETLINK y
228 --- config.h~ 2009-03-10 04:49:18.000000000 +0200
229 +++ config.h 2009-03-10 04:49:55.762832175 +0200
231 #define HAVE_IP_TOOLS 0
233 #define HAVE_SELINUX 1
234 +#define HAVE_NETLINK 1
235 --- config.make~ 2009-03-10 04:49:18.000000000 +0200
236 +++ config.make 2009-03-10 04:50:19.880072014 +0200