]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
ss: Drop list traversal from unix_stats_print()
authorPhil Sutter <phil@nwl.cc>
Fri, 2 Dec 2016 10:39:50 +0000 (11:39 +0100)
committerStephen Hemminger <stephen@networkplumber.org>
Fri, 2 Dec 2016 22:07:46 +0000 (14:07 -0800)
Although this complicates the dedicated procfs-based code path in
unix_show() a bit, it's the only sane way to get rid of unix_show_sock()
output diverging from other socket types in that it prints all socket
details in a new line.

As a side effect, it allows to eliminate all procfs specific code in
the same function.

Signed-off-by: Phil Sutter <phil@nwl.cc>
misc/ss.c

index 2b6602e12ca775b79bd5559cbe6f9681e1bbd395..8441e9b7ade9d874daf3ec2b3a315c2a0cbb51a7 100644 (file)
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -3018,15 +3018,13 @@ int unix_state_map[] = { SS_CLOSE, SS_SYN_SENT,
 
 #define MAX_UNIX_REMEMBER (1024*1024/sizeof(struct sockstat))
 
-static void unix_list_free(struct sockstat *list)
+static void unix_list_drop_first(struct sockstat **list)
 {
-       while (list) {
-               struct sockstat *s = list;
+       struct sockstat *s = *list;
 
-               list = list->next;
-               free(s->name);
-               free(s);
-       }
+       (*list) = (*list)->next;
+       free(s->name);
+       free(s);
 }
 
 static bool unix_type_skip(struct sockstat *s, struct filter *f)
@@ -3045,61 +3043,18 @@ static bool unix_use_proc(void)
        return getenv("PROC_NET_UNIX") || getenv("PROC_ROOT");
 }
 
-static void unix_stats_print(struct sockstat *list, struct filter *f)
+static void unix_stats_print(struct sockstat *s, struct filter *f)
 {
-       struct sockstat *s;
-       char *peer;
-       bool use_proc = unix_use_proc();
        char port_name[30] = {};
 
-       for (s = list; s; s = s->next) {
-               if (!(f->states & (1 << s->state)))
-                       continue;
-               if (unix_type_skip(s, f))
-                       continue;
-
-               peer = "*";
-               if (s->peer_name)
-                       peer = s->peer_name;
-
-               if (s->rport && use_proc) {
-                       struct sockstat *p;
-
-                       for (p = list; p; p = p->next) {
-                               if (s->rport == p->lport)
-                                       break;
-                       }
-
-                       if (!p) {
-                               peer = "?";
-                       } else {
-                               peer = p->name ? : "*";
-                       }
-               }
-
-               if (use_proc && f->f) {
-                       struct sockstat st = {
-                               .local.family = AF_UNIX,
-                               .remote.family = AF_UNIX,
-                       };
-
-                       memcpy(st.local.data, &s->name, sizeof(s->name));
-                       if (strcmp(peer, "*"))
-                               memcpy(st.remote.data, &peer, sizeof(peer));
-                       if (run_ssfilter(f->f, &st) == 0)
-                               continue;
-               }
-
-               sock_state_print(s);
+       sock_state_print(s);
 
-               sock_addr_print(s->name ?: "*", " ",
-                               int_to_str(s->lport, port_name), NULL);
-               sock_addr_print(peer, " ", int_to_str(s->rport, port_name),
-                               NULL);
+       sock_addr_print(s->name ?: "*", " ",
+                       int_to_str(s->lport, port_name), NULL);
+       sock_addr_print(s->peer_name ?: "*", " ",
+                       int_to_str(s->rport, port_name), NULL);
 
-               proc_ctx_print(s);
-               printf("\n");
-       }
+       proc_ctx_print(s);
 }
 
 static int unix_show_sock(const struct sockaddr_nl *addr, struct nlmsghdr *nlh,
@@ -3148,8 +3103,6 @@ static int unix_show_sock(const struct sockaddr_nl *addr, struct nlmsghdr *nlh,
 
        unix_stats_print(&stat, f);
 
-       if (show_mem || show_details)
-               printf("\t");
        if (show_mem)
                print_skmeminfo(tb, UNIX_DIAG_MEMINFO);
        if (show_details) {
@@ -3160,8 +3113,7 @@ static int unix_show_sock(const struct sockaddr_nl *addr, struct nlmsghdr *nlh,
                        printf(" %c-%c", mask & 1 ? '-' : '<', mask & 2 ? '-' : '>');
                }
        }
-       if (show_mem || show_details)
-               printf("\n");
+       printf("\n");
 
        return 0;
 }
@@ -3252,6 +3204,11 @@ static int unix_show(struct filter *f)
                        if (u->type == SOCK_DGRAM && u->state == SS_CLOSE && u->rport)
                                u->state = SS_ESTABLISHED;
                }
+               if (unix_type_skip(u, f) ||
+                   !(f->states & (1 << u->state))) {
+                       free(u);
+                       continue;
+               }
 
                if (!newformat) {
                        u->rport = 0;
@@ -3259,6 +3216,42 @@ static int unix_show(struct filter *f)
                        u->wq = 0;
                }
 
+               if (name[0]) {
+                       u->name = strdup(name);
+                       if (!u->name)
+                               break;
+               }
+
+               if (u->rport) {
+                       struct sockstat *p;
+
+                       for (p = list; p; p = p->next) {
+                               if (u->rport == p->lport)
+                                       break;
+                       }
+                       if (!p)
+                               u->peer_name = "?";
+                       else
+                               u->peer_name = p->name ? : "*";
+               }
+
+               if (f->f) {
+                       struct sockstat st = {
+                               .local.family = AF_UNIX,
+                               .remote.family = AF_UNIX,
+                       };
+
+                       memcpy(st.local.data, &u->name, sizeof(u->name));
+                       if (strcmp(u->peer_name, "*"))
+                               memcpy(st.remote.data, &u->peer_name,
+                                      sizeof(u->peer_name));
+                       if (run_ssfilter(f->f, &st) == 0) {
+                               free(u->name);
+                               free(u);
+                               continue;
+                       }
+               }
+
                insp = &list;
                while (*insp) {
                        if (u->type < (*insp)->type ||
@@ -3270,24 +3263,22 @@ static int unix_show(struct filter *f)
                u->next = *insp;
                *insp = u;
 
-               if (name[0]) {
-                       if ((u->name = malloc(strlen(name)+1)) == NULL)
-                               break;
-                       strcpy(u->name, name);
-               }
                if (++cnt > MAX_UNIX_REMEMBER) {
-                       unix_stats_print(list, f);
-                       unix_list_free(list);
-                       list = NULL;
+                       while (list) {
+                               unix_stats_print(list, f);
+                               printf("\n");
+
+                               unix_list_drop_first(&list);
+                       }
                        cnt = 0;
                }
        }
        fclose(fp);
-       if (list) {
+       while (list) {
                unix_stats_print(list, f);
-               unix_list_free(list);
-               list = NULL;
-               cnt = 0;
+               printf("\n");
+
+               unix_list_drop_first(&list);
        }
 
        return 0;