]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - misc/ss.c
whitespace cleanup
[mirror_iproute2.git] / misc / ss.c
index c8479545d1068186d992e1cb8f995e22d0cc71b8..706b5bada85b89213572ef7169a884cf3db4f645 100644 (file)
--- a/misc/ss.c
+++ b/misc/ss.c
 #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
@@ -1216,16 +1231,8 @@ void *parse_hostcond(char *addr)
                }
                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;
        }
@@ -1554,6 +1561,8 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r,
                               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);
@@ -1576,6 +1585,19 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r,
                                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 *
@@ -1583,6 +1605,15 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r,
                                         / 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",
@@ -1695,7 +1726,7 @@ static int inet_show_sock(struct nlmsghdr *nlh, struct filter *f, int protocol)
                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]);
@@ -1738,7 +1769,7 @@ static int tcpdiag_send(int fd, int protocol, struct filter *f)
                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;
@@ -1784,10 +1815,7 @@ static int tcpdiag_send(int fd, int protocol, struct filter *f)
 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;
@@ -1800,11 +1828,6 @@ static int sockdiag_send(int family, int fd, int protocol, struct filter *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;
@@ -1853,7 +1876,7 @@ static int inet_show_netlink(struct filter *f, FILE *dump_fp, int 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)
@@ -1906,7 +1929,7 @@ again:
                        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)
@@ -1969,7 +1992,7 @@ 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)");
@@ -2391,8 +2414,10 @@ static void unix_list_print(struct unixstat *list, struct filter *f)
        }
 }
 
-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];
@@ -2481,101 +2506,32 @@ static int unix_show_sock(struct nlmsghdr *nlh, struct filter *f)
        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;
@@ -2583,8 +2539,7 @@ static int unix_show_netlink(struct filter *f, FILE *dump_fp)
        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)
@@ -2597,7 +2552,7 @@ 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)
@@ -2671,7 +2626,8 @@ static int unix_show(struct filter *f)
        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];
@@ -2764,97 +2720,14 @@ static int packet_show_sock(struct nlmsghdr *nlh, struct filter *f)
        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);
 }
 
 
@@ -2871,10 +2744,10 @@ static int packet_show(struct filter *f)
        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)
@@ -2955,6 +2828,8 @@ static void netlink_show_one(struct filter *f,
                                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;
@@ -2972,14 +2847,14 @@ static void netlink_show_one(struct filter *f,
        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) {
@@ -3044,8 +2919,10 @@ static void netlink_show_one(struct filter *f,
        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;
@@ -3078,25 +2955,15 @@ static int netlink_show_sock(struct nlmsghdr *nlh, struct filter *f)
        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)
@@ -3108,11 +2975,11 @@ 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)
@@ -3758,6 +3625,10 @@ int main(int argc, char *argv[])
                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");