[libnetfilter_conntrack] Extend high-level API for netlink BSF to add negative logic

Pablo Neira netfilter-cvslog-bounces at lists.netfilter.org
Fri Jul 18 14:36:18 CEST 2008


Gitweb:		http://git.netfilter.org/cgi-bin/gitweb.cgi?p=libnetfilter_conntrack.git;a=commit;h=d65c9ce404a5a3dc4de220189daaf610f4ec306e
commit d65c9ce404a5a3dc4de220189daaf610f4ec306e
Author:     Pablo Neira Ayuso <pablo at netfilter.org>
AuthorDate: Fri Jul 18 14:36:06 2008 +0200
Commit:     Pablo Neira Ayuso <pablo at netfilter.org>
CommitDate: Fri Jul 18 14:36:06 2008 +0200

    Extend high-level API for netlink BSF to add negative logic
    
    This patch introduces nfct_filter_set_logic() to set the filtering
    logic which results in a more flexible solution.
    
    Signed-off-by: Pablo Neira Ayuso <pablo at netfilter.org>
       via  d65c9ce404a5a3dc4de220189daaf610f4ec306e (commit)
      from  563114a47ae03c988ca0e66eddda33d485e35f6b (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit d65c9ce404a5a3dc4de220189daaf610f4ec306e
Author: Pablo Neira Ayuso <pablo at netfilter.org>
Date:   Fri Jul 18 14:36:06 2008 +0200

    Extend high-level API for netlink BSF to add negative logic
    
    This patch introduces nfct_filter_set_logic() to set the filtering
    logic which results in a more flexible solution.
    
    Signed-off-by: Pablo Neira Ayuso <pablo at netfilter.org>

-----------------------------------------------------------------------

 include/internal.h                                 |    5 +
 .../libnetfilter_conntrack.h                       |   10 ++
 src/conntrack/api.c                                |   34 ++++++++
 src/conntrack/bsf.c                                |   89 +++++++++++++++----
 utils/conntrack_filter.c                           |    5 +
 5 files changed, 124 insertions(+), 19 deletions(-)
This patch introduces nfct_filter_set_logic() to set the filtering
logic which results in a more flexible solution.

Signed-off-by: Pablo Neira Ayuso <pablo at netfilter.org>

diff --git a/include/internal.h b/include/internal.h
index 33b0dcd..9dc33f2 100644
--- a/include/internal.h
+++ b/include/internal.h
@@ -185,6 +185,11 @@ struct nfct_filter {
 	 */
 
 	/*
+	 * filter logic: use positive or negative logic
+	 */
+	enum nfct_filter_logic logic[NFCT_FILTER_MAX];
+
+	/*
 	 * This the layer 4 protocol map for filtering.
 	 */
 	u_int32_t l4proto_map[IPPROTO_MAX/32];
diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack.h b/include/libnetfilter_conntrack/libnetfilter_conntrack.h
index 328cf8b..9840f90 100644
--- a/include/libnetfilter_conntrack/libnetfilter_conntrack.h
+++ b/include/libnetfilter_conntrack/libnetfilter_conntrack.h
@@ -356,6 +356,16 @@ extern void nfct_filter_add_attr_u32(struct nfct_filter *filter,
 				     const enum nfct_filter_attr attr,
 				     const u_int32_t value);
 
+enum nfct_filter_logic {
+	NFCT_FILTER_LOGIC_POSITIVE,
+	NFCT_FILTER_LOGIC_NEGATIVE,
+	NFCT_FILTER_LOGIC_MAX
+};
+
+extern int nfct_filter_set_logic(struct nfct_filter *filter,
+				 const enum nfct_filter_attr attr,
+				 const enum nfct_filter_logic logic);
+
 extern int nfct_filter_attach(int fd, struct nfct_filter *filter);
 extern int nfct_filter_detach(int fd);
 
diff --git a/src/conntrack/api.c b/src/conntrack/api.c
index 3bd96a8..fcd3fb4 100644
--- a/src/conntrack/api.c
+++ b/src/conntrack/api.c
@@ -908,6 +908,40 @@ void nfct_filter_add_attr_u32(struct nfct_filter *filter,
 }
 
 /**
+ * nfct_filter_set_logic - set the filter logic for an attribute type
+ * @filter: filter object that we want to modify
+ * @type: filter attribute type
+ * @logic: filter logic that we want to use
+ *
+ * You can only use this function once to set the filtering logic for 
+ * one attribute. You can define two logics: NFCT_FILTER_POSITIVE_LOGIC
+ * that accept events that match the filter, and NFCT_FILTER_NEGATIVE_LOGIC
+ * that rejects events that match the filter. Default filtering logic is
+ * NFCT_FILTER_POSITIVE_LOGIC.
+ *
+ * On error, it returns -1 and errno is appropriately set. On success, it 
+ * returns 0.
+ */
+int nfct_filter_set_logic(struct nfct_filter *filter,
+			  const enum nfct_filter_attr type,
+			  const enum nfct_filter_logic logic)
+{
+	if (type >= NFCT_FILTER_MAX) {
+		errno = ENOTSUP;
+                return -1;
+	}
+
+	if (filter->logic[type]) {
+		errno = EBUSY;
+		return -1;
+	}
+
+	filter->logic[type] = logic;
+
+	return 0;
+}
+
+/**
  * nfct_filter_attach - attach a filter to a socket descriptor
  * @fd: socket descriptor
  * @filter: filter that we want to attach to the socket
diff --git a/src/conntrack/bsf.c b/src/conntrack/bsf.c
index 2ac5fe1..cd9e883 100644
--- a/src/conntrack/bsf.c
+++ b/src/conntrack/bsf.c
@@ -122,6 +122,7 @@ add_state_filter_cta(struct sock_filter *this,
 		     unsigned int cta_protoinfo_proto,
 		     unsigned int cta_protoinfo_state,
 		     u_int16_t state_flags,
+		     unsigned int logic,
 		     size_t remain)
 {
 	struct sock_filter filter[14 + __FILTER_PROTO_MAX];
@@ -131,7 +132,7 @@ add_state_filter_cta(struct sock_filter *this,
 		.k	= NFCT_FILTER_REJECT,
 	};
 	unsigned int i, j;
-	unsigned int label_continue;
+	unsigned int label_continue, jt;
 
 	/* calculate the number of filter lines */
 	for (i = 0, j = 0; i < sizeof(state_flags) * 8; i++) {
@@ -151,7 +152,11 @@ add_state_filter_cta(struct sock_filter *this,
 
 	memset(filter, 0, sizeof(filter));
 
-	label_continue = j + 1;
+	jt = j + 1;
+	if (logic == NFCT_FILTER_LOGIC_POSITIVE)
+		label_continue = j + 1;
+	else
+		label_continue = j + 2;
 
 	set_basic_filter(filter,
 			 CTA_PROTOINFO,
@@ -164,7 +169,7 @@ add_state_filter_cta(struct sock_filter *this,
 		struct sock_filter cmp = {
 			.code	= BPF_JMP|BPF_JEQ|BPF_K,
 			.k	= i,
-			.jt	= label_continue - j - 1,
+			.jt	= jt - j - 1,
 		};
 
 		if (state_flags & (1 << i)) {
@@ -174,15 +179,27 @@ add_state_filter_cta(struct sock_filter *this,
 	}
 
 	memcpy(this, filter, sizeof(struct sock_filter) * (j + 14));
+
+	if (logic == NFCT_FILTER_LOGIC_NEGATIVE) {
+		struct sock_filter jump = {
+			.code	= BPF_JMP|BPF_JA,
+			.k	= 1,
+		};
+		memcpy(&this[j + 14], &jump, sizeof(jump));
+		j++;
+	}
+
 	memcpy(&this[j + 14], &verdict, sizeof(verdict));
+	j++;
 
-	return j + 14 + 1;
+	return j + 14;
 }
 
 static int 
 add_state_filter(struct sock_filter *this, 
 		 int proto,
 		 u_int16_t flags,
+		 unsigned int logic,
 		 size_t remain)
 {
 	struct {
@@ -212,6 +229,7 @@ add_state_filter(struct sock_filter *this,
 				    cta[proto].cta_protoinfo,
 				    cta[proto].cta_state,
 				    flags,
+				    logic,
 				    remain);
 }
 
@@ -223,12 +241,13 @@ bsf_add_state_filter(const struct nfct_filter *filter,
 	unsigned int i, j;
 
 	for (i = 0, j = 0; i < IPPROTO_MAX; i++) {
-		if (test_bit(i, filter->l4proto_map) &&
-		    filter->l4proto_state[i].map) {
-			j += add_state_filter(this, 
-					      i, 
-					      filter->l4proto_state[i].map,
-					      remain);
+		if (filter->l4proto_state[i].map) {
+			j += add_state_filter(
+				      this, 
+				      i, 
+				      filter->l4proto_state[i].map,
+				      filter->logic[NFCT_FILTER_L4PROTO_STATE],
+				      remain);
 		}
 	}
 
@@ -247,7 +266,7 @@ bsf_add_proto_filter(const struct nfct_filter *f,
 		.k	= NFCT_FILTER_REJECT,
 	};
 	unsigned int i, j;
-	unsigned int label_continue;
+	unsigned int label_continue, jt;
 
 	for (i = 0, j = 0; i < IPPROTO_MAX; i++) {
 		if (test_bit(i, f->l4proto_map)) {
@@ -264,7 +283,11 @@ bsf_add_proto_filter(const struct nfct_filter *f,
 		return -1;
 	}
 
-	label_continue = j + 1;
+	jt = j + 1;
+	if (f->logic[NFCT_FILTER_L4PROTO] == NFCT_FILTER_LOGIC_POSITIVE)
+		label_continue = j + 1;
+	else
+		label_continue = j + 2;
 
 	memset(filter, 0, sizeof(filter));
 
@@ -279,7 +302,7 @@ bsf_add_proto_filter(const struct nfct_filter *f,
 		struct sock_filter cmp = {
 			.code	= BPF_JMP|BPF_JEQ|BPF_K,
 			.k	= i,
-			.jt	= label_continue - j - 1,
+			.jt	= jt - j - 1,
 		};
 
 		if (test_bit(i, f->l4proto_map)) {
@@ -289,9 +312,20 @@ bsf_add_proto_filter(const struct nfct_filter *f,
 	}
 
 	memcpy(this, filter, sizeof(struct sock_filter) * (j + 14));
+
+	if (f->logic[NFCT_FILTER_L4PROTO] == NFCT_FILTER_LOGIC_NEGATIVE) {
+		struct sock_filter jump = {
+			.code	= BPF_JMP|BPF_JA,
+			.k	= 1,
+		};
+		memcpy(&this[j + 14], &jump, sizeof(jump));
+		j++;
+	}
+
 	memcpy(&this[j + 14], &verdict, sizeof(verdict));
+	j++;
 
-	return j + 14 + 1;
+	return j + 14;
 }
 
 static int
@@ -306,15 +340,17 @@ bsf_add_addr_ipv4_filter(const struct nfct_filter *f,
 		.code	= BPF_RET|BPF_K,
 		.k	= NFCT_FILTER_REJECT,
 	};
-	unsigned int i, j, dir;
-	unsigned int label_continue;
+	unsigned int i, j, dir, attr;
+	unsigned int label_continue, jt;
 
 	switch(type) {
 	case CTA_IP_V4_SRC:
 		dir = __FILTER_ADDR_SRC;
+		attr = NFCT_FILTER_SRC_IPV4;
 		break;
 	case CTA_IP_V4_DST:
 		dir = __FILTER_ADDR_DST;
+		attr = NFCT_FILTER_DST_IPV4;
 		break;
 	default:
 		return 0;
@@ -330,7 +366,11 @@ bsf_add_addr_ipv4_filter(const struct nfct_filter *f,
 		return -1;
 	}
 
-	label_continue = (f->l3proto_elems[dir] * 2) + 1;
+	jt = (f->l3proto_elems[dir] * 2) + 1;
+	if (f->logic[attr] == NFCT_FILTER_LOGIC_POSITIVE)
+		label_continue = (f->l3proto_elems[dir] * 2) + 1;
+	else
+		label_continue = (f->l3proto_elems[dir] * 2) + 2;
 
 	memset(filter, 0, sizeof(filter));
 
@@ -351,7 +391,7 @@ bsf_add_addr_ipv4_filter(const struct nfct_filter *f,
 			.code	= BPF_JMP|BPF_JEQ|BPF_K,
 			.k	= f->l3proto[dir][i].addr & 
 				  f->l3proto[dir][i].mask,
-			.jt	= label_continue - j - 2,
+			.jt	= jt - j - 2,
 			},
 		};
 		memcpy(&filter[j + 14], cmp, sizeof(cmp));
@@ -359,9 +399,20 @@ bsf_add_addr_ipv4_filter(const struct nfct_filter *f,
 	}
 
 	memcpy(this, filter, sizeof(struct sock_filter) * (j + 14));
+
+	if (f->logic[attr] == NFCT_FILTER_LOGIC_NEGATIVE) {
+		struct sock_filter jump = {
+			.code	= BPF_JMP|BPF_JA,
+			.k	= 1,
+		};
+		memcpy(&this[j + 14], &jump, sizeof(jump));
+		j++;
+	}
+
 	memcpy(&this[j + 14], &verdict, sizeof(verdict));
+	j++;
 
-	return j + 14 + 1;
+	return j + 14;
 }
 
 static int
diff --git a/utils/conntrack_filter.c b/utils/conntrack_filter.c
index 7d22950..eb26189 100644
--- a/utils/conntrack_filter.c
+++ b/utils/conntrack_filter.c
@@ -58,6 +58,11 @@ int main()
 		.mask = 0xffffffff,
 	};
 
+	/* ignore whatever that comes from 127.0.0.1 */
+	nfct_filter_set_logic(filter,
+			      NFCT_FILTER_SRC_IPV4,
+			      NFCT_FILTER_LOGIC_NEGATIVE);
+
 	nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV4, &filter_ipv4);
 
 	if (nfct_filter_attach(nfct_fd(h), filter) == -1) {



More information about the netfilter-cvslog mailing list