naccyde / rpms / iproute

Forked from rpms/iproute 5 months ago
Clone
Blob Blame History Raw
From d57e50c6402fb84b9fb21617a9e4e69551af50f2 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Mon, 30 May 2016 16:46:58 +0200
Subject: [PATCH] ss: Fix wrong filter behaviour

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1318005
Upstream Status: iproute2.git commit 57ff5a1096cab

commit 57ff5a1096cab63107d7e85bcd0d822614e33d73
Author: Vadim Kochan <vadim4j@gmail.com>
Date:   Thu Apr 30 07:30:24 2015 +0300

    ss: Fix wrong filter behaviour

    Fixed applying family & socket type filters.
    It was not possible to select UDP & UNIX sockets together.

    Now selected families are ORed.

    The problem was that filters were combined by AND.

    Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
    Reported-By: Mihai Moldovan <ionic@ionic.de>
---
 misc/ss.c | 91 ++++++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 49 insertions(+), 42 deletions(-)

diff --git a/misc/ss.c b/misc/ss.c
index 7750887..95f3c31 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -233,14 +233,12 @@ static struct filter current_filter;
 static void filter_db_set(struct filter *f, int db)
 {
 	f->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;
@@ -266,21 +264,31 @@ static void filter_default_dbs(struct filter *f)
 	filter_db_set(f, NETLINK_DB);
 }
 
-static void filter_merge(struct filter *af, struct filter *dbf, int states)
+static void filter_states_set(struct filter *f, int states)
 {
-	if (af->families)
-		af->families = (af->families | dbf->families) & af->families;
-	else
-		af->families = dbf->families;
+	if (states)
+		f->states = (f->states | states) & states;
+}
 
-	if (dbf->dbs)
-		af->dbs = (af->dbs | dbf->dbs) & dbf->dbs;
+static void filter_merge_defaults(struct filter *f)
+{
+	int db;
+	int af;
 
-	if (dbf->states)
-		af->states = (af->states | dbf->states) & dbf->states;
+	for (db = 0; db < MAX_DB; db++) {
+		if (!(f->dbs & (1 << db)))
+			continue;
 
-	if (states)
-		af->states = (af->states | states) & states;
+		if (!(default_dbs[db].families & f->families))
+			f->families |= default_dbs[db].families;
+	}
+	for (af = 0; af < AF_MAX; af++) {
+		if (!(f->families & (1 << af)))
+			continue;
+
+		if (!(default_afs[af].dbs & f->dbs))
+			f->dbs |= default_afs[af].dbs;
+	}
 }
 
 static FILE *generic_proc_open(const char *env, const char *name)
@@ -1540,7 +1548,7 @@ out:
 	if (fam != AF_UNSPEC) {
 		f->families = 0;
 		filter_af_set(f, fam);
-		filter_merge(f, f, 0);
+		filter_states_set(f, 0);
 	}
 
 	res = malloc(sizeof(*res));
@@ -3440,7 +3448,6 @@ int main(int argc, char *argv[])
 	const char *dump_tcpdiag = NULL;
 	FILE *filter_fp = NULL;
 	int ch;
-	struct filter dbs_filter = {};
 	int state_filter = 0;
 
 	while ((ch = getopt_long(argc, argv, "dhaletuwxnro460spbf:miA:D:F:vVzZN:",
@@ -3474,16 +3481,16 @@ int main(int argc, char *argv[])
 			show_bpf++;
 			break;
 		case 'd':
-			filter_db_set(&dbs_filter, DCCP_DB);
+			filter_db_set(&current_filter, DCCP_DB);
 			break;
 		case 't':
-			filter_db_set(&dbs_filter, TCP_DB);
+			filter_db_set(&current_filter, TCP_DB);
 			break;
 		case 'u':
-			filter_db_set(&dbs_filter, UDP_DB);
+			filter_db_set(&current_filter, UDP_DB);
 			break;
 		case 'w':
-			filter_db_set(&dbs_filter, RAW_DB);
+			filter_db_set(&current_filter, RAW_DB);
 			break;
 		case 'x':
 			filter_af_set(&current_filter, AF_UNIX);
@@ -3537,44 +3544,44 @@ int main(int argc, char *argv[])
 				if ((p1 = strchr(p, ',')) != NULL)
 					*p1 = 0;
 				if (strcmp(p, "all") == 0) {
-					filter_default_dbs(&dbs_filter);
+					filter_default_dbs(&current_filter);
 				} else if (strcmp(p, "inet") == 0) {
-					filter_db_set(&dbs_filter, UDP_DB);
-					filter_db_set(&dbs_filter, DCCP_DB);
-					filter_db_set(&dbs_filter, TCP_DB);
-					filter_db_set(&dbs_filter, RAW_DB);
+					filter_db_set(&current_filter, UDP_DB);
+					filter_db_set(&current_filter, DCCP_DB);
+					filter_db_set(&current_filter, TCP_DB);
+					filter_db_set(&current_filter, RAW_DB);
 				} else if (strcmp(p, "udp") == 0) {
-					filter_db_set(&dbs_filter, UDP_DB);
+					filter_db_set(&current_filter, UDP_DB);
 				} else if (strcmp(p, "dccp") == 0) {
-					filter_db_set(&dbs_filter, DCCP_DB);
+					filter_db_set(&current_filter, DCCP_DB);
 				} else if (strcmp(p, "tcp") == 0) {
-					filter_db_set(&dbs_filter, TCP_DB);
+					filter_db_set(&current_filter, TCP_DB);
 				} else if (strcmp(p, "raw") == 0) {
-					filter_db_set(&dbs_filter, RAW_DB);
+					filter_db_set(&current_filter, RAW_DB);
 				} else if (strcmp(p, "unix") == 0) {
-					filter_db_set(&dbs_filter, UNIX_ST_DB);
-					filter_db_set(&dbs_filter, UNIX_DG_DB);
-					filter_db_set(&dbs_filter, UNIX_SQ_DB);
+					filter_db_set(&current_filter, UNIX_ST_DB);
+					filter_db_set(&current_filter, UNIX_DG_DB);
+					filter_db_set(&current_filter, UNIX_SQ_DB);
 				} else if (strcasecmp(p, "unix_stream") == 0 ||
 					   strcmp(p, "u_str") == 0) {
-					filter_db_set(&dbs_filter, UNIX_ST_DB);
+					filter_db_set(&current_filter, UNIX_ST_DB);
 				} else if (strcasecmp(p, "unix_dgram") == 0 ||
 					   strcmp(p, "u_dgr") == 0) {
-					filter_db_set(&dbs_filter, UNIX_DG_DB);
+					filter_db_set(&current_filter, UNIX_DG_DB);
 				} else if (strcasecmp(p, "unix_seqpacket") == 0 ||
 					   strcmp(p, "u_seq") == 0) {
-					filter_db_set(&dbs_filter, UNIX_SQ_DB);
+					filter_db_set(&current_filter, UNIX_SQ_DB);
 				} else if (strcmp(p, "packet") == 0) {
-					filter_db_set(&dbs_filter, PACKET_R_DB);
-					filter_db_set(&dbs_filter, PACKET_DG_DB);
+					filter_db_set(&current_filter, PACKET_R_DB);
+					filter_db_set(&current_filter, PACKET_DG_DB);
 				} else if (strcmp(p, "packet_raw") == 0 ||
 					   strcmp(p, "p_raw") == 0) {
-					filter_db_set(&dbs_filter, PACKET_R_DB);
+					filter_db_set(&current_filter, PACKET_R_DB);
 				} else if (strcmp(p, "packet_dgram") == 0 ||
 					   strcmp(p, "p_dgr") == 0) {
-					filter_db_set(&dbs_filter, PACKET_DG_DB);
+					filter_db_set(&current_filter, PACKET_DG_DB);
 				} else if (strcmp(p, "netlink") == 0) {
-					filter_db_set(&dbs_filter, NETLINK_DB);
+					filter_db_set(&current_filter, NETLINK_DB);
 				} else {
 					fprintf(stderr, "ss: \"%s\" is illegal socket table id\n", p);
 					usage();
@@ -3667,11 +3674,11 @@ int main(int argc, char *argv[])
 	if (do_default) {
 		state_filter = state_filter ? state_filter : SS_CONN;
 		filter_default_dbs(&current_filter);
-		filter_merge(&current_filter, &current_filter, state_filter);
-	} else {
-		filter_merge(&current_filter, &dbs_filter, state_filter);
 	}
 
+	filter_states_set(&current_filter, state_filter);
+	filter_merge_defaults(&current_filter);
+
 	if (resolve_services && resolve_hosts &&
 	    (current_filter.dbs&(UNIX_DBM|(1<<TCP_DB)|(1<<UDP_DB)|(1<<DCCP_DB))))
 		init_service_resolver();
-- 
1.8.3.1