From mboxrd@z Thu Jan 1 00:00:00 1970 From: Vadim Kochan Subject: [PATCH iproute2 v2 3/3] ss: Filtering logic changing, with fixes Date: Sun, 4 Jan 2015 19:20:55 +0200 Message-ID: <1420392055-4754-4-git-send-email-vadim4j@gmail.com> References: <1420392055-4754-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]:42628 "EHLO mail-la0-f48.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752691AbbADRbZ (ORCPT ); Sun, 4 Jan 2015 12:31:25 -0500 Received: by mail-la0-f48.google.com with SMTP id gf13so16865792lab.21 for ; Sun, 04 Jan 2015 09:31:23 -0800 (PST) In-Reply-To: <1420392055-4754-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 | 318 ++++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 207 insertions(+), 111 deletions(-) diff --git a/misc/ss.c b/misc/ss.c index 20d3f75..d64d831 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -129,6 +129,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_default_dbs(struct filter *f) +{ + filter_db_set(f, UDP_DB); + filter_db_set(f, DCCP_DB); + filter_db_set(f, TCP_DB); + filter_db_set(f, RAW_DB); + filter_db_set(f, UNIX_ST_DB); + filter_db_set(f, UNIX_DG_DB); + filter_db_set(f, UNIX_SQ_DB); + filter_db_set(f, PACKET_R_DB); + filter_db_set(f, PACKET_DG_DB); + filter_db_set(f, NETLINK_DB); +} + +static void filter_merge(struct filter *af, struct filter *dbf, int states) +{ + if (af->families) + af->families = (af->families | dbf->families) & af->families; + else + af->families = dbf->families; + + if (dbf->dbs) + af->dbs = (af->dbs | dbf->dbs) & dbf->dbs; + + if (dbf->states) + af->states = (af->states | dbf->states) & dbf->states; + + if (states) + af->states = (af->states | states) & states; +} static FILE *generic_proc_open(const char *env, const char *name) { @@ -1172,12 +1287,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) @@ -1185,10 +1301,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) @@ -1210,10 +1327,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) @@ -1235,13 +1353,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; } @@ -1310,7 +1429,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)); @@ -2460,6 +2582,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; @@ -2702,7 +2827,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") && @@ -2870,7 +2995,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") && @@ -3133,7 +3258,9 @@ static int scan_state(const char *state) if (strcasecmp(state, sstate_namel[i]) == 0) return (1<