static int show_tipcinfo;
static int show_tos;
static int show_cgroup;
+static int show_inet_sockopt;
int oneline;
enum col_id {
memcpy(a->data, &cid, sizeof(cid));
}
+static char* find_port(char *addr, bool is_port)
+{
+ char *port = NULL;
+ if (is_port)
+ port = addr;
+ else
+ port = strchr(addr, ':');
+ if (port && *port == ':')
+ *port++ = '\0';
+ return port;
+}
+
void *parse_hostcond(char *addr, bool is_port)
{
char *port = NULL;
int fam = preferred_family;
struct filter *f = ¤t_filter;
- if (fam == AF_UNIX || strncmp(addr, "unix:", 5) == 0) {
+ if (strncmp(addr, "unix:", 5) == 0) {
+ fam = AF_UNIX;
+ addr += 5;
+ } else if (strncmp(addr, "link:", 5) == 0) {
+ fam = AF_PACKET;
+ addr += 5;
+ } else if (strncmp(addr, "netlink:", 8) == 0) {
+ fam = AF_NETLINK;
+ addr += 8;
+ } else if (strncmp(addr, "vsock:", 6) == 0) {
+ fam = AF_VSOCK;
+ addr += 6;
+ } else if (strncmp(addr, "inet:", 5) == 0) {
+ fam = AF_INET;
+ addr += 5;
+ } else if (strncmp(addr, "inet6:", 6) == 0) {
+ fam = AF_INET6;
+ addr += 6;
+ }
+
+ if (fam == AF_UNIX) {
char *p;
a.addr.family = AF_UNIX;
- if (strncmp(addr, "unix:", 5) == 0)
- addr += 5;
p = strdup(addr);
a.addr.bitlen = 8*strlen(p);
memcpy(a.addr.data, &p, sizeof(p));
- fam = AF_UNIX;
goto out;
}
- if (fam == AF_PACKET || strncmp(addr, "link:", 5) == 0) {
+ if (fam == AF_PACKET) {
a.addr.family = AF_PACKET;
a.addr.bitlen = 0;
- if (strncmp(addr, "link:", 5) == 0)
- addr += 5;
- port = strchr(addr, ':');
+ port = find_port(addr, is_port);
if (port) {
- *port = 0;
- if (port[1] && strcmp(port+1, "*")) {
- if (get_integer(&a.port, port+1, 0)) {
- if ((a.port = xll_name_to_index(port+1)) <= 0)
+ if (*port && strcmp(port, "*")) {
+ if (get_integer(&a.port, port, 0)) {
+ if ((a.port = xll_name_to_index(port)) <= 0)
return NULL;
}
}
}
- if (addr[0] && strcmp(addr, "*")) {
+ if (!is_port && addr[0] && strcmp(addr, "*")) {
unsigned short tmp;
a.addr.bitlen = 32;
return NULL;
a.addr.data[0] = ntohs(tmp);
}
- fam = AF_PACKET;
goto out;
}
- if (fam == AF_NETLINK || strncmp(addr, "netlink:", 8) == 0) {
+ if (fam == AF_NETLINK) {
a.addr.family = AF_NETLINK;
a.addr.bitlen = 0;
- if (strncmp(addr, "netlink:", 8) == 0)
- addr += 8;
- port = strchr(addr, ':');
+ port = find_port(addr, is_port);
if (port) {
- *port = 0;
- if (port[1] && strcmp(port+1, "*")) {
- if (get_integer(&a.port, port+1, 0)) {
- if (strcmp(port+1, "kernel") == 0)
+ if (*port && strcmp(port, "*")) {
+ if (get_integer(&a.port, port, 0)) {
+ if (strcmp(port, "kernel") == 0)
a.port = 0;
else
return NULL;
}
}
}
- if (addr[0] && strcmp(addr, "*")) {
+ if (!is_port && addr[0] && strcmp(addr, "*")) {
a.addr.bitlen = 32;
if (nl_proto_a2n(&a.addr.data[0], addr) == -1)
return NULL;
}
- fam = AF_NETLINK;
goto out;
}
- if (fam == AF_VSOCK || strncmp(addr, "vsock:", 6) == 0) {
+ if (fam == AF_VSOCK) {
__u32 cid = ~(__u32)0;
a.addr.family = AF_VSOCK;
- if (strncmp(addr, "vsock:", 6) == 0)
- addr += 6;
-
- if (is_port)
- port = addr;
- else {
- port = strchr(addr, ':');
- if (port) {
- *port = '\0';
- port++;
- }
- }
+
+ port = find_port(addr, is_port);
if (port && strcmp(port, "*") &&
get_u32((__u32 *)&a.port, port, 0))
return NULL;
- if (addr[0] && strcmp(addr, "*")) {
+ if (!is_port && addr[0] && strcmp(addr, "*")) {
a.addr.bitlen = 32;
if (get_u32(&cid, addr, 0))
return NULL;
}
vsock_set_inet_prefix(&a.addr, cid);
- fam = AF_VSOCK;
goto out;
}
- if (fam == AF_INET || !strncmp(addr, "inet:", 5)) {
- fam = AF_INET;
- if (!strncmp(addr, "inet:", 5))
- addr += 5;
- } else if (fam == AF_INET6 || !strncmp(addr, "inet6:", 6)) {
- fam = AF_INET6;
- if (!strncmp(addr, "inet6:", 6))
- addr += 6;
- }
-
/* URL-like literal [] */
if (addr[0] == '[') {
addr++;
out(" subflows:%d", s->mptcpi_subflows);
if (s->mptcpi_add_addr_signal)
out(" add_addr_signal:%d", s->mptcpi_add_addr_signal);
- if (s->mptcpi_add_addr_signal)
+ if (s->mptcpi_add_addr_accepted)
out(" add_addr_accepted:%d", s->mptcpi_add_addr_accepted);
if (s->mptcpi_subflows_max)
out(" subflows_max:%d", s->mptcpi_subflows_max);
out(" cgroup:%s", cg_id_to_path(rta_getattr_u64(tb[INET_DIAG_CGROUP_ID])));
}
+ if (show_inet_sockopt) {
+ if (tb[INET_DIAG_SOCKOPT] && RTA_PAYLOAD(tb[INET_DIAG_SOCKOPT]) >=
+ sizeof(struct inet_diag_sockopt)) {
+ const struct inet_diag_sockopt *sockopt =
+ RTA_DATA(tb[INET_DIAG_SOCKOPT]);
+ if (!oneline)
+ out("\n\tinet-sockopt: (");
+ else
+ out(" inet-sockopt: (");
+ if (sockopt->recverr)
+ out(" recverr");
+ if (sockopt->is_icsk)
+ out(" is_icsk");
+ if (sockopt->freebind)
+ out(" freebind");
+ if (sockopt->hdrincl)
+ out(" hdrincl");
+ if (sockopt->mc_loop)
+ out(" mc_loop");
+ if (sockopt->transparent)
+ out(" transparent");
+ if (sockopt->mc_all)
+ out(" mc_all");
+ if (sockopt->nodefrag)
+ out(" nodefrag");
+ if (sockopt->bind_address_no_port)
+ out(" bind_addr_no_port");
+ if (sockopt->recverr_rfc4884)
+ out(" recverr_rfc4884");
+ if (sockopt->defer_connect)
+ out(" defer_connect");
+ out(")");
+ }
+ }
+
if (show_mem || (show_tcpinfo && s->type != IPPROTO_UDP)) {
if (!oneline)
out("\n\t");
xdp_show_ring("cr", cr);
}
+static void xdp_show_stats(struct xdp_diag_stats *stats)
+{
+ if (oneline)
+ out(" stats(");
+ else
+ out("\n\tstats(");
+ out("rx dropped:%llu", stats->n_rx_dropped);
+ out(",rx invalid:%llu", stats->n_rx_invalid);
+ out(",rx queue full:%llu", stats->n_rx_full);
+ out(",rx fill ring empty:%llu", stats->n_fill_ring_empty);
+ out(",tx invalid:%llu", stats->n_tx_invalid);
+ out(",tx ring empty:%llu", stats->n_tx_ring_empty);
+ out(")");
+}
+
static int xdp_show_sock(struct nlmsghdr *nlh, void *arg)
{
struct xdp_diag_ring *rx = NULL, *tx = NULL, *fr = NULL, *cr = NULL;
struct rtattr *tb[XDP_DIAG_MAX + 1];
struct xdp_diag_info *info = NULL;
struct xdp_diag_umem *umem = NULL;
+ struct xdp_diag_stats *stats = NULL;
const struct filter *f = arg;
struct sockstat stat = {};
stat.rq = skmeminfo[SK_MEMINFO_RMEM_ALLOC];
}
+ if (tb[XDP_DIAG_STATS])
+ stats = RTA_DATA(tb[XDP_DIAG_STATS]);
if (xdp_stats_print(&stat, f))
return 0;
xdp_show_ring("tx", tx);
if (umem)
xdp_show_umem(umem, fr, cr);
+ if (stats)
+ xdp_show_stats(stats);
}
if (show_mem)
req.r.sdiag_family = AF_XDP;
req.r.xdiag_show = XDP_SHOW_INFO | XDP_SHOW_RING_CFG | XDP_SHOW_UMEM |
- XDP_SHOW_MEMINFO;
+ XDP_SHOW_MEMINFO | XDP_SHOW_STATS;
return handle_netlink_request(f, &req.nlh, sizeof(req), xdp_show_sock);
}
" -K, --kill forcibly close sockets, display what was closed\n"
" -H, --no-header Suppress header line\n"
" -O, --oneline socket's data printed on a single line\n"
+" --inet-sockopt show various inet socket options\n"
"\n"
" -A, --query=QUERY, --socket=QUERY\n"
" QUERY := {all|inet|tcp|mptcp|udp|raw|unix|unix_dgram|unix_stream|unix_seqpacket|packet|netlink|vsock_stream|vsock_dgram|tipc}[,QUERY]\n"
#define OPT_CGROUP 261
+#define OPT_INET_SOCKOPT 262
+
static const struct option long_opts[] = {
{ "numeric", 0, 0, 'n' },
{ "resolve", 0, 0, 'r' },
{ "xdp", 0, 0, OPT_XDPSOCK},
{ "mptcp", 0, 0, 'M' },
{ "oneline", 0, 0, 'O' },
+ { "inet-sockopt", 0, 0, OPT_INET_SOCKOPT },
{ 0 }
};
case 'O':
oneline = 1;
break;
+ case OPT_INET_SOCKOPT:
+ show_inet_sockopt = 1;
+ break;
case 'h':
help();
case '?':