#include <linux/packet_diag.h>
#include <linux/netlink_diag.h>
+#define MAGIC_SEQ 123456
+
+#define DIAG_REQUEST(_req, _r) \
+ struct { \
+ struct nlmsghdr nlh; \
+ _r; \
+ } _req = { \
+ .nlh = { \
+ .nlmsg_type = SOCK_DIAG_BY_FAMILY, \
+ .nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST,\
+ .nlmsg_seq = MAGIC_SEQ, \
+ .nlmsg_len = sizeof(_req), \
+ }, \
+ }
+
#if HAVE_SELINUX
#include <selinux/selinux.h>
#else
}
if (addr[0] && strcmp(addr, "*")) {
a.addr.bitlen = 32;
- if (get_u32(a.addr.data, addr, 0)) {
- if (strcmp(addr, "rtnl") == 0)
- a.addr.data[0] = 0;
- else if (strcmp(addr, "fw") == 0)
- a.addr.data[0] = 3;
- else if (strcmp(addr, "tcpdiag") == 0)
- a.addr.data[0] = 4;
- else
- return NULL;
- }
+ if (nl_proto_a2n(&a.addr.data[0], addr) == -1)
+ return NULL;
}
goto out;
}
info->tcpi_rcv_wscale);
if (info->tcpi_rto && info->tcpi_rto != 3000000)
printf(" rto:%g", (double)info->tcpi_rto/1000);
+ if (info->tcpi_backoff)
+ printf(" backoff:%u", info->tcpi_backoff);
if (info->tcpi_rtt)
printf(" rtt:%g/%g", (double)info->tcpi_rtt/1000,
(double)info->tcpi_rttvar/1000);
rtt = vinfo->tcpv_rtt;
}
+ if (tb[INET_DIAG_DCTCPINFO]) {
+ const struct tcp_dctcp_info *dinfo
+ = RTA_DATA(tb[INET_DIAG_DCTCPINFO]);
+
+ if (dinfo->dctcp_enabled) {
+ printf(" ce_state %u alpha %u ab_ecn %u ab_tot %u",
+ dinfo->dctcp_ce_state, dinfo->dctcp_alpha,
+ dinfo->dctcp_ab_ecn, dinfo->dctcp_ab_tot);
+ } else {
+ printf(" fallback_mode");
+ }
+ }
+
if (rtt > 0 && info->tcpi_snd_mss && info->tcpi_snd_cwnd) {
printf(" send %sbps",
sprint_bw(b1, (double) info->tcpi_snd_cwnd *
/ rtt));
}
+ if (info->tcpi_last_data_sent)
+ printf(" lastsnd:%u", info->tcpi_last_data_sent);
+
+ if (info->tcpi_last_data_recv)
+ printf(" lastrcv:%u", info->tcpi_last_data_recv);
+
+ if (info->tcpi_last_ack_recv)
+ printf(" lastack:%u", info->tcpi_last_ack_recv);
+
if (info->tcpi_pacing_rate &&
info->tcpi_pacing_rate != ~0ULL) {
printf(" pacing_rate %sbps",
printf(" sk:");
if (r->id.idiag_cookie[1] != 0)
printf("%08x", r->id.idiag_cookie[1]);
- printf("%08x", r->id.idiag_cookie[0]);
+ printf("%08x", r->id.idiag_cookie[0]);
if (tb[INET_DIAG_SHUTDOWN]) {
unsigned char mask;
mask = *(__u8 *)RTA_DATA(tb[INET_DIAG_SHUTDOWN]);
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;
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;
+ DIAG_REQUEST(req, struct inet_diag_req_v2 r);
char *bc = NULL;
int bclen;
struct msghdr msg;
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;
int fd, family;
struct sockaddr_nl nladdr;
struct msghdr msg;
- char buf[8192];
+ char buf[16384];
struct iovec iov[3];
if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG)) < 0)
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)
static int tcp_show_netlink_file(struct filter *f)
{
FILE *fp;
- char buf[8192];
+ char buf[16384];
if ((fp = fopen(getenv("TCPDIAG_FILE"), "r")) == NULL) {
perror("fopen($TCPDIAG_FILE)");
}
}
-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];
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[8192];
-
- if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG)) < 0)
- return -1;
+ int ret = -1;
+ struct rtnl_handle rth;
- if (send(fd, req, size, 0) < 0) {
- close(fd);
+ if (rtnl_open_byproto(&rth, 0, NETLINK_SOCK_DIAG))
return -1;
- }
- while (1) {
- ssize_t status;
- struct nlmsghdr *h;
- struct sockaddr_nl nladdr;
- socklen_t slen = sizeof(nladdr);
+ rth.dump = MAGIC_SEQ;
- 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 (rtnl_send(&rth, req, size) < 0)
+ goto Exit;
- if (dump_fp)
- fwrite(buf, 1, NLMSG_ALIGN(status), dump_fp);
+ if (rtnl_dump_filter(&rth, show_one_sock, f))
+ goto Exit;
- h = (struct nlmsghdr*)buf;
- while (NLMSG_OK(h, status)) {
- int err;
-
- 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)
{
- struct {
- struct nlmsghdr nlh;
- struct unix_diag_req r;
- } req;
-
- memset(&req, 0, sizeof(req));
- 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_seq = 123456;
+ DIAG_REQUEST(req, struct unix_diag_req r);
req.r.sdiag_family = AF_UNIX;
req.r.udiag_states = f->states;
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)
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)
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];
return 0;
}
-static int packet_show_netlink(struct filter *f, FILE *dump_fp)
+static int packet_show_netlink(struct filter *f)
{
- int fd;
- struct {
- struct nlmsghdr nlh;
- struct packet_diag_req r;
- } req;
- char buf[8192];
-
- if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG)) < 0)
- return -1;
-
- memset(&req, 0, sizeof(req));
- 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_seq = 123456;
+ 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;
- if (send(fd, &req, sizeof(req), 0) < 0) {
- close(fd);
- return -1;
- }
-
- while (1) {
- ssize_t status;
- struct nlmsghdr *h;
- struct sockaddr_nl nladdr;
- socklen_t slen = sizeof(nladdr);
-
- 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 (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, "UDIAG answers %d\n", errno);
- }
- close(fd);
- return -1;
- }
- if (!dump_fp) {
- err = packet_show_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;
+ return handle_netlink_request(f, &req.nlh, sizeof(req), packet_show_sock);
}
int ino;
unsigned long long sk;
- if (!(f->states & (1<<SS_CLOSE)))
+ if (preferred_family != AF_PACKET && !(f->states & (1 << SS_CLOSE)))
return 0;
- if (packet_show_netlink(f, NULL) == 0)
+ if (packet_show_netlink(f) == 0)
return 0;
if ((fp = net_packet_open()) == NULL)
int rq, int wq,
unsigned long long sk, unsigned long long cb)
{
+ SPRINT_BUF(prot_name);
+
if (f->f) {
struct tcpstat tst;
tst.local.family = AF_NETLINK;
if (state_width)
printf("%-*s ", state_width, "UNCONN");
printf("%-6d %-6d ", rq, wq);
- if (resolve_services && prot == 0)
- printf("%*s:", addr_width, "rtnl");
- else if (resolve_services && prot == 3)
- printf("%*s:", addr_width, "fw");
- else if (resolve_services && prot == 4)
- printf("%*s:", addr_width, "tcpdiag");
- else
+
+ if (resolve_services) {
+ printf("%*s:", addr_width, nl_proto_n2a(prot, prot_name,
+ sizeof(prot_name)));
+ } else {
printf("%*d:", addr_width, prot);
+ }
+
if (pid == -1) {
printf("%-*s ", serv_width, "*");
} else if (resolve_services) {
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;
return 0;
}
-static int netlink_show_netlink(struct filter *f, FILE *dump_fp)
+static int netlink_show_netlink(struct filter *f)
{
- struct {
- struct nlmsghdr nlh;
- struct netlink_diag_req r;
- } req;
-
- memset(&req, 0, sizeof(req));
- 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_seq = 123456;
+ DIAG_REQUEST(req, struct netlink_diag_req r);
req.r.sdiag_family = AF_NETLINK;
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)
int rq, wq, rc;
unsigned long long sk, cb;
- if (!(f->states & (1<<SS_CLOSE)))
+ if (preferred_family != AF_NETLINK && !(f->states & (1 << SS_CLOSE)))
return 0;
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)
printf("%-*s ", state_width, "State");
printf("%-6s %-6s ", "Recv-Q", "Send-Q");
+ /* Make enough space for the local/remote port field */
+ addr_width -= 13;
+ serv_width += 13;
+
printf("%*s:%-*s %*s:%-*s\n",
addr_width, "Local Address", serv_width, "Port",
addr_width, "Peer Address", serv_width, "Port");