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 <p...@nwl.cc> --- misc/ss.c | 137 +++++++++++++++++++++++++++++--------------------------------- 1 file changed, 64 insertions(+), 73 deletions(-) diff --git a/misc/ss.c b/misc/ss.c index b3475cc96ae7b..36b18ff2ce3cb 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -2788,15 +2788,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) @@ -2815,61 +2813,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, @@ -2916,8 +2871,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) { @@ -2928,8 +2881,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; } @@ -3020,6 +2972,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; @@ -3027,6 +2984,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 || @@ -3038,24 +3031,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; -- 2.10.0