Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next

Pablo Neira Ayuso says:

====================
Netfilter/IPVS updates for net-next

The following patchset contains a large Netfilter update for net-next,
to summarise:

1) Add support for stateful objects. This series provides a nf_tables
native alternative to the extended accounting infrastructure for
nf_tables. Two initial stateful objects are supported: counters and
quotas. Objects are identified by a user-defined name, you can fetch
and reset them anytime. You can also use a maps to allow fast lookups
using any arbitrary key combination. More info at:

http://marc.info/?l=netfilter-devel&m=148029128323837&w=2

2) On-demand registration of nf_conntrack and defrag hooks per netns.
Register nf_conntrack hooks if we have a stateful ruleset, ie.
state-based filtering or NAT. The new nf_conntrack_default_on sysctl
enables this from newly created netnamespaces. Default behaviour is not
modified. Patches from Florian Westphal.

3) Allocate 4k chunks and then use these for x_tables counter allocation
requests, this improves ruleset load time and also datapath ruleset
evaluation, patches from Florian Westphal.

4) Add support for ebpf to the existing x_tables bpf extension.
From Willem de Bruijn.

5) Update layer 4 checksum if any of the pseudoheader fields is updated.
This provides a limited form of 1:1 stateless NAT that make sense in
specific scenario, eg. load balancing.

6) Add support to flush sets in nf_tables. This series comes with a new
set->ops->deactivate_one() indirection given that we have to walk
over the list of set elements, then deactivate them one by one.
The existing set->ops->deactivate() performs an element lookup that
we don't need.

7) Two patches to avoid cloning packets, thus speed up packet forwarding
via nft_fwd from ingress. From Florian Westphal.

8) Two IPVS patches via Simon Horman: Decrement ttl in all modes to
prevent infinite loops, patch from Dwip Banerjee. And one minor
refactoring from Gao feng.

9) Revisit recent log support for nf_tables netdev families: One patch
to ensure that we correctly handle non-ethernet packets. Another
patch to add missing logger definition for netdev. Patches from
Liping Zhang.

10) Three patches for nft_fib, one to address insufficient register
initialization and another to solve incorrect (although harmless)
byteswap operation. Moreover update xt_rpfilter and nft_fib to match
lbcast packets with zeronet as source, eg. DHCP Discover packets
(0.0.0.0 -> 255.255.255.255). Also from Liping Zhang.

11) Built-in DCCP, SCTP and UDPlite conntrack and NAT support, from
Davide Caratti. While DCCP is rather hopeless lately, and UDPlite has
been broken in many-cast mode for some little time, let's give them a
chance by placing them at the same level as other existing protocols.
Thus, users don't explicitly have to modprobe support for this and
NAT rules work for them. Some people point to the lack of support in
SOHO Linux-based routers that make deployment of new protocols harder.
I guess other middleboxes outthere on the Internet are also to blame.
Anyway, let's see if this has any impact in the midrun.

12) Skip software SCTP software checksum calculation if the NIC comes
with SCTP checksum offload support. From Davide Caratti.

13) Initial core factoring to prepare conversion to hook array. Three
patches from Aaron Conole.

14) Gao Feng made a wrong conversion to switch in the xt_multiport
extension in a patch coming in the previous batch. Fix it in this
batch.

15) Get vmalloc call in sync with kmalloc flags to avoid a warning
and likely OOM killer intervention from x_tables. From Marcelo
Ricardo Leitner.

16) Update Arturo Borrero's email address in all source code headers.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+2534 -682
+11
Documentation/networking/nf_conntrack-sysctl.txt
··· 96 96 Size of connection tracking table. Default value is 97 97 nf_conntrack_buckets value * 4. 98 98 99 + nf_conntrack_default_on - BOOLEAN 100 + 0 - don't register conntrack in new net namespaces 101 + 1 - register conntrack in new net namespaces (default) 102 + 103 + This controls wheter newly created network namespaces have connection 104 + tracking enabled by default. It will be enabled automatically 105 + regardless of this setting if the new net namespace requires 106 + connection tracking, e.g. when NAT rules are created. 107 + This setting is only visible in initial user namespace, it has no 108 + effect on existing namespaces. 109 + 99 110 nf_conntrack_tcp_be_liberal - BOOLEAN 100 111 0 - disabled (default) 101 112 not 0 - enabled
+30 -1
include/linux/netfilter.h
··· 75 75 76 76 struct nf_hook_entry { 77 77 struct nf_hook_entry __rcu *next; 78 - struct nf_hook_ops ops; 78 + nf_hookfn *hook; 79 + void *priv; 79 80 const struct nf_hook_ops *orig_ops; 80 81 }; 82 + 83 + static inline void 84 + nf_hook_entry_init(struct nf_hook_entry *entry, const struct nf_hook_ops *ops) 85 + { 86 + entry->next = NULL; 87 + entry->hook = ops->hook; 88 + entry->priv = ops->priv; 89 + entry->orig_ops = ops; 90 + } 91 + 92 + static inline int 93 + nf_hook_entry_priority(const struct nf_hook_entry *entry) 94 + { 95 + return entry->orig_ops->priority; 96 + } 97 + 98 + static inline int 99 + nf_hook_entry_hookfn(const struct nf_hook_entry *entry, struct sk_buff *skb, 100 + struct nf_hook_state *state) 101 + { 102 + return entry->hook(entry->priv, skb, state); 103 + } 104 + 105 + static inline const struct nf_hook_ops * 106 + nf_hook_entry_ops(const struct nf_hook_entry *entry) 107 + { 108 + return entry->orig_ops; 109 + } 81 110 82 111 static inline void nf_hook_state_init(struct nf_hook_state *p, 83 112 unsigned int hook,
+1 -1
include/linux/netfilter/nf_conntrack_dccp.h
··· 25 25 #define CT_DCCP_ROLE_MAX (__CT_DCCP_ROLE_MAX - 1) 26 26 27 27 #ifdef __KERNEL__ 28 - #include <net/netfilter/nf_conntrack_tuple.h> 28 + #include <linux/netfilter/nf_conntrack_tuple_common.h> 29 29 30 30 struct nf_ct_dccp { 31 31 u_int8_t role[IP_CT_DIR_MAX];
+7 -31
include/linux/netfilter/x_tables.h
··· 403 403 return ret; 404 404 } 405 405 406 + struct xt_percpu_counter_alloc_state { 407 + unsigned int off; 408 + const char __percpu *mem; 409 + }; 406 410 407 - /* On SMP, ip(6)t_entry->counters.pcnt holds address of the 408 - * real (percpu) counter. On !SMP, its just the packet count, 409 - * so nothing needs to be done there. 410 - * 411 - * xt_percpu_counter_alloc returns the address of the percpu 412 - * counter, or 0 on !SMP. We force an alignment of 16 bytes 413 - * so that bytes/packets share a common cache line. 414 - * 415 - * Hence caller must use IS_ERR_VALUE to check for error, this 416 - * allows us to return 0 for single core systems without forcing 417 - * callers to deal with SMP vs. NONSMP issues. 418 - */ 419 - static inline unsigned long xt_percpu_counter_alloc(void) 420 - { 421 - if (nr_cpu_ids > 1) { 422 - void __percpu *res = __alloc_percpu(sizeof(struct xt_counters), 423 - sizeof(struct xt_counters)); 424 - 425 - if (res == NULL) 426 - return -ENOMEM; 427 - 428 - return (__force unsigned long) res; 429 - } 430 - 431 - return 0; 432 - } 433 - static inline void xt_percpu_counter_free(u64 pcnt) 434 - { 435 - if (nr_cpu_ids > 1) 436 - free_percpu((void __percpu *) (unsigned long) pcnt); 437 - } 411 + bool xt_percpu_counter_alloc(struct xt_percpu_counter_alloc_state *state, 412 + struct xt_counters *counter); 413 + void xt_percpu_counter_free(struct xt_counters *cnt); 438 414 439 415 static inline struct xt_counters * 440 416 xt_get_this_cpu_counter(struct xt_counters *cnt)
+6 -1
include/linux/netfilter_ingress.h
··· 19 19 { 20 20 struct nf_hook_entry *e = rcu_dereference(skb->dev->nf_hooks_ingress); 21 21 struct nf_hook_state state; 22 + int ret; 22 23 23 24 /* Must recheck the ingress hook head, in the event it became NULL 24 25 * after the check in nf_hook_ingress_active evaluated to true. ··· 30 29 nf_hook_state_init(&state, NF_NETDEV_INGRESS, 31 30 NFPROTO_NETDEV, skb->dev, NULL, NULL, 32 31 dev_net(skb->dev), NULL); 33 - return nf_hook_slow(skb, &state, e); 32 + ret = nf_hook_slow(skb, &state, e); 33 + if (ret == 0) 34 + return -1; 35 + 36 + return ret; 34 37 } 35 38 36 39 static inline void nf_hook_ingress_init(struct net_device *dev)
+9
include/net/netfilter/ipv4/nf_conntrack_ipv4.h
··· 15 15 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4; 16 16 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4; 17 17 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp; 18 + #ifdef CONFIG_NF_CT_PROTO_DCCP 19 + extern struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4; 20 + #endif 21 + #ifdef CONFIG_NF_CT_PROTO_SCTP 22 + extern struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4; 23 + #endif 24 + #ifdef CONFIG_NF_CT_PROTO_UDPLITE 25 + extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4; 26 + #endif 18 27 19 28 int nf_conntrack_ipv4_compat_init(void); 20 29 void nf_conntrack_ipv4_compat_fini(void);
+2 -1
include/net/netfilter/ipv4/nf_defrag_ipv4.h
··· 1 1 #ifndef _NF_DEFRAG_IPV4_H 2 2 #define _NF_DEFRAG_IPV4_H 3 3 4 - void nf_defrag_ipv4_enable(void); 4 + struct net; 5 + int nf_defrag_ipv4_enable(struct net *); 5 6 6 7 #endif /* _NF_DEFRAG_IPV4_H */
+9
include/net/netfilter/ipv6/nf_conntrack_ipv6.h
··· 6 6 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6; 7 7 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6; 8 8 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6; 9 + #ifdef CONFIG_NF_CT_PROTO_DCCP 10 + extern struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6; 11 + #endif 12 + #ifdef CONFIG_NF_CT_PROTO_SCTP 13 + extern struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6; 14 + #endif 15 + #ifdef CONFIG_NF_CT_PROTO_UDPLITE 16 + extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6; 17 + #endif 9 18 10 19 #include <linux/sysctl.h> 11 20 extern struct ctl_table nf_ct_ipv6_sysctl_table[];
+2 -1
include/net/netfilter/ipv6/nf_defrag_ipv6.h
··· 1 1 #ifndef _NF_DEFRAG_IPV6_H 2 2 #define _NF_DEFRAG_IPV6_H 3 3 4 - void nf_defrag_ipv6_enable(void); 4 + struct net; 5 + int nf_defrag_ipv6_enable(struct net *); 5 6 6 7 int nf_ct_frag6_init(void); 7 8 void nf_ct_frag6_cleanup(void);
+4
include/net/netfilter/nf_conntrack.h
··· 181 181 int nf_ct_l3proto_try_module_get(unsigned short l3proto); 182 182 void nf_ct_l3proto_module_put(unsigned short l3proto); 183 183 184 + /* load module; enable/disable conntrack in this namespace */ 185 + int nf_ct_netns_get(struct net *net, u8 nfproto); 186 + void nf_ct_netns_put(struct net *net, u8 nfproto); 187 + 184 188 /* 185 189 * Allocate a hashtable of hlist_head (if nulls == 0), 186 190 * or hlist_nulls_head (if nulls == 1)
+13 -3
include/net/netfilter/nf_conntrack_l3proto.h
··· 52 52 int (*tuple_to_nlattr)(struct sk_buff *skb, 53 53 const struct nf_conntrack_tuple *t); 54 54 55 + /* Called when netns wants to use connection tracking */ 56 + int (*net_ns_get)(struct net *); 57 + void (*net_ns_put)(struct net *); 58 + 55 59 /* 56 60 * Calculate size of tuple nlattr 57 61 */ ··· 67 63 68 64 size_t nla_size; 69 65 70 - /* Init l3proto pernet data */ 71 - int (*init_net)(struct net *net); 72 - 73 66 /* Module (if any) which this is connected to. */ 74 67 struct module *me; 75 68 }; 76 69 77 70 extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX]; 78 71 72 + #ifdef CONFIG_SYSCTL 79 73 /* Protocol pernet registration. */ 80 74 int nf_ct_l3proto_pernet_register(struct net *net, 81 75 struct nf_conntrack_l3proto *proto); 76 + #else 77 + static inline int nf_ct_l3proto_pernet_register(struct net *n, 78 + struct nf_conntrack_l3proto *p) 79 + { 80 + return 0; 81 + } 82 + #endif 83 + 82 84 void nf_ct_l3proto_pernet_unregister(struct net *net, 83 85 struct nf_conntrack_l3proto *proto); 84 86
+1
include/net/netfilter/nf_dup_netdev.h
··· 2 2 #define _NF_DUP_NETDEV_H_ 3 3 4 4 void nf_dup_netdev_egress(const struct nft_pktinfo *pkt, int oif); 5 + void nf_fwd_netdev_egress(const struct nft_pktinfo *pkt, int oif); 5 6 6 7 #endif
+3 -1
include/net/netfilter/nf_log.h
··· 109 109 const struct net_device *out, 110 110 const struct nf_loginfo *loginfo, 111 111 const char *prefix); 112 - void nf_log_l2packet(struct net *net, u_int8_t pf, unsigned int hooknum, 112 + void nf_log_l2packet(struct net *net, u_int8_t pf, 113 + __be16 protocol, 114 + unsigned int hooknum, 113 115 const struct sk_buff *skb, 114 116 const struct net_device *in, 115 117 const struct net_device *out,
+9
include/net/netfilter/nf_nat_l4proto.h
··· 54 54 extern const struct nf_nat_l4proto nf_nat_l4proto_icmp; 55 55 extern const struct nf_nat_l4proto nf_nat_l4proto_icmpv6; 56 56 extern const struct nf_nat_l4proto nf_nat_l4proto_unknown; 57 + #ifdef CONFIG_NF_NAT_PROTO_DCCP 58 + extern const struct nf_nat_l4proto nf_nat_l4proto_dccp; 59 + #endif 60 + #ifdef CONFIG_NF_NAT_PROTO_SCTP 61 + extern const struct nf_nat_l4proto nf_nat_l4proto_sctp; 62 + #endif 63 + #ifdef CONFIG_NF_NAT_PROTO_UDPLITE 64 + extern const struct nf_nat_l4proto nf_nat_l4proto_udplite; 65 + #endif 57 66 58 67 bool nf_nat_l4proto_in_range(const struct nf_conntrack_tuple *tuple, 59 68 enum nf_nat_manip_type maniptype,
+100 -1
include/net/netfilter/nf_tables.h
··· 259 259 * @lookup: look up an element within the set 260 260 * @insert: insert new element into set 261 261 * @activate: activate new element in the next generation 262 - * @deactivate: deactivate element in the next generation 262 + * @deactivate: lookup for element and deactivate it in the next generation 263 + * @deactivate_one: deactivate element in the next generation 263 264 * @remove: remove element from set 264 265 * @walk: iterate over all set elemeennts 265 266 * @privsize: function to return size of set private data ··· 295 294 void * (*deactivate)(const struct net *net, 296 295 const struct nft_set *set, 297 296 const struct nft_set_elem *elem); 297 + bool (*deactivate_one)(const struct net *net, 298 + const struct nft_set *set, 299 + void *priv); 298 300 void (*remove)(const struct nft_set *set, 299 301 const struct nft_set_elem *elem); 300 302 void (*walk)(const struct nft_ctx *ctx, ··· 330 326 * @name: name of the set 331 327 * @ktype: key type (numeric type defined by userspace, not used in the kernel) 332 328 * @dtype: data type (verdict or numeric type defined by userspace) 329 + * @objtype: object type (see NFT_OBJECT_* definitions) 333 330 * @size: maximum set size 334 331 * @nelems: number of elements 335 332 * @ndeact: number of deactivated elements queued for removal ··· 352 347 char name[NFT_SET_MAXNAMELEN]; 353 348 u32 ktype; 354 349 u32 dtype; 350 + u32 objtype; 355 351 u32 size; 356 352 atomic_t nelems; 357 353 u32 ndeact; ··· 422 416 * @NFT_SET_EXT_EXPIRATION: element expiration time 423 417 * @NFT_SET_EXT_USERDATA: user data associated with the element 424 418 * @NFT_SET_EXT_EXPR: expression assiociated with the element 419 + * @NFT_SET_EXT_OBJREF: stateful object reference associated with element 425 420 * @NFT_SET_EXT_NUM: number of extension types 426 421 */ 427 422 enum nft_set_extensions { ··· 433 426 NFT_SET_EXT_EXPIRATION, 434 427 NFT_SET_EXT_USERDATA, 435 428 NFT_SET_EXT_EXPR, 429 + NFT_SET_EXT_OBJREF, 436 430 NFT_SET_EXT_NUM 437 431 }; 438 432 ··· 560 552 void *elem) 561 553 { 562 554 return elem + set->ops->elemsize; 555 + } 556 + 557 + static inline struct nft_object **nft_set_ext_obj(const struct nft_set_ext *ext) 558 + { 559 + return nft_set_ext(ext, NFT_SET_EXT_OBJREF); 563 560 } 564 561 565 562 void *nft_set_elem_init(const struct nft_set *set, ··· 888 875 * @list: used internally 889 876 * @chains: chains in the table 890 877 * @sets: sets in the table 878 + * @objects: stateful objects in the table 891 879 * @hgenerator: handle generator state 892 880 * @use: number of chain references to this table 893 881 * @flags: table flag (see enum nft_table_flags) ··· 899 885 struct list_head list; 900 886 struct list_head chains; 901 887 struct list_head sets; 888 + struct list_head objects; 902 889 u64 hgenerator; 903 890 u32 use; 904 891 u16 flags:14, ··· 950 935 const struct nft_verdict *v); 951 936 952 937 /** 938 + * struct nft_object - nf_tables stateful object 939 + * 940 + * @list: table stateful object list node 941 + * @table: table this object belongs to 942 + * @type: pointer to object type 943 + * @data: pointer to object data 944 + * @name: name of this stateful object 945 + * @genmask: generation mask 946 + * @use: number of references to this stateful object 947 + * @data: object data, layout depends on type 948 + */ 949 + struct nft_object { 950 + struct list_head list; 951 + char name[NFT_OBJ_MAXNAMELEN]; 952 + struct nft_table *table; 953 + u32 genmask:2, 954 + use:30; 955 + /* runtime data below here */ 956 + const struct nft_object_type *type ____cacheline_aligned; 957 + unsigned char data[] 958 + __attribute__((aligned(__alignof__(u64)))); 959 + }; 960 + 961 + static inline void *nft_obj_data(const struct nft_object *obj) 962 + { 963 + return (void *)obj->data; 964 + } 965 + 966 + #define nft_expr_obj(expr) *((struct nft_object **)nft_expr_priv(expr)) 967 + 968 + struct nft_object *nf_tables_obj_lookup(const struct nft_table *table, 969 + const struct nlattr *nla, u32 objtype, 970 + u8 genmask); 971 + 972 + int nft_obj_notify(struct net *net, struct nft_table *table, 973 + struct nft_object *obj, u32 portid, u32 seq, 974 + int event, int family, int report, gfp_t gfp); 975 + 976 + /** 977 + * struct nft_object_type - stateful object type 978 + * 979 + * @eval: stateful object evaluation function 980 + * @list: list node in list of object types 981 + * @type: stateful object numeric type 982 + * @size: stateful object size 983 + * @owner: module owner 984 + * @maxattr: maximum netlink attribute 985 + * @policy: netlink attribute policy 986 + * @init: initialize object from netlink attributes 987 + * @destroy: release existing stateful object 988 + * @dump: netlink dump stateful object 989 + */ 990 + struct nft_object_type { 991 + void (*eval)(struct nft_object *obj, 992 + struct nft_regs *regs, 993 + const struct nft_pktinfo *pkt); 994 + struct list_head list; 995 + u32 type; 996 + unsigned int size; 997 + unsigned int maxattr; 998 + struct module *owner; 999 + const struct nla_policy *policy; 1000 + int (*init)(const struct nlattr * const tb[], 1001 + struct nft_object *obj); 1002 + void (*destroy)(struct nft_object *obj); 1003 + int (*dump)(struct sk_buff *skb, 1004 + struct nft_object *obj, 1005 + bool reset); 1006 + }; 1007 + 1008 + int nft_register_obj(struct nft_object_type *obj_type); 1009 + void nft_unregister_obj(struct nft_object_type *obj_type); 1010 + 1011 + /** 953 1012 * struct nft_traceinfo - nft tracing information and state 954 1013 * 955 1014 * @pkt: pktinfo currently processed ··· 1069 980 1070 981 #define MODULE_ALIAS_NFT_SET() \ 1071 982 MODULE_ALIAS("nft-set") 983 + 984 + #define MODULE_ALIAS_NFT_OBJ(type) \ 985 + MODULE_ALIAS("nft-obj-" __stringify(type)) 1072 986 1073 987 /* 1074 988 * The gencursor defines two generations, the currently active and the ··· 1248 1156 (((struct nft_trans_elem *)trans->data)->set) 1249 1157 #define nft_trans_elem(trans) \ 1250 1158 (((struct nft_trans_elem *)trans->data)->elem) 1159 + 1160 + struct nft_trans_obj { 1161 + struct nft_object *obj; 1162 + }; 1163 + 1164 + #define nft_trans_obj(trans) \ 1165 + (((struct nft_trans_obj *)trans->data)->obj) 1251 1166 1252 1167 #endif /* _NET_NF_TABLES_H */
+1
include/net/netfilter/nf_tables_core.h
··· 45 45 enum nft_registers sreg:8; 46 46 u8 csum_type; 47 47 u8 csum_offset; 48 + u8 csum_flags; 48 49 }; 49 50 50 51 extern const struct nft_expr_ops nft_payload_fast_ops;
+43
include/net/netns/conntrack.h
··· 6 6 #include <linux/atomic.h> 7 7 #include <linux/workqueue.h> 8 8 #include <linux/netfilter/nf_conntrack_tcp.h> 9 + #ifdef CONFIG_NF_CT_PROTO_DCCP 10 + #include <linux/netfilter/nf_conntrack_dccp.h> 11 + #endif 12 + #ifdef CONFIG_NF_CT_PROTO_SCTP 13 + #include <linux/netfilter/nf_conntrack_sctp.h> 14 + #endif 9 15 #include <linux/seqlock.h> 10 16 11 17 struct ctl_table_header; ··· 54 48 unsigned int timeout; 55 49 }; 56 50 51 + #ifdef CONFIG_NF_CT_PROTO_DCCP 52 + struct nf_dccp_net { 53 + struct nf_proto_net pn; 54 + int dccp_loose; 55 + unsigned int dccp_timeout[CT_DCCP_MAX + 1]; 56 + }; 57 + #endif 58 + 59 + #ifdef CONFIG_NF_CT_PROTO_SCTP 60 + struct nf_sctp_net { 61 + struct nf_proto_net pn; 62 + unsigned int timeouts[SCTP_CONNTRACK_MAX]; 63 + }; 64 + #endif 65 + 66 + #ifdef CONFIG_NF_CT_PROTO_UDPLITE 67 + enum udplite_conntrack { 68 + UDPLITE_CT_UNREPLIED, 69 + UDPLITE_CT_REPLIED, 70 + UDPLITE_CT_MAX 71 + }; 72 + 73 + struct nf_udplite_net { 74 + struct nf_proto_net pn; 75 + unsigned int timeouts[UDPLITE_CT_MAX]; 76 + }; 77 + #endif 78 + 57 79 struct nf_ip_net { 58 80 struct nf_generic_net generic; 59 81 struct nf_tcp_net tcp; 60 82 struct nf_udp_net udp; 61 83 struct nf_icmp_net icmp; 62 84 struct nf_icmp_net icmpv6; 85 + #ifdef CONFIG_NF_CT_PROTO_DCCP 86 + struct nf_dccp_net dccp; 87 + #endif 88 + #ifdef CONFIG_NF_CT_PROTO_SCTP 89 + struct nf_sctp_net sctp; 90 + #endif 91 + #ifdef CONFIG_NF_CT_PROTO_UDPLITE 92 + struct nf_udplite_net udplite; 93 + #endif 63 94 }; 64 95 65 96 struct ct_pcpu {
+6
include/net/netns/netfilter.h
··· 17 17 struct ctl_table_header *nf_log_dir_header; 18 18 #endif 19 19 struct nf_hook_entry __rcu *hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS]; 20 + #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4) 21 + bool defrag_ipv4; 22 + #endif 23 + #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6) 24 + bool defrag_ipv6; 25 + #endif 20 26 }; 21 27 #endif
+3
include/uapi/linux/netfilter/nf_conntrack_tuple_common.h
··· 2 2 #define _NF_CONNTRACK_TUPLE_COMMON_H 3 3 4 4 #include <linux/types.h> 5 + #ifndef __KERNEL__ 5 6 #include <linux/netfilter.h> 7 + #endif 8 + #include <linux/netfilter/nf_conntrack_common.h> /* IP_CT_IS_REPLY */ 6 9 7 10 enum ip_conntrack_dir { 8 11 IP_CT_DIR_ORIGINAL,
+70
include/uapi/linux/netfilter/nf_tables.h
··· 4 4 #define NFT_TABLE_MAXNAMELEN 32 5 5 #define NFT_CHAIN_MAXNAMELEN 32 6 6 #define NFT_SET_MAXNAMELEN 32 7 + #define NFT_OBJ_MAXNAMELEN 32 7 8 #define NFT_USERDATA_MAXLEN 256 8 9 9 10 /** ··· 86 85 * @NFT_MSG_NEWGEN: announce a new generation, only for events (enum nft_gen_attributes) 87 86 * @NFT_MSG_GETGEN: get the rule-set generation (enum nft_gen_attributes) 88 87 * @NFT_MSG_TRACE: trace event (enum nft_trace_attributes) 88 + * @NFT_MSG_NEWOBJ: create a stateful object (enum nft_obj_attributes) 89 + * @NFT_MSG_GETOBJ: get a stateful object (enum nft_obj_attributes) 90 + * @NFT_MSG_DELOBJ: delete a stateful object (enum nft_obj_attributes) 91 + * @NFT_MSG_GETOBJ_RESET: get and reset a stateful object (enum nft_obj_attributes) 89 92 */ 90 93 enum nf_tables_msg_types { 91 94 NFT_MSG_NEWTABLE, ··· 110 105 NFT_MSG_NEWGEN, 111 106 NFT_MSG_GETGEN, 112 107 NFT_MSG_TRACE, 108 + NFT_MSG_NEWOBJ, 109 + NFT_MSG_GETOBJ, 110 + NFT_MSG_DELOBJ, 111 + NFT_MSG_GETOBJ_RESET, 113 112 NFT_MSG_MAX, 114 113 }; 115 114 ··· 255 246 * @NFT_SET_MAP: set is used as a dictionary 256 247 * @NFT_SET_TIMEOUT: set uses timeouts 257 248 * @NFT_SET_EVAL: set contains expressions for evaluation 249 + * @NFT_SET_OBJECT: set contains stateful objects 258 250 */ 259 251 enum nft_set_flags { 260 252 NFT_SET_ANONYMOUS = 0x1, ··· 264 254 NFT_SET_MAP = 0x8, 265 255 NFT_SET_TIMEOUT = 0x10, 266 256 NFT_SET_EVAL = 0x20, 257 + NFT_SET_OBJECT = 0x40, 267 258 }; 268 259 269 260 /** ··· 306 295 * @NFTA_SET_TIMEOUT: default timeout value (NLA_U64) 307 296 * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32) 308 297 * @NFTA_SET_USERDATA: user data (NLA_BINARY) 298 + * @NFTA_SET_OBJ_TYPE: stateful object type (NLA_U32: NFT_OBJECT_*) 309 299 */ 310 300 enum nft_set_attributes { 311 301 NFTA_SET_UNSPEC, ··· 324 312 NFTA_SET_GC_INTERVAL, 325 313 NFTA_SET_USERDATA, 326 314 NFTA_SET_PAD, 315 + NFTA_SET_OBJ_TYPE, 327 316 __NFTA_SET_MAX 328 317 }; 329 318 #define NFTA_SET_MAX (__NFTA_SET_MAX - 1) ··· 348 335 * @NFTA_SET_ELEM_EXPIRATION: expiration time (NLA_U64) 349 336 * @NFTA_SET_ELEM_USERDATA: user data (NLA_BINARY) 350 337 * @NFTA_SET_ELEM_EXPR: expression (NLA_NESTED: nft_expr_attributes) 338 + * @NFTA_SET_ELEM_OBJREF: stateful object reference (NLA_STRING) 351 339 */ 352 340 enum nft_set_elem_attributes { 353 341 NFTA_SET_ELEM_UNSPEC, ··· 360 346 NFTA_SET_ELEM_USERDATA, 361 347 NFTA_SET_ELEM_EXPR, 362 348 NFTA_SET_ELEM_PAD, 349 + NFTA_SET_ELEM_OBJREF, 363 350 __NFTA_SET_ELEM_MAX 364 351 }; 365 352 #define NFTA_SET_ELEM_MAX (__NFTA_SET_ELEM_MAX - 1) ··· 674 659 NFT_PAYLOAD_CSUM_INET, 675 660 }; 676 661 662 + enum nft_payload_csum_flags { 663 + NFT_PAYLOAD_L4CSUM_PSEUDOHDR = (1 << 0), 664 + }; 665 + 677 666 /** 678 667 * enum nft_payload_attributes - nf_tables payload expression netlink attributes 679 668 * ··· 688 669 * @NFTA_PAYLOAD_SREG: source register to load data from (NLA_U32: nft_registers) 689 670 * @NFTA_PAYLOAD_CSUM_TYPE: checksum type (NLA_U32) 690 671 * @NFTA_PAYLOAD_CSUM_OFFSET: checksum offset relative to base (NLA_U32) 672 + * @NFTA_PAYLOAD_CSUM_FLAGS: checksum flags (NLA_U32) 691 673 */ 692 674 enum nft_payload_attributes { 693 675 NFTA_PAYLOAD_UNSPEC, ··· 699 679 NFTA_PAYLOAD_SREG, 700 680 NFTA_PAYLOAD_CSUM_TYPE, 701 681 NFTA_PAYLOAD_CSUM_OFFSET, 682 + NFTA_PAYLOAD_CSUM_FLAGS, 702 683 __NFTA_PAYLOAD_MAX 703 684 }; 704 685 #define NFTA_PAYLOAD_MAX (__NFTA_PAYLOAD_MAX - 1) ··· 989 968 990 969 enum nft_quota_flags { 991 970 NFT_QUOTA_F_INV = (1 << 0), 971 + NFT_QUOTA_F_DEPLETED = (1 << 1), 992 972 }; 993 973 994 974 /** ··· 997 975 * 998 976 * @NFTA_QUOTA_BYTES: quota in bytes (NLA_U16) 999 977 * @NFTA_QUOTA_FLAGS: flags (NLA_U32) 978 + * @NFTA_QUOTA_CONSUMED: quota already consumed in bytes (NLA_U64) 1000 979 */ 1001 980 enum nft_quota_attributes { 1002 981 NFTA_QUOTA_UNSPEC, 1003 982 NFTA_QUOTA_BYTES, 1004 983 NFTA_QUOTA_FLAGS, 1005 984 NFTA_QUOTA_PAD, 985 + NFTA_QUOTA_CONSUMED, 1006 986 __NFTA_QUOTA_MAX 1007 987 }; 1008 988 #define NFTA_QUOTA_MAX (__NFTA_QUOTA_MAX - 1) ··· 1149 1125 #define NFTA_FWD_MAX (__NFTA_FWD_MAX - 1) 1150 1126 1151 1127 /** 1128 + * enum nft_objref_attributes - nf_tables stateful object expression netlink attributes 1129 + * 1130 + * @NFTA_OBJREF_IMM_TYPE: object type for immediate reference (NLA_U32: nft_register) 1131 + * @NFTA_OBJREF_IMM_NAME: object name for immediate reference (NLA_STRING) 1132 + * @NFTA_OBJREF_SET_SREG: source register of the data to look for (NLA_U32: nft_registers) 1133 + * @NFTA_OBJREF_SET_NAME: name of the set where to look for (NLA_STRING) 1134 + * @NFTA_OBJREF_SET_ID: id of the set where to look for in this transaction (NLA_U32) 1135 + */ 1136 + enum nft_objref_attributes { 1137 + NFTA_OBJREF_UNSPEC, 1138 + NFTA_OBJREF_IMM_TYPE, 1139 + NFTA_OBJREF_IMM_NAME, 1140 + NFTA_OBJREF_SET_SREG, 1141 + NFTA_OBJREF_SET_NAME, 1142 + NFTA_OBJREF_SET_ID, 1143 + __NFTA_OBJREF_MAX 1144 + }; 1145 + #define NFTA_OBJREF_MAX (__NFTA_OBJREF_MAX - 1) 1146 + 1147 + /** 1152 1148 * enum nft_gen_attributes - nf_tables ruleset generation attributes 1153 1149 * 1154 1150 * @NFTA_GEN_ID: Ruleset generation ID (NLA_U32) ··· 1215 1171 NFTA_FIB_F_IIF = 1 << 3, /* restrict to iif */ 1216 1172 NFTA_FIB_F_OIF = 1 << 4, /* restrict to oif */ 1217 1173 }; 1174 + 1175 + #define NFT_OBJECT_UNSPEC 0 1176 + #define NFT_OBJECT_COUNTER 1 1177 + #define NFT_OBJECT_QUOTA 2 1178 + #define __NFT_OBJECT_MAX 3 1179 + #define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1) 1180 + 1181 + /** 1182 + * enum nft_object_attributes - nf_tables stateful object netlink attributes 1183 + * 1184 + * @NFTA_OBJ_TABLE: name of the table containing the expression (NLA_STRING) 1185 + * @NFTA_OBJ_NAME: name of this expression type (NLA_STRING) 1186 + * @NFTA_OBJ_TYPE: stateful object type (NLA_U32) 1187 + * @NFTA_OBJ_DATA: stateful object data (NLA_NESTED) 1188 + * @NFTA_OBJ_USE: number of references to this expression (NLA_U32) 1189 + */ 1190 + enum nft_object_attributes { 1191 + NFTA_OBJ_UNSPEC, 1192 + NFTA_OBJ_TABLE, 1193 + NFTA_OBJ_NAME, 1194 + NFTA_OBJ_TYPE, 1195 + NFTA_OBJ_DATA, 1196 + NFTA_OBJ_USE, 1197 + __NFTA_OBJ_MAX 1198 + }; 1199 + #define NFTA_OBJ_MAX (__NFTA_OBJ_MAX - 1) 1218 1200 1219 1201 /** 1220 1202 * enum nft_trace_attributes - nf_tables trace netlink attributes
+21
include/uapi/linux/netfilter/xt_bpf.h
··· 2 2 #define _XT_BPF_H 3 3 4 4 #include <linux/filter.h> 5 + #include <linux/limits.h> 5 6 #include <linux/types.h> 6 7 7 8 #define XT_BPF_MAX_NUM_INSTR 64 9 + #define XT_BPF_PATH_MAX (XT_BPF_MAX_NUM_INSTR * sizeof(struct sock_filter)) 8 10 9 11 struct bpf_prog; 10 12 11 13 struct xt_bpf_info { 12 14 __u16 bpf_program_num_elem; 13 15 struct sock_filter bpf_program[XT_BPF_MAX_NUM_INSTR]; 16 + 17 + /* only used in the kernel */ 18 + struct bpf_prog *filter __attribute__((aligned(8))); 19 + }; 20 + 21 + enum xt_bpf_modes { 22 + XT_BPF_MODE_BYTECODE, 23 + XT_BPF_MODE_FD_PINNED, 24 + XT_BPF_MODE_FD_ELF, 25 + }; 26 + 27 + struct xt_bpf_info_v1 { 28 + __u16 mode; 29 + __u16 bpf_program_num_elem; 30 + __s32 fd; 31 + union { 32 + struct sock_filter bpf_program[XT_BPF_MAX_NUM_INSTR]; 33 + char path[XT_BPF_PATH_MAX]; 34 + }; 14 35 15 36 /* only used in the kernel */ 16 37 struct bpf_prog *filter __attribute__((aligned(8)));
+4 -4
net/bridge/br_netfilter_hooks.c
··· 1008 1008 struct nf_hook_state state; 1009 1009 int ret; 1010 1010 1011 - elem = rcu_dereference(net->nf.hooks[NFPROTO_BRIDGE][hook]); 1012 - 1013 - while (elem && (elem->ops.priority <= NF_BR_PRI_BRNF)) 1014 - elem = rcu_dereference(elem->next); 1011 + for (elem = rcu_dereference(net->nf.hooks[NFPROTO_BRIDGE][hook]); 1012 + elem && nf_hook_entry_priority(elem) <= NF_BR_PRI_BRNF; 1013 + elem = rcu_dereference(elem->next)) 1014 + ; 1015 1015 1016 1016 if (!elem) 1017 1017 return okfn(net, sk, skb);
+2 -1
net/bridge/netfilter/nf_log_bridge.c
··· 24 24 const struct nf_loginfo *loginfo, 25 25 const char *prefix) 26 26 { 27 - nf_log_l2packet(net, pf, hooknum, skb, in, out, loginfo, prefix); 27 + nf_log_l2packet(net, pf, eth_hdr(skb)->h_proto, hooknum, skb, 28 + in, out, loginfo, prefix); 28 29 } 29 30 30 31 static struct nf_logger nf_bridge_logger __read_mostly = {
+8 -8
net/ipv4/netfilter/arp_tables.c
··· 411 411 } 412 412 413 413 static inline int 414 - find_check_entry(struct arpt_entry *e, const char *name, unsigned int size) 414 + find_check_entry(struct arpt_entry *e, const char *name, unsigned int size, 415 + struct xt_percpu_counter_alloc_state *alloc_state) 415 416 { 416 417 struct xt_entry_target *t; 417 418 struct xt_target *target; 418 - unsigned long pcnt; 419 419 int ret; 420 420 421 - pcnt = xt_percpu_counter_alloc(); 422 - if (IS_ERR_VALUE(pcnt)) 421 + if (!xt_percpu_counter_alloc(alloc_state, &e->counters)) 423 422 return -ENOMEM; 424 - e->counters.pcnt = pcnt; 425 423 426 424 t = arpt_get_target(e); 427 425 target = xt_request_find_target(NFPROTO_ARP, t->u.user.name, ··· 437 439 err: 438 440 module_put(t->u.kernel.target->me); 439 441 out: 440 - xt_percpu_counter_free(e->counters.pcnt); 442 + xt_percpu_counter_free(&e->counters); 441 443 442 444 return ret; 443 445 } ··· 517 519 if (par.target->destroy != NULL) 518 520 par.target->destroy(&par); 519 521 module_put(par.target->me); 520 - xt_percpu_counter_free(e->counters.pcnt); 522 + xt_percpu_counter_free(&e->counters); 521 523 } 522 524 523 525 /* Checks and translates the user-supplied table segment (held in ··· 526 528 static int translate_table(struct xt_table_info *newinfo, void *entry0, 527 529 const struct arpt_replace *repl) 528 530 { 531 + struct xt_percpu_counter_alloc_state alloc_state = { 0 }; 529 532 struct arpt_entry *iter; 530 533 unsigned int *offsets; 531 534 unsigned int i; ··· 589 590 /* Finally, each sanity check must pass */ 590 591 i = 0; 591 592 xt_entry_foreach(iter, entry0, newinfo->size) { 592 - ret = find_check_entry(iter, repl->name, repl->size); 593 + ret = find_check_entry(iter, repl->name, repl->size, 594 + &alloc_state); 593 595 if (ret != 0) 594 596 break; 595 597 ++i;
+8 -8
net/ipv4/netfilter/ip_tables.c
··· 531 531 532 532 static int 533 533 find_check_entry(struct ipt_entry *e, struct net *net, const char *name, 534 - unsigned int size) 534 + unsigned int size, 535 + struct xt_percpu_counter_alloc_state *alloc_state) 535 536 { 536 537 struct xt_entry_target *t; 537 538 struct xt_target *target; ··· 540 539 unsigned int j; 541 540 struct xt_mtchk_param mtpar; 542 541 struct xt_entry_match *ematch; 543 - unsigned long pcnt; 544 542 545 - pcnt = xt_percpu_counter_alloc(); 546 - if (IS_ERR_VALUE(pcnt)) 543 + if (!xt_percpu_counter_alloc(alloc_state, &e->counters)) 547 544 return -ENOMEM; 548 - e->counters.pcnt = pcnt; 549 545 550 546 j = 0; 551 547 mtpar.net = net; ··· 580 582 cleanup_match(ematch, net); 581 583 } 582 584 583 - xt_percpu_counter_free(e->counters.pcnt); 585 + xt_percpu_counter_free(&e->counters); 584 586 585 587 return ret; 586 588 } ··· 668 670 if (par.target->destroy != NULL) 669 671 par.target->destroy(&par); 670 672 module_put(par.target->me); 671 - xt_percpu_counter_free(e->counters.pcnt); 673 + xt_percpu_counter_free(&e->counters); 672 674 } 673 675 674 676 /* Checks and translates the user-supplied table segment (held in ··· 677 679 translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, 678 680 const struct ipt_replace *repl) 679 681 { 682 + struct xt_percpu_counter_alloc_state alloc_state = { 0 }; 680 683 struct ipt_entry *iter; 681 684 unsigned int *offsets; 682 685 unsigned int i; ··· 737 738 /* Finally, each sanity check must pass */ 738 739 i = 0; 739 740 xt_entry_foreach(iter, entry0, newinfo->size) { 740 - ret = find_check_entry(iter, net, repl->name, repl->size); 741 + ret = find_check_entry(iter, net, repl->name, repl->size, 742 + &alloc_state); 741 743 if (ret != 0) 742 744 break; 743 745 ++i;
+2 -2
net/ipv4/netfilter/ipt_CLUSTERIP.c
··· 419 419 } 420 420 cipinfo->config = config; 421 421 422 - ret = nf_ct_l3proto_try_module_get(par->family); 422 + ret = nf_ct_netns_get(par->net, par->family); 423 423 if (ret < 0) 424 424 pr_info("cannot load conntrack support for proto=%u\n", 425 425 par->family); ··· 444 444 445 445 clusterip_config_put(cipinfo->config); 446 446 447 - nf_ct_l3proto_module_put(par->family); 447 + nf_ct_netns_get(par->net, par->family); 448 448 } 449 449 450 450 #ifdef CONFIG_COMPAT
+7 -1
net/ipv4/netfilter/ipt_MASQUERADE.c
··· 41 41 pr_debug("bad rangesize %u\n", mr->rangesize); 42 42 return -EINVAL; 43 43 } 44 - return 0; 44 + return nf_ct_netns_get(par->net, par->family); 45 45 } 46 46 47 47 static unsigned int ··· 59 59 xt_out(par)); 60 60 } 61 61 62 + static void masquerade_tg_destroy(const struct xt_tgdtor_param *par) 63 + { 64 + nf_ct_netns_put(par->net, par->family); 65 + } 66 + 62 67 static struct xt_target masquerade_tg_reg __read_mostly = { 63 68 .name = "MASQUERADE", 64 69 .family = NFPROTO_IPV4, ··· 72 67 .table = "nat", 73 68 .hooks = 1 << NF_INET_POST_ROUTING, 74 69 .checkentry = masquerade_tg_check, 70 + .destroy = masquerade_tg_destroy, 75 71 .me = THIS_MODULE, 76 72 }; 77 73
+2 -2
net/ipv4/netfilter/ipt_SYNPROXY.c
··· 418 418 e->ip.invflags & XT_INV_PROTO) 419 419 return -EINVAL; 420 420 421 - return nf_ct_l3proto_try_module_get(par->family); 421 + return nf_ct_netns_get(par->net, par->family); 422 422 } 423 423 424 424 static void synproxy_tg4_destroy(const struct xt_tgdtor_param *par) 425 425 { 426 - nf_ct_l3proto_module_put(par->family); 426 + nf_ct_netns_put(par->net, par->family); 427 427 } 428 428 429 429 static struct xt_target synproxy_tg4_reg __read_mostly = {
+5 -3
net/ipv4/netfilter/ipt_rpfilter.c
··· 83 83 return true ^ invert; 84 84 85 85 iph = ip_hdr(skb); 86 - if (ipv4_is_multicast(iph->daddr)) { 87 - if (ipv4_is_zeronet(iph->saddr)) 88 - return ipv4_is_local_multicast(iph->daddr) ^ invert; 86 + if (ipv4_is_zeronet(iph->saddr)) { 87 + if (ipv4_is_lbcast(iph->daddr) || 88 + ipv4_is_local_multicast(iph->daddr)) 89 + return true ^ invert; 89 90 } 91 + 90 92 flow.flowi4_iif = LOOPBACK_IFINDEX; 91 93 flow.daddr = iph->saddr; 92 94 flow.saddr = rpfilter_get_saddr(iph->daddr);
+56 -15
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
··· 31 31 #include <net/netfilter/ipv4/nf_defrag_ipv4.h> 32 32 #include <net/netfilter/nf_log.h> 33 33 34 + static int conntrack4_net_id __read_mostly; 35 + static DEFINE_MUTEX(register_ipv4_hooks); 36 + 37 + struct conntrack4_net { 38 + unsigned int users; 39 + }; 40 + 34 41 static bool ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, 35 42 struct nf_conntrack_tuple *tuple) 36 43 { ··· 314 307 .owner = THIS_MODULE, 315 308 }; 316 309 317 - static int ipv4_init_net(struct net *net) 310 + static int ipv4_hooks_register(struct net *net) 318 311 { 319 - return 0; 312 + struct conntrack4_net *cnet = net_generic(net, conntrack4_net_id); 313 + int err = 0; 314 + 315 + mutex_lock(&register_ipv4_hooks); 316 + 317 + cnet->users++; 318 + if (cnet->users > 1) 319 + goto out_unlock; 320 + 321 + err = nf_defrag_ipv4_enable(net); 322 + if (err) { 323 + cnet->users = 0; 324 + goto out_unlock; 325 + } 326 + 327 + err = nf_register_net_hooks(net, ipv4_conntrack_ops, 328 + ARRAY_SIZE(ipv4_conntrack_ops)); 329 + 330 + if (err) 331 + cnet->users = 0; 332 + out_unlock: 333 + mutex_unlock(&register_ipv4_hooks); 334 + return err; 335 + } 336 + 337 + static void ipv4_hooks_unregister(struct net *net) 338 + { 339 + struct conntrack4_net *cnet = net_generic(net, conntrack4_net_id); 340 + 341 + mutex_lock(&register_ipv4_hooks); 342 + if (cnet->users && (--cnet->users == 0)) 343 + nf_unregister_net_hooks(net, ipv4_conntrack_ops, 344 + ARRAY_SIZE(ipv4_conntrack_ops)); 345 + mutex_unlock(&register_ipv4_hooks); 320 346 } 321 347 322 348 struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = { ··· 365 325 .nlattr_to_tuple = ipv4_nlattr_to_tuple, 366 326 .nla_policy = ipv4_nla_policy, 367 327 #endif 368 - .init_net = ipv4_init_net, 328 + .net_ns_get = ipv4_hooks_register, 329 + .net_ns_put = ipv4_hooks_unregister, 369 330 .me = THIS_MODULE, 370 331 }; 371 332 ··· 381 340 &nf_conntrack_l4proto_tcp4, 382 341 &nf_conntrack_l4proto_udp4, 383 342 &nf_conntrack_l4proto_icmp, 343 + #ifdef CONFIG_NF_CT_PROTO_DCCP 344 + &nf_conntrack_l4proto_dccp4, 345 + #endif 346 + #ifdef CONFIG_NF_CT_PROTO_SCTP 347 + &nf_conntrack_l4proto_sctp4, 348 + #endif 349 + #ifdef CONFIG_NF_CT_PROTO_UDPLITE 350 + &nf_conntrack_l4proto_udplite4, 351 + #endif 384 352 }; 385 353 386 354 static int ipv4_net_init(struct net *net) ··· 419 369 static struct pernet_operations ipv4_net_ops = { 420 370 .init = ipv4_net_init, 421 371 .exit = ipv4_net_exit, 372 + .id = &conntrack4_net_id, 373 + .size = sizeof(struct conntrack4_net), 422 374 }; 423 375 424 376 static int __init nf_conntrack_l3proto_ipv4_init(void) ··· 428 376 int ret = 0; 429 377 430 378 need_conntrack(); 431 - nf_defrag_ipv4_enable(); 432 379 433 380 ret = nf_register_sockopt(&so_getorigdst); 434 381 if (ret < 0) { ··· 441 390 goto cleanup_sockopt; 442 391 } 443 392 444 - ret = nf_register_hooks(ipv4_conntrack_ops, 445 - ARRAY_SIZE(ipv4_conntrack_ops)); 446 - if (ret < 0) { 447 - pr_err("nf_conntrack_ipv4: can't register hooks.\n"); 448 - goto cleanup_pernet; 449 - } 450 - 451 393 ret = nf_ct_l4proto_register(builtin_l4proto4, 452 394 ARRAY_SIZE(builtin_l4proto4)); 453 395 if (ret < 0) 454 - goto cleanup_hooks; 396 + goto cleanup_pernet; 455 397 456 398 ret = nf_ct_l3proto_register(&nf_conntrack_l3proto_ipv4); 457 399 if (ret < 0) { ··· 456 412 cleanup_l4proto: 457 413 nf_ct_l4proto_unregister(builtin_l4proto4, 458 414 ARRAY_SIZE(builtin_l4proto4)); 459 - cleanup_hooks: 460 - nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops)); 461 415 cleanup_pernet: 462 416 unregister_pernet_subsys(&ipv4_net_ops); 463 417 cleanup_sockopt: ··· 469 427 nf_ct_l3proto_unregister(&nf_conntrack_l3proto_ipv4); 470 428 nf_ct_l4proto_unregister(builtin_l4proto4, 471 429 ARRAY_SIZE(builtin_l4proto4)); 472 - nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops)); 473 430 unregister_pernet_subsys(&ipv4_net_ops); 474 431 nf_unregister_sockopt(&so_getorigdst); 475 432 }
+38 -3
net/ipv4/netfilter/nf_defrag_ipv4.c
··· 11 11 #include <linux/netfilter.h> 12 12 #include <linux/module.h> 13 13 #include <linux/skbuff.h> 14 + #include <net/netns/generic.h> 14 15 #include <net/route.h> 15 16 #include <net/ip.h> 16 17 ··· 22 21 #include <net/netfilter/nf_conntrack.h> 23 22 #endif 24 23 #include <net/netfilter/nf_conntrack_zones.h> 24 + 25 + static DEFINE_MUTEX(defrag4_mutex); 25 26 26 27 static int nf_ct_ipv4_gather_frags(struct net *net, struct sk_buff *skb, 27 28 u_int32_t user) ··· 105 102 }, 106 103 }; 107 104 105 + static void __net_exit defrag4_net_exit(struct net *net) 106 + { 107 + if (net->nf.defrag_ipv4) { 108 + nf_unregister_net_hooks(net, ipv4_defrag_ops, 109 + ARRAY_SIZE(ipv4_defrag_ops)); 110 + net->nf.defrag_ipv4 = false; 111 + } 112 + } 113 + 114 + static struct pernet_operations defrag4_net_ops = { 115 + .exit = defrag4_net_exit, 116 + }; 117 + 108 118 static int __init nf_defrag_init(void) 109 119 { 110 - return nf_register_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops)); 120 + return register_pernet_subsys(&defrag4_net_ops); 111 121 } 112 122 113 123 static void __exit nf_defrag_fini(void) 114 124 { 115 - nf_unregister_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops)); 125 + unregister_pernet_subsys(&defrag4_net_ops); 116 126 } 117 127 118 - void nf_defrag_ipv4_enable(void) 128 + int nf_defrag_ipv4_enable(struct net *net) 119 129 { 130 + int err = 0; 131 + 132 + might_sleep(); 133 + 134 + if (net->nf.defrag_ipv4) 135 + return 0; 136 + 137 + mutex_lock(&defrag4_mutex); 138 + if (net->nf.defrag_ipv4) 139 + goto out_unlock; 140 + 141 + err = nf_register_net_hooks(net, ipv4_defrag_ops, 142 + ARRAY_SIZE(ipv4_defrag_ops)); 143 + if (err == 0) 144 + net->nf.defrag_ipv4 = true; 145 + 146 + out_unlock: 147 + mutex_unlock(&defrag4_mutex); 148 + return err; 120 149 } 121 150 EXPORT_SYMBOL_GPL(nf_defrag_ipv4_enable); 122 151
+10 -7
net/ipv4/netfilter/nft_fib_ipv4.c
··· 101 101 } 102 102 103 103 iph = ip_hdr(pkt->skb); 104 - if (ipv4_is_multicast(iph->daddr) && 105 - ipv4_is_zeronet(iph->saddr) && 106 - ipv4_is_local_multicast(iph->daddr)) { 107 - nft_fib_store_result(dest, priv->result, pkt, 108 - get_ifindex(pkt->skb->dev)); 109 - return; 104 + if (ipv4_is_zeronet(iph->saddr)) { 105 + if (ipv4_is_lbcast(iph->daddr) || 106 + ipv4_is_local_multicast(iph->daddr)) { 107 + nft_fib_store_result(dest, priv->result, pkt, 108 + get_ifindex(pkt->skb->dev)); 109 + return; 110 + } 110 111 } 111 112 112 113 if (priv->flags & NFTA_FIB_F_MARK) ··· 122 121 fl4.daddr = iph->saddr; 123 122 fl4.saddr = get_saddr(iph->daddr); 124 123 } 124 + 125 + *dest = 0; 125 126 126 127 if (fib_lookup(nft_net(pkt), &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE)) 127 128 return; ··· 201 198 if (!tb[NFTA_FIB_RESULT]) 202 199 return ERR_PTR(-EINVAL); 203 200 204 - result = htonl(nla_get_be32(tb[NFTA_FIB_RESULT])); 201 + result = ntohl(nla_get_be32(tb[NFTA_FIB_RESULT])); 205 202 206 203 switch (result) { 207 204 case NFT_FIB_RESULT_OIF:
+9 -2
net/ipv4/netfilter/nft_masq_ipv4.c
··· 1 1 /* 2 - * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com> 2 + * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo@debian.org> 3 3 * 4 4 * This program is free software; you can redistribute it and/or modify 5 5 * it under the terms of the GNU General Public License version 2 as ··· 35 35 &range, nft_out(pkt)); 36 36 } 37 37 38 + static void 39 + nft_masq_ipv4_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) 40 + { 41 + nf_ct_netns_put(ctx->net, NFPROTO_IPV4); 42 + } 43 + 38 44 static struct nft_expr_type nft_masq_ipv4_type; 39 45 static const struct nft_expr_ops nft_masq_ipv4_ops = { 40 46 .type = &nft_masq_ipv4_type, 41 47 .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)), 42 48 .eval = nft_masq_ipv4_eval, 43 49 .init = nft_masq_init, 50 + .destroy = nft_masq_ipv4_destroy, 44 51 .dump = nft_masq_dump, 45 52 .validate = nft_masq_validate, 46 53 }; ··· 84 77 module_exit(nft_masq_ipv4_module_exit); 85 78 86 79 MODULE_LICENSE("GPL"); 87 - MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>"); 80 + MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org"); 88 81 MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "masq");
+9 -2
net/ipv4/netfilter/nft_redir_ipv4.c
··· 1 1 /* 2 - * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com> 2 + * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo@debian.org> 3 3 * 4 4 * This program is free software; you can redistribute it and/or modify 5 5 * it under the terms of the GNU General Public License version 2 as ··· 38 38 regs->verdict.code = nf_nat_redirect_ipv4(pkt->skb, &mr, nft_hook(pkt)); 39 39 } 40 40 41 + static void 42 + nft_redir_ipv4_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) 43 + { 44 + nf_ct_netns_put(ctx->net, NFPROTO_IPV4); 45 + } 46 + 41 47 static struct nft_expr_type nft_redir_ipv4_type; 42 48 static const struct nft_expr_ops nft_redir_ipv4_ops = { 43 49 .type = &nft_redir_ipv4_type, 44 50 .size = NFT_EXPR_SIZE(sizeof(struct nft_redir)), 45 51 .eval = nft_redir_ipv4_eval, 46 52 .init = nft_redir_init, 53 + .destroy = nft_redir_ipv4_destroy, 47 54 .dump = nft_redir_dump, 48 55 .validate = nft_redir_validate, 49 56 }; ··· 78 71 module_exit(nft_redir_ipv4_module_exit); 79 72 80 73 MODULE_LICENSE("GPL"); 81 - MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>"); 74 + MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>"); 82 75 MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "redir");
+8 -9
net/ipv6/netfilter/ip6_tables.c
··· 562 562 563 563 static int 564 564 find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, 565 - unsigned int size) 565 + unsigned int size, 566 + struct xt_percpu_counter_alloc_state *alloc_state) 566 567 { 567 568 struct xt_entry_target *t; 568 569 struct xt_target *target; ··· 571 570 unsigned int j; 572 571 struct xt_mtchk_param mtpar; 573 572 struct xt_entry_match *ematch; 574 - unsigned long pcnt; 575 573 576 - pcnt = xt_percpu_counter_alloc(); 577 - if (IS_ERR_VALUE(pcnt)) 574 + if (!xt_percpu_counter_alloc(alloc_state, &e->counters)) 578 575 return -ENOMEM; 579 - e->counters.pcnt = pcnt; 580 576 581 577 j = 0; 582 578 mtpar.net = net; ··· 610 612 cleanup_match(ematch, net); 611 613 } 612 614 613 - xt_percpu_counter_free(e->counters.pcnt); 615 + xt_percpu_counter_free(&e->counters); 614 616 615 617 return ret; 616 618 } ··· 697 699 if (par.target->destroy != NULL) 698 700 par.target->destroy(&par); 699 701 module_put(par.target->me); 700 - 701 - xt_percpu_counter_free(e->counters.pcnt); 702 + xt_percpu_counter_free(&e->counters); 702 703 } 703 704 704 705 /* Checks and translates the user-supplied table segment (held in ··· 706 709 translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, 707 710 const struct ip6t_replace *repl) 708 711 { 712 + struct xt_percpu_counter_alloc_state alloc_state = { 0 }; 709 713 struct ip6t_entry *iter; 710 714 unsigned int *offsets; 711 715 unsigned int i; ··· 766 768 /* Finally, each sanity check must pass */ 767 769 i = 0; 768 770 xt_entry_foreach(iter, entry0, newinfo->size) { 769 - ret = find_check_entry(iter, net, repl->name, repl->size); 771 + ret = find_check_entry(iter, net, repl->name, repl->size, 772 + &alloc_state); 770 773 if (ret != 0) 771 774 break; 772 775 ++i;
+2 -2
net/ipv6/netfilter/ip6t_SYNPROXY.c
··· 440 440 e->ipv6.invflags & XT_INV_PROTO) 441 441 return -EINVAL; 442 442 443 - return nf_ct_l3proto_try_module_get(par->family); 443 + return nf_ct_netns_get(par->net, par->family); 444 444 } 445 445 446 446 static void synproxy_tg6_destroy(const struct xt_tgdtor_param *par) 447 447 { 448 - nf_ct_l3proto_module_put(par->family); 448 + nf_ct_netns_put(par->net, par->family); 449 449 } 450 450 451 451 static struct xt_target synproxy_tg6_reg __read_mostly = {
+57 -13
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
··· 34 34 #include <net/netfilter/ipv6/nf_defrag_ipv6.h> 35 35 #include <net/netfilter/nf_log.h> 36 36 37 + static int conntrack6_net_id; 38 + static DEFINE_MUTEX(register_ipv6_hooks); 39 + 40 + struct conntrack6_net { 41 + unsigned int users; 42 + }; 43 + 37 44 static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, 38 45 struct nf_conntrack_tuple *tuple) 39 46 { ··· 315 308 } 316 309 #endif 317 310 311 + static int ipv6_hooks_register(struct net *net) 312 + { 313 + struct conntrack6_net *cnet = net_generic(net, conntrack6_net_id); 314 + int err = 0; 315 + 316 + mutex_lock(&register_ipv6_hooks); 317 + cnet->users++; 318 + if (cnet->users > 1) 319 + goto out_unlock; 320 + 321 + err = nf_defrag_ipv6_enable(net); 322 + if (err < 0) { 323 + cnet->users = 0; 324 + goto out_unlock; 325 + } 326 + 327 + err = nf_register_net_hooks(net, ipv6_conntrack_ops, 328 + ARRAY_SIZE(ipv6_conntrack_ops)); 329 + if (err) 330 + cnet->users = 0; 331 + out_unlock: 332 + mutex_unlock(&register_ipv6_hooks); 333 + return err; 334 + } 335 + 336 + static void ipv6_hooks_unregister(struct net *net) 337 + { 338 + struct conntrack6_net *cnet = net_generic(net, conntrack6_net_id); 339 + 340 + mutex_lock(&register_ipv6_hooks); 341 + if (cnet->users && (--cnet->users == 0)) 342 + nf_unregister_net_hooks(net, ipv6_conntrack_ops, 343 + ARRAY_SIZE(ipv6_conntrack_ops)); 344 + mutex_unlock(&register_ipv6_hooks); 345 + } 346 + 318 347 struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = { 319 348 .l3proto = PF_INET6, 320 349 .name = "ipv6", ··· 364 321 .nlattr_to_tuple = ipv6_nlattr_to_tuple, 365 322 .nla_policy = ipv6_nla_policy, 366 323 #endif 324 + .net_ns_get = ipv6_hooks_register, 325 + .net_ns_put = ipv6_hooks_unregister, 367 326 .me = THIS_MODULE, 368 327 }; 369 328 ··· 385 340 &nf_conntrack_l4proto_tcp6, 386 341 &nf_conntrack_l4proto_udp6, 387 342 &nf_conntrack_l4proto_icmpv6, 343 + #ifdef CONFIG_NF_CT_PROTO_DCCP 344 + &nf_conntrack_l4proto_dccp6, 345 + #endif 346 + #ifdef CONFIG_NF_CT_PROTO_SCTP 347 + &nf_conntrack_l4proto_sctp6, 348 + #endif 349 + #ifdef CONFIG_NF_CT_PROTO_UDPLITE 350 + &nf_conntrack_l4proto_udplite6, 351 + #endif 388 352 }; 389 353 390 354 static int ipv6_net_init(struct net *net) ··· 424 370 static struct pernet_operations ipv6_net_ops = { 425 371 .init = ipv6_net_init, 426 372 .exit = ipv6_net_exit, 373 + .id = &conntrack6_net_id, 374 + .size = sizeof(struct conntrack6_net), 427 375 }; 428 376 429 377 static int __init nf_conntrack_l3proto_ipv6_init(void) ··· 433 377 int ret = 0; 434 378 435 379 need_conntrack(); 436 - nf_defrag_ipv6_enable(); 437 380 438 381 ret = nf_register_sockopt(&so_getorigdst6); 439 382 if (ret < 0) { ··· 444 389 if (ret < 0) 445 390 goto cleanup_sockopt; 446 391 447 - ret = nf_register_hooks(ipv6_conntrack_ops, 448 - ARRAY_SIZE(ipv6_conntrack_ops)); 449 - if (ret < 0) { 450 - pr_err("nf_conntrack_ipv6: can't register pre-routing defrag " 451 - "hook.\n"); 452 - goto cleanup_pernet; 453 - } 454 - 455 392 ret = nf_ct_l4proto_register(builtin_l4proto6, 456 393 ARRAY_SIZE(builtin_l4proto6)); 457 394 if (ret < 0) 458 - goto cleanup_hooks; 395 + goto cleanup_pernet; 459 396 460 397 ret = nf_ct_l3proto_register(&nf_conntrack_l3proto_ipv6); 461 398 if (ret < 0) { ··· 458 411 cleanup_l4proto: 459 412 nf_ct_l4proto_unregister(builtin_l4proto6, 460 413 ARRAY_SIZE(builtin_l4proto6)); 461 - cleanup_hooks: 462 - nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops)); 463 414 cleanup_pernet: 464 415 unregister_pernet_subsys(&ipv6_net_ops); 465 416 cleanup_sockopt: ··· 471 426 nf_ct_l3proto_unregister(&nf_conntrack_l3proto_ipv6); 472 427 nf_ct_l4proto_unregister(builtin_l4proto6, 473 428 ARRAY_SIZE(builtin_l4proto6)); 474 - nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops)); 475 429 unregister_pernet_subsys(&ipv6_net_ops); 476 430 nf_unregister_sockopt(&so_getorigdst6); 477 431 }
+38 -4
net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
··· 30 30 #include <net/netfilter/nf_conntrack_zones.h> 31 31 #include <net/netfilter/ipv6/nf_defrag_ipv6.h> 32 32 33 + static DEFINE_MUTEX(defrag6_mutex); 34 + 33 35 static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, 34 36 struct sk_buff *skb) 35 37 { ··· 89 87 }, 90 88 }; 91 89 90 + static void __net_exit defrag6_net_exit(struct net *net) 91 + { 92 + if (net->nf.defrag_ipv6) { 93 + nf_unregister_net_hooks(net, ipv6_defrag_ops, 94 + ARRAY_SIZE(ipv6_defrag_ops)); 95 + net->nf.defrag_ipv6 = false; 96 + } 97 + } 98 + 99 + static struct pernet_operations defrag6_net_ops = { 100 + .exit = defrag6_net_exit, 101 + }; 102 + 92 103 static int __init nf_defrag_init(void) 93 104 { 94 105 int ret = 0; ··· 111 96 pr_err("nf_defrag_ipv6: can't initialize frag6.\n"); 112 97 return ret; 113 98 } 114 - ret = nf_register_hooks(ipv6_defrag_ops, ARRAY_SIZE(ipv6_defrag_ops)); 99 + ret = register_pernet_subsys(&defrag6_net_ops); 115 100 if (ret < 0) { 116 - pr_err("nf_defrag_ipv6: can't register hooks\n"); 101 + pr_err("nf_defrag_ipv6: can't register pernet ops\n"); 117 102 goto cleanup_frag6; 118 103 } 119 104 return ret; ··· 126 111 127 112 static void __exit nf_defrag_fini(void) 128 113 { 129 - nf_unregister_hooks(ipv6_defrag_ops, ARRAY_SIZE(ipv6_defrag_ops)); 114 + unregister_pernet_subsys(&defrag6_net_ops); 130 115 nf_ct_frag6_cleanup(); 131 116 } 132 117 133 - void nf_defrag_ipv6_enable(void) 118 + int nf_defrag_ipv6_enable(struct net *net) 134 119 { 120 + int err = 0; 121 + 122 + might_sleep(); 123 + 124 + if (net->nf.defrag_ipv6) 125 + return 0; 126 + 127 + mutex_lock(&defrag6_mutex); 128 + if (net->nf.defrag_ipv6) 129 + goto out_unlock; 130 + 131 + err = nf_register_net_hooks(net, ipv6_defrag_ops, 132 + ARRAY_SIZE(ipv6_defrag_ops)); 133 + if (err == 0) 134 + net->nf.defrag_ipv6 = true; 135 + 136 + out_unlock: 137 + mutex_unlock(&defrag6_mutex); 138 + return err; 135 139 } 136 140 EXPORT_SYMBOL_GPL(nf_defrag_ipv6_enable); 137 141
+1 -1
net/ipv6/netfilter/nft_fib_ipv6.c
··· 235 235 if (!tb[NFTA_FIB_RESULT]) 236 236 return ERR_PTR(-EINVAL); 237 237 238 - result = htonl(nla_get_be32(tb[NFTA_FIB_RESULT])); 238 + result = ntohl(nla_get_be32(tb[NFTA_FIB_RESULT])); 239 239 240 240 switch (result) { 241 241 case NFT_FIB_RESULT_OIF:
+9 -2
net/ipv6/netfilter/nft_masq_ipv6.c
··· 1 1 /* 2 - * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com> 2 + * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo@debian.org> 3 3 * 4 4 * This program is free software; you can redistribute it and/or modify 5 5 * it under the terms of the GNU General Public License version 2 as ··· 36 36 nft_out(pkt)); 37 37 } 38 38 39 + static void 40 + nft_masq_ipv6_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) 41 + { 42 + nf_ct_netns_put(ctx->net, NFPROTO_IPV6); 43 + } 44 + 39 45 static struct nft_expr_type nft_masq_ipv6_type; 40 46 static const struct nft_expr_ops nft_masq_ipv6_ops = { 41 47 .type = &nft_masq_ipv6_type, 42 48 .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)), 43 49 .eval = nft_masq_ipv6_eval, 44 50 .init = nft_masq_init, 51 + .destroy = nft_masq_ipv6_destroy, 45 52 .dump = nft_masq_dump, 46 53 .validate = nft_masq_validate, 47 54 }; ··· 85 78 module_exit(nft_masq_ipv6_module_exit); 86 79 87 80 MODULE_LICENSE("GPL"); 88 - MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>"); 81 + MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>"); 89 82 MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "masq");
+9 -2
net/ipv6/netfilter/nft_redir_ipv6.c
··· 1 1 /* 2 - * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com> 2 + * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo@debian.org> 3 3 * 4 4 * This program is free software; you can redistribute it and/or modify 5 5 * it under the terms of the GNU General Public License version 2 as ··· 39 39 nf_nat_redirect_ipv6(pkt->skb, &range, nft_hook(pkt)); 40 40 } 41 41 42 + static void 43 + nft_redir_ipv6_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) 44 + { 45 + nf_ct_netns_put(ctx->net, NFPROTO_IPV6); 46 + } 47 + 42 48 static struct nft_expr_type nft_redir_ipv6_type; 43 49 static const struct nft_expr_ops nft_redir_ipv6_ops = { 44 50 .type = &nft_redir_ipv6_type, 45 51 .size = NFT_EXPR_SIZE(sizeof(struct nft_redir)), 46 52 .eval = nft_redir_ipv6_eval, 47 53 .init = nft_redir_init, 54 + .destroy = nft_redir_ipv6_destroy, 48 55 .dump = nft_redir_dump, 49 56 .validate = nft_redir_validate, 50 57 }; ··· 79 72 module_exit(nft_redir_ipv6_module_exit); 80 73 81 74 MODULE_LICENSE("GPL"); 82 - MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>"); 75 + MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>"); 83 76 MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "redir");
+18 -12
net/netfilter/Kconfig
··· 146 146 to connection tracking entries. It selected by the connlabel match. 147 147 148 148 config NF_CT_PROTO_DCCP 149 - tristate 'DCCP protocol connection tracking support' 149 + bool 'DCCP protocol connection tracking support' 150 150 depends on NETFILTER_ADVANCED 151 - default IP_DCCP 151 + default y 152 152 help 153 153 With this option enabled, the layer 3 independent connection 154 154 tracking code will be able to do state tracking on DCCP connections. 155 155 156 - If unsure, say 'N'. 156 + If unsure, say Y. 157 157 158 158 config NF_CT_PROTO_GRE 159 159 tristate 160 160 161 161 config NF_CT_PROTO_SCTP 162 - tristate 'SCTP protocol connection tracking support' 162 + bool 'SCTP protocol connection tracking support' 163 163 depends on NETFILTER_ADVANCED 164 - default IP_SCTP 164 + default y 165 165 help 166 166 With this option enabled, the layer 3 independent connection 167 167 tracking code will be able to do state tracking on SCTP connections. 168 168 169 - If you want to compile it as a module, say M here and read 170 - <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. 169 + If unsure, say Y. 171 170 172 171 config NF_CT_PROTO_UDPLITE 173 - tristate 'UDP-Lite protocol connection tracking support' 172 + bool 'UDP-Lite protocol connection tracking support' 174 173 depends on NETFILTER_ADVANCED 174 + default y 175 175 help 176 176 With this option enabled, the layer 3 independent connection 177 177 tracking code will be able to do state tracking on UDP-Lite 178 178 connections. 179 179 180 - To compile it as a module, choose M here. If unsure, say N. 180 + If unsure, say Y. 181 181 182 182 config NF_CONNTRACK_AMANDA 183 183 tristate "Amanda backup protocol support" ··· 384 384 default y 385 385 386 386 config NF_NAT_PROTO_DCCP 387 - tristate 387 + bool 388 388 depends on NF_NAT && NF_CT_PROTO_DCCP 389 389 default NF_NAT && NF_CT_PROTO_DCCP 390 390 391 391 config NF_NAT_PROTO_UDPLITE 392 - tristate 392 + bool 393 393 depends on NF_NAT && NF_CT_PROTO_UDPLITE 394 394 default NF_NAT && NF_CT_PROTO_UDPLITE 395 395 396 396 config NF_NAT_PROTO_SCTP 397 - tristate 397 + bool 398 398 default NF_NAT && NF_CT_PROTO_SCTP 399 399 depends on NF_NAT && NF_CT_PROTO_SCTP 400 400 select LIBCRC32C ··· 550 550 help 551 551 This option adds the "nat" expression that you can use to perform 552 552 typical Network Address Translation (NAT) packet transformations. 553 + 554 + config NFT_OBJREF 555 + tristate "Netfilter nf_tables stateful object reference module" 556 + help 557 + This option adds the "objref" expression that allows you to refer to 558 + stateful objects, such as counters and quotas. 553 559 554 560 config NFT_QUEUE 555 561 depends on NETFILTER_NETLINK_QUEUE
+9 -9
net/netfilter/Makefile
··· 5 5 nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMESTAMP) += nf_conntrack_timestamp.o 6 6 nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o 7 7 nf_conntrack-$(CONFIG_NF_CONNTRACK_LABELS) += nf_conntrack_labels.o 8 + nf_conntrack-$(CONFIG_NF_CT_PROTO_DCCP) += nf_conntrack_proto_dccp.o 9 + nf_conntrack-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o 10 + nf_conntrack-$(CONFIG_NF_CT_PROTO_UDPLITE) += nf_conntrack_proto_udplite.o 8 11 9 12 obj-$(CONFIG_NETFILTER) = netfilter.o 10 13 ··· 19 16 # connection tracking 20 17 obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o 21 18 22 - # SCTP protocol connection tracking 23 - obj-$(CONFIG_NF_CT_PROTO_DCCP) += nf_conntrack_proto_dccp.o 24 19 obj-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o 25 - obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o 26 - obj-$(CONFIG_NF_CT_PROTO_UDPLITE) += nf_conntrack_proto_udplite.o 27 20 28 21 # netlink interface for nf_conntrack 29 22 obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o ··· 44 45 nf_nat-y := nf_nat_core.o nf_nat_proto_unknown.o nf_nat_proto_common.o \ 45 46 nf_nat_proto_udp.o nf_nat_proto_tcp.o nf_nat_helper.o 46 47 48 + # NAT protocols (nf_nat) 49 + nf_nat-$(CONFIG_NF_NAT_PROTO_DCCP) += nf_nat_proto_dccp.o 50 + nf_nat-$(CONFIG_NF_NAT_PROTO_SCTP) += nf_nat_proto_sctp.o 51 + nf_nat-$(CONFIG_NF_NAT_PROTO_UDPLITE) += nf_nat_proto_udplite.o 52 + 47 53 # generic transport layer logging 48 54 obj-$(CONFIG_NF_LOG_COMMON) += nf_log_common.o 49 55 ··· 57 53 58 54 obj-$(CONFIG_NF_NAT) += nf_nat.o 59 55 obj-$(CONFIG_NF_NAT_REDIRECT) += nf_nat_redirect.o 60 - 61 - # NAT protocols (nf_nat) 62 - obj-$(CONFIG_NF_NAT_PROTO_DCCP) += nf_nat_proto_dccp.o 63 - obj-$(CONFIG_NF_NAT_PROTO_UDPLITE) += nf_nat_proto_udplite.o 64 - obj-$(CONFIG_NF_NAT_PROTO_SCTP) += nf_nat_proto_sctp.o 65 56 66 57 # NAT helpers 67 58 obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o ··· 88 89 obj-$(CONFIG_NFT_CT) += nft_ct.o 89 90 obj-$(CONFIG_NFT_LIMIT) += nft_limit.o 90 91 obj-$(CONFIG_NFT_NAT) += nft_nat.o 92 + obj-$(CONFIG_NFT_OBJREF) += nft_objref.o 91 93 obj-$(CONFIG_NFT_QUEUE) += nft_queue.o 92 94 obj-$(CONFIG_NFT_QUOTA) += nft_quota.o 93 95 obj-$(CONFIG_NFT_REJECT) += nft_reject.o
+6 -10
net/netfilter/core.c
··· 102 102 if (!entry) 103 103 return -ENOMEM; 104 104 105 - entry->orig_ops = reg; 106 - entry->ops = *reg; 107 - entry->next = NULL; 105 + nf_hook_entry_init(entry, reg); 108 106 109 107 mutex_lock(&nf_hook_mutex); 110 108 111 109 /* Find the spot in the list */ 112 - while ((p = nf_entry_dereference(*pp)) != NULL) { 113 - if (reg->priority < p->orig_ops->priority) 110 + for (; (p = nf_entry_dereference(*pp)) != NULL; pp = &p->next) { 111 + if (reg->priority < nf_hook_entry_priority(p)) 114 112 break; 115 - pp = &p->next; 116 113 } 117 114 rcu_assign_pointer(entry->next, p); 118 115 rcu_assign_pointer(*pp, entry); ··· 136 139 return; 137 140 138 141 mutex_lock(&nf_hook_mutex); 139 - while ((p = nf_entry_dereference(*pp)) != NULL) { 140 - if (p->orig_ops == reg) { 142 + for (; (p = nf_entry_dereference(*pp)) != NULL; pp = &p->next) { 143 + if (nf_hook_entry_ops(p) == reg) { 141 144 rcu_assign_pointer(*pp, p->next); 142 145 break; 143 146 } 144 - pp = &p->next; 145 147 } 146 148 mutex_unlock(&nf_hook_mutex); 147 149 if (!p) { ··· 307 311 int ret; 308 312 309 313 do { 310 - verdict = entry->ops.hook(entry->ops.priv, skb, state); 314 + verdict = nf_hook_entry_hookfn(entry, skb, state); 311 315 switch (verdict & NF_VERDICT_MASK) { 312 316 case NF_ACCEPT: 313 317 entry = rcu_dereference(entry->next);
+1 -1
net/netfilter/ipvs/ip_vs_ctl.c
··· 3260 3260 3261 3261 3262 3262 svc = ip_vs_genl_find_service(ipvs, attrs[IPVS_CMD_ATTR_SERVICE]); 3263 - if (IS_ERR(svc) || svc == NULL) 3263 + if (IS_ERR_OR_NULL(svc)) 3264 3264 goto out_err; 3265 3265 3266 3266 /* Dump the destinations */
+54
net/netfilter/ipvs/ip_vs_xmit.c
··· 254 254 return true; 255 255 } 256 256 257 + static inline bool decrement_ttl(struct netns_ipvs *ipvs, 258 + int skb_af, 259 + struct sk_buff *skb) 260 + { 261 + struct net *net = ipvs->net; 262 + 263 + #ifdef CONFIG_IP_VS_IPV6 264 + if (skb_af == AF_INET6) { 265 + struct dst_entry *dst = skb_dst(skb); 266 + 267 + /* check and decrement ttl */ 268 + if (ipv6_hdr(skb)->hop_limit <= 1) { 269 + /* Force OUTPUT device used as source address */ 270 + skb->dev = dst->dev; 271 + icmpv6_send(skb, ICMPV6_TIME_EXCEED, 272 + ICMPV6_EXC_HOPLIMIT, 0); 273 + __IP6_INC_STATS(net, ip6_dst_idev(dst), 274 + IPSTATS_MIB_INHDRERRORS); 275 + 276 + return false; 277 + } 278 + 279 + /* don't propagate ttl change to cloned packets */ 280 + if (!skb_make_writable(skb, sizeof(struct ipv6hdr))) 281 + return false; 282 + 283 + ipv6_hdr(skb)->hop_limit--; 284 + } else 285 + #endif 286 + { 287 + if (ip_hdr(skb)->ttl <= 1) { 288 + /* Tell the sender its packet died... */ 289 + __IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS); 290 + icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0); 291 + return false; 292 + } 293 + 294 + /* don't propagate ttl change to cloned packets */ 295 + if (!skb_make_writable(skb, sizeof(struct iphdr))) 296 + return false; 297 + 298 + /* Decrease ttl */ 299 + ip_decrease_ttl(ip_hdr(skb)); 300 + } 301 + 302 + return true; 303 + } 304 + 257 305 /* Get route to destination or remote server */ 258 306 static int 259 307 __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb, ··· 373 325 ip_rt_put(rt); 374 326 return local; 375 327 } 328 + 329 + if (!decrement_ttl(ipvs, skb_af, skb)) 330 + goto err_put; 376 331 377 332 if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL))) { 378 333 mtu = dst_mtu(&rt->dst); ··· 523 472 dst_release(&rt->dst); 524 473 return local; 525 474 } 475 + 476 + if (!decrement_ttl(ipvs, skb_af, skb)) 477 + goto err_put; 526 478 527 479 /* MTU checking */ 528 480 if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL)))
+65 -8
net/netfilter/nf_conntrack_proto.c
··· 125 125 } 126 126 EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put); 127 127 128 + int nf_ct_netns_get(struct net *net, u8 nfproto) 129 + { 130 + const struct nf_conntrack_l3proto *l3proto; 131 + int ret; 132 + 133 + might_sleep(); 134 + 135 + ret = nf_ct_l3proto_try_module_get(nfproto); 136 + if (ret < 0) 137 + return ret; 138 + 139 + /* we already have a reference, can't fail */ 140 + rcu_read_lock(); 141 + l3proto = __nf_ct_l3proto_find(nfproto); 142 + rcu_read_unlock(); 143 + 144 + if (!l3proto->net_ns_get) 145 + return 0; 146 + 147 + ret = l3proto->net_ns_get(net); 148 + if (ret < 0) 149 + nf_ct_l3proto_module_put(nfproto); 150 + 151 + return ret; 152 + } 153 + EXPORT_SYMBOL_GPL(nf_ct_netns_get); 154 + 155 + void nf_ct_netns_put(struct net *net, u8 nfproto) 156 + { 157 + const struct nf_conntrack_l3proto *l3proto; 158 + 159 + might_sleep(); 160 + 161 + /* same as nf_conntrack_netns_get(), reference assumed */ 162 + rcu_read_lock(); 163 + l3proto = __nf_ct_l3proto_find(nfproto); 164 + rcu_read_unlock(); 165 + 166 + if (WARN_ON(!l3proto)) 167 + return; 168 + 169 + if (l3proto->net_ns_put) 170 + l3proto->net_ns_put(net); 171 + 172 + nf_ct_l3proto_module_put(nfproto); 173 + } 174 + EXPORT_SYMBOL_GPL(nf_ct_netns_put); 175 + 128 176 struct nf_conntrack_l4proto * 129 177 nf_ct_l4proto_find_get(u_int16_t l3num, u_int8_t l4num) 130 178 { ··· 238 190 } 239 191 EXPORT_SYMBOL_GPL(nf_ct_l3proto_register); 240 192 193 + #ifdef CONFIG_SYSCTL 194 + extern unsigned int nf_conntrack_default_on; 195 + 241 196 int nf_ct_l3proto_pernet_register(struct net *net, 242 197 struct nf_conntrack_l3proto *proto) 243 198 { 244 - int ret; 199 + if (nf_conntrack_default_on == 0) 200 + return 0; 245 201 246 - if (proto->init_net) { 247 - ret = proto->init_net(net); 248 - if (ret < 0) 249 - return ret; 250 - } 251 - 252 - return 0; 202 + return proto->net_ns_get ? proto->net_ns_get(net) : 0; 253 203 } 254 204 EXPORT_SYMBOL_GPL(nf_ct_l3proto_pernet_register); 205 + #endif 255 206 256 207 void nf_ct_l3proto_unregister(struct nf_conntrack_l3proto *proto) 257 208 { ··· 271 224 void nf_ct_l3proto_pernet_unregister(struct net *net, 272 225 struct nf_conntrack_l3proto *proto) 273 226 { 227 + /* 228 + * nf_conntrack_default_on *might* have registered hooks. 229 + * ->net_ns_put must cope with more puts() than get(), i.e. 230 + * if nf_conntrack_default_on was 0 at time of 231 + * nf_ct_l3proto_pernet_register invocation this net_ns_put() 232 + * should be a noop. 233 + */ 234 + if (proto->net_ns_put) 235 + proto->net_ns_put(net); 236 + 274 237 /* Remove all contrack entries for this protocol */ 275 238 nf_ct_iterate_cleanup(net, kill_l3proto, proto, 0, 0); 276 239 }
+10 -69
net/netfilter/nf_conntrack_proto_dccp.c
··· 9 9 * 10 10 */ 11 11 #include <linux/kernel.h> 12 - #include <linux/module.h> 13 12 #include <linux/init.h> 14 13 #include <linux/sysctl.h> 15 14 #include <linux/spinlock.h> ··· 383 384 }, 384 385 }; 385 386 386 - /* this module per-net specifics */ 387 - static unsigned int dccp_net_id __read_mostly; 388 - struct dccp_net { 389 - struct nf_proto_net pn; 390 - int dccp_loose; 391 - unsigned int dccp_timeout[CT_DCCP_MAX + 1]; 392 - }; 393 - 394 - static inline struct dccp_net *dccp_pernet(struct net *net) 387 + static inline struct nf_dccp_net *dccp_pernet(struct net *net) 395 388 { 396 - return net_generic(net, dccp_net_id); 389 + return &net->ct.nf_ct_proto.dccp; 397 390 } 398 391 399 392 static bool dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, ··· 415 424 unsigned int dataoff, unsigned int *timeouts) 416 425 { 417 426 struct net *net = nf_ct_net(ct); 418 - struct dccp_net *dn; 427 + struct nf_dccp_net *dn; 419 428 struct dccp_hdr _dh, *dh; 420 429 const char *msg; 421 430 u_int8_t state; ··· 710 719 static int dccp_timeout_nlattr_to_obj(struct nlattr *tb[], 711 720 struct net *net, void *data) 712 721 { 713 - struct dccp_net *dn = dccp_pernet(net); 722 + struct nf_dccp_net *dn = dccp_pernet(net); 714 723 unsigned int *timeouts = data; 715 724 int i; 716 725 ··· 811 820 #endif /* CONFIG_SYSCTL */ 812 821 813 822 static int dccp_kmemdup_sysctl_table(struct net *net, struct nf_proto_net *pn, 814 - struct dccp_net *dn) 823 + struct nf_dccp_net *dn) 815 824 { 816 825 #ifdef CONFIG_SYSCTL 817 826 if (pn->ctl_table) ··· 841 850 842 851 static int dccp_init_net(struct net *net, u_int16_t proto) 843 852 { 844 - struct dccp_net *dn = dccp_pernet(net); 853 + struct nf_dccp_net *dn = dccp_pernet(net); 845 854 struct nf_proto_net *pn = &dn->pn; 846 855 847 856 if (!pn->users) { ··· 859 868 return dccp_kmemdup_sysctl_table(net, pn, dn); 860 869 } 861 870 862 - static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = { 871 + struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4 __read_mostly = { 863 872 .l3proto = AF_INET, 864 873 .l4proto = IPPROTO_DCCP, 865 874 .name = "dccp", ··· 889 898 .nla_policy = dccp_timeout_nla_policy, 890 899 }, 891 900 #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ 892 - .net_id = &dccp_net_id, 893 901 .init_net = dccp_init_net, 894 902 }; 903 + EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_dccp4); 895 904 896 - static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = { 905 + struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6 __read_mostly = { 897 906 .l3proto = AF_INET6, 898 907 .l4proto = IPPROTO_DCCP, 899 908 .name = "dccp", ··· 923 932 .nla_policy = dccp_timeout_nla_policy, 924 933 }, 925 934 #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ 926 - .net_id = &dccp_net_id, 927 935 .init_net = dccp_init_net, 928 936 }; 929 - 930 - static struct nf_conntrack_l4proto *dccp_proto[] = { 931 - &dccp_proto4, 932 - &dccp_proto6, 933 - }; 934 - 935 - static __net_init int dccp_net_init(struct net *net) 936 - { 937 - return nf_ct_l4proto_pernet_register(net, dccp_proto, 938 - ARRAY_SIZE(dccp_proto)); 939 - } 940 - 941 - static __net_exit void dccp_net_exit(struct net *net) 942 - { 943 - nf_ct_l4proto_pernet_unregister(net, dccp_proto, 944 - ARRAY_SIZE(dccp_proto)); 945 - } 946 - 947 - static struct pernet_operations dccp_net_ops = { 948 - .init = dccp_net_init, 949 - .exit = dccp_net_exit, 950 - .id = &dccp_net_id, 951 - .size = sizeof(struct dccp_net), 952 - }; 953 - 954 - static int __init nf_conntrack_proto_dccp_init(void) 955 - { 956 - int ret; 957 - 958 - ret = register_pernet_subsys(&dccp_net_ops); 959 - if (ret < 0) 960 - return ret; 961 - ret = nf_ct_l4proto_register(dccp_proto, ARRAY_SIZE(dccp_proto)); 962 - if (ret < 0) 963 - unregister_pernet_subsys(&dccp_net_ops); 964 - return ret; 965 - } 966 - 967 - static void __exit nf_conntrack_proto_dccp_fini(void) 968 - { 969 - nf_ct_l4proto_unregister(dccp_proto, ARRAY_SIZE(dccp_proto)); 970 - unregister_pernet_subsys(&dccp_net_ops); 971 - } 972 - 973 - module_init(nf_conntrack_proto_dccp_init); 974 - module_exit(nf_conntrack_proto_dccp_fini); 975 - 976 - MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 977 - MODULE_DESCRIPTION("DCCP connection tracking protocol helper"); 978 - MODULE_LICENSE("GPL"); 937 + EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_dccp6);
+9 -67
net/netfilter/nf_conntrack_proto_sctp.c
··· 15 15 #include <linux/types.h> 16 16 #include <linux/timer.h> 17 17 #include <linux/netfilter.h> 18 - #include <linux/module.h> 19 18 #include <linux/in.h> 20 19 #include <linux/ip.h> 21 20 #include <linux/sctp.h> ··· 143 144 } 144 145 }; 145 146 146 - static unsigned int sctp_net_id __read_mostly; 147 - struct sctp_net { 148 - struct nf_proto_net pn; 149 - unsigned int timeouts[SCTP_CONNTRACK_MAX]; 150 - }; 151 - 152 - static inline struct sctp_net *sctp_pernet(struct net *net) 147 + static inline struct nf_sctp_net *sctp_pernet(struct net *net) 153 148 { 154 - return net_generic(net, sctp_net_id); 149 + return &net->ct.nf_ct_proto.sctp; 155 150 } 156 151 157 152 static bool sctp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, ··· 593 600 struct net *net, void *data) 594 601 { 595 602 unsigned int *timeouts = data; 596 - struct sctp_net *sn = sctp_pernet(net); 603 + struct nf_sctp_net *sn = sctp_pernet(net); 597 604 int i; 598 605 599 606 /* set default SCTP timeouts. */ ··· 701 708 #endif 702 709 703 710 static int sctp_kmemdup_sysctl_table(struct nf_proto_net *pn, 704 - struct sctp_net *sn) 711 + struct nf_sctp_net *sn) 705 712 { 706 713 #ifdef CONFIG_SYSCTL 707 714 if (pn->ctl_table) ··· 728 735 729 736 static int sctp_init_net(struct net *net, u_int16_t proto) 730 737 { 731 - struct sctp_net *sn = sctp_pernet(net); 738 + struct nf_sctp_net *sn = sctp_pernet(net); 732 739 struct nf_proto_net *pn = &sn->pn; 733 740 734 741 if (!pn->users) { ··· 741 748 return sctp_kmemdup_sysctl_table(pn, sn); 742 749 } 743 750 744 - static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = { 751 + struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = { 745 752 .l3proto = PF_INET, 746 753 .l4proto = IPPROTO_SCTP, 747 754 .name = "sctp", ··· 771 778 .nla_policy = sctp_timeout_nla_policy, 772 779 }, 773 780 #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ 774 - .net_id = &sctp_net_id, 775 781 .init_net = sctp_init_net, 776 782 }; 783 + EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_sctp4); 777 784 778 - static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = { 785 + struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = { 779 786 .l3proto = PF_INET6, 780 787 .l4proto = IPPROTO_SCTP, 781 788 .name = "sctp", ··· 805 812 }, 806 813 #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ 807 814 #endif 808 - .net_id = &sctp_net_id, 809 815 .init_net = sctp_init_net, 810 816 }; 811 - 812 - static struct nf_conntrack_l4proto *sctp_proto[] = { 813 - &nf_conntrack_l4proto_sctp4, 814 - &nf_conntrack_l4proto_sctp6, 815 - }; 816 - 817 - static int sctp_net_init(struct net *net) 818 - { 819 - return nf_ct_l4proto_pernet_register(net, sctp_proto, 820 - ARRAY_SIZE(sctp_proto)); 821 - } 822 - 823 - static void sctp_net_exit(struct net *net) 824 - { 825 - nf_ct_l4proto_pernet_unregister(net, sctp_proto, 826 - ARRAY_SIZE(sctp_proto)); 827 - } 828 - 829 - static struct pernet_operations sctp_net_ops = { 830 - .init = sctp_net_init, 831 - .exit = sctp_net_exit, 832 - .id = &sctp_net_id, 833 - .size = sizeof(struct sctp_net), 834 - }; 835 - 836 - static int __init nf_conntrack_proto_sctp_init(void) 837 - { 838 - int ret; 839 - 840 - ret = register_pernet_subsys(&sctp_net_ops); 841 - if (ret < 0) 842 - return ret; 843 - ret = nf_ct_l4proto_register(sctp_proto, ARRAY_SIZE(sctp_proto)); 844 - if (ret < 0) 845 - unregister_pernet_subsys(&sctp_net_ops); 846 - return ret; 847 - } 848 - 849 - static void __exit nf_conntrack_proto_sctp_fini(void) 850 - { 851 - nf_ct_l4proto_unregister(sctp_proto, ARRAY_SIZE(sctp_proto)); 852 - unregister_pernet_subsys(&sctp_net_ops); 853 - } 854 - 855 - module_init(nf_conntrack_proto_sctp_init); 856 - module_exit(nf_conntrack_proto_sctp_fini); 857 - 858 - MODULE_LICENSE("GPL"); 859 - MODULE_AUTHOR("Kiran Kumar Immidi"); 860 - MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP"); 861 - MODULE_ALIAS("ip_conntrack_proto_sctp"); 817 + EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_sctp6);
+9 -70
net/netfilter/nf_conntrack_proto_udplite.c
··· 9 9 10 10 #include <linux/types.h> 11 11 #include <linux/timer.h> 12 - #include <linux/module.h> 13 12 #include <linux/udp.h> 14 13 #include <linux/seq_file.h> 15 14 #include <linux/skbuff.h> ··· 23 24 #include <net/netfilter/nf_conntrack_ecache.h> 24 25 #include <net/netfilter/nf_log.h> 25 26 26 - enum udplite_conntrack { 27 - UDPLITE_CT_UNREPLIED, 28 - UDPLITE_CT_REPLIED, 29 - UDPLITE_CT_MAX 30 - }; 31 - 32 27 static unsigned int udplite_timeouts[UDPLITE_CT_MAX] = { 33 28 [UDPLITE_CT_UNREPLIED] = 30*HZ, 34 29 [UDPLITE_CT_REPLIED] = 180*HZ, 35 30 }; 36 31 37 - static unsigned int udplite_net_id __read_mostly; 38 - struct udplite_net { 39 - struct nf_proto_net pn; 40 - unsigned int timeouts[UDPLITE_CT_MAX]; 41 - }; 42 - 43 - static inline struct udplite_net *udplite_pernet(struct net *net) 32 + static inline struct nf_udplite_net *udplite_pernet(struct net *net) 44 33 { 45 - return net_generic(net, udplite_net_id); 34 + return &net->ct.nf_ct_proto.udplite; 46 35 } 47 36 48 37 static bool udplite_pkt_to_tuple(const struct sk_buff *skb, ··· 165 178 struct net *net, void *data) 166 179 { 167 180 unsigned int *timeouts = data; 168 - struct udplite_net *un = udplite_pernet(net); 181 + struct nf_udplite_net *un = udplite_pernet(net); 169 182 170 183 /* set default timeouts for UDPlite. */ 171 184 timeouts[UDPLITE_CT_UNREPLIED] = un->timeouts[UDPLITE_CT_UNREPLIED]; ··· 224 237 #endif /* CONFIG_SYSCTL */ 225 238 226 239 static int udplite_kmemdup_sysctl_table(struct nf_proto_net *pn, 227 - struct udplite_net *un) 240 + struct nf_udplite_net *un) 228 241 { 229 242 #ifdef CONFIG_SYSCTL 230 243 if (pn->ctl_table) ··· 244 257 245 258 static int udplite_init_net(struct net *net, u_int16_t proto) 246 259 { 247 - struct udplite_net *un = udplite_pernet(net); 260 + struct nf_udplite_net *un = udplite_pernet(net); 248 261 struct nf_proto_net *pn = &un->pn; 249 262 250 263 if (!pn->users) { ··· 257 270 return udplite_kmemdup_sysctl_table(pn, un); 258 271 } 259 272 260 - static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly = 273 + struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly = 261 274 { 262 275 .l3proto = PF_INET, 263 276 .l4proto = IPPROTO_UDPLITE, ··· 286 299 .nla_policy = udplite_timeout_nla_policy, 287 300 }, 288 301 #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ 289 - .net_id = &udplite_net_id, 290 302 .init_net = udplite_init_net, 291 303 }; 304 + EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udplite4); 292 305 293 - static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly = 306 + struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly = 294 307 { 295 308 .l3proto = PF_INET6, 296 309 .l4proto = IPPROTO_UDPLITE, ··· 319 332 .nla_policy = udplite_timeout_nla_policy, 320 333 }, 321 334 #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ 322 - .net_id = &udplite_net_id, 323 335 .init_net = udplite_init_net, 324 336 }; 325 - 326 - static struct nf_conntrack_l4proto *udplite_proto[] = { 327 - &nf_conntrack_l4proto_udplite4, 328 - &nf_conntrack_l4proto_udplite6, 329 - }; 330 - 331 - static int udplite_net_init(struct net *net) 332 - { 333 - return nf_ct_l4proto_pernet_register(net, udplite_proto, 334 - ARRAY_SIZE(udplite_proto)); 335 - } 336 - 337 - static void udplite_net_exit(struct net *net) 338 - { 339 - nf_ct_l4proto_pernet_unregister(net, udplite_proto, 340 - ARRAY_SIZE(udplite_proto)); 341 - } 342 - 343 - static struct pernet_operations udplite_net_ops = { 344 - .init = udplite_net_init, 345 - .exit = udplite_net_exit, 346 - .id = &udplite_net_id, 347 - .size = sizeof(struct udplite_net), 348 - }; 349 - 350 - static int __init nf_conntrack_proto_udplite_init(void) 351 - { 352 - int ret; 353 - 354 - ret = register_pernet_subsys(&udplite_net_ops); 355 - if (ret < 0) 356 - return ret; 357 - ret = nf_ct_l4proto_register(udplite_proto, ARRAY_SIZE(udplite_proto)); 358 - if (ret < 0) 359 - unregister_pernet_subsys(&udplite_net_ops); 360 - return ret; 361 - } 362 - 363 - static void __exit nf_conntrack_proto_udplite_exit(void) 364 - { 365 - nf_ct_l4proto_unregister(udplite_proto, ARRAY_SIZE(udplite_proto)); 366 - unregister_pernet_subsys(&udplite_net_ops); 367 - } 368 - 369 - module_init(nf_conntrack_proto_udplite_init); 370 - module_exit(nf_conntrack_proto_udplite_exit); 371 - 372 - MODULE_LICENSE("GPL"); 337 + EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udplite6);
+10
net/netfilter/nf_conntrack_standalone.c
··· 452 452 /* size the user *wants to set */ 453 453 static unsigned int nf_conntrack_htable_size_user __read_mostly; 454 454 455 + extern unsigned int nf_conntrack_default_on; 456 + unsigned int nf_conntrack_default_on __read_mostly = 1; 457 + 455 458 static int 456 459 nf_conntrack_hash_sysctl(struct ctl_table *table, int write, 457 460 void __user *buffer, size_t *lenp, loff_t *ppos) ··· 517 514 .procname = "nf_conntrack_expect_max", 518 515 .data = &nf_ct_expect_max, 519 516 .maxlen = sizeof(int), 517 + .mode = 0644, 518 + .proc_handler = proc_dointvec, 519 + }, 520 + { 521 + .procname = "nf_conntrack_default_on", 522 + .data = &nf_conntrack_default_on, 523 + .maxlen = sizeof(unsigned int), 520 524 .mode = 0644, 521 525 .proc_handler = proc_dointvec, 522 526 },
+25 -8
net/netfilter/nf_dup_netdev.c
··· 14 14 #include <linux/netfilter/nf_tables.h> 15 15 #include <net/netfilter/nf_tables.h> 16 16 17 + static void nf_do_netdev_egress(struct sk_buff *skb, struct net_device *dev) 18 + { 19 + if (skb_mac_header_was_set(skb)) 20 + skb_push(skb, skb->mac_len); 21 + 22 + skb->dev = dev; 23 + dev_queue_xmit(skb); 24 + } 25 + 26 + void nf_fwd_netdev_egress(const struct nft_pktinfo *pkt, int oif) 27 + { 28 + struct net_device *dev; 29 + 30 + dev = dev_get_by_index_rcu(nft_net(pkt), oif); 31 + if (!dev) { 32 + kfree_skb(pkt->skb); 33 + return; 34 + } 35 + 36 + nf_do_netdev_egress(pkt->skb, dev); 37 + } 38 + EXPORT_SYMBOL_GPL(nf_fwd_netdev_egress); 39 + 17 40 void nf_dup_netdev_egress(const struct nft_pktinfo *pkt, int oif) 18 41 { 19 42 struct net_device *dev; ··· 47 24 return; 48 25 49 26 skb = skb_clone(pkt->skb, GFP_ATOMIC); 50 - if (skb == NULL) 51 - return; 52 - 53 - if (skb_mac_header_was_set(skb)) 54 - skb_push(skb, skb->mac_len); 55 - 56 - skb->dev = dev; 57 - dev_queue_xmit(skb); 27 + if (skb) 28 + nf_do_netdev_egress(skb, dev); 58 29 } 59 30 EXPORT_SYMBOL_GPL(nf_dup_netdev_egress); 60 31
+2 -1
net/netfilter/nf_log_common.c
··· 177 177 178 178 /* bridge and netdev logging families share this code. */ 179 179 void nf_log_l2packet(struct net *net, u_int8_t pf, 180 + __be16 protocol, 180 181 unsigned int hooknum, 181 182 const struct sk_buff *skb, 182 183 const struct net_device *in, ··· 185 184 const struct nf_loginfo *loginfo, 186 185 const char *prefix) 187 186 { 188 - switch (eth_hdr(skb)->h_proto) { 187 + switch (protocol) { 189 188 case htons(ETH_P_IP): 190 189 nf_log_packet(net, NFPROTO_IPV4, hooknum, skb, in, out, 191 190 loginfo, "%s", prefix);
+2 -1
net/netfilter/nf_log_netdev.c
··· 23 23 const struct nf_loginfo *loginfo, 24 24 const char *prefix) 25 25 { 26 - nf_log_l2packet(net, pf, hooknum, skb, in, out, loginfo, prefix); 26 + nf_log_l2packet(net, pf, skb->protocol, hooknum, skb, in, out, 27 + loginfo, prefix); 27 28 } 28 29 29 30 static struct nf_logger nf_netdev_logger __read_mostly = {
+12
net/netfilter/nf_nat_core.c
··· 682 682 &nf_nat_l4proto_tcp); 683 683 RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_UDP], 684 684 &nf_nat_l4proto_udp); 685 + #ifdef CONFIG_NF_NAT_PROTO_DCCP 686 + RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_DCCP], 687 + &nf_nat_l4proto_dccp); 688 + #endif 689 + #ifdef CONFIG_NF_NAT_PROTO_SCTP 690 + RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_SCTP], 691 + &nf_nat_l4proto_sctp); 692 + #endif 693 + #ifdef CONFIG_NF_NAT_PROTO_UDPLITE 694 + RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_UDPLITE], 695 + &nf_nat_l4proto_udplite); 696 + #endif 685 697 mutex_unlock(&nf_nat_proto_mutex); 686 698 687 699 RCU_INIT_POINTER(nf_nat_l3protos[l3proto->l3proto], l3proto);
+1 -35
net/netfilter/nf_nat_proto_dccp.c
··· 10 10 */ 11 11 12 12 #include <linux/kernel.h> 13 - #include <linux/module.h> 14 - #include <linux/init.h> 15 13 #include <linux/skbuff.h> 16 14 #include <linux/dccp.h> 17 15 ··· 71 73 return true; 72 74 } 73 75 74 - static const struct nf_nat_l4proto nf_nat_l4proto_dccp = { 76 + const struct nf_nat_l4proto nf_nat_l4proto_dccp = { 75 77 .l4proto = IPPROTO_DCCP, 76 78 .manip_pkt = dccp_manip_pkt, 77 79 .in_range = nf_nat_l4proto_in_range, ··· 80 82 .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, 81 83 #endif 82 84 }; 83 - 84 - static int __init nf_nat_proto_dccp_init(void) 85 - { 86 - int err; 87 - 88 - err = nf_nat_l4proto_register(NFPROTO_IPV4, &nf_nat_l4proto_dccp); 89 - if (err < 0) 90 - goto err1; 91 - err = nf_nat_l4proto_register(NFPROTO_IPV6, &nf_nat_l4proto_dccp); 92 - if (err < 0) 93 - goto err2; 94 - return 0; 95 - 96 - err2: 97 - nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_dccp); 98 - err1: 99 - return err; 100 - } 101 - 102 - static void __exit nf_nat_proto_dccp_fini(void) 103 - { 104 - nf_nat_l4proto_unregister(NFPROTO_IPV6, &nf_nat_l4proto_dccp); 105 - nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_dccp); 106 - 107 - } 108 - 109 - module_init(nf_nat_proto_dccp_init); 110 - module_exit(nf_nat_proto_dccp_fini); 111 - 112 - MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 113 - MODULE_DESCRIPTION("DCCP NAT protocol helper"); 114 - MODULE_LICENSE("GPL");
+5 -35
net/netfilter/nf_nat_proto_sctp.c
··· 7 7 */ 8 8 9 9 #include <linux/types.h> 10 - #include <linux/init.h> 11 10 #include <linux/sctp.h> 12 - #include <linux/module.h> 13 11 #include <net/sctp/checksum.h> 14 12 15 13 #include <net/netfilter/nf_nat_l4proto.h> ··· 47 49 hdr->dest = tuple->dst.u.sctp.port; 48 50 } 49 51 50 - hdr->checksum = sctp_compute_cksum(skb, hdroff); 52 + if (skb->ip_summed != CHECKSUM_PARTIAL) { 53 + hdr->checksum = sctp_compute_cksum(skb, hdroff); 54 + skb->ip_summed = CHECKSUM_NONE; 55 + } 51 56 52 57 return true; 53 58 } 54 59 55 - static const struct nf_nat_l4proto nf_nat_l4proto_sctp = { 60 + const struct nf_nat_l4proto nf_nat_l4proto_sctp = { 56 61 .l4proto = IPPROTO_SCTP, 57 62 .manip_pkt = sctp_manip_pkt, 58 63 .in_range = nf_nat_l4proto_in_range, ··· 64 63 .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, 65 64 #endif 66 65 }; 67 - 68 - static int __init nf_nat_proto_sctp_init(void) 69 - { 70 - int err; 71 - 72 - err = nf_nat_l4proto_register(NFPROTO_IPV4, &nf_nat_l4proto_sctp); 73 - if (err < 0) 74 - goto err1; 75 - err = nf_nat_l4proto_register(NFPROTO_IPV6, &nf_nat_l4proto_sctp); 76 - if (err < 0) 77 - goto err2; 78 - return 0; 79 - 80 - err2: 81 - nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_sctp); 82 - err1: 83 - return err; 84 - } 85 - 86 - static void __exit nf_nat_proto_sctp_exit(void) 87 - { 88 - nf_nat_l4proto_unregister(NFPROTO_IPV6, &nf_nat_l4proto_sctp); 89 - nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_sctp); 90 - } 91 - 92 - module_init(nf_nat_proto_sctp_init); 93 - module_exit(nf_nat_proto_sctp_exit); 94 - 95 - MODULE_LICENSE("GPL"); 96 - MODULE_DESCRIPTION("SCTP NAT protocol helper"); 97 - MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+1 -34
net/netfilter/nf_nat_proto_udplite.c
··· 8 8 */ 9 9 10 10 #include <linux/types.h> 11 - #include <linux/init.h> 12 11 #include <linux/udp.h> 13 12 14 13 #include <linux/netfilter.h> 15 - #include <linux/module.h> 16 14 #include <net/netfilter/nf_nat.h> 17 15 #include <net/netfilter/nf_nat_l3proto.h> 18 16 #include <net/netfilter/nf_nat_l4proto.h> ··· 62 64 return true; 63 65 } 64 66 65 - static const struct nf_nat_l4proto nf_nat_l4proto_udplite = { 67 + const struct nf_nat_l4proto nf_nat_l4proto_udplite = { 66 68 .l4proto = IPPROTO_UDPLITE, 67 69 .manip_pkt = udplite_manip_pkt, 68 70 .in_range = nf_nat_l4proto_in_range, ··· 71 73 .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, 72 74 #endif 73 75 }; 74 - 75 - static int __init nf_nat_proto_udplite_init(void) 76 - { 77 - int err; 78 - 79 - err = nf_nat_l4proto_register(NFPROTO_IPV4, &nf_nat_l4proto_udplite); 80 - if (err < 0) 81 - goto err1; 82 - err = nf_nat_l4proto_register(NFPROTO_IPV6, &nf_nat_l4proto_udplite); 83 - if (err < 0) 84 - goto err2; 85 - return 0; 86 - 87 - err2: 88 - nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_udplite); 89 - err1: 90 - return err; 91 - } 92 - 93 - static void __exit nf_nat_proto_udplite_fini(void) 94 - { 95 - nf_nat_l4proto_unregister(NFPROTO_IPV6, &nf_nat_l4proto_udplite); 96 - nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_udplite); 97 - } 98 - 99 - module_init(nf_nat_proto_udplite_init); 100 - module_exit(nf_nat_proto_udplite_fini); 101 - 102 - MODULE_LICENSE("GPL"); 103 - MODULE_DESCRIPTION("UDP-Lite NAT protocol helper"); 104 - MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+2 -3
net/netfilter/nf_queue.c
··· 185 185 186 186 do { 187 187 repeat: 188 - verdict = (*entryp)->ops.hook((*entryp)->ops.priv, skb, state); 188 + verdict = nf_hook_entry_hookfn((*entryp), skb, state); 189 189 if (verdict != NF_ACCEPT) { 190 190 if (verdict != NF_REPEAT) 191 191 return verdict; ··· 200 200 void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) 201 201 { 202 202 struct nf_hook_entry *hook_entry = entry->hook; 203 - struct nf_hook_ops *elem = &hook_entry->ops; 204 203 struct sk_buff *skb = entry->skb; 205 204 const struct nf_afinfo *afinfo; 206 205 int err; ··· 208 209 209 210 /* Continue traversal iff userspace said ok... */ 210 211 if (verdict == NF_REPEAT) 211 - verdict = elem->hook(elem->priv, skb, &entry->state); 212 + verdict = nf_hook_entry_hookfn(hook_entry, skb, &entry->state); 212 213 213 214 if (verdict == NF_ACCEPT) { 214 215 afinfo = nf_get_afinfo(entry->state.pf);
+702 -16
net/netfilter/nf_tables_api.c
··· 22 22 #include <net/sock.h> 23 23 24 24 static LIST_HEAD(nf_tables_expressions); 25 + static LIST_HEAD(nf_tables_objects); 25 26 26 27 /** 27 28 * nft_register_afinfo - register nf_tables address family info ··· 111 110 ctx->seq = nlh->nlmsg_seq; 112 111 } 113 112 114 - static struct nft_trans *nft_trans_alloc(struct nft_ctx *ctx, int msg_type, 115 - u32 size) 113 + static struct nft_trans *nft_trans_alloc_gfp(const struct nft_ctx *ctx, 114 + int msg_type, u32 size, gfp_t gfp) 116 115 { 117 116 struct nft_trans *trans; 118 117 119 - trans = kzalloc(sizeof(struct nft_trans) + size, GFP_KERNEL); 118 + trans = kzalloc(sizeof(struct nft_trans) + size, gfp); 120 119 if (trans == NULL) 121 120 return NULL; 122 121 ··· 124 123 trans->ctx = *ctx; 125 124 126 125 return trans; 126 + } 127 + 128 + static struct nft_trans *nft_trans_alloc(const struct nft_ctx *ctx, 129 + int msg_type, u32 size) 130 + { 131 + return nft_trans_alloc_gfp(ctx, msg_type, size, GFP_KERNEL); 127 132 } 128 133 129 134 static void nft_trans_destroy(struct nft_trans *trans) ··· 306 299 return err; 307 300 308 301 nft_deactivate_next(ctx->net, set); 302 + ctx->table->use--; 303 + 304 + return err; 305 + } 306 + 307 + static int nft_trans_obj_add(struct nft_ctx *ctx, int msg_type, 308 + struct nft_object *obj) 309 + { 310 + struct nft_trans *trans; 311 + 312 + trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_obj)); 313 + if (trans == NULL) 314 + return -ENOMEM; 315 + 316 + if (msg_type == NFT_MSG_NEWOBJ) 317 + nft_activate_next(ctx->net, obj); 318 + 319 + nft_trans_obj(trans) = obj; 320 + list_add_tail(&trans->list, &ctx->net->nft.commit_list); 321 + 322 + return 0; 323 + } 324 + 325 + static int nft_delobj(struct nft_ctx *ctx, struct nft_object *obj) 326 + { 327 + int err; 328 + 329 + err = nft_trans_obj_add(ctx, NFT_MSG_DELOBJ, obj); 330 + if (err < 0) 331 + return err; 332 + 333 + nft_deactivate_next(ctx->net, obj); 309 334 ctx->table->use--; 310 335 311 336 return err; ··· 727 688 nla_strlcpy(table->name, name, NFT_TABLE_MAXNAMELEN); 728 689 INIT_LIST_HEAD(&table->chains); 729 690 INIT_LIST_HEAD(&table->sets); 691 + INIT_LIST_HEAD(&table->objects); 730 692 table->flags = flags; 731 693 732 694 nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); ··· 749 709 { 750 710 int err; 751 711 struct nft_chain *chain, *nc; 712 + struct nft_object *obj, *ne; 752 713 struct nft_set *set, *ns; 753 714 754 715 list_for_each_entry(chain, &ctx->table->chains, list) { ··· 772 731 continue; 773 732 774 733 err = nft_delset(ctx, set); 734 + if (err < 0) 735 + goto out; 736 + } 737 + 738 + list_for_each_entry_safe(obj, ne, &ctx->table->objects, list) { 739 + err = nft_delobj(ctx, obj); 775 740 if (err < 0) 776 741 goto out; 777 742 } ··· 2458 2411 [NFTA_SET_GC_INTERVAL] = { .type = NLA_U32 }, 2459 2412 [NFTA_SET_USERDATA] = { .type = NLA_BINARY, 2460 2413 .len = NFT_USERDATA_MAXLEN }, 2414 + [NFTA_SET_OBJ_TYPE] = { .type = NLA_U32 }, 2461 2415 }; 2462 2416 2463 2417 static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = { ··· 2510 2462 } 2511 2463 return ERR_PTR(-ENOENT); 2512 2464 } 2465 + EXPORT_SYMBOL_GPL(nf_tables_set_lookup); 2513 2466 2514 2467 struct nft_set *nf_tables_set_lookup_byid(const struct net *net, 2515 2468 const struct nlattr *nla, ··· 2529 2480 } 2530 2481 return ERR_PTR(-ENOENT); 2531 2482 } 2483 + EXPORT_SYMBOL_GPL(nf_tables_set_lookup_byid); 2532 2484 2533 2485 static int nf_tables_set_alloc_name(struct nft_ctx *ctx, struct nft_set *set, 2534 2486 const char *name) ··· 2618 2568 if (nla_put_be32(skb, NFTA_SET_DATA_LEN, htonl(set->dlen))) 2619 2569 goto nla_put_failure; 2620 2570 } 2571 + if (set->flags & NFT_SET_OBJECT && 2572 + nla_put_be32(skb, NFTA_SET_OBJ_TYPE, htonl(set->objtype))) 2573 + goto nla_put_failure; 2621 2574 2622 2575 if (set->timeout && 2623 2576 nla_put_be64(skb, NFTA_SET_TIMEOUT, ··· 2850 2797 unsigned int size; 2851 2798 bool create; 2852 2799 u64 timeout; 2853 - u32 ktype, dtype, flags, policy, gc_int; 2800 + u32 ktype, dtype, flags, policy, gc_int, objtype; 2854 2801 struct nft_set_desc desc; 2855 2802 unsigned char *udata; 2856 2803 u16 udlen; ··· 2880 2827 flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS])); 2881 2828 if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT | 2882 2829 NFT_SET_INTERVAL | NFT_SET_TIMEOUT | 2883 - NFT_SET_MAP | NFT_SET_EVAL)) 2830 + NFT_SET_MAP | NFT_SET_EVAL | 2831 + NFT_SET_OBJECT)) 2884 2832 return -EINVAL; 2885 - /* Only one of both operations is supported */ 2886 - if ((flags & (NFT_SET_MAP | NFT_SET_EVAL)) == 2887 - (NFT_SET_MAP | NFT_SET_EVAL)) 2833 + /* Only one of these operations is supported */ 2834 + if ((flags & (NFT_SET_MAP | NFT_SET_EVAL | NFT_SET_OBJECT)) == 2835 + (NFT_SET_MAP | NFT_SET_EVAL | NFT_SET_OBJECT)) 2888 2836 return -EOPNOTSUPP; 2889 2837 } 2890 2838 ··· 2909 2855 desc.dlen = sizeof(struct nft_verdict); 2910 2856 } else if (flags & NFT_SET_MAP) 2911 2857 return -EINVAL; 2858 + 2859 + if (nla[NFTA_SET_OBJ_TYPE] != NULL) { 2860 + if (!(flags & NFT_SET_OBJECT)) 2861 + return -EINVAL; 2862 + 2863 + objtype = ntohl(nla_get_be32(nla[NFTA_SET_OBJ_TYPE])); 2864 + if (objtype == NFT_OBJECT_UNSPEC || 2865 + objtype > NFT_OBJECT_MAX) 2866 + return -EINVAL; 2867 + } else if (flags & NFT_SET_OBJECT) 2868 + return -EINVAL; 2869 + else 2870 + objtype = NFT_OBJECT_UNSPEC; 2912 2871 2913 2872 timeout = 0; 2914 2873 if (nla[NFTA_SET_TIMEOUT] != NULL) { ··· 3010 2943 set->ktype = ktype; 3011 2944 set->klen = desc.klen; 3012 2945 set->dtype = dtype; 2946 + set->objtype = objtype; 3013 2947 set->dlen = desc.dlen; 3014 2948 set->flags = flags; 3015 2949 set->size = desc.size; ··· 3132 3064 list_add_tail_rcu(&binding->list, &set->bindings); 3133 3065 return 0; 3134 3066 } 3067 + EXPORT_SYMBOL_GPL(nf_tables_bind_set); 3135 3068 3136 3069 void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set, 3137 3070 struct nft_set_binding *binding) ··· 3143 3074 nft_is_active(ctx->net, set)) 3144 3075 nf_tables_set_destroy(ctx, set); 3145 3076 } 3077 + EXPORT_SYMBOL_GPL(nf_tables_unbind_set); 3146 3078 3147 3079 const struct nft_set_ext_type nft_set_ext_types[] = { 3148 3080 [NFT_SET_EXT_KEY] = { ··· 3154 3084 }, 3155 3085 [NFT_SET_EXT_EXPR] = { 3156 3086 .align = __alignof__(struct nft_expr), 3087 + }, 3088 + [NFT_SET_EXT_OBJREF] = { 3089 + .len = sizeof(struct nft_object *), 3090 + .align = __alignof__(struct nft_object *), 3157 3091 }, 3158 3092 [NFT_SET_EXT_FLAGS] = { 3159 3093 .len = sizeof(u8), ··· 3245 3171 3246 3172 if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPR) && 3247 3173 nft_expr_dump(skb, NFTA_SET_ELEM_EXPR, nft_set_ext_expr(ext)) < 0) 3174 + goto nla_put_failure; 3175 + 3176 + if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) && 3177 + nla_put_string(skb, NFTA_SET_ELEM_OBJREF, 3178 + (*nft_set_ext_obj(ext))->name) < 0) 3248 3179 goto nla_put_failure; 3249 3180 3250 3181 if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) && ··· 3546 3467 nft_data_uninit(nft_set_ext_data(ext), set->dtype); 3547 3468 if (destroy_expr && nft_set_ext_exists(ext, NFT_SET_EXT_EXPR)) 3548 3469 nf_tables_expr_destroy(NULL, nft_set_ext_expr(ext)); 3549 - 3470 + if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF)) 3471 + (*nft_set_ext_obj(ext))->use--; 3550 3472 kfree(elem); 3551 3473 } 3552 3474 EXPORT_SYMBOL_GPL(nft_set_elem_destroy); ··· 3572 3492 const struct nlattr *attr, u32 nlmsg_flags) 3573 3493 { 3574 3494 struct nlattr *nla[NFTA_SET_ELEM_MAX + 1]; 3495 + u8 genmask = nft_genmask_next(ctx->net); 3575 3496 struct nft_data_desc d1, d2; 3576 3497 struct nft_set_ext_tmpl tmpl; 3577 3498 struct nft_set_ext *ext, *ext2; 3578 3499 struct nft_set_elem elem; 3579 3500 struct nft_set_binding *binding; 3501 + struct nft_object *obj = NULL; 3580 3502 struct nft_userdata *udata; 3581 3503 struct nft_data data; 3582 3504 enum nft_registers dreg; ··· 3641 3559 nft_set_ext_add(&tmpl, NFT_SET_EXT_TIMEOUT); 3642 3560 } 3643 3561 3562 + if (nla[NFTA_SET_ELEM_OBJREF] != NULL) { 3563 + if (!(set->flags & NFT_SET_OBJECT)) { 3564 + err = -EINVAL; 3565 + goto err2; 3566 + } 3567 + obj = nf_tables_obj_lookup(ctx->table, nla[NFTA_SET_ELEM_OBJREF], 3568 + set->objtype, genmask); 3569 + if (IS_ERR(obj)) { 3570 + err = PTR_ERR(obj); 3571 + goto err2; 3572 + } 3573 + nft_set_ext_add(&tmpl, NFT_SET_EXT_OBJREF); 3574 + } 3575 + 3644 3576 if (nla[NFTA_SET_ELEM_DATA] != NULL) { 3645 3577 err = nft_data_init(ctx, &data, sizeof(data), &d2, 3646 3578 nla[NFTA_SET_ELEM_DATA]); ··· 3713 3617 udata->len = ulen - 1; 3714 3618 nla_memcpy(&udata->data, nla[NFTA_SET_ELEM_USERDATA], ulen); 3715 3619 } 3620 + if (obj) { 3621 + *nft_set_ext_obj(ext) = obj; 3622 + obj->use++; 3623 + } 3716 3624 3717 3625 trans = nft_trans_elem_alloc(ctx, NFT_MSG_NEWSETELEM, set); 3718 3626 if (trans == NULL) ··· 3726 3626 err = set->ops->insert(ctx->net, set, &elem, &ext2); 3727 3627 if (err) { 3728 3628 if (err == -EEXIST) { 3729 - if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA) && 3730 - nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) && 3731 - memcmp(nft_set_ext_data(ext), 3732 - nft_set_ext_data(ext2), set->dlen) != 0) 3629 + if ((nft_set_ext_exists(ext, NFT_SET_EXT_DATA) && 3630 + nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) && 3631 + memcmp(nft_set_ext_data(ext), 3632 + nft_set_ext_data(ext2), set->dlen) != 0) || 3633 + (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) && 3634 + nft_set_ext_exists(ext2, NFT_SET_EXT_OBJREF) && 3635 + *nft_set_ext_obj(ext) != *nft_set_ext_obj(ext2))) 3733 3636 err = -EBUSY; 3734 3637 else if (!(nlmsg_flags & NLM_F_EXCL)) 3735 3638 err = 0; ··· 3882 3779 return err; 3883 3780 } 3884 3781 3782 + static int nft_flush_set(const struct nft_ctx *ctx, 3783 + const struct nft_set *set, 3784 + const struct nft_set_iter *iter, 3785 + const struct nft_set_elem *elem) 3786 + { 3787 + struct nft_trans *trans; 3788 + int err; 3789 + 3790 + trans = nft_trans_alloc_gfp(ctx, NFT_MSG_DELSETELEM, 3791 + sizeof(struct nft_trans_elem), GFP_ATOMIC); 3792 + if (!trans) 3793 + return -ENOMEM; 3794 + 3795 + if (!set->ops->deactivate_one(ctx->net, set, elem->priv)) { 3796 + err = -ENOENT; 3797 + goto err1; 3798 + } 3799 + 3800 + nft_trans_elem_set(trans) = (struct nft_set *)set; 3801 + nft_trans_elem(trans) = *((struct nft_set_elem *)elem); 3802 + list_add_tail(&trans->list, &ctx->net->nft.commit_list); 3803 + 3804 + return 0; 3805 + err1: 3806 + kfree(trans); 3807 + return err; 3808 + } 3809 + 3885 3810 static int nf_tables_delsetelem(struct net *net, struct sock *nlsk, 3886 3811 struct sk_buff *skb, const struct nlmsghdr *nlh, 3887 3812 const struct nlattr * const nla[]) ··· 3919 3788 struct nft_set *set; 3920 3789 struct nft_ctx ctx; 3921 3790 int rem, err = 0; 3922 - 3923 - if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL) 3924 - return -EINVAL; 3925 3791 3926 3792 err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, genmask); 3927 3793 if (err < 0) ··· 3930 3802 return PTR_ERR(set); 3931 3803 if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT) 3932 3804 return -EBUSY; 3805 + 3806 + if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL) { 3807 + struct nft_set_dump_args args = { 3808 + .iter = { 3809 + .genmask = genmask, 3810 + .fn = nft_flush_set, 3811 + }, 3812 + }; 3813 + set->ops->walk(&ctx, set, &args.iter); 3814 + 3815 + return args.iter.err; 3816 + } 3933 3817 3934 3818 nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) { 3935 3819 err = nft_del_setelem(&ctx, set, attr); ··· 3977 3837 return gcb; 3978 3838 } 3979 3839 EXPORT_SYMBOL_GPL(nft_set_gc_batch_alloc); 3840 + 3841 + /* 3842 + * Stateful objects 3843 + */ 3844 + 3845 + /** 3846 + * nft_register_obj- register nf_tables stateful object type 3847 + * @obj: object type 3848 + * 3849 + * Registers the object type for use with nf_tables. Returns zero on 3850 + * success or a negative errno code otherwise. 3851 + */ 3852 + int nft_register_obj(struct nft_object_type *obj_type) 3853 + { 3854 + if (obj_type->type == NFT_OBJECT_UNSPEC) 3855 + return -EINVAL; 3856 + 3857 + nfnl_lock(NFNL_SUBSYS_NFTABLES); 3858 + list_add_rcu(&obj_type->list, &nf_tables_objects); 3859 + nfnl_unlock(NFNL_SUBSYS_NFTABLES); 3860 + return 0; 3861 + } 3862 + EXPORT_SYMBOL_GPL(nft_register_obj); 3863 + 3864 + /** 3865 + * nft_unregister_obj - unregister nf_tables object type 3866 + * @obj: object type 3867 + * 3868 + * Unregisters the object type for use with nf_tables. 3869 + */ 3870 + void nft_unregister_obj(struct nft_object_type *obj_type) 3871 + { 3872 + nfnl_lock(NFNL_SUBSYS_NFTABLES); 3873 + list_del_rcu(&obj_type->list); 3874 + nfnl_unlock(NFNL_SUBSYS_NFTABLES); 3875 + } 3876 + EXPORT_SYMBOL_GPL(nft_unregister_obj); 3877 + 3878 + struct nft_object *nf_tables_obj_lookup(const struct nft_table *table, 3879 + const struct nlattr *nla, 3880 + u32 objtype, u8 genmask) 3881 + { 3882 + struct nft_object *obj; 3883 + 3884 + list_for_each_entry(obj, &table->objects, list) { 3885 + if (!nla_strcmp(nla, obj->name) && 3886 + objtype == obj->type->type && 3887 + nft_active_genmask(obj, genmask)) 3888 + return obj; 3889 + } 3890 + return ERR_PTR(-ENOENT); 3891 + } 3892 + EXPORT_SYMBOL_GPL(nf_tables_obj_lookup); 3893 + 3894 + static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = { 3895 + [NFTA_OBJ_TABLE] = { .type = NLA_STRING }, 3896 + [NFTA_OBJ_NAME] = { .type = NLA_STRING }, 3897 + [NFTA_OBJ_TYPE] = { .type = NLA_U32 }, 3898 + [NFTA_OBJ_DATA] = { .type = NLA_NESTED }, 3899 + }; 3900 + 3901 + static struct nft_object *nft_obj_init(const struct nft_object_type *type, 3902 + const struct nlattr *attr) 3903 + { 3904 + struct nlattr *tb[type->maxattr + 1]; 3905 + struct nft_object *obj; 3906 + int err; 3907 + 3908 + if (attr) { 3909 + err = nla_parse_nested(tb, type->maxattr, attr, type->policy); 3910 + if (err < 0) 3911 + goto err1; 3912 + } else { 3913 + memset(tb, 0, sizeof(tb[0]) * (type->maxattr + 1)); 3914 + } 3915 + 3916 + err = -ENOMEM; 3917 + obj = kzalloc(sizeof(struct nft_object) + type->size, GFP_KERNEL); 3918 + if (obj == NULL) 3919 + goto err1; 3920 + 3921 + err = type->init((const struct nlattr * const *)tb, obj); 3922 + if (err < 0) 3923 + goto err2; 3924 + 3925 + obj->type = type; 3926 + return obj; 3927 + err2: 3928 + kfree(obj); 3929 + err1: 3930 + return ERR_PTR(err); 3931 + } 3932 + 3933 + static int nft_object_dump(struct sk_buff *skb, unsigned int attr, 3934 + struct nft_object *obj, bool reset) 3935 + { 3936 + struct nlattr *nest; 3937 + 3938 + nest = nla_nest_start(skb, attr); 3939 + if (!nest) 3940 + goto nla_put_failure; 3941 + if (obj->type->dump(skb, obj, reset) < 0) 3942 + goto nla_put_failure; 3943 + nla_nest_end(skb, nest); 3944 + return 0; 3945 + 3946 + nla_put_failure: 3947 + return -1; 3948 + } 3949 + 3950 + static const struct nft_object_type *__nft_obj_type_get(u32 objtype) 3951 + { 3952 + const struct nft_object_type *type; 3953 + 3954 + list_for_each_entry(type, &nf_tables_objects, list) { 3955 + if (objtype == type->type) 3956 + return type; 3957 + } 3958 + return NULL; 3959 + } 3960 + 3961 + static const struct nft_object_type *nft_obj_type_get(u32 objtype) 3962 + { 3963 + const struct nft_object_type *type; 3964 + 3965 + type = __nft_obj_type_get(objtype); 3966 + if (type != NULL && try_module_get(type->owner)) 3967 + return type; 3968 + 3969 + #ifdef CONFIG_MODULES 3970 + if (type == NULL) { 3971 + nfnl_unlock(NFNL_SUBSYS_NFTABLES); 3972 + request_module("nft-obj-%u", objtype); 3973 + nfnl_lock(NFNL_SUBSYS_NFTABLES); 3974 + if (__nft_obj_type_get(objtype)) 3975 + return ERR_PTR(-EAGAIN); 3976 + } 3977 + #endif 3978 + return ERR_PTR(-ENOENT); 3979 + } 3980 + 3981 + static int nf_tables_newobj(struct net *net, struct sock *nlsk, 3982 + struct sk_buff *skb, const struct nlmsghdr *nlh, 3983 + const struct nlattr * const nla[]) 3984 + { 3985 + const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 3986 + const struct nft_object_type *type; 3987 + u8 genmask = nft_genmask_next(net); 3988 + int family = nfmsg->nfgen_family; 3989 + struct nft_af_info *afi; 3990 + struct nft_table *table; 3991 + struct nft_object *obj; 3992 + struct nft_ctx ctx; 3993 + u32 objtype; 3994 + int err; 3995 + 3996 + if (!nla[NFTA_OBJ_TYPE] || 3997 + !nla[NFTA_OBJ_NAME] || 3998 + !nla[NFTA_OBJ_DATA]) 3999 + return -EINVAL; 4000 + 4001 + afi = nf_tables_afinfo_lookup(net, family, true); 4002 + if (IS_ERR(afi)) 4003 + return PTR_ERR(afi); 4004 + 4005 + table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask); 4006 + if (IS_ERR(table)) 4007 + return PTR_ERR(table); 4008 + 4009 + objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE])); 4010 + obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask); 4011 + if (IS_ERR(obj)) { 4012 + err = PTR_ERR(obj); 4013 + if (err != -ENOENT) 4014 + return err; 4015 + 4016 + obj = NULL; 4017 + } 4018 + 4019 + if (obj != NULL) { 4020 + if (nlh->nlmsg_flags & NLM_F_EXCL) 4021 + return -EEXIST; 4022 + 4023 + return 0; 4024 + } 4025 + 4026 + nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); 4027 + 4028 + type = nft_obj_type_get(objtype); 4029 + if (IS_ERR(type)) 4030 + return PTR_ERR(type); 4031 + 4032 + obj = nft_obj_init(type, nla[NFTA_OBJ_DATA]); 4033 + if (IS_ERR(obj)) { 4034 + err = PTR_ERR(obj); 4035 + goto err1; 4036 + } 4037 + obj->table = table; 4038 + nla_strlcpy(obj->name, nla[NFTA_OBJ_NAME], NFT_OBJ_MAXNAMELEN); 4039 + 4040 + err = nft_trans_obj_add(&ctx, NFT_MSG_NEWOBJ, obj); 4041 + if (err < 0) 4042 + goto err2; 4043 + 4044 + list_add_tail_rcu(&obj->list, &table->objects); 4045 + table->use++; 4046 + return 0; 4047 + err2: 4048 + if (obj->type->destroy) 4049 + obj->type->destroy(obj); 4050 + kfree(obj); 4051 + err1: 4052 + module_put(type->owner); 4053 + return err; 4054 + } 4055 + 4056 + static int nf_tables_fill_obj_info(struct sk_buff *skb, struct net *net, 4057 + u32 portid, u32 seq, int event, u32 flags, 4058 + int family, const struct nft_table *table, 4059 + struct nft_object *obj, bool reset) 4060 + { 4061 + struct nfgenmsg *nfmsg; 4062 + struct nlmsghdr *nlh; 4063 + 4064 + event |= NFNL_SUBSYS_NFTABLES << 8; 4065 + nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), flags); 4066 + if (nlh == NULL) 4067 + goto nla_put_failure; 4068 + 4069 + nfmsg = nlmsg_data(nlh); 4070 + nfmsg->nfgen_family = family; 4071 + nfmsg->version = NFNETLINK_V0; 4072 + nfmsg->res_id = htons(net->nft.base_seq & 0xffff); 4073 + 4074 + if (nla_put_string(skb, NFTA_OBJ_TABLE, table->name) || 4075 + nla_put_string(skb, NFTA_OBJ_NAME, obj->name) || 4076 + nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->type->type)) || 4077 + nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) || 4078 + nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset)) 4079 + goto nla_put_failure; 4080 + 4081 + nlmsg_end(skb, nlh); 4082 + return 0; 4083 + 4084 + nla_put_failure: 4085 + nlmsg_trim(skb, nlh); 4086 + return -1; 4087 + } 4088 + 4089 + struct nft_obj_filter { 4090 + char table[NFT_OBJ_MAXNAMELEN]; 4091 + u32 type; 4092 + }; 4093 + 4094 + static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb) 4095 + { 4096 + const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); 4097 + const struct nft_af_info *afi; 4098 + const struct nft_table *table; 4099 + unsigned int idx = 0, s_idx = cb->args[0]; 4100 + struct nft_obj_filter *filter = cb->data; 4101 + struct net *net = sock_net(skb->sk); 4102 + int family = nfmsg->nfgen_family; 4103 + struct nft_object *obj; 4104 + bool reset = false; 4105 + 4106 + if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET) 4107 + reset = true; 4108 + 4109 + rcu_read_lock(); 4110 + cb->seq = net->nft.base_seq; 4111 + 4112 + list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 4113 + if (family != NFPROTO_UNSPEC && family != afi->family) 4114 + continue; 4115 + 4116 + list_for_each_entry_rcu(table, &afi->tables, list) { 4117 + list_for_each_entry_rcu(obj, &table->objects, list) { 4118 + if (!nft_is_active(net, obj)) 4119 + goto cont; 4120 + if (idx < s_idx) 4121 + goto cont; 4122 + if (idx > s_idx) 4123 + memset(&cb->args[1], 0, 4124 + sizeof(cb->args) - sizeof(cb->args[0])); 4125 + if (filter->table[0] && 4126 + strcmp(filter->table, table->name)) 4127 + goto cont; 4128 + if (filter->type != NFT_OBJECT_UNSPEC && 4129 + obj->type->type != filter->type) 4130 + goto cont; 4131 + 4132 + if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid, 4133 + cb->nlh->nlmsg_seq, 4134 + NFT_MSG_NEWOBJ, 4135 + NLM_F_MULTI | NLM_F_APPEND, 4136 + afi->family, table, obj, reset) < 0) 4137 + goto done; 4138 + 4139 + nl_dump_check_consistent(cb, nlmsg_hdr(skb)); 4140 + cont: 4141 + idx++; 4142 + } 4143 + } 4144 + } 4145 + done: 4146 + rcu_read_unlock(); 4147 + 4148 + cb->args[0] = idx; 4149 + return skb->len; 4150 + } 4151 + 4152 + static int nf_tables_dump_obj_done(struct netlink_callback *cb) 4153 + { 4154 + kfree(cb->data); 4155 + 4156 + return 0; 4157 + } 4158 + 4159 + static struct nft_obj_filter * 4160 + nft_obj_filter_alloc(const struct nlattr * const nla[]) 4161 + { 4162 + struct nft_obj_filter *filter; 4163 + 4164 + filter = kzalloc(sizeof(*filter), GFP_KERNEL); 4165 + if (!filter) 4166 + return ERR_PTR(-ENOMEM); 4167 + 4168 + if (nla[NFTA_OBJ_TABLE]) 4169 + nla_strlcpy(filter->table, nla[NFTA_OBJ_TABLE], 4170 + NFT_TABLE_MAXNAMELEN); 4171 + if (nla[NFTA_OBJ_TYPE]) 4172 + filter->type = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE])); 4173 + 4174 + return filter; 4175 + } 4176 + 4177 + static int nf_tables_getobj(struct net *net, struct sock *nlsk, 4178 + struct sk_buff *skb, const struct nlmsghdr *nlh, 4179 + const struct nlattr * const nla[]) 4180 + { 4181 + const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 4182 + u8 genmask = nft_genmask_cur(net); 4183 + int family = nfmsg->nfgen_family; 4184 + const struct nft_af_info *afi; 4185 + const struct nft_table *table; 4186 + struct nft_object *obj; 4187 + struct sk_buff *skb2; 4188 + bool reset = false; 4189 + u32 objtype; 4190 + int err; 4191 + 4192 + if (nlh->nlmsg_flags & NLM_F_DUMP) { 4193 + struct netlink_dump_control c = { 4194 + .dump = nf_tables_dump_obj, 4195 + .done = nf_tables_dump_obj_done, 4196 + }; 4197 + 4198 + if (nla[NFTA_OBJ_TABLE] || 4199 + nla[NFTA_OBJ_TYPE]) { 4200 + struct nft_obj_filter *filter; 4201 + 4202 + filter = nft_obj_filter_alloc(nla); 4203 + if (IS_ERR(filter)) 4204 + return -ENOMEM; 4205 + 4206 + c.data = filter; 4207 + } 4208 + return netlink_dump_start(nlsk, skb, nlh, &c); 4209 + } 4210 + 4211 + if (!nla[NFTA_OBJ_NAME] || 4212 + !nla[NFTA_OBJ_TYPE]) 4213 + return -EINVAL; 4214 + 4215 + afi = nf_tables_afinfo_lookup(net, family, false); 4216 + if (IS_ERR(afi)) 4217 + return PTR_ERR(afi); 4218 + 4219 + table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask); 4220 + if (IS_ERR(table)) 4221 + return PTR_ERR(table); 4222 + 4223 + objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE])); 4224 + obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask); 4225 + if (IS_ERR(obj)) 4226 + return PTR_ERR(obj); 4227 + 4228 + skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); 4229 + if (!skb2) 4230 + return -ENOMEM; 4231 + 4232 + if (NFNL_MSG_TYPE(nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET) 4233 + reset = true; 4234 + 4235 + err = nf_tables_fill_obj_info(skb2, net, NETLINK_CB(skb).portid, 4236 + nlh->nlmsg_seq, NFT_MSG_NEWOBJ, 0, 4237 + family, table, obj, reset); 4238 + if (err < 0) 4239 + goto err; 4240 + 4241 + return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid); 4242 + err: 4243 + kfree_skb(skb2); 4244 + return err; 4245 + 4246 + return 0; 4247 + } 4248 + 4249 + static void nft_obj_destroy(struct nft_object *obj) 4250 + { 4251 + if (obj->type->destroy) 4252 + obj->type->destroy(obj); 4253 + 4254 + module_put(obj->type->owner); 4255 + kfree(obj); 4256 + } 4257 + 4258 + static int nf_tables_delobj(struct net *net, struct sock *nlsk, 4259 + struct sk_buff *skb, const struct nlmsghdr *nlh, 4260 + const struct nlattr * const nla[]) 4261 + { 4262 + const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 4263 + u8 genmask = nft_genmask_next(net); 4264 + int family = nfmsg->nfgen_family; 4265 + struct nft_af_info *afi; 4266 + struct nft_table *table; 4267 + struct nft_object *obj; 4268 + struct nft_ctx ctx; 4269 + u32 objtype; 4270 + 4271 + if (!nla[NFTA_OBJ_TYPE] || 4272 + !nla[NFTA_OBJ_NAME]) 4273 + return -EINVAL; 4274 + 4275 + afi = nf_tables_afinfo_lookup(net, family, true); 4276 + if (IS_ERR(afi)) 4277 + return PTR_ERR(afi); 4278 + 4279 + table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask); 4280 + if (IS_ERR(table)) 4281 + return PTR_ERR(table); 4282 + 4283 + objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE])); 4284 + obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask); 4285 + if (IS_ERR(obj)) 4286 + return PTR_ERR(obj); 4287 + if (obj->use > 0) 4288 + return -EBUSY; 4289 + 4290 + nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); 4291 + 4292 + return nft_delobj(&ctx, obj); 4293 + } 4294 + 4295 + int nft_obj_notify(struct net *net, struct nft_table *table, 4296 + struct nft_object *obj, u32 portid, u32 seq, int event, 4297 + int family, int report, gfp_t gfp) 4298 + { 4299 + struct sk_buff *skb; 4300 + int err; 4301 + 4302 + if (!report && 4303 + !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES)) 4304 + return 0; 4305 + 4306 + err = -ENOBUFS; 4307 + skb = nlmsg_new(NLMSG_GOODSIZE, gfp); 4308 + if (skb == NULL) 4309 + goto err; 4310 + 4311 + err = nf_tables_fill_obj_info(skb, net, portid, seq, event, 0, family, 4312 + table, obj, false); 4313 + if (err < 0) { 4314 + kfree_skb(skb); 4315 + goto err; 4316 + } 4317 + 4318 + err = nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, report, gfp); 4319 + err: 4320 + if (err < 0) { 4321 + nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, err); 4322 + } 4323 + return err; 4324 + } 4325 + EXPORT_SYMBOL_GPL(nft_obj_notify); 4326 + 4327 + static int nf_tables_obj_notify(const struct nft_ctx *ctx, 4328 + struct nft_object *obj, int event) 4329 + { 4330 + return nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, 4331 + ctx->seq, event, ctx->afi->family, ctx->report, 4332 + GFP_KERNEL); 4333 + } 3980 4334 3981 4335 static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net, 3982 4336 u32 portid, u32 seq) ··· 4632 3998 [NFT_MSG_GETGEN] = { 4633 3999 .call = nf_tables_getgen, 4634 4000 }, 4001 + [NFT_MSG_NEWOBJ] = { 4002 + .call_batch = nf_tables_newobj, 4003 + .attr_count = NFTA_OBJ_MAX, 4004 + .policy = nft_obj_policy, 4005 + }, 4006 + [NFT_MSG_GETOBJ] = { 4007 + .call = nf_tables_getobj, 4008 + .attr_count = NFTA_OBJ_MAX, 4009 + .policy = nft_obj_policy, 4010 + }, 4011 + [NFT_MSG_DELOBJ] = { 4012 + .call_batch = nf_tables_delobj, 4013 + .attr_count = NFTA_OBJ_MAX, 4014 + .policy = nft_obj_policy, 4015 + }, 4016 + [NFT_MSG_GETOBJ_RESET] = { 4017 + .call = nf_tables_getobj, 4018 + .attr_count = NFTA_OBJ_MAX, 4019 + .policy = nft_obj_policy, 4020 + }, 4635 4021 }; 4636 4022 4637 4023 static void nft_chain_commit_update(struct nft_trans *trans) ··· 4693 4039 case NFT_MSG_DELSETELEM: 4694 4040 nft_set_elem_destroy(nft_trans_elem_set(trans), 4695 4041 nft_trans_elem(trans).priv, true); 4042 + break; 4043 + case NFT_MSG_DELOBJ: 4044 + nft_obj_destroy(nft_trans_obj(trans)); 4696 4045 break; 4697 4046 } 4698 4047 kfree(trans); ··· 4804 4147 atomic_dec(&te->set->nelems); 4805 4148 te->set->ndeact--; 4806 4149 break; 4150 + case NFT_MSG_NEWOBJ: 4151 + nft_clear(net, nft_trans_obj(trans)); 4152 + nf_tables_obj_notify(&trans->ctx, nft_trans_obj(trans), 4153 + NFT_MSG_NEWOBJ); 4154 + nft_trans_destroy(trans); 4155 + break; 4156 + case NFT_MSG_DELOBJ: 4157 + list_del_rcu(&nft_trans_obj(trans)->list); 4158 + nf_tables_obj_notify(&trans->ctx, nft_trans_obj(trans), 4159 + NFT_MSG_DELOBJ); 4160 + break; 4807 4161 } 4808 4162 } 4809 4163 ··· 4848 4180 case NFT_MSG_NEWSETELEM: 4849 4181 nft_set_elem_destroy(nft_trans_elem_set(trans), 4850 4182 nft_trans_elem(trans).priv, true); 4183 + break; 4184 + case NFT_MSG_NEWOBJ: 4185 + nft_obj_destroy(nft_trans_obj(trans)); 4851 4186 break; 4852 4187 } 4853 4188 kfree(trans); ··· 4930 4259 te->set->ops->activate(net, te->set, &te->elem); 4931 4260 te->set->ndeact--; 4932 4261 4262 + nft_trans_destroy(trans); 4263 + break; 4264 + case NFT_MSG_NEWOBJ: 4265 + trans->ctx.table->use--; 4266 + list_del_rcu(&nft_trans_obj(trans)->list); 4267 + break; 4268 + case NFT_MSG_DELOBJ: 4269 + trans->ctx.table->use++; 4270 + nft_clear(trans->ctx.net, nft_trans_obj(trans)); 4933 4271 nft_trans_destroy(trans); 4934 4272 break; 4935 4273 } ··· 5487 4807 { 5488 4808 struct nft_table *table, *nt; 5489 4809 struct nft_chain *chain, *nc; 4810 + struct nft_object *obj, *ne; 5490 4811 struct nft_rule *rule, *nr; 5491 4812 struct nft_set *set, *ns; 5492 4813 struct nft_ctx ctx = { ··· 5513 4832 list_del(&set->list); 5514 4833 table->use--; 5515 4834 nft_set_destroy(set); 4835 + } 4836 + list_for_each_entry_safe(obj, ne, &table->objects, list) { 4837 + list_del(&obj->list); 4838 + table->use--; 4839 + nft_obj_destroy(obj); 5516 4840 } 5517 4841 list_for_each_entry_safe(chain, nc, &table->chains, list) { 5518 4842 list_del(&chain->list);
+177 -51
net/netfilter/nft_counter.c
··· 31 31 struct nft_counter_percpu __percpu *counter; 32 32 }; 33 33 34 - static void nft_counter_eval(const struct nft_expr *expr, 35 - struct nft_regs *regs, 36 - const struct nft_pktinfo *pkt) 34 + static inline void nft_counter_do_eval(struct nft_counter_percpu_priv *priv, 35 + struct nft_regs *regs, 36 + const struct nft_pktinfo *pkt) 37 37 { 38 - struct nft_counter_percpu_priv *priv = nft_expr_priv(expr); 39 38 struct nft_counter_percpu *this_cpu; 40 39 41 40 local_bh_disable(); ··· 46 47 local_bh_enable(); 47 48 } 48 49 49 - static void nft_counter_fetch(const struct nft_counter_percpu __percpu *counter, 50 - struct nft_counter *total) 50 + static inline void nft_counter_obj_eval(struct nft_object *obj, 51 + struct nft_regs *regs, 52 + const struct nft_pktinfo *pkt) 51 53 { 52 - const struct nft_counter_percpu *cpu_stats; 53 - u64 bytes, packets; 54 - unsigned int seq; 55 - int cpu; 54 + struct nft_counter_percpu_priv *priv = nft_obj_data(obj); 56 55 57 - memset(total, 0, sizeof(*total)); 58 - for_each_possible_cpu(cpu) { 59 - cpu_stats = per_cpu_ptr(counter, cpu); 60 - do { 61 - seq = u64_stats_fetch_begin_irq(&cpu_stats->syncp); 62 - bytes = cpu_stats->counter.bytes; 63 - packets = cpu_stats->counter.packets; 64 - } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, seq)); 65 - 66 - total->packets += packets; 67 - total->bytes += bytes; 68 - } 56 + nft_counter_do_eval(priv, regs, pkt); 69 57 } 70 58 71 - static int nft_counter_dump(struct sk_buff *skb, const struct nft_expr *expr) 59 + static int nft_counter_do_init(const struct nlattr * const tb[], 60 + struct nft_counter_percpu_priv *priv) 72 61 { 73 - struct nft_counter_percpu_priv *priv = nft_expr_priv(expr); 74 - struct nft_counter total; 75 - 76 - nft_counter_fetch(priv->counter, &total); 77 - 78 - if (nla_put_be64(skb, NFTA_COUNTER_BYTES, cpu_to_be64(total.bytes), 79 - NFTA_COUNTER_PAD) || 80 - nla_put_be64(skb, NFTA_COUNTER_PACKETS, cpu_to_be64(total.packets), 81 - NFTA_COUNTER_PAD)) 82 - goto nla_put_failure; 83 - return 0; 84 - 85 - nla_put_failure: 86 - return -1; 87 - } 88 - 89 - static const struct nla_policy nft_counter_policy[NFTA_COUNTER_MAX + 1] = { 90 - [NFTA_COUNTER_PACKETS] = { .type = NLA_U64 }, 91 - [NFTA_COUNTER_BYTES] = { .type = NLA_U64 }, 92 - }; 93 - 94 - static int nft_counter_init(const struct nft_ctx *ctx, 95 - const struct nft_expr *expr, 96 - const struct nlattr * const tb[]) 97 - { 98 - struct nft_counter_percpu_priv *priv = nft_expr_priv(expr); 99 62 struct nft_counter_percpu __percpu *cpu_stats; 100 63 struct nft_counter_percpu *this_cpu; 101 64 ··· 80 119 return 0; 81 120 } 82 121 122 + static int nft_counter_obj_init(const struct nlattr * const tb[], 123 + struct nft_object *obj) 124 + { 125 + struct nft_counter_percpu_priv *priv = nft_obj_data(obj); 126 + 127 + return nft_counter_do_init(tb, priv); 128 + } 129 + 130 + static void nft_counter_do_destroy(struct nft_counter_percpu_priv *priv) 131 + { 132 + free_percpu(priv->counter); 133 + } 134 + 135 + static void nft_counter_obj_destroy(struct nft_object *obj) 136 + { 137 + struct nft_counter_percpu_priv *priv = nft_obj_data(obj); 138 + 139 + nft_counter_do_destroy(priv); 140 + } 141 + 142 + static void nft_counter_fetch(struct nft_counter_percpu __percpu *counter, 143 + struct nft_counter *total) 144 + { 145 + struct nft_counter_percpu *cpu_stats; 146 + u64 bytes, packets; 147 + unsigned int seq; 148 + int cpu; 149 + 150 + memset(total, 0, sizeof(*total)); 151 + for_each_possible_cpu(cpu) { 152 + cpu_stats = per_cpu_ptr(counter, cpu); 153 + do { 154 + seq = u64_stats_fetch_begin_irq(&cpu_stats->syncp); 155 + bytes = cpu_stats->counter.bytes; 156 + packets = cpu_stats->counter.packets; 157 + } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, seq)); 158 + 159 + total->packets += packets; 160 + total->bytes += bytes; 161 + } 162 + } 163 + 164 + static u64 __nft_counter_reset(u64 *counter) 165 + { 166 + u64 ret, old; 167 + 168 + do { 169 + old = *counter; 170 + ret = cmpxchg64(counter, old, 0); 171 + } while (ret != old); 172 + 173 + return ret; 174 + } 175 + 176 + static void nft_counter_reset(struct nft_counter_percpu __percpu *counter, 177 + struct nft_counter *total) 178 + { 179 + struct nft_counter_percpu *cpu_stats; 180 + u64 bytes, packets; 181 + unsigned int seq; 182 + int cpu; 183 + 184 + memset(total, 0, sizeof(*total)); 185 + for_each_possible_cpu(cpu) { 186 + bytes = packets = 0; 187 + 188 + cpu_stats = per_cpu_ptr(counter, cpu); 189 + do { 190 + seq = u64_stats_fetch_begin_irq(&cpu_stats->syncp); 191 + packets += __nft_counter_reset(&cpu_stats->counter.packets); 192 + bytes += __nft_counter_reset(&cpu_stats->counter.bytes); 193 + } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, seq)); 194 + 195 + total->packets += packets; 196 + total->bytes += bytes; 197 + } 198 + } 199 + 200 + static int nft_counter_do_dump(struct sk_buff *skb, 201 + const struct nft_counter_percpu_priv *priv, 202 + bool reset) 203 + { 204 + struct nft_counter total; 205 + 206 + if (reset) 207 + nft_counter_reset(priv->counter, &total); 208 + else 209 + nft_counter_fetch(priv->counter, &total); 210 + 211 + if (nla_put_be64(skb, NFTA_COUNTER_BYTES, cpu_to_be64(total.bytes), 212 + NFTA_COUNTER_PAD) || 213 + nla_put_be64(skb, NFTA_COUNTER_PACKETS, cpu_to_be64(total.packets), 214 + NFTA_COUNTER_PAD)) 215 + goto nla_put_failure; 216 + return 0; 217 + 218 + nla_put_failure: 219 + return -1; 220 + } 221 + 222 + static int nft_counter_obj_dump(struct sk_buff *skb, 223 + struct nft_object *obj, bool reset) 224 + { 225 + struct nft_counter_percpu_priv *priv = nft_obj_data(obj); 226 + 227 + return nft_counter_do_dump(skb, priv, reset); 228 + } 229 + 230 + static const struct nla_policy nft_counter_policy[NFTA_COUNTER_MAX + 1] = { 231 + [NFTA_COUNTER_PACKETS] = { .type = NLA_U64 }, 232 + [NFTA_COUNTER_BYTES] = { .type = NLA_U64 }, 233 + }; 234 + 235 + static struct nft_object_type nft_counter_obj __read_mostly = { 236 + .type = NFT_OBJECT_COUNTER, 237 + .size = sizeof(struct nft_counter_percpu_priv), 238 + .maxattr = NFTA_COUNTER_MAX, 239 + .policy = nft_counter_policy, 240 + .eval = nft_counter_obj_eval, 241 + .init = nft_counter_obj_init, 242 + .destroy = nft_counter_obj_destroy, 243 + .dump = nft_counter_obj_dump, 244 + .owner = THIS_MODULE, 245 + }; 246 + 247 + static void nft_counter_eval(const struct nft_expr *expr, 248 + struct nft_regs *regs, 249 + const struct nft_pktinfo *pkt) 250 + { 251 + struct nft_counter_percpu_priv *priv = nft_expr_priv(expr); 252 + 253 + nft_counter_do_eval(priv, regs, pkt); 254 + } 255 + 256 + static int nft_counter_dump(struct sk_buff *skb, const struct nft_expr *expr) 257 + { 258 + const struct nft_counter_percpu_priv *priv = nft_expr_priv(expr); 259 + 260 + return nft_counter_do_dump(skb, priv, false); 261 + } 262 + 263 + static int nft_counter_init(const struct nft_ctx *ctx, 264 + const struct nft_expr *expr, 265 + const struct nlattr * const tb[]) 266 + { 267 + struct nft_counter_percpu_priv *priv = nft_expr_priv(expr); 268 + 269 + return nft_counter_do_init(tb, priv); 270 + } 271 + 83 272 static void nft_counter_destroy(const struct nft_ctx *ctx, 84 273 const struct nft_expr *expr) 85 274 { 86 275 struct nft_counter_percpu_priv *priv = nft_expr_priv(expr); 87 276 88 - free_percpu(priv->counter); 277 + nft_counter_do_destroy(priv); 89 278 } 90 279 91 280 static int nft_counter_clone(struct nft_expr *dst, const struct nft_expr *src) ··· 285 174 286 175 static int __init nft_counter_module_init(void) 287 176 { 288 - return nft_register_expr(&nft_counter_type); 177 + int err; 178 + 179 + err = nft_register_obj(&nft_counter_obj); 180 + if (err < 0) 181 + return err; 182 + 183 + err = nft_register_expr(&nft_counter_type); 184 + if (err < 0) 185 + goto err1; 186 + 187 + return 0; 188 + err1: 189 + nft_unregister_obj(&nft_counter_obj); 190 + return err; 289 191 } 290 192 291 193 static void __exit nft_counter_module_exit(void) 292 194 { 293 195 nft_unregister_expr(&nft_counter_type); 196 + nft_unregister_obj(&nft_counter_obj); 294 197 } 295 198 296 199 module_init(nft_counter_module_init); ··· 313 188 MODULE_LICENSE("GPL"); 314 189 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 315 190 MODULE_ALIAS_NFT_EXPR("counter"); 191 + MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_COUNTER);
+13 -13
net/netfilter/nft_ct.c
··· 208 208 [NFTA_CT_SREG] = { .type = NLA_U32 }, 209 209 }; 210 210 211 - static int nft_ct_l3proto_try_module_get(uint8_t family) 211 + static int nft_ct_netns_get(struct net *net, uint8_t family) 212 212 { 213 213 int err; 214 214 215 215 if (family == NFPROTO_INET) { 216 - err = nf_ct_l3proto_try_module_get(NFPROTO_IPV4); 216 + err = nf_ct_netns_get(net, NFPROTO_IPV4); 217 217 if (err < 0) 218 218 goto err1; 219 - err = nf_ct_l3proto_try_module_get(NFPROTO_IPV6); 219 + err = nf_ct_netns_get(net, NFPROTO_IPV6); 220 220 if (err < 0) 221 221 goto err2; 222 222 } else { 223 - err = nf_ct_l3proto_try_module_get(family); 223 + err = nf_ct_netns_get(net, family); 224 224 if (err < 0) 225 225 goto err1; 226 226 } 227 227 return 0; 228 228 229 229 err2: 230 - nf_ct_l3proto_module_put(NFPROTO_IPV4); 230 + nf_ct_netns_put(net, NFPROTO_IPV4); 231 231 err1: 232 232 return err; 233 233 } 234 234 235 - static void nft_ct_l3proto_module_put(uint8_t family) 235 + static void nft_ct_netns_put(struct net *net, uint8_t family) 236 236 { 237 237 if (family == NFPROTO_INET) { 238 - nf_ct_l3proto_module_put(NFPROTO_IPV4); 239 - nf_ct_l3proto_module_put(NFPROTO_IPV6); 238 + nf_ct_netns_put(net, NFPROTO_IPV4); 239 + nf_ct_netns_put(net, NFPROTO_IPV6); 240 240 } else 241 - nf_ct_l3proto_module_put(family); 241 + nf_ct_netns_put(net, family); 242 242 } 243 243 244 244 static int nft_ct_get_init(const struct nft_ctx *ctx, ··· 342 342 if (err < 0) 343 343 return err; 344 344 345 - err = nft_ct_l3proto_try_module_get(ctx->afi->family); 345 + err = nft_ct_netns_get(ctx->net, ctx->afi->family); 346 346 if (err < 0) 347 347 return err; 348 348 ··· 390 390 if (err < 0) 391 391 goto err1; 392 392 393 - err = nft_ct_l3proto_try_module_get(ctx->afi->family); 393 + err = nft_ct_netns_get(ctx->net, ctx->afi->family); 394 394 if (err < 0) 395 395 goto err1; 396 396 ··· 405 405 static void nft_ct_get_destroy(const struct nft_ctx *ctx, 406 406 const struct nft_expr *expr) 407 407 { 408 - nft_ct_l3proto_module_put(ctx->afi->family); 408 + nf_ct_netns_put(ctx->net, ctx->afi->family); 409 409 } 410 410 411 411 static void nft_ct_set_destroy(const struct nft_ctx *ctx, ··· 423 423 break; 424 424 } 425 425 426 - nft_ct_l3proto_module_put(ctx->afi->family); 426 + nft_ct_netns_put(ctx->net, ctx->afi->family); 427 427 } 428 428 429 429 static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr)
+1 -1
net/netfilter/nft_fib.c
··· 86 86 if ((priv->flags & (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR)) == 0) 87 87 return -EINVAL; 88 88 89 - priv->result = htonl(nla_get_be32(tb[NFTA_FIB_RESULT])); 89 + priv->result = ntohl(nla_get_be32(tb[NFTA_FIB_RESULT])); 90 90 priv->dreg = nft_parse_register(tb[NFTA_FIB_DREG]); 91 91 92 92 switch (priv->result) {
+2 -2
net/netfilter/nft_fwd_netdev.c
··· 26 26 struct nft_fwd_netdev *priv = nft_expr_priv(expr); 27 27 int oif = regs->data[priv->sreg_dev]; 28 28 29 - nf_dup_netdev_egress(pkt, oif); 30 - regs->verdict.code = NF_DROP; 29 + nf_fwd_netdev_egress(pkt, oif); 30 + regs->verdict.code = NF_STOLEN; 31 31 } 32 32 33 33 static const struct nla_policy nft_fwd_netdev_policy[NFTA_FWD_MAX + 1] = {
+3 -3
net/netfilter/nft_masq.c
··· 1 1 /* 2 - * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com> 2 + * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo@debian.org> 3 3 * 4 4 * This program is free software; you can redistribute it and/or modify 5 5 * it under the terms of the GNU General Public License version 2 as ··· 77 77 } 78 78 } 79 79 80 - return 0; 80 + return nf_ct_netns_get(ctx->net, ctx->afi->family); 81 81 } 82 82 EXPORT_SYMBOL_GPL(nft_masq_init); 83 83 ··· 105 105 EXPORT_SYMBOL_GPL(nft_masq_dump); 106 106 107 107 MODULE_LICENSE("GPL"); 108 - MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>"); 108 + MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
+10 -1
net/netfilter/nft_nat.c
··· 209 209 return -EINVAL; 210 210 } 211 211 212 - return 0; 212 + return nf_ct_netns_get(ctx->net, family); 213 213 } 214 214 215 215 static int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr) ··· 257 257 return -1; 258 258 } 259 259 260 + static void 261 + nft_nat_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) 262 + { 263 + const struct nft_nat *priv = nft_expr_priv(expr); 264 + 265 + nf_ct_netns_put(ctx->net, priv->family); 266 + } 267 + 260 268 static struct nft_expr_type nft_nat_type; 261 269 static const struct nft_expr_ops nft_nat_ops = { 262 270 .type = &nft_nat_type, 263 271 .size = NFT_EXPR_SIZE(sizeof(struct nft_nat)), 264 272 .eval = nft_nat_eval, 265 273 .init = nft_nat_init, 274 + .destroy = nft_nat_destroy, 266 275 .dump = nft_nat_dump, 267 276 .validate = nft_nat_validate, 268 277 };
+226
net/netfilter/nft_objref.c
··· 1 + /* 2 + * Copyright (c) 2012-2016 Pablo Neira Ayuso <pablo@netfilter.org> 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms and conditions of the GNU General Public License, 6 + * version 2, as published by the Free Software Foundation. 7 + */ 8 + 9 + #include <linux/init.h> 10 + #include <linux/module.h> 11 + #include <linux/skbuff.h> 12 + #include <linux/netlink.h> 13 + #include <linux/netfilter.h> 14 + #include <linux/netfilter/nf_tables.h> 15 + #include <net/netfilter/nf_tables.h> 16 + 17 + #define nft_objref_priv(expr) *((struct nft_object **)nft_expr_priv(expr)) 18 + 19 + static void nft_objref_eval(const struct nft_expr *expr, 20 + struct nft_regs *regs, 21 + const struct nft_pktinfo *pkt) 22 + { 23 + struct nft_object *obj = nft_objref_priv(expr); 24 + 25 + obj->type->eval(obj, regs, pkt); 26 + } 27 + 28 + static int nft_objref_init(const struct nft_ctx *ctx, 29 + const struct nft_expr *expr, 30 + const struct nlattr * const tb[]) 31 + { 32 + struct nft_object *obj = nft_objref_priv(expr); 33 + u8 genmask = nft_genmask_next(ctx->net); 34 + u32 objtype; 35 + 36 + if (!tb[NFTA_OBJREF_IMM_NAME] || 37 + !tb[NFTA_OBJREF_IMM_TYPE]) 38 + return -EINVAL; 39 + 40 + objtype = ntohl(nla_get_be32(tb[NFTA_OBJREF_IMM_TYPE])); 41 + obj = nf_tables_obj_lookup(ctx->table, tb[NFTA_OBJREF_IMM_NAME], objtype, 42 + genmask); 43 + if (IS_ERR(obj)) 44 + return -ENOENT; 45 + 46 + nft_objref_priv(expr) = obj; 47 + obj->use++; 48 + 49 + return 0; 50 + } 51 + 52 + static int nft_objref_dump(struct sk_buff *skb, const struct nft_expr *expr) 53 + { 54 + const struct nft_object *obj = nft_objref_priv(expr); 55 + 56 + if (nla_put_string(skb, NFTA_OBJREF_IMM_NAME, obj->name) || 57 + nla_put_be32(skb, NFTA_OBJREF_IMM_TYPE, htonl(obj->type->type))) 58 + goto nla_put_failure; 59 + 60 + return 0; 61 + 62 + nla_put_failure: 63 + return -1; 64 + } 65 + 66 + static void nft_objref_destroy(const struct nft_ctx *ctx, 67 + const struct nft_expr *expr) 68 + { 69 + struct nft_object *obj = nft_objref_priv(expr); 70 + 71 + obj->use--; 72 + } 73 + 74 + static struct nft_expr_type nft_objref_type; 75 + static const struct nft_expr_ops nft_objref_ops = { 76 + .type = &nft_objref_type, 77 + .size = NFT_EXPR_SIZE(sizeof(struct nft_object *)), 78 + .eval = nft_objref_eval, 79 + .init = nft_objref_init, 80 + .destroy = nft_objref_destroy, 81 + .dump = nft_objref_dump, 82 + }; 83 + 84 + struct nft_objref_map { 85 + struct nft_set *set; 86 + enum nft_registers sreg:8; 87 + struct nft_set_binding binding; 88 + }; 89 + 90 + static void nft_objref_map_eval(const struct nft_expr *expr, 91 + struct nft_regs *regs, 92 + const struct nft_pktinfo *pkt) 93 + { 94 + struct nft_objref_map *priv = nft_expr_priv(expr); 95 + const struct nft_set *set = priv->set; 96 + const struct nft_set_ext *ext; 97 + struct nft_object *obj; 98 + bool found; 99 + 100 + found = set->ops->lookup(nft_net(pkt), set, &regs->data[priv->sreg], 101 + &ext); 102 + if (!found) { 103 + regs->verdict.code = NFT_BREAK; 104 + return; 105 + } 106 + obj = *nft_set_ext_obj(ext); 107 + obj->type->eval(obj, regs, pkt); 108 + } 109 + 110 + static int nft_objref_map_init(const struct nft_ctx *ctx, 111 + const struct nft_expr *expr, 112 + const struct nlattr * const tb[]) 113 + { 114 + struct nft_objref_map *priv = nft_expr_priv(expr); 115 + u8 genmask = nft_genmask_next(ctx->net); 116 + struct nft_set *set; 117 + int err; 118 + 119 + set = nf_tables_set_lookup(ctx->table, tb[NFTA_OBJREF_SET_NAME], genmask); 120 + if (IS_ERR(set)) { 121 + if (tb[NFTA_OBJREF_SET_ID]) { 122 + set = nf_tables_set_lookup_byid(ctx->net, 123 + tb[NFTA_OBJREF_SET_ID], 124 + genmask); 125 + } 126 + if (IS_ERR(set)) 127 + return PTR_ERR(set); 128 + } 129 + 130 + if (!(set->flags & NFT_SET_OBJECT)) 131 + return -EINVAL; 132 + 133 + priv->sreg = nft_parse_register(tb[NFTA_OBJREF_SET_SREG]); 134 + err = nft_validate_register_load(priv->sreg, set->klen); 135 + if (err < 0) 136 + return err; 137 + 138 + priv->binding.flags = set->flags & NFT_SET_OBJECT; 139 + 140 + err = nf_tables_bind_set(ctx, set, &priv->binding); 141 + if (err < 0) 142 + return err; 143 + 144 + priv->set = set; 145 + return 0; 146 + } 147 + 148 + static int nft_objref_map_dump(struct sk_buff *skb, const struct nft_expr *expr) 149 + { 150 + const struct nft_objref_map *priv = nft_expr_priv(expr); 151 + 152 + if (nft_dump_register(skb, NFTA_OBJREF_SET_SREG, priv->sreg) || 153 + nla_put_string(skb, NFTA_OBJREF_SET_NAME, priv->set->name)) 154 + goto nla_put_failure; 155 + 156 + return 0; 157 + 158 + nla_put_failure: 159 + return -1; 160 + } 161 + 162 + static void nft_objref_map_destroy(const struct nft_ctx *ctx, 163 + const struct nft_expr *expr) 164 + { 165 + struct nft_objref_map *priv = nft_expr_priv(expr); 166 + 167 + nf_tables_unbind_set(ctx, priv->set, &priv->binding); 168 + } 169 + 170 + static struct nft_expr_type nft_objref_type; 171 + static const struct nft_expr_ops nft_objref_map_ops = { 172 + .type = &nft_objref_type, 173 + .size = NFT_EXPR_SIZE(sizeof(struct nft_objref_map)), 174 + .eval = nft_objref_map_eval, 175 + .init = nft_objref_map_init, 176 + .destroy = nft_objref_map_destroy, 177 + .dump = nft_objref_map_dump, 178 + }; 179 + 180 + static const struct nft_expr_ops * 181 + nft_objref_select_ops(const struct nft_ctx *ctx, 182 + const struct nlattr * const tb[]) 183 + { 184 + if (tb[NFTA_OBJREF_SET_SREG] && 185 + (tb[NFTA_OBJREF_SET_NAME] || 186 + tb[NFTA_OBJREF_SET_ID])) 187 + return &nft_objref_map_ops; 188 + else if (tb[NFTA_OBJREF_IMM_NAME] && 189 + tb[NFTA_OBJREF_IMM_TYPE]) 190 + return &nft_objref_ops; 191 + 192 + return ERR_PTR(-EOPNOTSUPP); 193 + } 194 + 195 + static const struct nla_policy nft_objref_policy[NFTA_OBJREF_MAX + 1] = { 196 + [NFTA_OBJREF_IMM_NAME] = { .type = NLA_STRING }, 197 + [NFTA_OBJREF_IMM_TYPE] = { .type = NLA_U32 }, 198 + [NFTA_OBJREF_SET_SREG] = { .type = NLA_U32 }, 199 + [NFTA_OBJREF_SET_NAME] = { .type = NLA_STRING }, 200 + [NFTA_OBJREF_SET_ID] = { .type = NLA_U32 }, 201 + }; 202 + 203 + static struct nft_expr_type nft_objref_type __read_mostly = { 204 + .name = "objref", 205 + .select_ops = nft_objref_select_ops, 206 + .policy = nft_objref_policy, 207 + .maxattr = NFTA_OBJREF_MAX, 208 + .owner = THIS_MODULE, 209 + }; 210 + 211 + static int __init nft_objref_module_init(void) 212 + { 213 + return nft_register_expr(&nft_objref_type); 214 + } 215 + 216 + static void __exit nft_objref_module_exit(void) 217 + { 218 + nft_unregister_expr(&nft_objref_type); 219 + } 220 + 221 + module_init(nft_objref_module_init); 222 + module_exit(nft_objref_module_exit); 223 + 224 + MODULE_LICENSE("GPL"); 225 + MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); 226 + MODULE_ALIAS_NFT_EXPR("objref");
+102 -5
net/netfilter/nft_payload.c
··· 1 1 /* 2 2 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> 3 + * Copyright (c) 2016 Pablo Neira Ayuso <pablo@netfilter.org> 3 4 * 4 5 * This program is free software; you can redistribute it and/or modify 5 6 * it under the terms of the GNU General Public License version 2 as ··· 18 17 #include <linux/netfilter/nf_tables.h> 19 18 #include <net/netfilter/nf_tables_core.h> 20 19 #include <net/netfilter/nf_tables.h> 20 + /* For layer 4 checksum field offset. */ 21 + #include <linux/tcp.h> 22 + #include <linux/udp.h> 23 + #include <linux/icmpv6.h> 21 24 22 25 /* add vlan header into the user buffer for if tag was removed by offloads */ 23 26 static bool ··· 169 164 .dump = nft_payload_dump, 170 165 }; 171 166 167 + static inline void nft_csum_replace(__sum16 *sum, __wsum fsum, __wsum tsum) 168 + { 169 + *sum = csum_fold(csum_add(csum_sub(~csum_unfold(*sum), fsum), tsum)); 170 + if (*sum == 0) 171 + *sum = CSUM_MANGLED_0; 172 + } 173 + 174 + static bool nft_payload_udp_checksum(struct sk_buff *skb, unsigned int thoff) 175 + { 176 + struct udphdr *uh, _uh; 177 + 178 + uh = skb_header_pointer(skb, thoff, sizeof(_uh), &_uh); 179 + if (!uh) 180 + return false; 181 + 182 + return uh->check; 183 + } 184 + 185 + static int nft_payload_l4csum_offset(const struct nft_pktinfo *pkt, 186 + struct sk_buff *skb, 187 + unsigned int *l4csum_offset) 188 + { 189 + switch (pkt->tprot) { 190 + case IPPROTO_TCP: 191 + *l4csum_offset = offsetof(struct tcphdr, check); 192 + break; 193 + case IPPROTO_UDP: 194 + if (!nft_payload_udp_checksum(skb, pkt->xt.thoff)) 195 + return -1; 196 + /* Fall through. */ 197 + case IPPROTO_UDPLITE: 198 + *l4csum_offset = offsetof(struct udphdr, check); 199 + break; 200 + case IPPROTO_ICMPV6: 201 + *l4csum_offset = offsetof(struct icmp6hdr, icmp6_cksum); 202 + break; 203 + default: 204 + return -1; 205 + } 206 + 207 + *l4csum_offset += pkt->xt.thoff; 208 + return 0; 209 + } 210 + 211 + static int nft_payload_l4csum_update(const struct nft_pktinfo *pkt, 212 + struct sk_buff *skb, 213 + __wsum fsum, __wsum tsum) 214 + { 215 + int l4csum_offset; 216 + __sum16 sum; 217 + 218 + /* If we cannot determine layer 4 checksum offset or this packet doesn't 219 + * require layer 4 checksum recalculation, skip this packet. 220 + */ 221 + if (nft_payload_l4csum_offset(pkt, skb, &l4csum_offset) < 0) 222 + return 0; 223 + 224 + if (skb_copy_bits(skb, l4csum_offset, &sum, sizeof(sum)) < 0) 225 + return -1; 226 + 227 + /* Checksum mangling for an arbitrary amount of bytes, based on 228 + * inet_proto_csum_replace*() functions. 229 + */ 230 + if (skb->ip_summed != CHECKSUM_PARTIAL) { 231 + nft_csum_replace(&sum, fsum, tsum); 232 + if (skb->ip_summed == CHECKSUM_COMPLETE) { 233 + skb->csum = ~csum_add(csum_sub(~(skb->csum), fsum), 234 + tsum); 235 + } 236 + } else { 237 + sum = ~csum_fold(csum_add(csum_sub(csum_unfold(sum), fsum), 238 + tsum)); 239 + } 240 + 241 + if (!skb_make_writable(skb, l4csum_offset + sizeof(sum)) || 242 + skb_store_bits(skb, l4csum_offset, &sum, sizeof(sum)) < 0) 243 + return -1; 244 + 245 + return 0; 246 + } 247 + 172 248 static void nft_payload_set_eval(const struct nft_expr *expr, 173 249 struct nft_regs *regs, 174 250 const struct nft_pktinfo *pkt) ··· 290 204 291 205 fsum = skb_checksum(skb, offset, priv->len, 0); 292 206 tsum = csum_partial(src, priv->len, 0); 293 - sum = csum_fold(csum_add(csum_sub(~csum_unfold(sum), fsum), 294 - tsum)); 295 - if (sum == 0) 296 - sum = CSUM_MANGLED_0; 207 + nft_csum_replace(&sum, fsum, tsum); 297 208 298 209 if (!skb_make_writable(skb, csum_offset + sizeof(sum)) || 299 210 skb_store_bits(skb, csum_offset, &sum, sizeof(sum)) < 0) 211 + goto err; 212 + 213 + if (priv->csum_flags && 214 + nft_payload_l4csum_update(pkt, skb, fsum, tsum) < 0) 300 215 goto err; 301 216 } 302 217 ··· 327 240 if (tb[NFTA_PAYLOAD_CSUM_OFFSET]) 328 241 priv->csum_offset = 329 242 ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_OFFSET])); 243 + if (tb[NFTA_PAYLOAD_CSUM_FLAGS]) { 244 + u32 flags; 245 + 246 + flags = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_FLAGS])); 247 + if (flags & ~NFT_PAYLOAD_L4CSUM_PSEUDOHDR) 248 + return -EINVAL; 249 + 250 + priv->csum_flags = flags; 251 + } 330 252 331 253 switch (priv->csum_type) { 332 254 case NFT_PAYLOAD_CSUM_NONE: ··· 358 262 nla_put_be32(skb, NFTA_PAYLOAD_LEN, htonl(priv->len)) || 359 263 nla_put_be32(skb, NFTA_PAYLOAD_CSUM_TYPE, htonl(priv->csum_type)) || 360 264 nla_put_be32(skb, NFTA_PAYLOAD_CSUM_OFFSET, 361 - htonl(priv->csum_offset))) 265 + htonl(priv->csum_offset)) || 266 + nla_put_be32(skb, NFTA_PAYLOAD_CSUM_FLAGS, htonl(priv->csum_flags))) 362 267 goto nla_put_failure; 363 268 return 0; 364 269
+136 -22
net/netfilter/nft_quota.c
··· 17 17 18 18 struct nft_quota { 19 19 u64 quota; 20 - bool invert; 21 - atomic64_t remain; 20 + unsigned long flags; 21 + atomic64_t consumed; 22 22 }; 23 23 24 24 static inline bool nft_overquota(struct nft_quota *priv, 25 - const struct nft_pktinfo *pkt) 25 + const struct sk_buff *skb) 26 26 { 27 - return atomic64_sub_return(pkt->skb->len, &priv->remain) < 0; 27 + return atomic64_add_return(skb->len, &priv->consumed) >= priv->quota; 28 28 } 29 29 30 - static void nft_quota_eval(const struct nft_expr *expr, 31 - struct nft_regs *regs, 32 - const struct nft_pktinfo *pkt) 30 + static inline bool nft_quota_invert(struct nft_quota *priv) 33 31 { 34 - struct nft_quota *priv = nft_expr_priv(expr); 32 + return priv->flags & NFT_QUOTA_F_INV; 33 + } 35 34 36 - if (nft_overquota(priv, pkt) ^ priv->invert) 35 + static inline void nft_quota_do_eval(struct nft_quota *priv, 36 + struct nft_regs *regs, 37 + const struct nft_pktinfo *pkt) 38 + { 39 + if (nft_overquota(priv, pkt->skb) ^ nft_quota_invert(priv)) 37 40 regs->verdict.code = NFT_BREAK; 38 41 } 39 42 40 43 static const struct nla_policy nft_quota_policy[NFTA_QUOTA_MAX + 1] = { 41 44 [NFTA_QUOTA_BYTES] = { .type = NLA_U64 }, 42 45 [NFTA_QUOTA_FLAGS] = { .type = NLA_U32 }, 46 + [NFTA_QUOTA_CONSUMED] = { .type = NLA_U64 }, 43 47 }; 44 48 45 - static int nft_quota_init(const struct nft_ctx *ctx, 46 - const struct nft_expr *expr, 47 - const struct nlattr * const tb[]) 49 + #define NFT_QUOTA_DEPLETED_BIT 1 /* From NFT_QUOTA_F_DEPLETED. */ 50 + 51 + static void nft_quota_obj_eval(struct nft_object *obj, 52 + struct nft_regs *regs, 53 + const struct nft_pktinfo *pkt) 48 54 { 49 - struct nft_quota *priv = nft_expr_priv(expr); 50 - u32 flags = 0; 51 - u64 quota; 55 + struct nft_quota *priv = nft_obj_data(obj); 56 + bool overquota; 57 + 58 + overquota = nft_overquota(priv, pkt->skb); 59 + if (overquota ^ nft_quota_invert(priv)) 60 + regs->verdict.code = NFT_BREAK; 61 + 62 + if (overquota && 63 + !test_and_set_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags)) 64 + nft_obj_notify(nft_net(pkt), obj->table, obj, 0, 0, 65 + NFT_MSG_NEWOBJ, nft_pf(pkt), 0, GFP_ATOMIC); 66 + } 67 + 68 + static int nft_quota_do_init(const struct nlattr * const tb[], 69 + struct nft_quota *priv) 70 + { 71 + unsigned long flags = 0; 72 + u64 quota, consumed = 0; 52 73 53 74 if (!tb[NFTA_QUOTA_BYTES]) 54 75 return -EINVAL; ··· 78 57 if (quota > S64_MAX) 79 58 return -EOVERFLOW; 80 59 60 + if (tb[NFTA_QUOTA_CONSUMED]) { 61 + consumed = be64_to_cpu(nla_get_be64(tb[NFTA_QUOTA_CONSUMED])); 62 + if (consumed > quota) 63 + return -EINVAL; 64 + } 65 + 81 66 if (tb[NFTA_QUOTA_FLAGS]) { 82 67 flags = ntohl(nla_get_be32(tb[NFTA_QUOTA_FLAGS])); 83 68 if (flags & ~NFT_QUOTA_F_INV) 84 69 return -EINVAL; 70 + if (flags & NFT_QUOTA_F_DEPLETED) 71 + return -EOPNOTSUPP; 85 72 } 86 73 87 74 priv->quota = quota; 88 - priv->invert = (flags & NFT_QUOTA_F_INV) ? true : false; 89 - atomic64_set(&priv->remain, quota); 75 + priv->flags = flags; 76 + atomic64_set(&priv->consumed, consumed); 90 77 91 78 return 0; 92 79 } 93 80 94 - static int nft_quota_dump(struct sk_buff *skb, const struct nft_expr *expr) 81 + static int nft_quota_obj_init(const struct nlattr * const tb[], 82 + struct nft_object *obj) 95 83 { 96 - const struct nft_quota *priv = nft_expr_priv(expr); 97 - u32 flags = priv->invert ? NFT_QUOTA_F_INV : 0; 84 + struct nft_quota *priv = nft_obj_data(obj); 85 + 86 + return nft_quota_do_init(tb, priv); 87 + } 88 + 89 + static int nft_quota_do_dump(struct sk_buff *skb, struct nft_quota *priv, 90 + bool reset) 91 + { 92 + u32 flags = priv->flags; 93 + u64 consumed; 94 + 95 + if (reset) { 96 + consumed = atomic64_xchg(&priv->consumed, 0); 97 + if (test_and_clear_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags)) 98 + flags |= NFT_QUOTA_F_DEPLETED; 99 + } else { 100 + consumed = atomic64_read(&priv->consumed); 101 + } 102 + 103 + /* Since we inconditionally increment consumed quota for each packet 104 + * that we see, don't go over the quota boundary in what we send to 105 + * userspace. 106 + */ 107 + if (consumed > priv->quota) 108 + consumed = priv->quota; 98 109 99 110 if (nla_put_be64(skb, NFTA_QUOTA_BYTES, cpu_to_be64(priv->quota), 111 + NFTA_QUOTA_PAD) || 112 + nla_put_be64(skb, NFTA_QUOTA_CONSUMED, cpu_to_be64(consumed), 100 113 NFTA_QUOTA_PAD) || 101 114 nla_put_be32(skb, NFTA_QUOTA_FLAGS, htonl(flags))) 102 115 goto nla_put_failure; ··· 138 83 139 84 nla_put_failure: 140 85 return -1; 86 + } 87 + 88 + static int nft_quota_obj_dump(struct sk_buff *skb, struct nft_object *obj, 89 + bool reset) 90 + { 91 + struct nft_quota *priv = nft_obj_data(obj); 92 + 93 + return nft_quota_do_dump(skb, priv, reset); 94 + } 95 + 96 + static struct nft_object_type nft_quota_obj __read_mostly = { 97 + .type = NFT_OBJECT_QUOTA, 98 + .size = sizeof(struct nft_quota), 99 + .maxattr = NFTA_QUOTA_MAX, 100 + .policy = nft_quota_policy, 101 + .init = nft_quota_obj_init, 102 + .eval = nft_quota_obj_eval, 103 + .dump = nft_quota_obj_dump, 104 + .owner = THIS_MODULE, 105 + }; 106 + 107 + static void nft_quota_eval(const struct nft_expr *expr, 108 + struct nft_regs *regs, 109 + const struct nft_pktinfo *pkt) 110 + { 111 + struct nft_quota *priv = nft_expr_priv(expr); 112 + 113 + nft_quota_do_eval(priv, regs, pkt); 114 + } 115 + 116 + static int nft_quota_init(const struct nft_ctx *ctx, 117 + const struct nft_expr *expr, 118 + const struct nlattr * const tb[]) 119 + { 120 + struct nft_quota *priv = nft_expr_priv(expr); 121 + 122 + return nft_quota_do_init(tb, priv); 123 + } 124 + 125 + static int nft_quota_dump(struct sk_buff *skb, const struct nft_expr *expr) 126 + { 127 + struct nft_quota *priv = nft_expr_priv(expr); 128 + 129 + return nft_quota_do_dump(skb, priv, false); 141 130 } 142 131 143 132 static struct nft_expr_type nft_quota_type; ··· 204 105 205 106 static int __init nft_quota_module_init(void) 206 107 { 207 - return nft_register_expr(&nft_quota_type); 108 + int err; 109 + 110 + err = nft_register_obj(&nft_quota_obj); 111 + if (err < 0) 112 + return err; 113 + 114 + err = nft_register_expr(&nft_quota_type); 115 + if (err < 0) 116 + goto err1; 117 + 118 + return 0; 119 + err1: 120 + nft_unregister_obj(&nft_quota_obj); 121 + return err; 208 122 } 209 123 210 124 static void __exit nft_quota_module_exit(void) 211 125 { 212 - nft_unregister_expr(&nft_quota_type); 126 + nft_unregister_expr(&nft_quota_type); 127 + nft_unregister_obj(&nft_quota_obj); 213 128 } 214 129 215 130 module_init(nft_quota_module_init); ··· 232 119 MODULE_LICENSE("GPL"); 233 120 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); 234 121 MODULE_ALIAS_NFT_EXPR("quota"); 122 + MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_QUOTA);
+3 -3
net/netfilter/nft_redir.c
··· 1 1 /* 2 - * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com> 2 + * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo@debian.org> 3 3 * 4 4 * This program is free software; you can redistribute it and/or modify 5 5 * it under the terms of the GNU General Public License version 2 as ··· 79 79 return -EINVAL; 80 80 } 81 81 82 - return 0; 82 + return nf_ct_netns_get(ctx->net, ctx->afi->family); 83 83 } 84 84 EXPORT_SYMBOL_GPL(nft_redir_init); 85 85 ··· 108 108 EXPORT_SYMBOL_GPL(nft_redir_dump); 109 109 110 110 MODULE_LICENSE("GPL"); 111 - MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>"); 111 + MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
+18 -7
net/netfilter/nft_set_hash.c
··· 167 167 nft_set_elem_clear_busy(&he->ext); 168 168 } 169 169 170 + static bool nft_hash_deactivate_one(const struct net *net, 171 + const struct nft_set *set, void *priv) 172 + { 173 + struct nft_hash_elem *he = priv; 174 + 175 + if (!nft_set_elem_mark_busy(&he->ext) || 176 + !nft_is_active(net, &he->ext)) { 177 + nft_set_elem_change_active(net, set, &he->ext); 178 + return true; 179 + } 180 + return false; 181 + } 182 + 170 183 static void *nft_hash_deactivate(const struct net *net, 171 184 const struct nft_set *set, 172 185 const struct nft_set_elem *elem) ··· 194 181 195 182 rcu_read_lock(); 196 183 he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params); 197 - if (he != NULL) { 198 - if (!nft_set_elem_mark_busy(&he->ext) || 199 - !nft_is_active(net, &he->ext)) 200 - nft_set_elem_change_active(net, set, &he->ext); 201 - else 202 - he = NULL; 203 - } 184 + if (he != NULL && 185 + !nft_hash_deactivate_one(net, set, he)) 186 + he = NULL; 187 + 204 188 rcu_read_unlock(); 205 189 206 190 return he; ··· 397 387 .insert = nft_hash_insert, 398 388 .activate = nft_hash_activate, 399 389 .deactivate = nft_hash_deactivate, 390 + .deactivate_one = nft_hash_deactivate_one, 400 391 .remove = nft_hash_remove, 401 392 .lookup = nft_hash_lookup, 402 393 .update = nft_hash_update,
+11 -1
net/netfilter/nft_set_rbtree.c
··· 171 171 nft_set_elem_change_active(net, set, &rbe->ext); 172 172 } 173 173 174 + static bool nft_rbtree_deactivate_one(const struct net *net, 175 + const struct nft_set *set, void *priv) 176 + { 177 + struct nft_rbtree_elem *rbe = priv; 178 + 179 + nft_set_elem_change_active(net, set, &rbe->ext); 180 + return true; 181 + } 182 + 174 183 static void *nft_rbtree_deactivate(const struct net *net, 175 184 const struct nft_set *set, 176 185 const struct nft_set_elem *elem) ··· 213 204 parent = parent->rb_right; 214 205 continue; 215 206 } 216 - nft_set_elem_change_active(net, set, &rbe->ext); 207 + nft_rbtree_deactivate_one(net, set, rbe); 217 208 return rbe; 218 209 } 219 210 } ··· 304 295 .insert = nft_rbtree_insert, 305 296 .remove = nft_rbtree_remove, 306 297 .deactivate = nft_rbtree_deactivate, 298 + .deactivate_one = nft_rbtree_deactivate_one, 307 299 .activate = nft_rbtree_activate, 308 300 .lookup = nft_rbtree_lookup, 309 301 .walk = nft_rbtree_walk,
+57 -1
net/netfilter/x_tables.c
··· 40 40 MODULE_DESCRIPTION("{ip,ip6,arp,eb}_tables backend module"); 41 41 42 42 #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) 43 + #define XT_PCPU_BLOCK_SIZE 4096 43 44 44 45 struct compat_delta { 45 46 unsigned int offset; /* offset in kernel */ ··· 959 958 if (sz <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) 960 959 info = kmalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); 961 960 if (!info) { 962 - info = vmalloc(sz); 961 + info = __vmalloc(sz, GFP_KERNEL | __GFP_NOWARN | 962 + __GFP_NORETRY | __GFP_HIGHMEM, 963 + PAGE_KERNEL); 963 964 if (!info) 964 965 return NULL; 965 966 } ··· 1617 1614 #endif /*CONFIG_PROC_FS*/ 1618 1615 } 1619 1616 EXPORT_SYMBOL_GPL(xt_proto_fini); 1617 + 1618 + /** 1619 + * xt_percpu_counter_alloc - allocate x_tables rule counter 1620 + * 1621 + * @state: pointer to xt_percpu allocation state 1622 + * @counter: pointer to counter struct inside the ip(6)/arpt_entry struct 1623 + * 1624 + * On SMP, the packet counter [ ip(6)t_entry->counters.pcnt ] will then 1625 + * contain the address of the real (percpu) counter. 1626 + * 1627 + * Rule evaluation needs to use xt_get_this_cpu_counter() helper 1628 + * to fetch the real percpu counter. 1629 + * 1630 + * To speed up allocation and improve data locality, a 4kb block is 1631 + * allocated. 1632 + * 1633 + * xt_percpu_counter_alloc_state contains the base address of the 1634 + * allocated page and the current sub-offset. 1635 + * 1636 + * returns false on error. 1637 + */ 1638 + bool xt_percpu_counter_alloc(struct xt_percpu_counter_alloc_state *state, 1639 + struct xt_counters *counter) 1640 + { 1641 + BUILD_BUG_ON(XT_PCPU_BLOCK_SIZE < (sizeof(*counter) * 2)); 1642 + 1643 + if (nr_cpu_ids <= 1) 1644 + return true; 1645 + 1646 + if (!state->mem) { 1647 + state->mem = __alloc_percpu(XT_PCPU_BLOCK_SIZE, 1648 + XT_PCPU_BLOCK_SIZE); 1649 + if (!state->mem) 1650 + return false; 1651 + } 1652 + counter->pcnt = (__force unsigned long)(state->mem + state->off); 1653 + state->off += sizeof(*counter); 1654 + if (state->off > (XT_PCPU_BLOCK_SIZE - sizeof(*counter))) { 1655 + state->mem = NULL; 1656 + state->off = 0; 1657 + } 1658 + return true; 1659 + } 1660 + EXPORT_SYMBOL_GPL(xt_percpu_counter_alloc); 1661 + 1662 + void xt_percpu_counter_free(struct xt_counters *counters) 1663 + { 1664 + unsigned long pcnt = counters->pcnt; 1665 + 1666 + if (nr_cpu_ids > 1 && (pcnt & (XT_PCPU_BLOCK_SIZE - 1)) == 0) 1667 + free_percpu((void __percpu *)pcnt); 1668 + } 1669 + EXPORT_SYMBOL_GPL(xt_percpu_counter_free); 1620 1670 1621 1671 static int __net_init xt_net_init(struct net *net) 1622 1672 {
+2 -2
net/netfilter/xt_CONNSECMARK.c
··· 106 106 return -EINVAL; 107 107 } 108 108 109 - ret = nf_ct_l3proto_try_module_get(par->family); 109 + ret = nf_ct_netns_get(par->net, par->family); 110 110 if (ret < 0) 111 111 pr_info("cannot load conntrack support for proto=%u\n", 112 112 par->family); ··· 115 115 116 116 static void connsecmark_tg_destroy(const struct xt_tgdtor_param *par) 117 117 { 118 - nf_ct_l3proto_module_put(par->family); 118 + nf_ct_netns_put(par->net, par->family); 119 119 } 120 120 121 121 static struct xt_target connsecmark_tg_reg __read_mostly = {
+3 -3
net/netfilter/xt_CT.c
··· 216 216 goto err1; 217 217 #endif 218 218 219 - ret = nf_ct_l3proto_try_module_get(par->family); 219 + ret = nf_ct_netns_get(par->net, par->family); 220 220 if (ret < 0) 221 221 goto err1; 222 222 ··· 260 260 err3: 261 261 nf_ct_tmpl_free(ct); 262 262 err2: 263 - nf_ct_l3proto_module_put(par->family); 263 + nf_ct_netns_put(par->net, par->family); 264 264 err1: 265 265 return ret; 266 266 } ··· 341 341 if (help) 342 342 module_put(help->helper->me); 343 343 344 - nf_ct_l3proto_module_put(par->family); 344 + nf_ct_netns_put(par->net, par->family); 345 345 346 346 xt_ct_destroy_timeout(ct); 347 347 nf_ct_put(info->ct);
+9 -2
net/netfilter/xt_NETMAP.c
··· 60 60 61 61 if (!(range->flags & NF_NAT_RANGE_MAP_IPS)) 62 62 return -EINVAL; 63 - return 0; 63 + return nf_ct_netns_get(par->net, par->family); 64 + } 65 + 66 + static void netmap_tg_destroy(const struct xt_tgdtor_param *par) 67 + { 68 + nf_ct_netns_put(par->net, par->family); 64 69 } 65 70 66 71 static unsigned int ··· 116 111 pr_debug("bad rangesize %u.\n", mr->rangesize); 117 112 return -EINVAL; 118 113 } 119 - return 0; 114 + return nf_ct_netns_get(par->net, par->family); 120 115 } 121 116 122 117 static struct xt_target netmap_tg_reg[] __read_mostly = { ··· 132 127 (1 << NF_INET_LOCAL_OUT) | 133 128 (1 << NF_INET_LOCAL_IN), 134 129 .checkentry = netmap_tg6_checkentry, 130 + .destroy = netmap_tg_destroy, 135 131 .me = THIS_MODULE, 136 132 }, 137 133 { ··· 147 141 (1 << NF_INET_LOCAL_OUT) | 148 142 (1 << NF_INET_LOCAL_IN), 149 143 .checkentry = netmap_tg4_check, 144 + .destroy = netmap_tg_destroy, 150 145 .me = THIS_MODULE, 151 146 }, 152 147 };
+10 -2
net/netfilter/xt_REDIRECT.c
··· 40 40 41 41 if (range->flags & NF_NAT_RANGE_MAP_IPS) 42 42 return -EINVAL; 43 - return 0; 43 + 44 + return nf_ct_netns_get(par->net, par->family); 45 + } 46 + 47 + static void redirect_tg_destroy(const struct xt_tgdtor_param *par) 48 + { 49 + nf_ct_netns_put(par->net, par->family); 44 50 } 45 51 46 52 /* FIXME: Take multiple ranges --RR */ ··· 62 56 pr_debug("bad rangesize %u.\n", mr->rangesize); 63 57 return -EINVAL; 64 58 } 65 - return 0; 59 + return nf_ct_netns_get(par->net, par->family); 66 60 } 67 61 68 62 static unsigned int ··· 78 72 .revision = 0, 79 73 .table = "nat", 80 74 .checkentry = redirect_tg6_checkentry, 75 + .destroy = redirect_tg_destroy, 81 76 .target = redirect_tg6, 82 77 .targetsize = sizeof(struct nf_nat_range), 83 78 .hooks = (1 << NF_INET_PRE_ROUTING) | ··· 92 85 .table = "nat", 93 86 .target = redirect_tg4, 94 87 .checkentry = redirect_tg4_check, 88 + .destroy = redirect_tg_destroy, 95 89 .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), 96 90 .hooks = (1 << NF_INET_PRE_ROUTING) | 97 91 (1 << NF_INET_LOCAL_OUT),
+10 -5
net/netfilter/xt_TPROXY.c
··· 531 531 static int tproxy_tg6_check(const struct xt_tgchk_param *par) 532 532 { 533 533 const struct ip6t_ip6 *i = par->entryinfo; 534 + int err; 535 + 536 + err = nf_defrag_ipv6_enable(par->net); 537 + if (err) 538 + return err; 534 539 535 540 if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP) && 536 541 !(i->invflags & IP6T_INV_PROTO)) ··· 550 545 static int tproxy_tg4_check(const struct xt_tgchk_param *par) 551 546 { 552 547 const struct ipt_ip *i = par->entryinfo; 548 + int err; 549 + 550 + err = nf_defrag_ipv4_enable(par->net); 551 + if (err) 552 + return err; 553 553 554 554 if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP) 555 555 && !(i->invflags & IPT_INV_PROTO)) ··· 606 596 607 597 static int __init tproxy_tg_init(void) 608 598 { 609 - nf_defrag_ipv4_enable(); 610 - #ifdef XT_TPROXY_HAVE_IPV6 611 - nf_defrag_ipv6_enable(); 612 - #endif 613 - 614 599 return xt_register_targets(tproxy_tg_reg, ARRAY_SIZE(tproxy_tg_reg)); 615 600 } 616 601
+80 -16
net/netfilter/xt_bpf.c
··· 10 10 #include <linux/module.h> 11 11 #include <linux/skbuff.h> 12 12 #include <linux/filter.h> 13 + #include <linux/bpf.h> 13 14 14 15 #include <linux/netfilter/xt_bpf.h> 15 16 #include <linux/netfilter/x_tables.h> ··· 21 20 MODULE_ALIAS("ipt_bpf"); 22 21 MODULE_ALIAS("ip6t_bpf"); 23 22 24 - static int bpf_mt_check(const struct xt_mtchk_param *par) 23 + static int __bpf_mt_check_bytecode(struct sock_filter *insns, __u16 len, 24 + struct bpf_prog **ret) 25 25 { 26 - struct xt_bpf_info *info = par->matchinfo; 27 26 struct sock_fprog_kern program; 28 27 29 - program.len = info->bpf_program_num_elem; 30 - program.filter = info->bpf_program; 28 + program.len = len; 29 + program.filter = insns; 31 30 32 - if (bpf_prog_create(&info->filter, &program)) { 31 + if (bpf_prog_create(ret, &program)) { 33 32 pr_info("bpf: check failed: parse error\n"); 34 33 return -EINVAL; 35 34 } 36 35 37 36 return 0; 37 + } 38 + 39 + static int __bpf_mt_check_fd(int fd, struct bpf_prog **ret) 40 + { 41 + struct bpf_prog *prog; 42 + 43 + prog = bpf_prog_get_type(fd, BPF_PROG_TYPE_SOCKET_FILTER); 44 + if (IS_ERR(prog)) 45 + return PTR_ERR(prog); 46 + 47 + *ret = prog; 48 + return 0; 49 + } 50 + 51 + static int bpf_mt_check(const struct xt_mtchk_param *par) 52 + { 53 + struct xt_bpf_info *info = par->matchinfo; 54 + 55 + return __bpf_mt_check_bytecode(info->bpf_program, 56 + info->bpf_program_num_elem, 57 + &info->filter); 58 + } 59 + 60 + static int bpf_mt_check_v1(const struct xt_mtchk_param *par) 61 + { 62 + struct xt_bpf_info_v1 *info = par->matchinfo; 63 + 64 + if (info->mode == XT_BPF_MODE_BYTECODE) 65 + return __bpf_mt_check_bytecode(info->bpf_program, 66 + info->bpf_program_num_elem, 67 + &info->filter); 68 + else if (info->mode == XT_BPF_MODE_FD_PINNED || 69 + info->mode == XT_BPF_MODE_FD_ELF) 70 + return __bpf_mt_check_fd(info->fd, &info->filter); 71 + else 72 + return -EINVAL; 38 73 } 39 74 40 75 static bool bpf_mt(const struct sk_buff *skb, struct xt_action_param *par) ··· 80 43 return BPF_PROG_RUN(info->filter, skb); 81 44 } 82 45 46 + static bool bpf_mt_v1(const struct sk_buff *skb, struct xt_action_param *par) 47 + { 48 + const struct xt_bpf_info_v1 *info = par->matchinfo; 49 + 50 + return !!bpf_prog_run_save_cb(info->filter, (struct sk_buff *) skb); 51 + } 52 + 83 53 static void bpf_mt_destroy(const struct xt_mtdtor_param *par) 84 54 { 85 55 const struct xt_bpf_info *info = par->matchinfo; 56 + 86 57 bpf_prog_destroy(info->filter); 87 58 } 88 59 89 - static struct xt_match bpf_mt_reg __read_mostly = { 90 - .name = "bpf", 91 - .revision = 0, 92 - .family = NFPROTO_UNSPEC, 93 - .checkentry = bpf_mt_check, 94 - .match = bpf_mt, 95 - .destroy = bpf_mt_destroy, 96 - .matchsize = sizeof(struct xt_bpf_info), 97 - .me = THIS_MODULE, 60 + static void bpf_mt_destroy_v1(const struct xt_mtdtor_param *par) 61 + { 62 + const struct xt_bpf_info_v1 *info = par->matchinfo; 63 + 64 + bpf_prog_destroy(info->filter); 65 + } 66 + 67 + static struct xt_match bpf_mt_reg[] __read_mostly = { 68 + { 69 + .name = "bpf", 70 + .revision = 0, 71 + .family = NFPROTO_UNSPEC, 72 + .checkentry = bpf_mt_check, 73 + .match = bpf_mt, 74 + .destroy = bpf_mt_destroy, 75 + .matchsize = sizeof(struct xt_bpf_info), 76 + .me = THIS_MODULE, 77 + }, 78 + { 79 + .name = "bpf", 80 + .revision = 1, 81 + .family = NFPROTO_UNSPEC, 82 + .checkentry = bpf_mt_check_v1, 83 + .match = bpf_mt_v1, 84 + .destroy = bpf_mt_destroy_v1, 85 + .matchsize = sizeof(struct xt_bpf_info_v1), 86 + .me = THIS_MODULE, 87 + }, 98 88 }; 99 89 100 90 static int __init bpf_mt_init(void) 101 91 { 102 - return xt_register_match(&bpf_mt_reg); 92 + return xt_register_matches(bpf_mt_reg, ARRAY_SIZE(bpf_mt_reg)); 103 93 } 104 94 105 95 static void __exit bpf_mt_exit(void) 106 96 { 107 - xt_unregister_match(&bpf_mt_reg); 97 + xt_unregister_matches(bpf_mt_reg, ARRAY_SIZE(bpf_mt_reg)); 108 98 } 109 99 110 100 module_init(bpf_mt_init);
+2 -2
net/netfilter/xt_connbytes.c
··· 110 110 sinfo->direction != XT_CONNBYTES_DIR_BOTH) 111 111 return -EINVAL; 112 112 113 - ret = nf_ct_l3proto_try_module_get(par->family); 113 + ret = nf_ct_netns_get(par->net, par->family); 114 114 if (ret < 0) 115 115 pr_info("cannot load conntrack support for proto=%u\n", 116 116 par->family); ··· 129 129 130 130 static void connbytes_mt_destroy(const struct xt_mtdtor_param *par) 131 131 { 132 - nf_ct_l3proto_module_put(par->family); 132 + nf_ct_netns_put(par->net, par->family); 133 133 } 134 134 135 135 static struct xt_match connbytes_mt_reg __read_mostly = {
+3 -3
net/netfilter/xt_connlabel.c
··· 61 61 return -EINVAL; 62 62 } 63 63 64 - ret = nf_ct_l3proto_try_module_get(par->family); 64 + ret = nf_ct_netns_get(par->net, par->family); 65 65 if (ret < 0) { 66 66 pr_info("cannot load conntrack support for proto=%u\n", 67 67 par->family); ··· 70 70 71 71 ret = nf_connlabels_get(par->net, info->bit); 72 72 if (ret < 0) 73 - nf_ct_l3proto_module_put(par->family); 73 + nf_ct_netns_put(par->net, par->family); 74 74 return ret; 75 75 } 76 76 77 77 static void connlabel_mt_destroy(const struct xt_mtdtor_param *par) 78 78 { 79 79 nf_connlabels_put(par->net); 80 - nf_ct_l3proto_module_put(par->family); 80 + nf_ct_netns_put(par->net, par->family); 81 81 } 82 82 83 83 static struct xt_match connlabels_mt_reg __read_mostly = {
+3 -3
net/netfilter/xt_connlimit.c
··· 368 368 369 369 net_get_random_once(&connlimit_rnd, sizeof(connlimit_rnd)); 370 370 371 - ret = nf_ct_l3proto_try_module_get(par->family); 371 + ret = nf_ct_netns_get(par->net, par->family); 372 372 if (ret < 0) { 373 373 pr_info("cannot load conntrack support for " 374 374 "address family %u\n", par->family); ··· 378 378 /* init private data */ 379 379 info->data = kmalloc(sizeof(struct xt_connlimit_data), GFP_KERNEL); 380 380 if (info->data == NULL) { 381 - nf_ct_l3proto_module_put(par->family); 381 + nf_ct_netns_put(par->net, par->family); 382 382 return -ENOMEM; 383 383 } 384 384 ··· 414 414 const struct xt_connlimit_info *info = par->matchinfo; 415 415 unsigned int i; 416 416 417 - nf_ct_l3proto_module_put(par->family); 417 + nf_ct_netns_put(par->net, par->family); 418 418 419 419 for (i = 0; i < ARRAY_SIZE(info->data->climit_root4); ++i) 420 420 destroy_tree(&info->data->climit_root4[i]);
+4 -4
net/netfilter/xt_connmark.c
··· 77 77 { 78 78 int ret; 79 79 80 - ret = nf_ct_l3proto_try_module_get(par->family); 80 + ret = nf_ct_netns_get(par->net, par->family); 81 81 if (ret < 0) 82 82 pr_info("cannot load conntrack support for proto=%u\n", 83 83 par->family); ··· 86 86 87 87 static void connmark_tg_destroy(const struct xt_tgdtor_param *par) 88 88 { 89 - nf_ct_l3proto_module_put(par->family); 89 + nf_ct_netns_put(par->net, par->family); 90 90 } 91 91 92 92 static bool ··· 107 107 { 108 108 int ret; 109 109 110 - ret = nf_ct_l3proto_try_module_get(par->family); 110 + ret = nf_ct_netns_get(par->net, par->family); 111 111 if (ret < 0) 112 112 pr_info("cannot load conntrack support for proto=%u\n", 113 113 par->family); ··· 116 116 117 117 static void connmark_mt_destroy(const struct xt_mtdtor_param *par) 118 118 { 119 - nf_ct_l3proto_module_put(par->family); 119 + nf_ct_netns_put(par->net, par->family); 120 120 } 121 121 122 122 static struct xt_target connmark_tg_reg __read_mostly = {
+2 -2
net/netfilter/xt_conntrack.c
··· 271 271 { 272 272 int ret; 273 273 274 - ret = nf_ct_l3proto_try_module_get(par->family); 274 + ret = nf_ct_netns_get(par->net, par->family); 275 275 if (ret < 0) 276 276 pr_info("cannot load conntrack support for proto=%u\n", 277 277 par->family); ··· 280 280 281 281 static void conntrack_mt_destroy(const struct xt_mtdtor_param *par) 282 282 { 283 - nf_ct_l3proto_module_put(par->family); 283 + nf_ct_netns_put(par->net, par->family); 284 284 } 285 285 286 286 static struct xt_match conntrack_mt_reg[] __read_mostly = {
+2 -2
net/netfilter/xt_helper.c
··· 59 59 struct xt_helper_info *info = par->matchinfo; 60 60 int ret; 61 61 62 - ret = nf_ct_l3proto_try_module_get(par->family); 62 + ret = nf_ct_netns_get(par->net, par->family); 63 63 if (ret < 0) { 64 64 pr_info("cannot load conntrack support for proto=%u\n", 65 65 par->family); ··· 71 71 72 72 static void helper_mt_destroy(const struct xt_mtdtor_param *par) 73 73 { 74 - nf_ct_l3proto_module_put(par->family); 74 + nf_ct_netns_put(par->net, par->family); 75 75 } 76 76 77 77 static struct xt_match helper_mt_reg __read_mostly = {
+19 -7
net/netfilter/xt_multiport.c
··· 44 44 45 45 switch (minfo->flags) { 46 46 case XT_MULTIPORT_SOURCE: 47 - return (src >= s && src <= e) ^ minfo->invert; 47 + if (src >= s && src <= e) 48 + return true ^ minfo->invert; 49 + break; 48 50 case XT_MULTIPORT_DESTINATION: 49 - return (dst >= s && dst <= e) ^ minfo->invert; 51 + if (dst >= s && dst <= e) 52 + return true ^ minfo->invert; 53 + break; 50 54 case XT_MULTIPORT_EITHER: 51 - return ((dst >= s && dst <= e) || 52 - (src >= s && src <= e)) ^ minfo->invert; 55 + if ((dst >= s && dst <= e) || 56 + (src >= s && src <= e)) 57 + return true ^ minfo->invert; 58 + break; 53 59 default: 54 60 break; 55 61 } ··· 65 59 66 60 switch (minfo->flags) { 67 61 case XT_MULTIPORT_SOURCE: 68 - return (src == s) ^ minfo->invert; 62 + if (src == s) 63 + return true ^ minfo->invert; 64 + break; 69 65 case XT_MULTIPORT_DESTINATION: 70 - return (dst == s) ^ minfo->invert; 66 + if (dst == s) 67 + return true ^ minfo->invert; 68 + break; 71 69 case XT_MULTIPORT_EITHER: 72 - return (src == s || dst == s) ^ minfo->invert; 70 + if (src == s || dst == s) 71 + return true ^ minfo->invert; 72 + break; 73 73 default: 74 74 break; 75 75 }
+17 -1
net/netfilter/xt_nat.c
··· 23 23 par->target->name); 24 24 return -EINVAL; 25 25 } 26 - return 0; 26 + return nf_ct_netns_get(par->net, par->family); 27 + } 28 + 29 + static int xt_nat_checkentry(const struct xt_tgchk_param *par) 30 + { 31 + return nf_ct_netns_get(par->net, par->family); 32 + } 33 + 34 + static void xt_nat_destroy(const struct xt_tgdtor_param *par) 35 + { 36 + nf_ct_netns_put(par->net, par->family); 27 37 } 28 38 29 39 static void xt_nat_convert_range(struct nf_nat_range *dst, ··· 116 106 .name = "SNAT", 117 107 .revision = 0, 118 108 .checkentry = xt_nat_checkentry_v0, 109 + .destroy = xt_nat_destroy, 119 110 .target = xt_snat_target_v0, 120 111 .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), 121 112 .family = NFPROTO_IPV4, ··· 129 118 .name = "DNAT", 130 119 .revision = 0, 131 120 .checkentry = xt_nat_checkentry_v0, 121 + .destroy = xt_nat_destroy, 132 122 .target = xt_dnat_target_v0, 133 123 .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), 134 124 .family = NFPROTO_IPV4, ··· 141 129 { 142 130 .name = "SNAT", 143 131 .revision = 1, 132 + .checkentry = xt_nat_checkentry, 133 + .destroy = xt_nat_destroy, 144 134 .target = xt_snat_target_v1, 145 135 .targetsize = sizeof(struct nf_nat_range), 146 136 .table = "nat", ··· 153 139 { 154 140 .name = "DNAT", 155 141 .revision = 1, 142 + .checkentry = xt_nat_checkentry, 143 + .destroy = xt_nat_destroy, 156 144 .target = xt_dnat_target_v1, 157 145 .targetsize = sizeof(struct nf_nat_range), 158 146 .table = "nat",
+28 -5
net/netfilter/xt_socket.c
··· 147 147 } 148 148 #endif 149 149 150 + static int socket_mt_enable_defrag(struct net *net, int family) 151 + { 152 + switch (family) { 153 + case NFPROTO_IPV4: 154 + return nf_defrag_ipv4_enable(net); 155 + #ifdef XT_SOCKET_HAVE_IPV6 156 + case NFPROTO_IPV6: 157 + return nf_defrag_ipv6_enable(net); 158 + #endif 159 + } 160 + WARN_ONCE(1, "Unknown family %d\n", family); 161 + return 0; 162 + } 163 + 150 164 static int socket_mt_v1_check(const struct xt_mtchk_param *par) 151 165 { 152 166 const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo; 167 + int err; 168 + 169 + err = socket_mt_enable_defrag(par->net, par->family); 170 + if (err) 171 + return err; 153 172 154 173 if (info->flags & ~XT_SOCKET_FLAGS_V1) { 155 174 pr_info("unknown flags 0x%x\n", info->flags & ~XT_SOCKET_FLAGS_V1); ··· 180 161 static int socket_mt_v2_check(const struct xt_mtchk_param *par) 181 162 { 182 163 const struct xt_socket_mtinfo2 *info = (struct xt_socket_mtinfo2 *) par->matchinfo; 164 + int err; 165 + 166 + err = socket_mt_enable_defrag(par->net, par->family); 167 + if (err) 168 + return err; 183 169 184 170 if (info->flags & ~XT_SOCKET_FLAGS_V2) { 185 171 pr_info("unknown flags 0x%x\n", info->flags & ~XT_SOCKET_FLAGS_V2); ··· 197 173 { 198 174 const struct xt_socket_mtinfo3 *info = 199 175 (struct xt_socket_mtinfo3 *)par->matchinfo; 176 + int err; 200 177 178 + err = socket_mt_enable_defrag(par->net, par->family); 179 + if (err) 180 + return err; 201 181 if (info->flags & ~XT_SOCKET_FLAGS_V3) { 202 182 pr_info("unknown flags 0x%x\n", 203 183 info->flags & ~XT_SOCKET_FLAGS_V3); ··· 296 268 297 269 static int __init socket_mt_init(void) 298 270 { 299 - nf_defrag_ipv4_enable(); 300 - #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) 301 - nf_defrag_ipv6_enable(); 302 - #endif 303 - 304 271 return xt_register_matches(socket_mt_reg, ARRAY_SIZE(socket_mt_reg)); 305 272 } 306 273
+2 -2
net/netfilter/xt_state.c
··· 43 43 { 44 44 int ret; 45 45 46 - ret = nf_ct_l3proto_try_module_get(par->family); 46 + ret = nf_ct_netns_get(par->net, par->family); 47 47 if (ret < 0) 48 48 pr_info("cannot load conntrack support for proto=%u\n", 49 49 par->family); ··· 52 52 53 53 static void state_mt_destroy(const struct xt_mtdtor_param *par) 54 54 { 55 - nf_ct_l3proto_module_put(par->family); 55 + nf_ct_netns_put(par->net, par->family); 56 56 } 57 57 58 58 static struct xt_match state_mt_reg __read_mostly = {