From: Phil Sutter Date: Fri, 2 Dec 2016 10:39:50 +0000 (+0100) Subject: ss: Drop list traversal from unix_stats_print() X-Git-Tag: v4.10.0~110 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2d0e538f3e1cd88b193e1b3da9271aff39cf271c;p=thirdparty%2Fiproute2.git ss: Drop list traversal from unix_stats_print() 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 --- diff --git a/misc/ss.c b/misc/ss.c index 2b6602e12..8441e9b7a 100644 --- 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;