From e5cb42249f7fd5b730667150c9c19f10d2f215fd Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 25 Jul 2008 13:05:12 +0200 Subject: cleanup: split internal.h into several internal header files This patch cleanups the internal headers by splitting them into several logical pieces. Signed-off-by: Pablo Neira Ayuso --- include/Makefile.am | 5 +- include/internal.h | 340 ---------- include/internal/Makefile.am | 2 + include/internal/bitops.h | 32 + include/internal/deprecated.h | 65 ++ include/internal/extern.h | 12 + include/internal/internal.h | 75 +++ include/internal/linux_list.h | 728 +++++++++++++++++++++ include/internal/object.h | 217 ++++++ include/internal/prototypes.h | 37 ++ include/internal/types.h | 21 + include/libnetfilter_conntrack/Makefile.am | 3 - .../libnetfilter_conntrack_extensions.h | 38 -- .../libnetfilter_conntrack_l3extensions.h | 29 - include/linux_list.h | 725 -------------------- 15 files changed, 1190 insertions(+), 1139 deletions(-) delete mode 100644 include/internal.h create mode 100644 include/internal/Makefile.am create mode 100644 include/internal/bitops.h create mode 100644 include/internal/deprecated.h create mode 100644 include/internal/extern.h create mode 100644 include/internal/internal.h create mode 100644 include/internal/linux_list.h create mode 100644 include/internal/object.h create mode 100644 include/internal/prototypes.h create mode 100644 include/internal/types.h delete mode 100644 include/libnetfilter_conntrack/libnetfilter_conntrack_extensions.h delete mode 100644 include/libnetfilter_conntrack/libnetfilter_conntrack_l3extensions.h delete mode 100644 include/linux_list.h (limited to 'include') diff --git a/include/Makefile.am b/include/Makefile.am index 7113c9c..6fb2881 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,4 +1 @@ - -SUBDIRS = libnetfilter_conntrack - -noinst_HEADERS = linux_list.h internal.h +SUBDIRS = libnetfilter_conntrack internal diff --git a/include/internal.h b/include/internal.h deleted file mode 100644 index 9dc33f2..0000000 --- a/include/internal.h +++ /dev/null @@ -1,340 +0,0 @@ -/* - * (C) 2006 by Pablo Neira Ayuso - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * WARNING: Do *NOT* ever include this file, only for internal use! - * Use the set/get API in order to set/get the conntrack attributes - */ - -#ifndef __LIBNETFILTER_CONNTRACK_INTERNAL__ -#define __LIBNETFILTER_CONNTRACK_INTERNAL__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifndef IPPROTO_SCTP -#define IPPROTO_SCTP 132 -#endif - -#ifndef IPPROTO_UDPLITE -#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); - -struct nfct_handle { - struct nfnl_handle *nfnlh; - struct nfnl_subsys_handle *nfnlssh_ct; - struct nfnl_subsys_handle *nfnlssh_exp; - nfct_callback callback; /* user callback */ - void *callback_data; /* user data for callback */ - nfct_handler handler; /* netlink handler */ - - /* callback handler for the new API */ - struct nfnl_callback nfnl_cb; - int(*cb)(enum nf_conntrack_msg_type type, - struct nf_conntrack *ct, - void *data); - int(*expect_cb)(enum nf_conntrack_msg_type type, - struct nf_expect *exp, - void *data); -}; - -union __nfct_l4_src { - /* Add other protocols here. */ - u_int16_t all; - struct { - u_int16_t port; - } tcp; - struct { - u_int16_t port; - } udp; - struct { - u_int16_t id; - } icmp; - struct { - u_int16_t port; - } sctp; -}; - -union __nfct_l4_dst { - /* Add other protocols here. */ - u_int16_t all; - struct { - u_int16_t port; - } tcp; - struct { - u_int16_t port; - } udp; - struct { - u_int8_t type, code; - } icmp; - struct { - u_int16_t port; - } sctp; -}; - -union __nfct_address { - u_int32_t v4; - struct in6_addr v6; -}; - -struct __nfct_tuple { - union __nfct_address src; - union __nfct_address dst; - - u_int8_t l3protonum; - u_int8_t protonum; - union __nfct_l4_src l4src; - union __nfct_l4_dst l4dst; - - struct { - u_int32_t correction_pos; - u_int32_t offset_before; - u_int32_t offset_after; - } natseq; -}; - -#define __DIR_ORIG 0 -#define __DIR_REPL 1 -#define __DIR_MASTER 2 -#define __DIR_MAX __DIR_MASTER+1 - -union __nfct_protoinfo { - struct { - u_int8_t state; - struct { - u_int8_t value; - u_int8_t mask; - } flags[__DIR_MAX]; - } tcp; - struct { - u_int8_t state; - u_int32_t vtag[__DIR_MAX]; - } sctp; - -}; - -struct __nfct_counters { - u_int64_t packets; - u_int64_t bytes; -}; - -struct __nfct_nat { - u_int32_t min_ip, max_ip; - union __nfct_l4_src l4min, l4max; -}; - -struct nf_conntrack { - struct __nfct_tuple tuple[__DIR_MAX]; - - u_int32_t timeout; - u_int32_t mark; - u_int32_t secmark; - u_int32_t status; - u_int32_t use; - u_int32_t id; - - union __nfct_protoinfo protoinfo; - struct __nfct_counters counters[__DIR_MAX]; - struct __nfct_nat snat; - struct __nfct_nat dnat; - - 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. - */ - - /* - * 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]; - - 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; - struct nf_conntrack mask; - u_int32_t timeout; - u_int32_t id; - u_int16_t expectfn_queue_id; - - u_int32_t set[1]; -}; - -/* container used to pass data to nfnl callbacks */ -struct __data_container { - struct nfct_handle *h; - enum nf_conntrack_msg_type type; - void *data; -}; - -static inline void set_bit(int nr, u_int32_t *addr) -{ - addr[nr >> 5] |= (1UL << (nr & 31)); -} - -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; -} - -#define BUFFER_SIZE(ret, size, len, offset) \ - size += ret; \ - if (ret > len) \ - ret = len; \ - offset += ret; \ - len -= ret; - -int __build_conntrack(struct nfnl_subsys_handle *ssh, struct nfnlhdr *req, size_t size, u_int16_t type, u_int16_t flags, const struct nf_conntrack *ct); -void __build_tuple(struct nfnlhdr *req, size_t size, const struct __nfct_tuple *t, const int type); -int __parse_message_type(const struct nlmsghdr *nlh); -void __parse_conntrack(const struct nlmsghdr *nlh, const struct nfattr *cda[], struct nf_conntrack *ct); -void __parse_tuple(const struct nfattr *attr, struct __nfct_tuple *tuple, int dir, u_int32_t *set); -int __snprintf_conntrack(char *buf, unsigned int len, const struct nf_conntrack *ct, unsigned int type, unsigned int msg_output, unsigned int flags); -int __snprintf_address(char *buf, unsigned int len, const struct __nfct_tuple *tuple); -int __snprintf_protocol(char *buf, unsigned int len, const struct nf_conntrack *ct); -int __snprintf_proto(char *buf, unsigned int len, const struct __nfct_tuple *tuple); -int __snprintf_conntrack_default(char *buf, unsigned int len, const struct nf_conntrack *ct, const unsigned int msg_type, const unsigned int flags); -int __snprintf_conntrack_xml(char *buf, unsigned int len, const struct nf_conntrack *ct, const unsigned int msg_type, const unsigned int flags); - - -int __callback(struct nlmsghdr *nlh, struct nfattr *nfa[], void *data); - -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); - -extern set_exp_attr set_exp_attr_array[]; -extern get_exp_attr get_exp_attr_array[]; - -int __build_expect(struct nfnl_subsys_handle *ssh, struct nfnlhdr *req, size_t size, u_int16_t type, u_int16_t flags, const struct nf_expect *exp); -int __parse_expect_message_type(const struct nlmsghdr *nlh); -void __parse_expect(const struct nlmsghdr *nlh, const struct nfattr *cda[], struct nf_expect *exp); -int __expect_callback(struct nlmsghdr *nlh, struct nfattr *nfa[], void *data); -int __snprintf_expect(char *buf, unsigned int len, const struct nf_expect *exp, unsigned int type, unsigned int msg_output, unsigned int flags); -int __snprintf_expect_default(char *buf, unsigned int len, const struct nf_expect *exp, unsigned int msg_type, unsigned int flags); - -/* backward compatibility of the deprecated API */ -extern struct nfct_l3proto ipv4; -extern struct nfct_l3proto ipv6; - -extern struct nfct_proto tcp; -extern struct nfct_proto udp; -extern struct nfct_proto sctp; -extern struct nfct_proto icmp; - -#define TS_ORIG \ -({ \ - ((1 << ATTR_ORIG_IPV4_SRC) | (1 << ATTR_ORIG_IPV4_DST) | \ - (1 << ATTR_ORIG_IPV6_SRC) | (1 << ATTR_ORIG_IPV6_DST) | \ - (1 << ATTR_ORIG_PORT_SRC) | (1 << ATTR_ORIG_PORT_DST) | \ - (1 << ATTR_ORIG_L3PROTO) | (1 << ATTR_ORIG_L4PROTO) | \ - (1 << ATTR_ICMP_TYPE) | (1 << ATTR_ICMP_CODE) | \ - (1 << ATTR_ICMP_ID)); \ -}) - -#define TS_REPL \ -({ \ - ((1 << ATTR_REPL_IPV4_SRC) | (1 << ATTR_REPL_IPV4_DST) | \ - (1 << ATTR_REPL_IPV6_SRC) | (1 << ATTR_REPL_IPV6_DST) | \ - (1 << ATTR_REPL_PORT_SRC) | (1 << ATTR_REPL_PORT_DST) | \ - (1 << ATTR_REPL_L3PROTO) | (1 << ATTR_REPL_L4PROTO) | \ - (1 << ATTR_ICMP_TYPE) | (1 << ATTR_ICMP_CODE) | \ - (1 << ATTR_ICMP_ID)); \ -}) - -#define TUPLE_SET(dir) (dir == __DIR_ORIG ? TS_ORIG : TS_REPL) - -#endif diff --git a/include/internal/Makefile.am b/include/internal/Makefile.am new file mode 100644 index 0000000..a4fadd5 --- /dev/null +++ b/include/internal/Makefile.am @@ -0,0 +1,2 @@ +noinst_HEADERS = bitops.h extern.h linux_list.h prototypes.h \ + deprecated.h internal.h object.h types.h diff --git a/include/internal/bitops.h b/include/internal/bitops.h new file mode 100644 index 0000000..b1bd848 --- /dev/null +++ b/include/internal/bitops.h @@ -0,0 +1,32 @@ +/* + * WARNING: Do *NOT* ever include this file, only for internal use! + */ +#ifndef _NFCT_BITOPS_H_ +#define _NFCT_BITOPS_H_ + +static inline void set_bit(int nr, u_int32_t *addr) +{ + addr[nr >> 5] |= (1UL << (nr & 31)); +} + +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; +} + +#endif diff --git a/include/internal/deprecated.h b/include/internal/deprecated.h new file mode 100644 index 0000000..fe6f890 --- /dev/null +++ b/include/internal/deprecated.h @@ -0,0 +1,65 @@ +/* + * WARNING: Do *NOT* ever include this file, only for internal use! + */ +#ifndef _NFCT_DEPRECATED_H_ +#define _NFCT_DEPRECATED_H_ + +typedef int (*nfct_handler)(struct nfct_handle *cth, struct nlmsghdr *nlh, + void *arg); + +/* some systems have old libc's */ +#include +#ifndef IPPROTO_SCTP +#define IPPROTO_SCTP 132 +#endif + +#include "internal/linux_list.h" + +/* extensions */ +struct nfct_proto { + struct list_head head; + + char *name; + u_int8_t protonum; + char *version; + + void (*parse_proto)(struct nfattr **, struct nfct_tuple *); + void (*parse_protoinfo)(struct nfattr **, struct nfct_conntrack *); + void (*build_tuple_proto)(struct nfnlhdr *, int, struct nfct_tuple *); + void (*build_protoinfo)(struct nfnlhdr *, int, struct nfct_conntrack *); + int (*print_protoinfo)(char *, union nfct_protoinfo *); + int (*print_proto)(char *, struct nfct_tuple *); + int (*compare)(struct nfct_conntrack *, struct nfct_conntrack *, + unsigned int); +}; + +extern void nfct_register_proto(struct nfct_proto *h); + +struct nfct_l3proto { + struct list_head head; + + char *name; + u_int16_t protonum; + char *version; + + void (*parse_proto)(struct nfattr **, struct nfct_tuple *); + void (*build_tuple_proto)(struct nfnlhdr *, int, struct nfct_tuple *); + int (*print_proto)(char *, struct nfct_tuple *); + int (*compare)(struct nfct_conntrack *, struct nfct_conntrack *, + unsigned int); +}; + +extern void nfct_register_l3proto(struct nfct_l3proto *h); + +/* backward compatibility of the deprecated API */ +extern struct nfct_l3proto ipv4; +extern struct nfct_l3proto ipv6; + +extern struct nfct_proto tcp; +extern struct nfct_proto udp; +extern struct nfct_proto sctp; +extern struct nfct_proto icmp; + +extern void deprecated_backward_support(); + +#endif diff --git a/include/internal/extern.h b/include/internal/extern.h new file mode 100644 index 0000000..a43cde7 --- /dev/null +++ b/include/internal/extern.h @@ -0,0 +1,12 @@ +#ifndef _NFCT_EXTERN_H_ +#define _NFCT_EXTERN_H_ + +extern set_attr set_attr_array[]; +extern get_attr get_attr_array[]; +extern copy_attr copy_attr_array[]; +extern filter_attr filter_attr_array[]; + +extern set_exp_attr set_exp_attr_array[]; +extern get_exp_attr get_exp_attr_array[]; + +#endif diff --git a/include/internal/internal.h b/include/internal/internal.h new file mode 100644 index 0000000..e7fc22e --- /dev/null +++ b/include/internal/internal.h @@ -0,0 +1,75 @@ +/* + * (C) 2006 by Pablo Neira Ayuso + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + * WARNING: Do *NOT* ever include this file, only for internal use! + * Use the set/get API in order to set/get the conntrack attributes + */ + +#ifndef __LIBNETFILTER_CONNTRACK_INTERNAL__ +#define __LIBNETFILTER_CONNTRACK_INTERNAL__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "internal/deprecated.h" +#include "internal/object.h" +#include "internal/prototypes.h" +#include "internal/types.h" +#include "internal/extern.h" +#include "internal/bitops.h" + +#ifndef IPPROTO_SCTP +#define IPPROTO_SCTP 132 +#endif + +#ifndef IPPROTO_UDPLITE +#define IPPROTO_UDPLITE 136 +#endif + +#ifndef IPPROTO_DCCP +#define IPPROTO_DCCP 33 +#endif + +#define BUFFER_SIZE(ret, size, len, offset) \ + size += ret; \ + if (ret > len) \ + ret = len; \ + offset += ret; \ + len -= ret; + +#define TS_ORIG \ +({ \ + ((1 << ATTR_ORIG_IPV4_SRC) | (1 << ATTR_ORIG_IPV4_DST) | \ + (1 << ATTR_ORIG_IPV6_SRC) | (1 << ATTR_ORIG_IPV6_DST) | \ + (1 << ATTR_ORIG_PORT_SRC) | (1 << ATTR_ORIG_PORT_DST) | \ + (1 << ATTR_ORIG_L3PROTO) | (1 << ATTR_ORIG_L4PROTO) | \ + (1 << ATTR_ICMP_TYPE) | (1 << ATTR_ICMP_CODE) | \ + (1 << ATTR_ICMP_ID)); \ +}) + +#define TS_REPL \ +({ \ + ((1 << ATTR_REPL_IPV4_SRC) | (1 << ATTR_REPL_IPV4_DST) | \ + (1 << ATTR_REPL_IPV6_SRC) | (1 << ATTR_REPL_IPV6_DST) | \ + (1 << ATTR_REPL_PORT_SRC) | (1 << ATTR_REPL_PORT_DST) | \ + (1 << ATTR_REPL_L3PROTO) | (1 << ATTR_REPL_L4PROTO) | \ + (1 << ATTR_ICMP_TYPE) | (1 << ATTR_ICMP_CODE) | \ + (1 << ATTR_ICMP_ID)); \ +}) + +#define TUPLE_SET(dir) (dir == __DIR_ORIG ? TS_ORIG : TS_REPL) + +#endif diff --git a/include/internal/linux_list.h b/include/internal/linux_list.h new file mode 100644 index 0000000..7b561c3 --- /dev/null +++ b/include/internal/linux_list.h @@ -0,0 +1,728 @@ +/* + * WARNING: Do *NOT* ever include this file, only for internal use! + */ +#ifndef _LINUX_LIST_H +#define _LINUX_LIST_H + +#undef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + +/** + * container_of - cast a member of a structure out to the containing structure + * + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +/* + * Check at compile time that something is of a particular type. + * Always evaluates to 1 so you may use it easily in comparisons. + */ +#define typecheck(type,x) \ +({ type __dummy; \ + typeof(x) __dummy2; \ + (void)(&__dummy == &__dummy2); \ + 1; \ +}) + +#define prefetch(x) 1 + +/* empty define to make this work in userspace -HW */ +#ifndef smp_wmb +#define smp_wmb() +#endif + +/* + * These are non-NULL pointers that will result in page faults + * under normal circumstances, used to verify that nobody uses + * non-initialized list entries. + */ +#define LIST_POISON1 ((void *) 0x00100100) +#define LIST_POISON2 ((void *) 0x00200200) + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add_rcu(struct list_head * new, + struct list_head * prev, struct list_head * next) +{ + new->next = next; + new->prev = prev; + smp_wmb(); + next->prev = new; + prev->next = new; +} + +/** + * list_add_rcu - add a new entry to rcu-protected list + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as list_add_rcu() + * or list_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * list_for_each_entry_rcu(). + */ +static inline void list_add_rcu(struct list_head *new, struct list_head *head) +{ + __list_add_rcu(new, head, head->next); +} + +/** + * list_add_tail_rcu - add a new entry to rcu-protected list + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as list_add_tail_rcu() + * or list_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * list_for_each_entry_rcu(). + */ +static inline void list_add_tail_rcu(struct list_head *new, + struct list_head *head) +{ + __list_add_rcu(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = LIST_POISON1; + entry->prev = LIST_POISON2; +} + +/** + * list_del_rcu - deletes entry from list without re-initialization + * @entry: the element to delete from the list. + * + * Note: list_empty on entry does not return true after this, + * the entry is in an undefined state. It is useful for RCU based + * lockfree traversal. + * + * In particular, it means that we can not poison the forward + * pointers that may still be used for walking the list. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as list_del_rcu() + * or list_add_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * list_for_each_entry_rcu(). + * + * Note that the caller is not permitted to immediately free + * the newly deleted entry. Instead, either synchronize_kernel() + * or call_rcu() must be used to defer freeing until an RCU + * grace period has elapsed. + */ +static inline void list_del_rcu(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->prev = LIST_POISON2; +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_empty_careful - tests whether a list is + * empty _and_ checks that no other CPU might be + * in the process of still modifying either member + * + * NOTE: using list_empty_careful() without synchronization + * can only be safe if the only activity that can happen + * to the list entry is list_del_init(). Eg. it cannot be used + * if another CPU could re-list_add() it. + * + * @head: the list to test. + */ +static inline int list_empty_careful(const struct list_head *head) +{ + struct list_head *next = head->next; + return (next == head) && (next == head->prev); +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, prefetch(pos->next)) + +/** + * __list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This variant differs from list_for_each() in that it's the + * simplest possible list iteration code, no prefetching is done. + * Use this for code that knows the list to be very short (empty + * or 1 entry) most of the time. + */ +#define __list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ + pos = pos->prev, prefetch(pos->prev)) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member), \ + prefetch(pos->member.prev); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member), \ + prefetch(pos->member.prev)) + +/** + * list_prepare_entry - prepare a pos entry for use as a start point in + * list_for_each_entry_continue + * @pos: the type * to use as a start point + * @head: the head of the list + * @member: the name of the list_struct within the struct. + */ +#define list_prepare_entry(pos, head, member) \ + ((pos) ? : list_entry(head, typeof(*pos), member)) + +/** + * list_for_each_entry_continue - iterate over list of given type + * continuing after existing point + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_continue(pos, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_rcu - iterate over an rcu-protected list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_rcu(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next)) + +#define __list_for_each_rcu(pos, head) \ + for (pos = (head)->next; pos != (head); \ + pos = pos->next, ({ smp_read_barrier_depends(); 0;})) + +/** + * list_for_each_safe_rcu - iterate over an rcu-protected list safe + * against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_safe_rcu(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next) + +/** + * list_for_each_entry_rcu - iterate over rcu list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_entry_rcu(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + ({ smp_read_barrier_depends(); 0;}), \ + prefetch(pos->member.next)) + + +/** + * list_for_each_continue_rcu - iterate over an rcu-protected list + * continuing after existing point. + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_continue_rcu(pos, head) \ + for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \ + (pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next)) + +/* + * Double linked lists with a single pointer list head. + * Mostly useful for hash tables where the two pointer list head is + * too wasteful. + * You lose the ability to access the tail in O(1). + */ + +struct hlist_head { + struct hlist_node *first; +}; + +struct hlist_node { + struct hlist_node *next, **pprev; +}; + +#define HLIST_HEAD_INIT { .first = NULL } +#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } +#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) +#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL) + +static inline int hlist_unhashed(const struct hlist_node *h) +{ + return !h->pprev; +} + +static inline int hlist_empty(const struct hlist_head *h) +{ + return !h->first; +} + +static inline void __hlist_del(struct hlist_node *n) +{ + struct hlist_node *next = n->next; + struct hlist_node **pprev = n->pprev; + *pprev = next; + if (next) + next->pprev = pprev; +} + +static inline void hlist_del(struct hlist_node *n) +{ + __hlist_del(n); + n->next = LIST_POISON1; + n->pprev = LIST_POISON2; +} + +/** + * hlist_del_rcu - deletes entry from hash list without re-initialization + * @n: the element to delete from the hash list. + * + * Note: list_unhashed() on entry does not return true after this, + * the entry is in an undefined state. It is useful for RCU based + * lockfree traversal. + * + * In particular, it means that we can not poison the forward + * pointers that may still be used for walking the hash list. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as hlist_add_head_rcu() + * or hlist_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * hlist_for_each_entry(). + */ +static inline void hlist_del_rcu(struct hlist_node *n) +{ + __hlist_del(n); + n->pprev = LIST_POISON2; +} + +static inline void hlist_del_init(struct hlist_node *n) +{ + if (n->pprev) { + __hlist_del(n); + INIT_HLIST_NODE(n); + } +} + +#define hlist_del_rcu_init hlist_del_init + +static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + if (first) + first->pprev = &n->next; + h->first = n; + n->pprev = &h->first; +} + + +/** + * hlist_add_head_rcu - adds the specified element to the specified hlist, + * while permitting racing traversals. + * @n: the element to add to the hash list. + * @h: the list to add to. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as hlist_add_head_rcu() + * or hlist_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * hlist_for_each_entry(), but only if smp_read_barrier_depends() + * is used to prevent memory-consistency problems on Alpha CPUs. + * Regardless of the type of CPU, the list-traversal primitive + * must be guarded by rcu_read_lock(). + * + * OK, so why don't we have an hlist_for_each_entry_rcu()??? + */ +static inline void hlist_add_head_rcu(struct hlist_node *n, + struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + n->pprev = &h->first; + smp_wmb(); + if (first) + first->pprev = &n->next; + h->first = n; +} + +/* next must be != NULL */ +static inline void hlist_add_before(struct hlist_node *n, + struct hlist_node *next) +{ + n->pprev = next->pprev; + n->next = next; + next->pprev = &n->next; + *(n->pprev) = n; +} + +static inline void hlist_add_after(struct hlist_node *n, + struct hlist_node *next) +{ + next->next = n->next; + n->next = next; + next->pprev = &n->next; + + if(next->next) + next->next->pprev = &next->next; +} + +#define hlist_entry(ptr, type, member) container_of(ptr,type,member) + +#define hlist_for_each(pos, head) \ + for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \ + pos = pos->next) + +#define hlist_for_each_safe(pos, n, head) \ + for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ + pos = n) + +/** + * hlist_for_each_entry - iterate over list of given type + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry(tpos, pos, head, member) \ + for (pos = (head)->first; \ + pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_continue - iterate over a hlist continuing after existing point + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_continue(tpos, pos, member) \ + for (pos = (pos)->next; \ + pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_from - iterate over a hlist continuing from existing point + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_from(tpos, pos, member) \ + for (; pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @n: another &struct hlist_node to use as temporary storage + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ + for (pos = (head)->first; \ + pos && ({ n = pos->next; 1; }) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = n) + +/** + * hlist_for_each_entry_rcu - iterate over rcu list of given type + * @pos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as hlist_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define hlist_for_each_entry_rcu(tpos, pos, head, member) \ + for (pos = (head)->first; \ + pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next, ({ smp_read_barrier_depends(); 0; }) ) + +#endif diff --git a/include/internal/object.h b/include/internal/object.h new file mode 100644 index 0000000..e39a576 --- /dev/null +++ b/include/internal/object.h @@ -0,0 +1,217 @@ +/* + * WARNING: Do *NOT* ever include this file, only for internal use! + * Use the set/get API in order to set/get the conntrack attributes + */ + +#ifndef _NFCT_OBJECT_H_ +#define _NFCT_OBJECT_H_ + +/* + * nfct callback handler object + */ + +struct nfct_handle { + struct nfnl_handle *nfnlh; + struct nfnl_subsys_handle *nfnlssh_ct; + struct nfnl_subsys_handle *nfnlssh_exp; + + /* deprecated old API */ + nfct_callback callback; + void *callback_data; + nfct_handler handler; + + /* callback handler for the new API */ + struct nfnl_callback nfnl_cb; + + int (*cb)(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data); + + int (*expect_cb)(enum nf_conntrack_msg_type type, + struct nf_expect *exp, + void *data); +}; + +/* container used to pass data to nfnl callbacks */ +struct __data_container { + struct nfct_handle *h; + enum nf_conntrack_msg_type type; + void *data; +}; + +/* + * conntrack object + */ + +union __nfct_l4_src { + /* Add other protocols here. */ + u_int16_t all; + struct { + u_int16_t port; + } tcp; + struct { + u_int16_t port; + } udp; + struct { + u_int16_t id; + } icmp; + struct { + u_int16_t port; + } sctp; +}; + +union __nfct_l4_dst { + /* Add other protocols here. */ + u_int16_t all; + struct { + u_int16_t port; + } tcp; + struct { + u_int16_t port; + } udp; + struct { + u_int8_t type, code; + } icmp; + struct { + u_int16_t port; + } sctp; +}; + +union __nfct_address { + u_int32_t v4; + struct in6_addr v6; +}; + +struct __nfct_tuple { + union __nfct_address src; + union __nfct_address dst; + + u_int8_t l3protonum; + u_int8_t protonum; + union __nfct_l4_src l4src; + union __nfct_l4_dst l4dst; + + struct { + u_int32_t correction_pos; + u_int32_t offset_before; + u_int32_t offset_after; + } natseq; +}; + +#define __DIR_ORIG 0 +#define __DIR_REPL 1 +#define __DIR_MASTER 2 +#define __DIR_MAX __DIR_MASTER+1 + +union __nfct_protoinfo { + struct { + u_int8_t state; + struct { + u_int8_t value; + u_int8_t mask; + } flags[__DIR_MAX]; + } tcp; + struct { + u_int8_t state; + u_int32_t vtag[__DIR_MAX]; + } sctp; + +}; + +struct __nfct_counters { + u_int64_t packets; + u_int64_t bytes; +}; + +struct __nfct_nat { + u_int32_t min_ip, max_ip; + union __nfct_l4_src l4min, l4max; +}; + +struct nf_conntrack { + struct __nfct_tuple tuple[__DIR_MAX]; + + u_int32_t timeout; + u_int32_t mark; + u_int32_t secmark; + u_int32_t status; + u_int32_t use; + u_int32_t id; + + union __nfct_protoinfo protoinfo; + struct __nfct_counters counters[__DIR_MAX]; + struct __nfct_nat snat; + struct __nfct_nat dnat; + + u_int32_t set[2]; +}; + +/* + * conntrack filter object + */ + +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. + */ + + /* + * 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]; + + 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]; +}; + +/* + * expectation object + */ + +struct nf_expect { + struct nf_conntrack master; + struct nf_conntrack expected; + struct nf_conntrack mask; + u_int32_t timeout; + u_int32_t id; + u_int16_t expectfn_queue_id; + + u_int32_t set[1]; +}; + +#endif diff --git a/include/internal/prototypes.h b/include/internal/prototypes.h new file mode 100644 index 0000000..bab9082 --- /dev/null +++ b/include/internal/prototypes.h @@ -0,0 +1,37 @@ +#ifndef _NFCT_PROTOTYPES_H_ +#define _NFCT_PROTOTYPES_H_ + +/* + * conntrack internal prototypes + */ +int __build_conntrack(struct nfnl_subsys_handle *ssh, struct nfnlhdr *req, size_t size, u_int16_t type, u_int16_t flags, const struct nf_conntrack *ct); +void __build_tuple(struct nfnlhdr *req, size_t size, const struct __nfct_tuple *t, const int type); +int __parse_message_type(const struct nlmsghdr *nlh); +void __parse_conntrack(const struct nlmsghdr *nlh, const struct nfattr *cda[], struct nf_conntrack *ct); +void __parse_tuple(const struct nfattr *attr, struct __nfct_tuple *tuple, int dir, u_int32_t *set); +int __snprintf_conntrack(char *buf, unsigned int len, const struct nf_conntrack *ct, unsigned int type, unsigned int msg_output, unsigned int flags); +int __snprintf_address(char *buf, unsigned int len, const struct __nfct_tuple *tuple); +int __snprintf_protocol(char *buf, unsigned int len, const struct nf_conntrack *ct); +int __snprintf_proto(char *buf, unsigned int len, const struct __nfct_tuple *tuple); +int __snprintf_conntrack_default(char *buf, unsigned int len, const struct nf_conntrack *ct, const unsigned int msg_type, const unsigned int flags); +int __snprintf_conntrack_xml(char *buf, unsigned int len, const struct nf_conntrack *ct, const unsigned int msg_type, const unsigned int flags); + +int __callback(struct nlmsghdr *nlh, struct nfattr *nfa[], void *data); + +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); + +/* + * expectation internal prototypes + */ +int __build_expect(struct nfnl_subsys_handle *ssh, struct nfnlhdr *req, size_t size, u_int16_t type, u_int16_t flags, const struct nf_expect *exp); +int __parse_expect_message_type(const struct nlmsghdr *nlh); +void __parse_expect(const struct nlmsghdr *nlh, const struct nfattr *cda[], struct nf_expect *exp); +int __expect_callback(struct nlmsghdr *nlh, struct nfattr *nfa[], void *data); +int __snprintf_expect(char *buf, unsigned int len, const struct nf_expect *exp, unsigned int type, unsigned int msg_output, unsigned int flags); +int __snprintf_expect_default(char *buf, unsigned int len, const struct nf_expect *exp, unsigned int msg_type, unsigned int flags); + +#endif diff --git a/include/internal/types.h b/include/internal/types.h new file mode 100644 index 0000000..a13722c --- /dev/null +++ b/include/internal/types.h @@ -0,0 +1,21 @@ +/* + * WARNING: Do *NOT* ever include this file, only for internal use! + */ +#ifndef _NFCT_TYPES_H_ +#define _NFCT_TYPES_H_ + +/* + * conntrack types + */ +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); + +/* + * expectation types + */ +typedef void (*set_exp_attr)(struct nf_expect *exp, const void *value); +typedef const void *(*get_exp_attr)(const struct nf_expect *exp); + +#endif diff --git a/include/libnetfilter_conntrack/Makefile.am b/include/libnetfilter_conntrack/Makefile.am index 9e4a2d1..c5f762f 100644 --- a/include/libnetfilter_conntrack/Makefile.am +++ b/include/libnetfilter_conntrack/Makefile.am @@ -1,5 +1,2 @@ pkginclude_HEADERS = libnetfilter_conntrack.h linux_nfnetlink_conntrack.h libnetfilter_conntrack_tcp.h libnetfilter_conntrack_udp.h libnetfilter_conntrack_icmp.h libnetfilter_conntrack_sctp.h libnetfilter_conntrack_ipv4.h libnetfilter_conntrack_ipv6.h - -noinst_HEADERS = libnetfilter_conntrack_extensions.h \ - libnetfilter_conntrack_l3extensions.h diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack_extensions.h b/include/libnetfilter_conntrack/libnetfilter_conntrack_extensions.h deleted file mode 100644 index db7828d..0000000 --- a/include/libnetfilter_conntrack/libnetfilter_conntrack_extensions.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * (C) 2005 by Pablo Neira Ayuso - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - -#ifndef _LIBNETFILTER_CONNTRACK_EXTENSIONS_H_ -#define _LIBNETFILTER_CONNTRACK_EXTENSIONS_H_ - -/* some systems have old libc's */ -#include -#ifndef IPPROTO_SCTP -#define IPPROTO_SCTP 132 -#endif - -#include "linux_list.h" - -struct nfct_proto { - struct list_head head; - - char *name; - u_int8_t protonum; - char *version; - - void (*parse_proto)(struct nfattr **, struct nfct_tuple *); - void (*parse_protoinfo)(struct nfattr **, struct nfct_conntrack *); - void (*build_tuple_proto)(struct nfnlhdr *, int, struct nfct_tuple *); - void (*build_protoinfo)(struct nfnlhdr *, int, struct nfct_conntrack *); - int (*print_protoinfo)(char *, union nfct_protoinfo *); - int (*print_proto)(char *, struct nfct_tuple *); - int (*compare)(struct nfct_conntrack *, struct nfct_conntrack *, - unsigned int); -}; - -extern void nfct_register_proto(struct nfct_proto *h); - -#endif diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack_l3extensions.h b/include/libnetfilter_conntrack/libnetfilter_conntrack_l3extensions.h deleted file mode 100644 index 86e002a..0000000 --- a/include/libnetfilter_conntrack/libnetfilter_conntrack_l3extensions.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * (C) 2005 by Pablo Neira Ayuso - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - -#ifndef _LIBNETFILTER_CONNTRACK_L3EXTENSIONS_H_ -#define _LIBNETFILTER_CONNTRACK_L3EXTENSIONS_H_ - -#include "linux_list.h" - -struct nfct_l3proto { - struct list_head head; - - char *name; - u_int16_t protonum; - char *version; - - void (*parse_proto)(struct nfattr **, struct nfct_tuple *); - void (*build_tuple_proto)(struct nfnlhdr *, int, struct nfct_tuple *); - int (*print_proto)(char *, struct nfct_tuple *); - int (*compare)(struct nfct_conntrack *, struct nfct_conntrack *, - unsigned int); -}; - -extern void nfct_register_l3proto(struct nfct_l3proto *h); - -#endif diff --git a/include/linux_list.h b/include/linux_list.h deleted file mode 100644 index 57b56d7..0000000 --- a/include/linux_list.h +++ /dev/null @@ -1,725 +0,0 @@ -#ifndef _LINUX_LIST_H -#define _LINUX_LIST_H - -#undef offsetof -#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) - -/** - * container_of - cast a member of a structure out to the containing structure - * - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - */ -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - -/* - * Check at compile time that something is of a particular type. - * Always evaluates to 1 so you may use it easily in comparisons. - */ -#define typecheck(type,x) \ -({ type __dummy; \ - typeof(x) __dummy2; \ - (void)(&__dummy == &__dummy2); \ - 1; \ -}) - -#define prefetch(x) 1 - -/* empty define to make this work in userspace -HW */ -#ifndef smp_wmb -#define smp_wmb() -#endif - -/* - * These are non-NULL pointers that will result in page faults - * under normal circumstances, used to verify that nobody uses - * non-initialized list entries. - */ -#define LIST_POISON1 ((void *) 0x00100100) -#define LIST_POISON2 ((void *) 0x00200200) - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/** - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static inline void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_add_rcu(struct list_head * new, - struct list_head * prev, struct list_head * next) -{ - new->next = next; - new->prev = prev; - smp_wmb(); - next->prev = new; - prev->next = new; -} - -/** - * list_add_rcu - add a new entry to rcu-protected list - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - * - * The caller must take whatever precautions are necessary - * (such as holding appropriate locks) to avoid racing - * with another list-mutation primitive, such as list_add_rcu() - * or list_del_rcu(), running on this same list. - * However, it is perfectly legal to run concurrently with - * the _rcu list-traversal primitives, such as - * list_for_each_entry_rcu(). - */ -static inline void list_add_rcu(struct list_head *new, struct list_head *head) -{ - __list_add_rcu(new, head, head->next); -} - -/** - * list_add_tail_rcu - add a new entry to rcu-protected list - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - * - * The caller must take whatever precautions are necessary - * (such as holding appropriate locks) to avoid racing - * with another list-mutation primitive, such as list_add_tail_rcu() - * or list_del_rcu(), running on this same list. - * However, it is perfectly legal to run concurrently with - * the _rcu list-traversal primitives, such as - * list_for_each_entry_rcu(). - */ -static inline void list_add_tail_rcu(struct list_head *new, - struct list_head *head) -{ - __list_add_rcu(new, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_del(struct list_head * prev, struct list_head * next) -{ - next->prev = prev; - prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is - * in an undefined state. - */ -static inline void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - entry->next = LIST_POISON1; - entry->prev = LIST_POISON2; -} - -/** - * list_del_rcu - deletes entry from list without re-initialization - * @entry: the element to delete from the list. - * - * Note: list_empty on entry does not return true after this, - * the entry is in an undefined state. It is useful for RCU based - * lockfree traversal. - * - * In particular, it means that we can not poison the forward - * pointers that may still be used for walking the list. - * - * The caller must take whatever precautions are necessary - * (such as holding appropriate locks) to avoid racing - * with another list-mutation primitive, such as list_del_rcu() - * or list_add_rcu(), running on this same list. - * However, it is perfectly legal to run concurrently with - * the _rcu list-traversal primitives, such as - * list_for_each_entry_rcu(). - * - * Note that the caller is not permitted to immediately free - * the newly deleted entry. Instead, either synchronize_kernel() - * or call_rcu() must be used to defer freeing until an RCU - * grace period has elapsed. - */ -static inline void list_del_rcu(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - entry->prev = LIST_POISON2; -} - -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -static inline void list_del_init(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - INIT_LIST_HEAD(entry); -} - -/** - * list_move - delete from one list and add as another's head - * @list: the entry to move - * @head: the head that will precede our entry - */ -static inline void list_move(struct list_head *list, struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add(list, head); -} - -/** - * list_move_tail - delete from one list and add as another's tail - * @list: the entry to move - * @head: the head that will follow our entry - */ -static inline void list_move_tail(struct list_head *list, - struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add_tail(list, head); -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static inline int list_empty(const struct list_head *head) -{ - return head->next == head; -} - -/** - * list_empty_careful - tests whether a list is - * empty _and_ checks that no other CPU might be - * in the process of still modifying either member - * - * NOTE: using list_empty_careful() without synchronization - * can only be safe if the only activity that can happen - * to the list entry is list_del_init(). Eg. it cannot be used - * if another CPU could re-list_add() it. - * - * @head: the list to test. - */ -static inline int list_empty_careful(const struct list_head *head) -{ - struct list_head *next = head->next; - return (next == head) && (next == head->prev); -} - -static inline void __list_splice(struct list_head *list, - struct list_head *head) -{ - struct list_head *first = list->next; - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; -} - -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -static inline void list_splice(struct list_head *list, struct list_head *head) -{ - if (!list_empty(list)) - __list_splice(list, head); -} - -/** - * list_splice_init - join two lists and reinitialise the emptied list. - * @list: the new list to add. - * @head: the place to add it in the first list. - * - * The list at @list is reinitialised - */ -static inline void list_splice_init(struct list_head *list, - struct list_head *head) -{ - if (!list_empty(list)) { - __list_splice(list, head); - INIT_LIST_HEAD(list); - } -} - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - container_of(ptr, type, member) - -/** - * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next, prefetch(pos->next); pos != (head); \ - pos = pos->next, prefetch(pos->next)) - -/** - * __list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - * - * This variant differs from list_for_each() in that it's the - * simplest possible list iteration code, no prefetching is done. - * Use this for code that knows the list to be very short (empty - * or 1 entry) most of the time. - */ -#define __list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -/** - * list_for_each_prev - iterate over a list backwards - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each_prev(pos, head) \ - for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ - pos = pos->prev, prefetch(pos->prev)) - -/** - * list_for_each_safe - iterate over a list safe against removal of list entry - * @pos: the &struct list_head to use as a loop counter. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -/** - * list_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - prefetch(pos->member.next); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next)) - -/** - * list_for_each_entry_reverse - iterate backwards over list of given type. - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_reverse(pos, head, member) \ - for (pos = list_entry((head)->prev, typeof(*pos), member), \ - prefetch(pos->member.prev); \ - &pos->member != (head); \ - pos = list_entry(pos->member.prev, typeof(*pos), member), \ - prefetch(pos->member.prev)) - -/** - * list_prepare_entry - prepare a pos entry for use as a start point in - * list_for_each_entry_continue - * @pos: the type * to use as a start point - * @head: the head of the list - * @member: the name of the list_struct within the struct. - */ -#define list_prepare_entry(pos, head, member) \ - ((pos) ? : list_entry(head, typeof(*pos), member)) - -/** - * list_for_each_entry_continue - iterate over list of given type - * continuing after existing point - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_continue(pos, head, member) \ - for (pos = list_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next)) - -/** - * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @pos: the type * to use as a loop counter. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_safe(pos, n, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -/** - * list_for_each_rcu - iterate over an rcu-protected list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - * - * This list-traversal primitive may safely run concurrently with - * the _rcu list-mutation primitives such as list_add_rcu() - * as long as the traversal is guarded by rcu_read_lock(). - */ -#define list_for_each_rcu(pos, head) \ - for (pos = (head)->next, prefetch(pos->next); pos != (head); \ - pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next)) - -#define __list_for_each_rcu(pos, head) \ - for (pos = (head)->next; pos != (head); \ - pos = pos->next, ({ smp_read_barrier_depends(); 0;})) - -/** - * list_for_each_safe_rcu - iterate over an rcu-protected list safe - * against removal of list entry - * @pos: the &struct list_head to use as a loop counter. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - * - * This list-traversal primitive may safely run concurrently with - * the _rcu list-mutation primitives such as list_add_rcu() - * as long as the traversal is guarded by rcu_read_lock(). - */ -#define list_for_each_safe_rcu(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next) - -/** - * list_for_each_entry_rcu - iterate over rcu list of given type - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * This list-traversal primitive may safely run concurrently with - * the _rcu list-mutation primitives such as list_add_rcu() - * as long as the traversal is guarded by rcu_read_lock(). - */ -#define list_for_each_entry_rcu(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - prefetch(pos->member.next); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member), \ - ({ smp_read_barrier_depends(); 0;}), \ - prefetch(pos->member.next)) - - -/** - * list_for_each_continue_rcu - iterate over an rcu-protected list - * continuing after existing point. - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - * - * This list-traversal primitive may safely run concurrently with - * the _rcu list-mutation primitives such as list_add_rcu() - * as long as the traversal is guarded by rcu_read_lock(). - */ -#define list_for_each_continue_rcu(pos, head) \ - for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \ - (pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next)) - -/* - * Double linked lists with a single pointer list head. - * Mostly useful for hash tables where the two pointer list head is - * too wasteful. - * You lose the ability to access the tail in O(1). - */ - -struct hlist_head { - struct hlist_node *first; -}; - -struct hlist_node { - struct hlist_node *next, **pprev; -}; - -#define HLIST_HEAD_INIT { .first = NULL } -#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } -#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) -#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL) - -static inline int hlist_unhashed(const struct hlist_node *h) -{ - return !h->pprev; -} - -static inline int hlist_empty(const struct hlist_head *h) -{ - return !h->first; -} - -static inline void __hlist_del(struct hlist_node *n) -{ - struct hlist_node *next = n->next; - struct hlist_node **pprev = n->pprev; - *pprev = next; - if (next) - next->pprev = pprev; -} - -static inline void hlist_del(struct hlist_node *n) -{ - __hlist_del(n); - n->next = LIST_POISON1; - n->pprev = LIST_POISON2; -} - -/** - * hlist_del_rcu - deletes entry from hash list without re-initialization - * @n: the element to delete from the hash list. - * - * Note: list_unhashed() on entry does not return true after this, - * the entry is in an undefined state. It is useful for RCU based - * lockfree traversal. - * - * In particular, it means that we can not poison the forward - * pointers that may still be used for walking the hash list. - * - * The caller must take whatever precautions are necessary - * (such as holding appropriate locks) to avoid racing - * with another list-mutation primitive, such as hlist_add_head_rcu() - * or hlist_del_rcu(), running on this same list. - * However, it is perfectly legal to run concurrently with - * the _rcu list-traversal primitives, such as - * hlist_for_each_entry(). - */ -static inline void hlist_del_rcu(struct hlist_node *n) -{ - __hlist_del(n); - n->pprev = LIST_POISON2; -} - -static inline void hlist_del_init(struct hlist_node *n) -{ - if (n->pprev) { - __hlist_del(n); - INIT_HLIST_NODE(n); - } -} - -#define hlist_del_rcu_init hlist_del_init - -static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) -{ - struct hlist_node *first = h->first; - n->next = first; - if (first) - first->pprev = &n->next; - h->first = n; - n->pprev = &h->first; -} - - -/** - * hlist_add_head_rcu - adds the specified element to the specified hlist, - * while permitting racing traversals. - * @n: the element to add to the hash list. - * @h: the list to add to. - * - * The caller must take whatever precautions are necessary - * (such as holding appropriate locks) to avoid racing - * with another list-mutation primitive, such as hlist_add_head_rcu() - * or hlist_del_rcu(), running on this same list. - * However, it is perfectly legal to run concurrently with - * the _rcu list-traversal primitives, such as - * hlist_for_each_entry(), but only if smp_read_barrier_depends() - * is used to prevent memory-consistency problems on Alpha CPUs. - * Regardless of the type of CPU, the list-traversal primitive - * must be guarded by rcu_read_lock(). - * - * OK, so why don't we have an hlist_for_each_entry_rcu()??? - */ -static inline void hlist_add_head_rcu(struct hlist_node *n, - struct hlist_head *h) -{ - struct hlist_node *first = h->first; - n->next = first; - n->pprev = &h->first; - smp_wmb(); - if (first) - first->pprev = &n->next; - h->first = n; -} - -/* next must be != NULL */ -static inline void hlist_add_before(struct hlist_node *n, - struct hlist_node *next) -{ - n->pprev = next->pprev; - n->next = next; - next->pprev = &n->next; - *(n->pprev) = n; -} - -static inline void hlist_add_after(struct hlist_node *n, - struct hlist_node *next) -{ - next->next = n->next; - n->next = next; - next->pprev = &n->next; - - if(next->next) - next->next->pprev = &next->next; -} - -#define hlist_entry(ptr, type, member) container_of(ptr,type,member) - -#define hlist_for_each(pos, head) \ - for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \ - pos = pos->next) - -#define hlist_for_each_safe(pos, n, head) \ - for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ - pos = n) - -/** - * hlist_for_each_entry - iterate over list of given type - * @tpos: the type * to use as a loop counter. - * @pos: the &struct hlist_node to use as a loop counter. - * @head: the head for your list. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry(tpos, pos, head, member) \ - for (pos = (head)->first; \ - pos && ({ prefetch(pos->next); 1;}) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_continue - iterate over a hlist continuing after existing point - * @tpos: the type * to use as a loop counter. - * @pos: the &struct hlist_node to use as a loop counter. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_continue(tpos, pos, member) \ - for (pos = (pos)->next; \ - pos && ({ prefetch(pos->next); 1;}) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_from - iterate over a hlist continuing from existing point - * @tpos: the type * to use as a loop counter. - * @pos: the &struct hlist_node to use as a loop counter. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_from(tpos, pos, member) \ - for (; pos && ({ prefetch(pos->next); 1;}) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next) - -/** - * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @tpos: the type * to use as a loop counter. - * @pos: the &struct hlist_node to use as a loop counter. - * @n: another &struct hlist_node to use as temporary storage - * @head: the head for your list. - * @member: the name of the hlist_node within the struct. - */ -#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ - for (pos = (head)->first; \ - pos && ({ n = pos->next; 1; }) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = n) - -/** - * hlist_for_each_entry_rcu - iterate over rcu list of given type - * @pos: the type * to use as a loop counter. - * @pos: the &struct hlist_node to use as a loop counter. - * @head: the head for your list. - * @member: the name of the hlist_node within the struct. - * - * This list-traversal primitive may safely run concurrently with - * the _rcu list-mutation primitives such as hlist_add_rcu() - * as long as the traversal is guarded by rcu_read_lock(). - */ -#define hlist_for_each_entry_rcu(tpos, pos, head, member) \ - for (pos = (head)->first; \ - pos && ({ prefetch(pos->next); 1;}) && \ - ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = pos->next, ({ smp_read_barrier_depends(); 0; }) ) - -#endif -- cgit v1.2.3