diff options
Diffstat (limited to 'kernel/include/linux/netfilter/ipset')
4 files changed, 295 insertions, 23 deletions
diff --git a/kernel/include/linux/netfilter/ipset/ip_set.h b/kernel/include/linux/netfilter/ipset/ip_set.h index 3949e32..7691b7a 100644 --- a/kernel/include/linux/netfilter/ipset/ip_set.h +++ b/kernel/include/linux/netfilter/ipset/ip_set.h @@ -99,7 +99,7 @@ struct ip_set_counter { struct ip_set_comment_rcu { struct rcu_head rcu; - char str[0]; + char str[]; }; struct ip_set_comment { @@ -122,6 +122,7 @@ struct ip_set_ext { u32 timeout; u8 packets_op; u8 bytes_op; + bool target; }; struct ip_set; @@ -188,8 +189,24 @@ struct ip_set_type_variant { /* Return true if "b" set is the same as "a" * according to the create set parameters */ bool (*same_set)(const struct ip_set *a, const struct ip_set *b); + /* Cancel ongoing garbage collectors before destroying the set*/ + void (*cancel_gc)(struct ip_set *set); + /* Region-locking is used */ + bool region_lock; }; +struct ip_set_region { + spinlock_t lock; /* Region lock */ + size_t ext_size; /* Size of the dynamic extensions */ + u32 elements; /* Number of elements vs timeout */ +}; + +/* Max range where every element is added/deleted in one step */ +#define IPSET_MAX_RANGE (1<<14) + +/* The max revision number supported by any set type + 1 */ +#define IPSET_REVISION_MAX 9 + /* The core set type structure */ struct ip_set_type { struct list_head list; @@ -207,6 +224,8 @@ struct ip_set_type { u8 family; /* Type revisions */ u8 revision_min, revision_max; + /* Revision-specific supported (create) flags */ + u8 create_flags[IPSET_REVISION_MAX+1]; /* Set features to control swapping */ u16 features; @@ -228,6 +247,8 @@ extern void ip_set_type_unregister(struct ip_set_type *set_type); /* A generic IP set */ struct ip_set { + /* For call_cru in destroy */ + struct rcu_head rcu; /* The name of the set */ char name[IPSET_MAXNAMELEN]; /* Lock protecting the set data */ @@ -437,13 +458,6 @@ ip6addrptr(const struct sk_buff *skb, bool src, struct in6_addr *addr) sizeof(*addr)); } -/* Calculate the bytes required to store the inclusive range of a-b */ -static inline int -bitmap_bytes(u32 a, u32 b) -{ - return 4 * ((((b - a + 8) / 8) + 3) / 4); -} - /* How often should the gc be run by default */ #define IPSET_GC_TIME (3 * 60) @@ -518,8 +532,18 @@ ip_set_init_skbinfo(struct ip_set_skbinfo *skbinfo, *skbinfo = ext->skbinfo; } +static inline void +nf_inet_addr_mask_inplace(union nf_inet_addr *a1, + const union nf_inet_addr *mask) +{ + a1->all[0] &= mask->all[0]; + a1->all[1] &= mask->all[1]; + a1->all[2] &= mask->all[2]; + a1->all[3] &= mask->all[3]; +} + #define IP_SET_INIT_KEXT(skb, opt, set) \ - { .bytes = (skb)->len, .packets = 1, \ + { .bytes = (skb)->len, .packets = 1, .target = true,\ .timeout = ip_set_adt_opt_timeout(opt, set) } #define IP_SET_INIT_UEXT(set) \ diff --git a/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in b/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in index 5f12ad8..3a0e0b4 100644 --- a/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in +++ b/kernel/include/linux/netfilter/ipset/ip_set_compat.h.in @@ -5,6 +5,8 @@ * xt_set.c, ip_set_core.c, ip_set_getport.c, pfxlen.c too. */ +#@HAVE_INIT_DEFERRABLE_WORK@ HAVE_INIT_DEFERRABLE_WORK +#@HAVE_SYSTEM_POWER_EFFICIENT_WQ@ HAVE_SYSTEM_POWER_EFFICIENT_WQ #@HAVE_STRUCT_XT_ACTION_PARAM@ HAVE_STRUCT_XT_ACTION_PARAM #@HAVE_VZALLOC@ HAVE_VZALLOC #@HAVE_ETHER_ADDR_EQUAL@ HAVE_ETHER_ADDR_EQUAL @@ -26,6 +28,8 @@ #@HAVE_RBTREE_POSTORDER_FOR_EACH_ENTRY_SAFE@ HAVE_RBTREE_POSTORDER_FOR_EACH_ENTRY_SAFE #@HAVE_KVCALLOC@ HAVE_KVCALLOC #@HAVE_KVFREE@ HAVE_KVFREE +#@HAVE_BITMAP_ZALLOC@ HAVE_BITMAP_ZALLOC +#@HAVE_BITMAP_ZERO@ HAVE_BITMAP_ZERO #@HAVE_XT_MTCHK_PARAM_STRUCT_NET@ HAVE_XT_MTCHK_PARAM_STRUCT_NET #@HAVE_TCF_EMATCH_OPS_CHANGE_ARG_NET@ HAVE_TCF_EMATCH_OPS_CHANGE_ARG_NET #@HAVE_TCF_EMATCH_STRUCT_NET@ HAVE_TCF_EMATCH_STRUCT_NET @@ -47,9 +51,26 @@ #@HAVE_PASSING_EXTENDED_ACK_TO_CALLBACKS@ HAVE_PASSING_EXTENDED_ACK_TO_CALLBACKS #@HAVE_TYPEDEF_SCTP_SCTPHDR_T@ HAVE_TYPEDEF_SCTP_SCTPHDR_T #@HAVE_TIMER_SETUP@ HAVE_TIMER_SETUP +#@HAVE_TIMER_SHUTDOWN_SYNC@ HAVE_TIMER_SHUTDOWN_SYNC #@HAVE_STRSCPY@ HAVE_STRSCPY +#@HAVE_STRSCPY_PAD@ HAVE_STRSCPY_PAD #@HAVE_SYNCHRONIZE_RCU_BH@ HAVE_SYNCHRONIZE_RCU_BH #@HAVE_LOCKDEP_NFNL_IS_HELD@ HAVE_LOCKDEP_NFNL_IS_HELD +#@HAVE_COND_RESCHED_RCU@ HAVE_COND_RESCHED_RCU +#@HAVE_SKB_IIF@ HAVE_SKB_IIF +#@HAVE_LIST_FOR_EACH_ENTRY_RCU_FOUR_ARGS@ HAVE_LIST_FOR_EACH_ENTRY_RCU_FOUR_ARGS +#@HAVE_SKB_PROTOCOL@ HAVE_SKB_PROTOCOL +#@HAVE_NLA_POLICY_EXACT_LEN@ HAVE_NLA_POLICY_EXACT_LEN +#@HAVE_KVZALLOC@ HAVE_KVZALLOC +#@HAVE_GFP_KERNEL_ACCOUNT@ HAVE_GFP_KERNEL_ACCOUNT +#@HAVE_NLA_STRSCPY@ HAVE_NLA_STRSCPY +#@HAVE_NFNL_MSG_PUT@ HAVE_NFNL_MSG_PUT +#@HAVE_NFNL_INFO_IN_NFNL_CALLBACK@ HAVE_NFNL_INFO_IN_NFNL_CALLBACK +#@HAVE_NFNL_CALLBACK_TYPE@ HAVE_NFNL_CALLBACK_TYPE +#@HAVE_EAGAIN_IN_NFNETLINK_UNICAST@ HAVE_EAGAIN_IN_NFNETLINK_UNICAST +#@HAVE_NLMSG_UNICAST@ HAVE_NLMSG_UNICAST +#@HAVE_NF_BRIDGE_GET_PYSINDEV_NET@ HAVE_NF_BRIDGE_GET_PYSINDEV_NET +#@HAVE_RCUPDATE_WAIT_H@ HAVE_RCUPDATE_WAIT_H #ifdef HAVE_EXPORT_SYMBOL_GPL_IN_MODULE_H #include <linux/module.h> @@ -148,11 +169,32 @@ do { \ #endif #endif +#ifndef HAVE_RCUPDATE_WAIT_H +#ifndef HAVE_COND_RESCHED_RCU +static inline void cond_resched_rcu(void) +{ +#if defined(CONFIG_DEBUG_ATOMIC_SLEEP) || !defined(CONFIG_PREEMPT_RCU) + rcu_read_unlock(); + cond_resched(); + rcu_read_lock(); +#endif +} +#endif +#endif + #if defined(CONFIG_NETFILTER_NETLINK) || defined(CONFIG_NETFILTER_NETLINK_MODULE) #else #error "NETFILTER_NETLINK must be enabled: select NFACCT/NFQUEUE/LOG over NFNETLINK" #endif +#ifndef HAVE_INIT_DEFERRABLE_WORK +#define INIT_DEFERRABLE_WORK INIT_DELAYED_WORK_DEFERRABLE +#endif + +#ifndef HAVE_SYSTEM_POWER_EFFICIENT_EQ +#define system_power_efficient_wq system_wq +#endif + #ifndef HAVE_STRUCT_XT_ACTION_PARAM #define xt_action_param xt_match_param #endif @@ -240,6 +282,16 @@ static inline void kvfree(const void *addr) } #endif +#ifndef HAVE_BITMAP_ZALLOC +#define bitmap_zalloc(nbits, flags) \ + kmalloc(BITS_TO_LONGS(nbits) * sizeof(unsigned long), (flags) | __GFP_ZERO) +#endif + +#ifndef HAVE_BITMAP_ZERO +#define bitmap_zero(dst, nbits) \ + memset(dst, 0, BITS_TO_LONGS(nbits) * sizeof(unsigned long)) +#endif + #ifndef HAVE_NLA_PUT_BE16 static inline int nla_put_be16(struct sk_buff *skb, int attrtype, __be16 value) { @@ -307,29 +359,72 @@ static inline int nla_put_in6_addr(struct sk_buff *skb, int attrtype, } #endif -#ifdef HAVE_PASSING_EXTENDED_ACK_TO_CALLBACKS -#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e) fn(net, nl, skb, nlh, cda, e) -#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e) fn(net, nl, skb, ad, nlh, cda, e) -#define IPSET_SOCK_NET(net, ctnl) net +#ifdef HAVE_NFNL_INFO_IN_NFNL_CALLBACK +#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e, i) fn(skb, i, cda) +#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e, i) fn(net, nl, skb, ad, nlh, cda, i) +#define IPSET_SOCK_NET(n, ctnl, i) (i)->net +#define INFO_NLH(i, n) (i)->nlh +#define INFO_NET(i, n) (i)->net +#define INFO_SK(i, n) (i)->sk +#define CALL_AD(net, ctnl, skb, set, tb, adt, flags, l) call_ad(net, ctnl, skb, set, tb, adt, flags, l) +#elif defined(HAVE_PASSING_EXTENDED_ACK_TO_CALLBACKS) +#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e, i) fn(net, nl, skb, nlh, cda, e) +#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e, i) fn(net, nl, skb, ad, nlh, cda, e) +#define IPSET_SOCK_NET(net, ctnl, i) net +#define INFO_NLH(i, n) n +#define INFO_NET(i, n) n +#define INFO_SK(i, n) n +#define CALL_AD(net, ctnl, skb, set, tb, adt, flags, l) call_ad(net, ctnl, skb, set, tb, adt, flags, l) #elif defined(HAVE_NET_IN_NFNL_CALLBACK_FN) -#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e) fn(net, nl, skb, nlh, cda) -#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e) fn(net, nl, skb, ad, nlh, cda) -#define IPSET_SOCK_NET(net, ctnl) net +#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e, i) fn(net, nl, skb, nlh, cda) +#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e, i) fn(net, nl, skb, ad, nlh, cda) +#define IPSET_SOCK_NET(net, ctnl, i) net +#define INFO_NLH(i, n) n +#define INFO_NET(i, n) n +#define INFO_SK(i, n) n +#define CALL_AD(net, ctnl, skb, set, tb, adt, flags, l) call_ad(net, ctnl, skb, set, tb, adt, flags, l) +#else +#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e, i) fn(nl, skb, nlh, cda) +#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e, i) fn(nl, skb, ad, nlh, cda) +#define IPSET_SOCK_NET(net, ctnl, i) sock_net(ctnl) +#define INFO_NLH(i, n) n +#define INFO_NET(i, n) n +#define INFO_SK(i, n) n +#define CALL_AD(net, ctnl, skb, set, tb, adt, flags, l) call_ad(ctnl, skb, set, tb, adt, flags, l) +#endif + +#ifdef HAVE_NFNL_CALLBACK_TYPE +#define SET_NFNL_CALLBACK_TYPE(t) .type = t, #else -#define IPSET_CBFN(fn, net, nl, skb, nlh, cda, e) fn(nl, skb, nlh, cda) -#define IPSET_CBFN_AD(fn, net, nl, skb, ad, nlh, cda, e) fn(nl, skb, ad, nlh, cda) -#define IPSET_SOCK_NET(net, ctnl) sock_net(ctnl) +#define SET_NFNL_CALLBACK_TYPE(t) #endif #ifndef HAVE_TC_SKB_PROTOCOL #include <linux/if_vlan.h> -static inline __be16 tc_skb_protocol(const struct sk_buff *skb) + +/* RHEL defines it */ +#ifndef skb_vlan_tag_present +#if !defined(vlan_tx_tag_present) && \ + !defined(NETIF_F_HW_VLAN_TX) && \ + !defined(NETIF_F_HW_VLAN_CTAG_TX) +#define vlan_tx_tag_present(skb) 0 +#endif +#define skb_vlan_tag_present vlan_tx_tag_present +#endif + +#ifndef HAVE_SKB_PROTOCOL +static inline __be16 skb_protocol(const struct sk_buff *skb, bool skip_vlan) { - if (vlan_tx_tag_present(skb)) + if (skb_vlan_tag_present(skb)) +#ifdef HAVE_VLAN_PROTO_IN_SK_BUFF return skb->vlan_proto; +#else + return htons(ETH_P_8021Q); +#endif return skb->protocol; } #endif +#endif #ifdef HAVE_XT_NET #define IPSET_DEV_NET(par) xt_net(par) @@ -346,6 +441,36 @@ static inline u16 nfnl_msg_type(u8 subsys, u8 msg_type) } #endif +#ifndef HAVE_NFNL_MSG_PUT +#include <linux/netfilter/nfnetlink.h> +static inline void nfnl_fill_hdr(struct nlmsghdr *nlh, u8 family, u8 version, + __be16 res_id) +{ + struct nfgenmsg *nfmsg; + + nfmsg = nlmsg_data(nlh); + nfmsg->nfgen_family = family; + nfmsg->version = version; + nfmsg->res_id = res_id; +} + +static inline struct nlmsghdr *nfnl_msg_put(struct sk_buff *skb, u32 portid, + u32 seq, int type, int flags, + u8 family, u8 version, + __be16 res_id) +{ + struct nlmsghdr *nlh; + + nlh = nlmsg_put(skb, portid, seq, type, sizeof(struct nfgenmsg), flags); + if (!nlh) + return NULL; + + nfnl_fill_hdr(nlh, family, version, res_id); + + return nlh; +} +#endif + #ifdef HAVE_NETLINK_EXTENDED_ACK #define NETLINK_ACK(in_skb, nlh, err, extack) netlink_ack(in_skb, nlh, err, extack) #else @@ -386,8 +511,53 @@ static inline u16 nfnl_msg_type(u8 subsys, u8 msg_type) struct type *var = set->data #endif +#ifndef HAVE_TIMER_SHUTDOWN_SYNC +#define timer_shutdown_sync(timer) del_timer_sync(timer) +#endif + #ifndef HAVE_STRSCPY -#define strscpy(dst, src, n) (strncpy(dst, src, n) == (dst)) +static inline ssize_t strscpy(char * dest, const char * src, size_t count) +{ + size_t ret = strlcpy(dest, src, count); + + return (ret >= count ? -E2BIG : ret); +} +#endif + +#ifndef HAVE_STRSCPY_PAD +static inline ssize_t strscpy_pad(char *dest, const char *src, size_t count) +{ + ssize_t written; + + written = strscpy(dest, src, count); + if (written < 0 || written == count - 1) + return written; + + memset(dest + written + 1, 0, count - written - 1); + + return written; +} +#endif + +#ifndef HAVE_NLA_STRSCPY +#define nla_strscpy nla_strlcpy +#endif + +#if !defined(HAVE_EAGAIN_IN_NFNETLINK_UNICAST) || !defined(HAVE_NLMSG_UNICAST) +#define NFNETLINK_UNICAST(cntl, skb, net, portid) ipset_nfnetlink_unicast(cntl, skb, portid) +static inline int ipset_nfnetlink_unicast(struct sock *ctnl, struct sk_buff *skb, u32 portid) +{ + int err = netlink_unicast(ctnl, skb, portid, MSG_DONTWAIT); + + if (err > 0) + err = 0; + if (err == -EAGAIN) + err = -ENOBUFS; + + return err; +} +#else +#define NFNETLINK_UNICAST(cntl, skb, net, portid) nfnetlink_unicast(skb, net, portid) #endif #ifndef smp_mb__before_atomic @@ -403,5 +573,68 @@ static inline u16 nfnl_msg_type(u8 subsys, u8 msg_type) #define SIZE_MAX (~(size_t)0) #endif +#ifndef TCF_EM_IPSET +#define TCF_EM_IPSET 8 +#endif + +#ifndef HAVE_SKB_IIF +#define skb_iif iif +#endif + +#ifndef HAVE_DEV_GET_BY_INDEX_RCU +/* This should not be considered RCU-safe on all architectures. + * You probably should consider upgrading your kernel in case of + * kernel crashes including em_ipset and this function call. + */ +#define dev_get_by_index_rcu __dev_get_by_index +#endif + +#ifdef HAVE_LIST_FOR_EACH_ENTRY_RCU_FOUR_ARGS +#define list_for_each_entry_rcu_compat(pos, head, member, cond) \ + list_for_each_entry_rcu(pos, head, member, cond) +#else +#define list_for_each_entry_rcu_compat(pos, head, member, cond) \ + list_for_each_entry_rcu(pos, head, member) +#endif + +#ifndef HAVE_NLA_POLICY_EXACT_LEN +#define NLA_POLICY_EXACT_LEN(_len) { \ + .type = NLA_UNSPEC, \ + .len = _len \ +} +#endif + +#ifndef HAVE_KVZALLOC +#include <linux/slab.h> +#include <linux/vmalloc.h> +#ifndef GFP_KERNEL_ACCOUNT +#define GFP_KERNEL_ACCOUNT GFP_KERNEL +#endif +static inline void *kvzalloc(size_t size, gfp_t flags) +{ + void *members = NULL; + + if (size < KMALLOC_MAX_SIZE) + members = kzalloc(size, GFP_KERNEL | __GFP_NOWARN); + + if (members) { + pr_debug("%p: allocated with kmalloc\n", members); + return members; + } + + members = vzalloc(size); + if (!members) + return NULL; + pr_debug("%p: allocated with vmalloc\n", members); + + return members; +} +#endif + +#ifndef unsafe_memcpy +#define unsafe_memcpy(dst, src, bytes, justification) \ + memcpy(dst, src, bytes) +#endif + #endif /* IP_SET_COMPAT_HEADERS */ #endif /* __IP_SET_COMPAT_H */ diff --git a/kernel/include/linux/netfilter/ipset/ip_set_compiler.h.in b/kernel/include/linux/netfilter/ipset/ip_set_compiler.h.in new file mode 100644 index 0000000..1b392f8 --- /dev/null +++ b/kernel/include/linux/netfilter/ipset/ip_set_compiler.h.in @@ -0,0 +1,15 @@ +#ifndef __IP_SET_COMPILER_H +#define __IP_SET_COMPILER_H + +/* Compiler attributes */ +#ifndef __has_attribute +# define __has_attribute(x) __GCC4_has_attribute_##x +# define __GCC4_has_attribute___fallthrough__ 0 +#endif + +#if __has_attribute(__fallthrough__) +# define fallthrough __attribute__((__fallthrough__)) +#else +# define fallthrough do {} while (0) /* fallthrough */ +#endif +#endif /* __IP_SET_COMPILER_H */ diff --git a/kernel/include/linux/netfilter/ipset/ip_set_getport.h b/kernel/include/linux/netfilter/ipset/ip_set_getport.h index 09c5a96..83b88f1 100644 --- a/kernel/include/linux/netfilter/ipset/ip_set_getport.h +++ b/kernel/include/linux/netfilter/ipset/ip_set_getport.h @@ -4,7 +4,7 @@ #include <linux/skbuff.h> #include <linux/types.h> -#include <uapi/linux/in.h> +#include <linux/in.h> extern bool ip_set_get_ip4_port(const struct sk_buff *skb, bool src, __be16 *port, u8 *proto); |