]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - misc/ss.c
ss: Make leading ":" always optional for sport and dport
[mirror_iproute2.git] / misc / ss.c
index e55657259431d93d6e580f793d5a3b049d977dc7..5c934fa067fb0d2bafcd060caec6b20e963faba2 100644 (file)
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -114,6 +114,7 @@ static int sctp_ino;
 static int show_tipcinfo;
 static int show_tos;
 static int show_cgroup;
+static int show_inet_sockopt;
 int oneline;
 
 enum col_id {
@@ -2110,6 +2111,18 @@ static void vsock_set_inet_prefix(inet_prefix *a, __u32 cid)
        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;
@@ -2118,35 +2131,49 @@ void *parse_hostcond(char *addr, bool is_port)
        int fam = preferred_family;
        struct filter *f = &current_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;
@@ -2154,77 +2181,51 @@ void *parse_hostcond(char *addr, bool is_port)
                                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++;
@@ -3135,7 +3136,7 @@ static void mptcp_stats_print(struct mptcp_info *s)
                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);
@@ -3333,6 +3334,41 @@ static int inet_show_sock(struct nlmsghdr *nlh,
                        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");
@@ -4500,6 +4536,21 @@ static void xdp_show_umem(struct xdp_diag_umem *umem, struct xdp_diag_ring *fr,
                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;
@@ -4507,6 +4558,7 @@ static int xdp_show_sock(struct nlmsghdr *nlh, void *arg)
        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 = {};
 
@@ -4541,6 +4593,8 @@ static int xdp_show_sock(struct nlmsghdr *nlh, void *arg)
 
                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;
@@ -4552,6 +4606,8 @@ static int xdp_show_sock(struct nlmsghdr *nlh, void *arg)
                        xdp_show_ring("tx", tx);
                if (umem)
                        xdp_show_umem(umem, fr, cr);
+               if (stats)
+                       xdp_show_stats(stats);
        }
 
        if (show_mem)
@@ -4570,7 +4626,7 @@ static int xdp_show(struct filter *f)
 
        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);
 }
@@ -5210,6 +5266,7 @@ static void _usage(FILE *dest)
 "   -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"
@@ -5299,6 +5356,8 @@ static int scan_state(const char *state)
 
 #define OPT_CGROUP 261
 
+#define OPT_INET_SOCKOPT 262
+
 static const struct option long_opts[] = {
        { "numeric", 0, 0, 'n' },
        { "resolve", 0, 0, 'r' },
@@ -5341,6 +5400,7 @@ static const struct option long_opts[] = {
        { "xdp", 0, 0, OPT_XDPSOCK},
        { "mptcp", 0, 0, 'M' },
        { "oneline", 0, 0, 'O' },
+       { "inet-sockopt", 0, 0, OPT_INET_SOCKOPT },
        { 0 }
 
 };
@@ -5539,6 +5599,9 @@ int main(int argc, char *argv[])
                case 'O':
                        oneline = 1;
                        break;
+               case OPT_INET_SOCKOPT:
+                       show_inet_sockopt = 1;
+                       break;
                case 'h':
                        help();
                case '?':