From: Vadim Kochan Date: Sun, 4 Jan 2015 20:18:40 +0000 (+0200) Subject: ss: Filtering logic changing, with fixes X-Git-Tag: v3.19.0~25 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9db7bf15e22b6a1b8bc09c4a1e29571cbca55c94;p=thirdparty%2Fiproute2.git ss: Filtering logic changing, with fixes 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 --- diff --git a/misc/ss.c b/misc/ss.c index 505822427..08d210ae8 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; @@ -2710,7 +2835,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") && @@ -2878,7 +3003,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") && @@ -3141,7 +3266,9 @@ static int scan_state(const char *state) if (strcasecmp(state, sstate_namel[i]) == 0) return (1<