From mboxrd@z Thu Jan 1 00:00:00 1970 From: Vadim Kochan Subject: [PATCH iproute2 3/3] ss: Filtering logic changing, with fixes Date: Sat, 3 Jan 2015 02:44:37 +0200 Message-ID: <1420245877-11763-4-git-send-email-vadim4j@gmail.com> References: <1420245877-11763-1-git-send-email-vadim4j@gmail.com> Cc: Vadim Kochan To: netdev@vger.kernel.org Return-path: Received: from mail-la0-f48.google.com ([209.85.215.48]:36247 "EHLO mail-la0-f48.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752377AbbACAzD (ORCPT ); Fri, 2 Jan 2015 19:55:03 -0500 Received: by mail-la0-f48.google.com with SMTP id gf13so15647688lab.7 for ; Fri, 02 Jan 2015 16:55:00 -0800 (PST) In-Reply-To: <1420245877-11763-1-git-send-email-vadim4j@gmail.com> Sender: netdev-owner@vger.kernel.org List-ID: From: Vadim Kochan This patch fixes some filtering combinations issues which does not work on the 'master' version: $ ss -4 shows inet & unix sockets, instead of only inet sockets $ ss -u needs to specify 'state closed' $ ss src unix:*X11* needs to specify '-x' shortcut for UNIX family $ ss -A all shows only sockets with established states There might some other issues which was not observed. Also changed logic for calculating families, socket types and states filtering. I think that this version is a little simpler one. Now there are 2 predefined default tables which describes the following maping: family -> (states, dbs) db -> (states, families) Signed-off-by: Vadim Kochan --- misc/ss.c | 315 +++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 210 insertions(+), 105 deletions(-) diff --git a/misc/ss.c b/misc/ss.c index c68af19..31f316e 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -128,6 +128,7 @@ enum #define PACKET_DBM ((1<states |= default_dbs[db].states; + f->families |= default_dbs[db].families; + f->dbs |= 1 << db; + do_default = 0; +} + +static void filter_af_set(struct filter *f, int af) +{ + f->dbs |= default_afs[af].dbs; + f->states |= default_afs[af].states; + f->families |= 1 << af; + do_default = 0; +} + +static int filter_af_get(struct filter *f, int af) +{ + return f->families & (1 << af); +} + +static void filter_merge(struct filter *to, struct filter *from) +{ + if (to->families) + to->families = (to->families | from->families) & to->families; + else + to->families |= from->families; + + if (from->dbs) + to->dbs = (to->dbs | from->dbs) & from->dbs; + else + to->dbs |= from->dbs; + + if (from->states) + to->states = (to->states | from->states) & from->states; + else + to->states |= from->states; +} + static FILE *generic_proc_open(const char *env, const char *name) { const char *p = getenv(env); @@ -1171,12 +1279,13 @@ void *parse_hostcond(char *addr) char *port = NULL; struct aafilter a; struct aafilter *res; - int fam = preferred_family; + int fam = 0; + struct filter *f = ¤t_filter; memset(&a, 0, sizeof(a)); a.port = -1; - if (fam == AF_UNIX || strncmp(addr, "unix:", 5) == 0) { + if (filter_af_get(f, AF_UNIX) || strncmp(addr, "unix:", 5) == 0) { char *p; a.addr.family = AF_UNIX; if (strncmp(addr, "unix:", 5) == 0) @@ -1184,10 +1293,11 @@ void *parse_hostcond(char *addr) 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 (filter_af_get(f, AF_PACKET) || strncmp(addr, "link:", 5) == 0) { a.addr.family = AF_PACKET; a.addr.bitlen = 0; if (strncmp(addr, "link:", 5) == 0) @@ -1209,10 +1319,11 @@ void *parse_hostcond(char *addr) return NULL; a.addr.data[0] = ntohs(tmp); } + fam = AF_PACKET; goto out; } - if (fam == AF_NETLINK || strncmp(addr, "netlink:", 8) == 0) { + if (filter_af_get(f, AF_NETLINK) || strncmp(addr, "netlink:", 8) == 0) { a.addr.family = AF_NETLINK; a.addr.bitlen = 0; if (strncmp(addr, "netlink:", 8) == 0) @@ -1234,13 +1345,14 @@ void *parse_hostcond(char *addr) if (nl_proto_a2n(&a.addr.data[0], addr) == -1) return NULL; } + fam = AF_NETLINK; goto out; } - if (strncmp(addr, "inet:", 5) == 0) { + if (filter_af_get(f, AF_INET) || !strncmp(addr, "inet:", 5)) { addr += 5; fam = AF_INET; - } else if (strncmp(addr, "inet6:", 6) == 0) { + } else if (filter_af_get(f, AF_INET6) || !strncmp(addr, "inet6:", 6)) { addr += 6; fam = AF_INET6; } @@ -1309,7 +1421,10 @@ void *parse_hostcond(char *addr) } } - out: +out: + if (fam) + filter_af_set(f, fam); + res = malloc(sizeof(*res)); if (res) memcpy(res, &a, sizeof(a)); @@ -2459,6 +2574,9 @@ static int unix_show(struct filter *f) int cnt; struct unixstat *list = NULL; + if (!filter_af_get(f, AF_UNIX)) + return 0; + if (!getenv("PROC_NET_UNIX") && !getenv("PROC_ROOT") && unix_show_netlink(f) == 0) return 0; @@ -2701,7 +2819,7 @@ static int packet_show(struct filter *f) { FILE *fp; - if (preferred_family != AF_PACKET && !(f->states & (1 << SS_CLOSE))) + if (!filter_af_get(f, AF_PACKET) && !(f->states & (1 << SS_CLOSE))) return 0; if (!getenv("PROC_NET_PACKET") && !getenv("PROC_ROOT") && @@ -2869,7 +2987,7 @@ static int netlink_show(struct filter *f) int rq, wq, rc; unsigned long long sk, cb; - if (preferred_family != AF_NETLINK && !(f->states & (1 << SS_CLOSE))) + if (!filter_af_get(f, AF_NETLINK) && !(f->states & (1 << SS_CLOSE))) return 0; if (!getenv("PROC_NET_NETLINK") && !getenv("PROC_ROOT") && @@ -3132,7 +3250,9 @@ static int scan_state(const char *state) if (strcasecmp(state, sstate_namel[i]) == 0) return (1<