From 563114a47ae03c988ca0e66eddda33d485e35f6b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 17 Jul 2008 17:20:10 +0200 Subject: add berkeley socket filtering high-level API This patch adds an abstraction level to berkeley sockets filter (BSF) for Netlink sockets available since Linux kernel 2.6.26. This provides an easy way to attach filters without knowing about BSF at all. Signed-off-by: Pablo Neira Ayuso --- include/internal.h | 64 ++++++++++++++++++++++ .../libnetfilter_conntrack.h | 35 ++++++++++++ 2 files changed, 99 insertions(+) (limited to 'include') diff --git a/include/internal.h b/include/internal.h index 6661dbe..33b0dcd 100644 --- a/include/internal.h +++ b/include/internal.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -31,15 +32,22 @@ #define IPPROTO_UDPLITE 136 #endif +#ifndef IPPROTO_DCCP +#define IPPROTO_DCCP 33 +#endif + struct nfct_handle; +struct nfct_filter; typedef void (*set_attr)(struct nf_conntrack *ct, const void *value); typedef const void *(*get_attr)(const struct nf_conntrack *ct); typedef void (*copy_attr)(struct nf_conntrack *d, const struct nf_conntrack *o); +typedef void (*filter_attr)(struct nfct_filter *filter, const void *value); extern set_attr set_attr_array[]; extern get_attr get_attr_array[]; extern copy_attr copy_attr_array[]; +extern filter_attr filter_attr_array[]; typedef int (*nfct_handler)(struct nfct_handle *cth, struct nlmsghdr *nlh, void *arg); @@ -165,6 +173,50 @@ struct nf_conntrack { u_int32_t set[2]; }; +struct nfct_filter { + /* + * As many other objects in this library, the attributes are + * private. This gives us the chance to modify the layout and + * object size. + * + * Another observation, although this object might seem too + * memory consuming, it is only needed to build the filter. Thus, + * once it is attached, you can release this object. + */ + + /* + * This the layer 4 protocol map for filtering. + */ + u_int32_t l4proto_map[IPPROTO_MAX/32]; + + struct { + /* + * No limitations in the protocol filtering. We use a map of + * 16 bits per protocol. As for now, DCCP has 10 states, TCP has + * 10 states, SCTP has 8 state. Therefore, 16 bits is enough. + */ +#define __FILTER_PROTO_MAX 16 + u_int16_t map; + } l4proto_state[IPPROTO_MAX]; + +#define __FILTER_ADDR_SRC 0 +#define __FILTER_ADDR_DST 1 + + /* + * FIXME: For IPv4 filtering, up to 256 IPs or masks by now. + * This limitation is related to the existing autogenerated BSF code + * and the fact that the maximum jump offset if 2^8 = 256. + */ + u_int32_t l3proto_elems[2]; + struct { +#define __FILTER_ADDR_MAX 256 + u_int32_t addr; + u_int32_t mask; + } l3proto[2][__FILTER_ADDR_MAX]; + + u_int32_t set[1]; +}; + struct nf_expect { struct nf_conntrack master; struct nf_conntrack expected; @@ -193,6 +245,16 @@ static inline void unset_bit(int nr, u_int32_t *addr) addr[nr >> 5] &= ~(1UL << (nr & 31)); } +static inline void set_bit_u16(int nr, u_int16_t *addr) +{ + addr[nr >> 4] |= (1UL << (nr & 15)); +} + +static inline void unset_bit_u16(int nr, u_int16_t *addr) +{ + addr[nr >> 4] &= ~(1UL << (nr & 15)); +} + static inline int test_bit(int nr, const u_int32_t *addr) { return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0; @@ -224,6 +286,8 @@ int __setobjopt(struct nf_conntrack *ct, unsigned int option); int __getobjopt(const struct nf_conntrack *ct, unsigned int option); int __compare(const struct nf_conntrack *ct1, const struct nf_conntrack *ct2, unsigned int flags); +int __setup_netlink_socket_filter(int fd, struct nfct_filter *filter); + typedef void (*set_exp_attr)(struct nf_expect *exp, const void *value); typedef const void *(*get_exp_attr)(const struct nf_expect *exp); diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack.h b/include/libnetfilter_conntrack/libnetfilter_conntrack.h index a043f91..328cf8b 100644 --- a/include/libnetfilter_conntrack/libnetfilter_conntrack.h +++ b/include/libnetfilter_conntrack/libnetfilter_conntrack.h @@ -324,6 +324,41 @@ extern void nfct_copy_attr(struct nf_conntrack *ct1, const struct nf_conntrack *ct2, const enum nf_conntrack_attr type); +/* filter */ + +struct nfct_filter; + +extern struct nfct_filter *nfct_filter_create(void); +extern void nfct_filter_destroy(struct nfct_filter *filter); + +struct nfct_filter_proto { + u_int16_t proto; + u_int16_t state; +}; +struct nfct_filter_ipv4 { + u_int32_t addr; + u_int32_t mask; +}; + +enum nfct_filter_attr { + NFCT_FILTER_L4PROTO = 0, /* u_int32_t */ + NFCT_FILTER_L4PROTO_STATE, /* struct nfct_filter_proto */ + NFCT_FILTER_SRC_IPV4, /* struct nfct_filter_ipv4 */ + NFCT_FILTER_DST_IPV4, /* struct nfct_filter_ipv4 */ + NFCT_FILTER_MAX +}; + +extern void nfct_filter_add_attr(struct nfct_filter *filter, + const enum nfct_filter_attr attr, + const void *value); + +extern void nfct_filter_add_attr_u32(struct nfct_filter *filter, + const enum nfct_filter_attr attr, + const u_int32_t value); + +extern int nfct_filter_attach(int fd, struct nfct_filter *filter); +extern int nfct_filter_detach(int fd); + /* low level API: netlink functions */ extern int nfct_build_conntrack(struct nfnl_subsys_handle *ssh, -- cgit v1.2.3