summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2008-11-25 01:03:19 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2008-11-25 01:03:19 +0100
commit20506e55b12ba22b761a1ad84dc8a47ce8c82f2e (patch)
treea23824017b20e4161e6310fefdfd0a20503fca99 /src
parent972e6b3c19f3c79b59804308efac447bd2d016ec (diff)
bsf: major rework of the BSF generation code
This patch reworks the BSF automatic generation code. This feature needs more love and it has several limitations like that the maximum number of IPs are 127 due to BSF code restrictions. See this patch as a first step forward. This patch also adds the stack data type, which is used to resolve jump dynamically instead of the previous static approach. This patch also includes fixes in the limitations, previous calculations were wrong. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r--src/conntrack/Makefile.am3
-rw-r--r--src/conntrack/api.c6
-rw-r--r--src/conntrack/bsf.c495
-rw-r--r--src/conntrack/filter.c11
-rw-r--r--src/conntrack/stack.c67
5 files changed, 319 insertions, 263 deletions
diff --git a/src/conntrack/Makefile.am b/src/conntrack/Makefile.am
index 2d62177..d989d10 100644
--- a/src/conntrack/Makefile.am
+++ b/src/conntrack/Makefile.am
@@ -14,4 +14,5 @@ libnfconntrack_la_SOURCES = api.c callback.c \
compare.c \
copy.c \
filter.c bsf.c \
- grp.c grp_getter.c grp_setter.c
+ grp.c grp_getter.c grp_setter.c \
+ stack.c
diff --git a/src/conntrack/api.c b/src/conntrack/api.c
index 6dae83f..141aa9d 100644
--- a/src/conntrack/api.c
+++ b/src/conntrack/api.c
@@ -1009,8 +1009,8 @@ void nfct_filter_destroy(struct nfct_filter *filter)
* @type: filter attribute type
* @value: pointer to the value of the filter attribute
*
- * Limitations: You can add up to 256 IPv4 addresses and masks for
- * NFCT_FILTER_SRC_IPV4 and, similarly, 256 for NFCT_FILTER_DST_IPV4.
+ * Limitations: You can add up to 127 IPv4 addresses and masks for
+ * NFCT_FILTER_SRC_IPV4 and, similarly, 127 for NFCT_FILTER_DST_IPV4.
*/
void nfct_filter_add_attr(struct nfct_filter *filter,
const enum nfct_filter_attr type,
@@ -1033,6 +1033,8 @@ void nfct_filter_add_attr(struct nfct_filter *filter,
* @filter: filter object that we want to modify
* @type: filter attribute type
* @value: value of the filter attribute using unsigned int (32 bits).
+ *
+ * Limitations: You can add up to 255 protocols which is a reasonable limit.
*/
void nfct_filter_add_attr_u32(struct nfct_filter *filter,
const enum nfct_filter_attr type,
diff --git a/src/conntrack/bsf.c b/src/conntrack/bsf.c
index 0d20949..f2d14f8 100644
--- a/src/conntrack/bsf.c
+++ b/src/conntrack/bsf.c
@@ -6,6 +6,7 @@
*/
#include "internal/internal.h"
+#include "internal/stack.h"
#include <linux/filter.h>
#ifndef SKF_AD_NLATTR
@@ -32,175 +33,192 @@ static void show_filter(struct sock_filter *this, int size)
static inline void show_filter(struct sock_filter *this, int size) {}
#endif
-static void set_basic_filter(struct sock_filter *this,
- unsigned int first_type,
- unsigned int second_type,
- unsigned int third_type,
- unsigned int label,
- unsigned int word_size)
+#define NEW_POS(x) (sizeof(x)/sizeof(struct sock_filter))
+
+static inline int
+nfct_bsf_load_payload_offset(struct sock_filter *this, int pos)
{
- struct sock_filter filter[] = {
- [0] = {
- /* A = sizeof(struct nlmsghdr) + sizeof(struct nfgenmsg) */
- .code = BPF_LD|BPF_IMM,
- .k = sizeof(struct nlmsghdr) + sizeof(struct nfgenmsg),
- },
- [1] = {
- /* X = first_type */
- .code = BPF_LDX|BPF_IMM,
- .k = first_type,
- },
- [2] = {
- /* A = netlink attribute offset */
- .code = BPF_LD|BPF_B|BPF_ABS,
- .k = SKF_AD_OFF + SKF_AD_NLATTR,
- },
- [3] = {
- /* Reject if not found (A == 0) */
- .code = BPF_JMP|BPF_JEQ|BPF_K,
- .k = 0,
- .jt = label - 3 - 1,
- },
- [4] = {
- /* A += sizeof(struct nfattr) */
- .code = BPF_ALU|BPF_ADD|BPF_K,
- .k = sizeof(struct nfattr),
- },
- [5] = {
- /* X = second_type */
- .code = BPF_LDX|BPF_IMM,
- .k = second_type,
- },
- [6] = {
- /* A = netlink attribute offset */
- .code = BPF_LD|BPF_B|BPF_ABS,
- .k = SKF_AD_OFF + SKF_AD_NLATTR,
+ struct sock_filter __code = {
+ .code = BPF_LD|BPF_IMM,
+ .k = sizeof(struct nlmsghdr) + sizeof(struct nfgenmsg),
+ };
+ memcpy(&this[pos], &__code, sizeof(__code));
+ return NEW_POS(__code);
+}
+
+static inline int
+nfct_bsf_find_attr(struct sock_filter *this, int attr, int pos)
+{
+ struct sock_filter __code[] = {
+ [0] = {
+ /* X = attribute type */
+ .code = BPF_LDX|BPF_IMM,
+ .k = attr,
},
- [7] = {
- /* Reject if not found (A == 0) */
+ [1] = {
+ /* A = netlink attribute offset */
+ .code = BPF_LD|BPF_B|BPF_ABS,
+ .k = SKF_AD_OFF + SKF_AD_NLATTR,
+ }
+ };
+ memcpy(&this[pos], __code, sizeof(__code));
+ return NEW_POS(__code);
+}
+
+struct jump {
+ int line;
+ u_int8_t jt;
+ u_int8_t jf;
+};
+
+static inline int
+nfct_bsf_cmp_k_stack(struct sock_filter *this, int k,
+ int jump_true, int pos, struct stack *s)
+{
+ struct sock_filter __code = {
.code = BPF_JMP|BPF_JEQ|BPF_K,
- .k = 0,
- .jt = label - 7 - 1,
- },
- [8] = {
+ .k = k,
+ };
+ struct jump jmp = {
+ .line = pos,
+ .jt = jump_true - 1,
+ .jf = 0,
+ };
+ stack_push(s, &jmp);
+ memcpy(&this[pos], &__code, sizeof(__code));
+ return NEW_POS(__code);
+}
+
+static inline int
+nfct_bsf_alu_and(struct sock_filter *this, int k, int pos)
+{
+ struct sock_filter __code = {
+ .code = BPF_ALU|BPF_AND|BPF_K,
+ .k = k,
+ };
+ memcpy(&this[pos], &__code, sizeof(__code));
+ return NEW_POS(__code);
+}
+
+static inline int
+nfct_bsf_add_attr_data_offset(struct sock_filter *this, int pos)
+{
+ struct sock_filter __code = {
/* A += sizeof(struct nfattr) */
.code = BPF_ALU|BPF_ADD|BPF_K,
.k = sizeof(struct nfattr),
- },
- [9] = {
- /* X = third_type */
- .code = BPF_LDX|BPF_IMM,
- .k = third_type,
- },
- [10] = {
- /* A = netlink attribute offset */
- .code = BPF_LD|BPF_B|BPF_ABS,
- .k = SKF_AD_OFF + SKF_AD_NLATTR,
- },
- [11] = {
- /* Reject if not found (A == 0) */
- .code = BPF_JMP|BPF_JEQ|BPF_K,
- .k = 0,
- .jt = label - 11 - 1,
- },
- [12] = {
- /* X = A */
+ };
+ memcpy(&this[pos], &__code, sizeof(__code));
+ return NEW_POS(__code);
+}
+
+static inline int
+nfct_bsf_x_equal_a(struct sock_filter *this, int pos)
+{
+ struct sock_filter __code = {
.code = BPF_MISC|BPF_TAX,
- },
- [13] = {
+ };
+ memcpy(&this[pos], &__code, sizeof(__code));
+ return NEW_POS(__code);
+}
+
+static inline int
+nfct_bsf_load_attr(struct sock_filter *this, int word_size, int pos)
+{
+ struct sock_filter __code = {
/* A = skb->data[X + k:word_size] */
.code = BPF_LD|word_size|BPF_IND,
.k = sizeof(struct nfattr),
- },
+
};
+ memcpy(&this[pos], &__code, sizeof(__code));
+ return NEW_POS(__code);
+}
- memcpy(this, filter, sizeof(filter));
+static inline int
+nfct_bsf_ret_verdict(struct sock_filter *this, int verdict, int pos)
+{
+ struct sock_filter __code = {
+ .code = BPF_RET|BPF_K,
+ .k = verdict,
+ };
+ memcpy(&this[pos], &__code, sizeof(__code));
+ return NEW_POS(__code);
}
+static inline int
+nfct_bsf_jump_to(struct sock_filter *this, int line, int pos)
+{
+ struct sock_filter __code = {
+ .code = BPF_JMP|BPF_JA,
+ .k = line,
+ };
+ memcpy(&this[pos], &__code, sizeof(__code));
+ return NEW_POS(__code);
+};
+
static int
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)
+ unsigned int logic)
{
- struct sock_filter filter[14 + __FILTER_PROTO_MAX];
- struct sock_filter verdict = {
- /* Reject */
- .code = BPF_RET|BPF_K,
- .k = NFCT_FILTER_REJECT,
- };
unsigned int i, j;
unsigned int label_continue, jt;
+ struct stack *s;
+ struct jump jmp;
- /* calculate the number of filter lines */
- for (i = 0, j = 0; i < sizeof(state_flags) * 8; i++) {
- if (state_flags & (1 << i)) {
- j++;
- }
- }
-
- /* nothing to filter, skip */
- if (j == 0)
- return 0;
-
- if (j + 14 >= __FILTER_PROTO_MAX + 14 || j + 14 > remain) {
- errno = ENOSPC;
+ /* XXX: 32 maximum states + 3 jumps in the three-level iteration */
+ s = stack_create(sizeof(struct jump), 3 + 32);
+ if (s == NULL) {
+ errno = ENOMEM;
return -1;
}
- memset(filter, 0, sizeof(filter));
-
- jt = j + 1;
+ jt = 1;
if (logic == NFCT_FILTER_LOGIC_POSITIVE)
- label_continue = j + 1;
+ label_continue = 1;
else
- label_continue = j + 2;
-
- set_basic_filter(filter,
- CTA_PROTOINFO,
- cta_protoinfo_proto,
- cta_protoinfo_state,
- 14 + label_continue,
- BPF_B);
-
- for (i = 0, j = 0; i < sizeof(state_flags) * 8; i++) {
- struct sock_filter cmp = {
- .code = BPF_JMP|BPF_JEQ|BPF_K,
- .k = i,
- .jt = jt - j - 1,
- };
-
+ label_continue = 2;
+
+ j = 0;
+ j += nfct_bsf_load_payload_offset(this, j);
+ j += nfct_bsf_find_attr(this, CTA_PROTOINFO, j);
+ j += nfct_bsf_cmp_k_stack(this, 0, label_continue - j, j, s);
+ j += nfct_bsf_add_attr_data_offset(this, j);
+ j += nfct_bsf_find_attr(this, cta_protoinfo_proto, j);
+ j += nfct_bsf_cmp_k_stack(this, 0, label_continue - j, j, s);
+ j += nfct_bsf_add_attr_data_offset(this, j);
+ j += nfct_bsf_find_attr(this, cta_protoinfo_state, j);
+ j += nfct_bsf_cmp_k_stack(this, 0, label_continue - j, j, s);
+ j += nfct_bsf_x_equal_a(this, j);
+ j += nfct_bsf_load_attr(this, BPF_B, j);
+
+ for (i = 0; i < sizeof(state_flags) * 8; i++) {
if (state_flags & (1 << i)) {
- memcpy(&filter[j + 14], &cmp, sizeof(cmp));
- j++;
+ j += nfct_bsf_cmp_k_stack(this, i, jt - j, j, s);
}
}
- memcpy(this, filter, sizeof(struct sock_filter) * (j + 14));
+ while (stack_pop(s, &jmp) != -1)
+ this[jmp.line].jt += jmp.jt + j;
- 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++;
- }
+ if (logic == NFCT_FILTER_LOGIC_NEGATIVE)
+ j += nfct_bsf_jump_to(this, 1, j);
- memcpy(&this[j + 14], &verdict, sizeof(verdict));
- j++;
+ j += nfct_bsf_ret_verdict(this, NFCT_FILTER_REJECT, j);
- return j + 14;
+ stack_destroy(s);
+
+ return j;
}
static int
add_state_filter(struct sock_filter *this,
int proto,
u_int16_t flags,
- unsigned int logic,
- size_t remain)
+ unsigned int logic)
{
struct {
unsigned int cta_protoinfo;
@@ -229,25 +247,22 @@ add_state_filter(struct sock_filter *this,
cta[proto].cta_protoinfo,
cta[proto].cta_state,
flags,
- logic,
- remain);
+ logic);
}
static int
-bsf_add_state_filter(const struct nfct_filter *filter,
- struct sock_filter *this,
- size_t remain)
+bsf_add_state_filter(const struct nfct_filter *filter, struct sock_filter *this)
{
unsigned int i, j;
for (i = 0, j = 0; i < IPPROTO_MAX; i++) {
- if (filter->l4proto_state[i].map) {
+ if (filter->l4proto_state[i].map &&
+ filter->l4proto_state[i].len > 0) {
j += add_state_filter(
this,
i,
filter->l4proto_state[i].map,
- filter->logic[NFCT_FILTER_L4PROTO_STATE],
- remain);
+ filter->logic[NFCT_FILTER_L4PROTO_STATE]);
}
}
@@ -255,93 +270,71 @@ bsf_add_state_filter(const struct nfct_filter *filter,
}
static int
-bsf_add_proto_filter(const struct nfct_filter *f,
- struct sock_filter *this,
- size_t remain)
+bsf_add_proto_filter(const struct nfct_filter *f, struct sock_filter *this)
{
- struct sock_filter filter[14 + IPPROTO_MAX];
- struct sock_filter verdict = {
- /* Reject */
- .code = BPF_RET|BPF_K,
- .k = NFCT_FILTER_REJECT,
- };
unsigned int i, j;
unsigned int label_continue, jt;
-
- for (i = 0, j = 0; i < IPPROTO_MAX; i++) {
- if (test_bit(i, f->l4proto_map)) {
- j++;
- }
- }
+ struct stack *s;
+ struct jump jmp;
/* nothing to filter, skip */
- if (j == 0)
+ if (f->l4proto_len == 0)
return 0;
- if (j + 14 >= IPPROTO_MAX + 14 || j + 14 > remain) {
- errno = ENOSPC;
+ /* XXX: 255 maximum proto + 3 jumps in the three-level iteration */
+ s = stack_create(sizeof(struct jump), 3 + 255);
+ if (s == NULL) {
+ errno = ENOMEM;
return -1;
}
- jt = j + 1;
+ jt = 1;
if (f->logic[NFCT_FILTER_L4PROTO] == NFCT_FILTER_LOGIC_POSITIVE)
- label_continue = j + 1;
+ label_continue = 1;
else
- label_continue = j + 2;
-
- memset(filter, 0, sizeof(filter));
-
- set_basic_filter(filter,
- CTA_TUPLE_ORIG,
- CTA_TUPLE_PROTO,
- CTA_PROTO_NUM,
- 14 + label_continue,
- BPF_B);
-
- for (i = 0, j = 0; i < IPPROTO_MAX; i++) {
- struct sock_filter cmp = {
- .code = BPF_JMP|BPF_JEQ|BPF_K,
- .k = i,
- .jt = jt - j - 1,
- };
-
+ label_continue = 2;
+
+ j = 0;
+ j += nfct_bsf_load_payload_offset(this, j);
+ j += nfct_bsf_find_attr(this, CTA_TUPLE_ORIG, j);
+ j += nfct_bsf_cmp_k_stack(this, 0, label_continue - j, j, s);
+ j += nfct_bsf_add_attr_data_offset(this, j);
+ j += nfct_bsf_find_attr(this, CTA_TUPLE_PROTO, j);
+ j += nfct_bsf_cmp_k_stack(this, 0, label_continue - j, j, s);
+ j += nfct_bsf_add_attr_data_offset(this, j);
+ j += nfct_bsf_find_attr(this, CTA_PROTO_NUM, j);
+ j += nfct_bsf_cmp_k_stack(this, 0, label_continue - j, j, s);
+ j += nfct_bsf_x_equal_a(this, j);
+ j += nfct_bsf_load_attr(this, BPF_B, j);
+
+ for (i = 0; i < IPPROTO_MAX; i++) {
if (test_bit(i, f->l4proto_map)) {
- memcpy(&filter[j + 14], &cmp, sizeof(cmp));
- j++;
+ j += nfct_bsf_cmp_k_stack(this, i, jt - j, j, s);
}
}
- memcpy(this, filter, sizeof(struct sock_filter) * (j + 14));
+ while (stack_pop(s, &jmp) != -1)
+ this[jmp.line].jt += jmp.jt + j;
- 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++;
- }
+ if (f->logic[NFCT_FILTER_L4PROTO] == NFCT_FILTER_LOGIC_NEGATIVE)
+ j += nfct_bsf_jump_to(this, 1, j);
+
+ j += nfct_bsf_ret_verdict(this, NFCT_FILTER_REJECT, j);
- memcpy(&this[j + 14], &verdict, sizeof(verdict));
- j++;
+ stack_destroy(s);
- return j + 14;
+ return j;
}
static int
bsf_add_addr_ipv4_filter(const struct nfct_filter *f,
struct sock_filter *this,
- unsigned int type,
- size_t remain)
+ unsigned int type)
{
- struct sock_filter filter[14 + __FILTER_ADDR_MAX];
- struct sock_filter verdict = {
- /* Reject */
- .code = BPF_RET|BPF_K,
- .k = NFCT_FILTER_REJECT,
- };
unsigned int i, j, dir, attr;
unsigned int label_continue, jt;
+ struct stack *s;
+ struct jump jmp;
switch(type) {
case CTA_IP_V4_SRC:
@@ -360,107 +353,89 @@ bsf_add_addr_ipv4_filter(const struct nfct_filter *f,
if (f->l3proto_elems[dir] == 0)
return 0;
- if (f->l3proto_elems[dir] + 14 >= __FILTER_ADDR_MAX + 14 ||
- f->l3proto_elems[dir] + 14 > remain) {
- errno = ENOSPC;
+ /* XXX: 127 maximum IPs + 3 jumps in the three-level iteration */
+ s = stack_create(sizeof(struct jump), 3 + 127);
+ if (s == NULL) {
+ errno = ENOMEM;
return -1;
}
- jt = (f->l3proto_elems[dir] * 2) + 1;
+ jt = 1;
if (f->logic[attr] == NFCT_FILTER_LOGIC_POSITIVE)
- label_continue = (f->l3proto_elems[dir] * 2) + 1;
+ label_continue = 1;
else
- label_continue = (f->l3proto_elems[dir] * 2) + 2;
-
- memset(filter, 0, sizeof(filter));
-
- set_basic_filter(filter,
- CTA_TUPLE_ORIG,
- CTA_TUPLE_IP,
- type,
- 14 + label_continue,
- BPF_W);
-
- for (i = 0, j = 0; i < f->l3proto_elems[dir]; i++) {
- struct sock_filter cmp[] = {
- [0] = {
- .code = BPF_ALU|BPF_AND|BPF_K,
- .k = f->l3proto[dir][i].mask,
- },
- [1] = {
- .code = BPF_JMP|BPF_JEQ|BPF_K,
- .k = f->l3proto[dir][i].addr &
- f->l3proto[dir][i].mask,
- .jt = jt - j - 2,
- },
- };
- memcpy(&filter[j + 14], cmp, sizeof(cmp));
- j+=2;
+ label_continue = 2;
+
+ j = 0;
+ j += nfct_bsf_load_payload_offset(this, j);
+ j += nfct_bsf_find_attr(this, CTA_TUPLE_ORIG, j);
+ j += nfct_bsf_cmp_k_stack(this, 0, label_continue - j, j, s);
+ j += nfct_bsf_add_attr_data_offset(this, j);
+ j += nfct_bsf_find_attr(this, CTA_TUPLE_IP, j);
+ j += nfct_bsf_cmp_k_stack(this, 0, label_continue - j, j, s);
+ j += nfct_bsf_add_attr_data_offset(this, j);
+ j += nfct_bsf_find_attr(this, type, j);
+ j += nfct_bsf_cmp_k_stack(this, 0, label_continue - j, j, s);
+ j += nfct_bsf_x_equal_a(this, j);
+ j += nfct_bsf_load_attr(this, BPF_W, j);
+
+ for (i = 0; i < f->l3proto_elems[dir]; i++) {
+ int ip = f->l3proto[dir][i].addr & f->l3proto[dir][i].mask;
+
+ j += nfct_bsf_alu_and(this, f->l3proto[dir][i].mask, j);
+ j += nfct_bsf_cmp_k_stack(this, ip, jt - j, j, s);
}
- memcpy(this, filter, sizeof(struct sock_filter) * (j + 14));
+ while (stack_pop(s, &jmp) != -1)
+ this[jmp.line].jt += jmp.jt + j;
- 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++;
- }
+ if (f->logic[attr] == NFCT_FILTER_LOGIC_NEGATIVE)
+ j += nfct_bsf_jump_to(this, 1, j);
+
+ j += nfct_bsf_ret_verdict(this, NFCT_FILTER_REJECT, j);
- memcpy(&this[j + 14], &verdict, sizeof(verdict));
- j++;
+ stack_destroy(s);
- return j + 14;
+ return j;
}
static int
-bsf_add_saddr_ipv4_filter(const struct nfct_filter *f,
- struct sock_filter *this,
- size_t remain)
+bsf_add_saddr_ipv4_filter(const struct nfct_filter *f, struct sock_filter *this)
{
- return bsf_add_addr_ipv4_filter(f, this, CTA_IP_V4_SRC, remain);
+ return bsf_add_addr_ipv4_filter(f, this, CTA_IP_V4_SRC);
}
static int
-bsf_add_daddr_ipv4_filter(const struct nfct_filter *f,
- struct sock_filter *this,
- size_t remain)
+bsf_add_daddr_ipv4_filter(const struct nfct_filter *f, struct sock_filter *this)
{
- return bsf_add_addr_ipv4_filter(f, this, CTA_IP_V4_DST, remain);
+ return bsf_add_addr_ipv4_filter(f, this, CTA_IP_V4_DST);
}
/* this buffer must be big enough to store all the autogenerated lines */
-#define BSF_BUFFER_SIZE 1024
+#define BSF_BUFFER_SIZE 2048
int __setup_netlink_socket_filter(int fd, struct nfct_filter *f)
{
struct sock_filter bsf[BSF_BUFFER_SIZE];
- struct sock_filter bsf_accept = {
- /* Accept */
- .code = BPF_RET|BPF_K,
- .k = NFCT_FILTER_ACCEPT,
- };
struct sock_fprog sf;
unsigned int j = 0;
memset(bsf, 0, sizeof(bsf));
- j += bsf_add_proto_filter(f, &bsf[j], BSF_BUFFER_SIZE-j);
- j += bsf_add_saddr_ipv4_filter(f, &bsf[j], BSF_BUFFER_SIZE-j);
- j += bsf_add_daddr_ipv4_filter(f, &bsf[j], BSF_BUFFER_SIZE-j);
- j += bsf_add_state_filter(f, &bsf[j], BSF_BUFFER_SIZE-j);
+ j += bsf_add_proto_filter(f, &bsf[j]);
+ j += bsf_add_saddr_ipv4_filter(f, &bsf[j]);
+ j += bsf_add_daddr_ipv4_filter(f, &bsf[j]);
+ j += bsf_add_state_filter(f, &bsf[j]);
/* nothing to filter, skip */
if (j == 0)
return 0;
- memcpy(&bsf[j], &bsf_accept, sizeof(struct sock_filter));
+ j += nfct_bsf_ret_verdict(bsf, NFCT_FILTER_ACCEPT, j);
- show_filter(bsf, j+1);
+ show_filter(bsf, j);
- sf.len = (sizeof(struct sock_filter) * (j + 1)) / sizeof(bsf[0]);
+ sf.len = (sizeof(struct sock_filter) * j) / sizeof(bsf[0]);
sf.filter = bsf;
return setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &sf, sizeof(sf));
diff --git a/src/conntrack/filter.c b/src/conntrack/filter.c
index 7966e54..7cee673 100644
--- a/src/conntrack/filter.c
+++ b/src/conntrack/filter.c
@@ -9,7 +9,11 @@
static void filter_attr_l4proto(struct nfct_filter *filter, const void *value)
{
+ if (filter->l4proto_len >= __FILTER_L4PROTO_MAX)
+ return;
+
set_bit(*((int *) value), filter->l4proto_map);
+ filter->l4proto_len++;
}
static void
@@ -18,12 +22,16 @@ filter_attr_l4proto_state(struct nfct_filter *filter, const void *value)
const struct nfct_filter_proto *this = value;
set_bit_u16(this->state, &filter->l4proto_state[this->proto].map);
+ filter->l4proto_state[this->proto].len++;
}
static void filter_attr_src_ipv4(struct nfct_filter *filter, const void *value)
{
const struct nfct_filter_ipv4 *this = value;
+ if (filter->l3proto_elems[0] >= __FILTER_ADDR_MAX)
+ return;
+
filter->l3proto[0][filter->l3proto_elems[0]].addr = this->addr;
filter->l3proto[0][filter->l3proto_elems[0]].mask = this->mask;
filter->l3proto_elems[0]++;
@@ -33,6 +41,9 @@ static void filter_attr_dst_ipv4(struct nfct_filter *filter, const void *value)
{
const struct nfct_filter_ipv4 *this = value;
+ if (filter->l3proto_elems[1] >= __FILTER_ADDR_MAX)
+ return;
+
filter->l3proto[1][filter->l3proto_elems[1]].addr = this->addr;
filter->l3proto[1][filter->l3proto_elems[1]].mask = this->mask;
filter->l3proto_elems[1]++;
diff --git a/src/conntrack/stack.c b/src/conntrack/stack.c
new file mode 100644
index 0000000..404e38b
--- /dev/null
+++ b/src/conntrack/stack.c
@@ -0,0 +1,67 @@
+/*
+ * (C) 2008 by Pablo Neira Ayuso <pablo@netfilter.org>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "internal/stack.h"
+
+struct stack {
+ int num_elems;
+ int max_elems;
+ size_t elem_size;
+ char *data;
+};
+
+struct stack *stack_create(size_t elem_size, int max_elems)
+{
+ struct stack *s;
+
+ s = calloc(sizeof(struct stack), 1);
+ if (s == NULL)
+ return NULL;
+
+ s->data = calloc(elem_size * max_elems, 1);
+ if (s->data == NULL) {
+ free(s);
+ return NULL;
+ }
+ s->elem_size = elem_size;
+ s->max_elems = max_elems;
+
+ return s;
+}
+
+void stack_destroy(struct stack *s)
+{
+ free(s->data);
+ free(s);
+}
+
+int stack_push(struct stack *s, void *data)
+{
+ if (s->num_elems >= s->max_elems) {
+ errno = ENOSPC;
+ return -1;
+ }
+ memcpy(s->data + (s->elem_size * s->num_elems), data, s->elem_size);
+ s->num_elems++;
+ return 0;
+}
+
+int stack_pop(struct stack *s, void *data)
+{
+ if (s->num_elems <= 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ s->num_elems--;
+ memcpy(data, s->data + (s->elem_size * s->num_elems), s->elem_size);
+ return 0;
+}