History

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. ====================

David S. Miller committed 9 years ago

Commit 5fccd642 parents 63c36c4 73c25fb90 files · +2513 −661Browse files

Unified · Split

90 files
  1. Documentation/networking/nf_conntrack-sysctl.txt +11 −0
  2. include/linux/netfilter.h +30 −1
  3. include/linux/netfilter/nf_conntrack_dccp.h +1 −1
  4. include/linux/netfilter/x_tables.h +7 −31
  5. include/linux/netfilter_ingress.h +6 −1
  6. include/net/netfilter/ipv4/nf_conntrack_ipv4.h +9 −0
  7. include/net/netfilter/ipv4/nf_defrag_ipv4.h +2 −1
  8. include/net/netfilter/ipv6/nf_conntrack_ipv6.h +9 −0
  9. include/net/netfilter/ipv6/nf_defrag_ipv6.h +2 −1
  10. include/net/netfilter/nf_conntrack.h +4 −0
  11. include/net/netfilter/nf_conntrack_l3proto.h +13 −3
  12. include/net/netfilter/nf_dup_netdev.h +1 −0
  13. include/net/netfilter/nf_log.h +3 −1
  14. include/net/netfilter/nf_nat_l4proto.h +9 −0
  15. include/net/netfilter/nf_tables.h +100 −1
  16. include/net/netfilter/nf_tables_core.h +1 −0
  17. include/net/netns/conntrack.h +43 −0
  18. include/net/netns/netfilter.h +6 −0
  19. include/uapi/linux/netfilter/nf_conntrack_tuple_common.h +3 −0
  20. include/uapi/linux/netfilter/nf_tables.h +70 −0
  21. include/uapi/linux/netfilter/xt_bpf.h +21 −0
  22. net/bridge/br_netfilter_hooks.c +4 −4
  23. net/bridge/netfilter/nf_log_bridge.c +2 −1
  24. net/ipv4/netfilter/arp_tables.c +8 −8
  25. net/ipv4/netfilter/ip_tables.c +8 −8
  26. net/ipv4/netfilter/ipt_CLUSTERIP.c +2 −2
  27. net/ipv4/netfilter/ipt_MASQUERADE.c +7 −1
  28. net/ipv4/netfilter/ipt_SYNPROXY.c +2 −2
  29. net/ipv4/netfilter/ipt_rpfilter.c +5 −3
  30. net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +56 −15
  31. net/ipv4/netfilter/nf_defrag_ipv4.c +38 −3
  32. net/ipv4/netfilter/nft_fib_ipv4.c +10 −7
  33. net/ipv4/netfilter/nft_masq_ipv4.c +9 −2
  34. net/ipv4/netfilter/nft_redir_ipv4.c +9 −2
  35. net/ipv6/netfilter/ip6_tables.c +8 −9
  36. net/ipv6/netfilter/ip6t_SYNPROXY.c +2 −2
  37. net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +57 −13
  38. net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +38 −4
  39. net/ipv6/netfilter/nft_fib_ipv6.c +1 −1
  40. net/ipv6/netfilter/nft_masq_ipv6.c +9 −2
  41. net/ipv6/netfilter/nft_redir_ipv6.c +9 −2
  42. net/netfilter/Kconfig +18 −12
  43. net/netfilter/Makefile +9 −9
  44. net/netfilter/core.c +6 −10
  45. net/netfilter/ipvs/ip_vs_ctl.c +1 −1
  46. net/netfilter/ipvs/ip_vs_xmit.c +54 −0
  47. net/netfilter/nf_conntrack_proto.c +65 −8
  48. net/netfilter/nf_conntrack_proto_dccp.c +10 −69
  49. net/netfilter/nf_conntrack_proto_sctp.c +9 −67
  50. net/netfilter/nf_conntrack_proto_udplite.c +9 −70
  51. net/netfilter/nf_conntrack_standalone.c +10 −0
  52. net/netfilter/nf_dup_netdev.c +25 −8
  53. net/netfilter/nf_log_common.c +2 −1
  54. net/netfilter/nf_log_netdev.c +2 −1
  55. net/netfilter/nf_nat_core.c +12 −0
  56. net/netfilter/nf_nat_proto_dccp.c +1 −35
  57. net/netfilter/nf_nat_proto_sctp.c +5 −35
  58. net/netfilter/nf_nat_proto_udplite.c +1 −34
  59. net/netfilter/nf_queue.c +2 −3
  60. net/netfilter/nf_tables_api.c +702 −16
  61. net/netfilter/nfnetlink_log.c +1 −0
  62. net/netfilter/nft_counter.c +156 −30
  63. net/netfilter/nft_ct.c +13 −13
  64. net/netfilter/nft_fib.c +1 −1
  65. net/netfilter/nft_fwd_netdev.c +2 −2
  66. net/netfilter/nft_masq.c +3 −3
  67. net/netfilter/nft_nat.c +10 −1
  68. net/netfilter/nft_objref.c +226 −0
  69. net/netfilter/nft_payload.c +102 −5
  70. net/netfilter/nft_quota.c +136 −22
  71. net/netfilter/nft_redir.c +3 −3
  72. net/netfilter/nft_set_hash.c +18 −7
  73. net/netfilter/nft_set_rbtree.c +11 −1
  74. net/netfilter/x_tables.c +57 −1
  75. net/netfilter/xt_CONNSECMARK.c +2 −2
  76. net/netfilter/xt_CT.c +3 −3
  77. net/netfilter/xt_NETMAP.c +9 −2
  78. net/netfilter/xt_REDIRECT.c +10 −2
  79. net/netfilter/xt_TPROXY.c +10 −5
  80. net/netfilter/xt_bpf.c +80 −16
  81. net/netfilter/xt_connbytes.c +2 −2
  82. net/netfilter/xt_connlabel.c +3 −3
  83. net/netfilter/xt_connlimit.c +3 −3
  84. net/netfilter/xt_connmark.c +4 −4
  85. net/netfilter/xt_conntrack.c +2 −2
  86. net/netfilter/xt_helper.c +2 −2
  87. net/netfilter/xt_multiport.c +19 −7
  88. net/netfilter/xt_nat.c +17 −1
  89. net/netfilter/xt_socket.c +28 −5
  90. net/netfilter/xt_state.c +2 −2
Documentation/networking/nf_conntrack-sysctl.txt+11−0
@@ -96,6 +96,17 @@ nf_conntrack_max - INTEGER · 95 unmodified lines
96 Size of connection tracking table. Default value is96 Size of connection tracking table. Default value is
97 nf_conntrack_buckets value * 4.97 nf_conntrack_buckets value * 4.
98 98
99nf_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
99nf_conntrack_tcp_be_liberal - BOOLEAN110nf_conntrack_tcp_be_liberal - BOOLEAN
100 0 - disabled (default)111 0 - disabled (default)
101 not 0 - enabled112 not 0 - enabled
include/linux/netfilter.h+30−1
@@ -75,10 +75,39 @@ struct nf_hook_ops { · 74 unmodified lines
75 75
76struct nf_hook_entry {76struct nf_hook_entry {
77 struct nf_hook_entry __rcu *next;77 struct nf_hook_entry __rcu *next;
78 struct nf_hook_ops ops;78 nf_hookfn *hook;
79 void *priv;
79 const struct nf_hook_ops *orig_ops;80 const struct nf_hook_ops *orig_ops;
80};81};
81 82
83static inline void
84nf_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
92static inline int
93nf_hook_entry_priority(const struct nf_hook_entry *entry)
94{
95 return entry->orig_ops->priority;
96}
97
98static inline int
99nf_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
105static inline const struct nf_hook_ops *
106nf_hook_entry_ops(const struct nf_hook_entry *entry)
107{
108 return entry->orig_ops;
109}
110
82static inline void nf_hook_state_init(struct nf_hook_state *p,111static inline void nf_hook_state_init(struct nf_hook_state *p,
83 unsigned int hook,112 unsigned int hook,
84 u_int8_t pf,113 u_int8_t pf,
include/linux/netfilter/nf_conntrack_dccp.h+1−1
@@ -25,7 +25,7 @@ enum ct_dccp_roles { · 24 unmodified lines
25#define CT_DCCP_ROLE_MAX (__CT_DCCP_ROLE_MAX - 1)25#define CT_DCCP_ROLE_MAX (__CT_DCCP_ROLE_MAX - 1)
26 26
27#ifdef __KERNEL__27#ifdef __KERNEL__
28#include <net/netfilter/nf_conntrack_tuple.h>28#include <linux/netfilter/nf_conntrack_tuple_common.h>
29 29
30struct nf_ct_dccp {30struct nf_ct_dccp {
31 u_int8_t role[IP_CT_DIR_MAX];31 u_int8_t role[IP_CT_DIR_MAX];
include/linux/netfilter/x_tables.h+7−31
@@ -403,38 +403,14 @@ static inline unsigned long ifname_compare_aligned(const char *_a, · 402 unmodified lines
403 return ret;403 return ret;
404}404}
405 405
406struct 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 the411bool xt_percpu_counter_alloc(struct xt_percpu_counter_alloc_state *state,
408 * real (percpu) counter. On !SMP, its just the packet count,412 struct xt_counters *counter);
409 * so nothing needs to be done there.413void xt_percpu_counter_free(struct xt_counters *cnt);
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 */
419static 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}
433static inline void xt_percpu_counter_free(u64 pcnt)
434{
435 if (nr_cpu_ids > 1)
436 free_percpu((void __percpu *) (unsigned long) pcnt);
437}
438 414
439static inline struct xt_counters *415static inline struct xt_counters *
440xt_get_this_cpu_counter(struct xt_counters *cnt)416xt_get_this_cpu_counter(struct xt_counters *cnt)
include/linux/netfilter_ingress.h+6−1
@@ -19,6 +19,7 @@ static inline int nf_hook_ingress(struct sk_buff *skb) · 18 unmodified lines
19{19{
20 struct nf_hook_entry *e = rcu_dereference(skb->dev->nf_hooks_ingress);20 struct nf_hook_entry *e = rcu_dereference(skb->dev->nf_hooks_ingress);
21 struct nf_hook_state state;21 struct nf_hook_state state;
22 int ret;
22 23
23 /* Must recheck the ingress hook head, in the event it became NULL24 /* Must recheck the ingress hook head, in the event it became NULL
24 * after the check in nf_hook_ingress_active evaluated to true.25 * after the check in nf_hook_ingress_active evaluated to true.
@@ -29,7 +30,11 @@ static inline int nf_hook_ingress(struct sk_buff *skb) · 4 unmodified lines
29 nf_hook_state_init(&state, NF_NETDEV_INGRESS,30 nf_hook_state_init(&state, NF_NETDEV_INGRESS,
30 NFPROTO_NETDEV, skb->dev, NULL, NULL,31 NFPROTO_NETDEV, skb->dev, NULL, NULL,
31 dev_net(skb->dev), NULL);32 dev_net(skb->dev), NULL);
32 return nf_hook_slow(skb, &state, e);33 ret = nf_hook_slow(skb, &state, e);
34 if (ret == 0)
35 return -1;
36
37 return ret;
33}38}
34 39
35static inline void nf_hook_ingress_init(struct net_device *dev)40static inline void nf_hook_ingress_init(struct net_device *dev)
include/net/netfilter/ipv4/nf_conntrack_ipv4.h+9−0
@@ -15,6 +15,15 @@ extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4; · 14 unmodified lines
15extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4;15extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4;
16extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;16extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;
17extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp;17extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp;
18#ifdef CONFIG_NF_CT_PROTO_DCCP
19extern struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4;
20#endif
21#ifdef CONFIG_NF_CT_PROTO_SCTP
22extern struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4;
23#endif
24#ifdef CONFIG_NF_CT_PROTO_UDPLITE
25extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4;
26#endif
18 27
19int nf_conntrack_ipv4_compat_init(void);28int nf_conntrack_ipv4_compat_init(void);
20void nf_conntrack_ipv4_compat_fini(void);29void nf_conntrack_ipv4_compat_fini(void);
include/net/netfilter/ipv4/nf_defrag_ipv4.h+2−1
@@ -1,6 +1,7 @@
1#ifndef _NF_DEFRAG_IPV4_H1#ifndef _NF_DEFRAG_IPV4_H
2#define _NF_DEFRAG_IPV4_H2#define _NF_DEFRAG_IPV4_H
3 3
4void nf_defrag_ipv4_enable(void);4struct net;
5int nf_defrag_ipv4_enable(struct net *);
5 6
6#endif /* _NF_DEFRAG_IPV4_H */7#endif /* _NF_DEFRAG_IPV4_H */
include/net/netfilter/ipv6/nf_conntrack_ipv6.h+9−0
@@ -6,6 +6,15 @@ extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6; · 5 unmodified lines
6extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6;6extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6;
7extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6;7extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6;
8extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6;8extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6;
9#ifdef CONFIG_NF_CT_PROTO_DCCP
10extern struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6;
11#endif
12#ifdef CONFIG_NF_CT_PROTO_SCTP
13extern struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6;
14#endif
15#ifdef CONFIG_NF_CT_PROTO_UDPLITE
16extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6;
17#endif
9 18
10#include <linux/sysctl.h>19#include <linux/sysctl.h>
11extern struct ctl_table nf_ct_ipv6_sysctl_table[];20extern struct ctl_table nf_ct_ipv6_sysctl_table[];
include/net/netfilter/ipv6/nf_defrag_ipv6.h+2−1
@@ -1,7 +1,8 @@
1#ifndef _NF_DEFRAG_IPV6_H1#ifndef _NF_DEFRAG_IPV6_H
2#define _NF_DEFRAG_IPV6_H2#define _NF_DEFRAG_IPV6_H
3 3
4void nf_defrag_ipv6_enable(void);4struct net;
5int nf_defrag_ipv6_enable(struct net *);
5 6
6int nf_ct_frag6_init(void);7int nf_ct_frag6_init(void);
7void nf_ct_frag6_cleanup(void);8void nf_ct_frag6_cleanup(void);
include/net/netfilter/nf_conntrack.h+4−0
@@ -181,6 +181,10 @@ static inline void nf_ct_put(struct nf_conn *ct) · 180 unmodified lines
181int nf_ct_l3proto_try_module_get(unsigned short l3proto);181int nf_ct_l3proto_try_module_get(unsigned short l3proto);
182void nf_ct_l3proto_module_put(unsigned short l3proto);182void nf_ct_l3proto_module_put(unsigned short l3proto);
183 183
184/* load module; enable/disable conntrack in this namespace */
185int nf_ct_netns_get(struct net *net, u8 nfproto);
186void nf_ct_netns_put(struct net *net, u8 nfproto);
187
184/*188/*
185 * Allocate a hashtable of hlist_head (if nulls == 0),189 * Allocate a hashtable of hlist_head (if nulls == 0),
186 * or hlist_nulls_head (if nulls == 1)190 * or hlist_nulls_head (if nulls == 1)
include/net/netfilter/nf_conntrack_l3proto.h+13−3
@@ -52,6 +52,10 @@ struct nf_conntrack_l3proto { · 51 unmodified lines
52 int (*tuple_to_nlattr)(struct sk_buff *skb,52 int (*tuple_to_nlattr)(struct sk_buff *skb,
53 const struct nf_conntrack_tuple *t);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 * Calculate size of tuple nlattr60 * Calculate size of tuple nlattr
57 */61 */
@@ -63,18 +67,24 @@ struct nf_conntrack_l3proto { · 5 unmodified lines
63 67
64 size_t nla_size;68 size_t nla_size;
65 69
66 /* Init l3proto pernet data */
67 int (*init_net)(struct net *net);
68
69 /* Module (if any) which this is connected to. */70 /* Module (if any) which this is connected to. */
70 struct module *me;71 struct module *me;
71};72};
72 73
73extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX];74extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX];
74 75
76#ifdef CONFIG_SYSCTL
75/* Protocol pernet registration. */77/* Protocol pernet registration. */
76int nf_ct_l3proto_pernet_register(struct net *net,78int nf_ct_l3proto_pernet_register(struct net *net,
77 struct nf_conntrack_l3proto *proto);79 struct nf_conntrack_l3proto *proto);
80#else
81static inline int nf_ct_l3proto_pernet_register(struct net *n,
82 struct nf_conntrack_l3proto *p)
83{
84 return 0;
85}
86#endif
87
78void nf_ct_l3proto_pernet_unregister(struct net *net,88void nf_ct_l3proto_pernet_unregister(struct net *net,
79 struct nf_conntrack_l3proto *proto);89 struct nf_conntrack_l3proto *proto);
80 90
include/net/netfilter/nf_dup_netdev.h+1−0
@@ -2,5 +2,6 @@ · 1 unmodified line
2#define _NF_DUP_NETDEV_H_2#define _NF_DUP_NETDEV_H_
3 3
4void nf_dup_netdev_egress(const struct nft_pktinfo *pkt, int oif);4void nf_dup_netdev_egress(const struct nft_pktinfo *pkt, int oif);
5void nf_fwd_netdev_egress(const struct nft_pktinfo *pkt, int oif);
5 6
6#endif7#endif
include/net/netfilter/nf_log.h+3−1
@@ -109,7 +109,9 @@ void nf_log_dump_packet_common(struct nf_log_buf *m, u_int8_t pf, · 108 unmodified lines
109 const struct net_device *out,109 const struct net_device *out,
110 const struct nf_loginfo *loginfo,110 const struct nf_loginfo *loginfo,
111 const char *prefix);111 const char *prefix);
112void nf_log_l2packet(struct net *net, u_int8_t pf, unsigned int hooknum,112void nf_log_l2packet(struct net *net, u_int8_t pf,
113 __be16 protocol,
114 unsigned int hooknum,
113 const struct sk_buff *skb,115 const struct sk_buff *skb,
114 const struct net_device *in,116 const struct net_device *in,
115 const struct net_device *out,117 const struct net_device *out,
include/net/netfilter/nf_nat_l4proto.h+9−0
@@ -54,6 +54,15 @@ extern const struct nf_nat_l4proto nf_nat_l4proto_udp; · 53 unmodified lines
54extern const struct nf_nat_l4proto nf_nat_l4proto_icmp;54extern const struct nf_nat_l4proto nf_nat_l4proto_icmp;
55extern const struct nf_nat_l4proto nf_nat_l4proto_icmpv6;55extern const struct nf_nat_l4proto nf_nat_l4proto_icmpv6;
56extern const struct nf_nat_l4proto nf_nat_l4proto_unknown;56extern const struct nf_nat_l4proto nf_nat_l4proto_unknown;
57#ifdef CONFIG_NF_NAT_PROTO_DCCP
58extern const struct nf_nat_l4proto nf_nat_l4proto_dccp;
59#endif
60#ifdef CONFIG_NF_NAT_PROTO_SCTP
61extern const struct nf_nat_l4proto nf_nat_l4proto_sctp;
62#endif
63#ifdef CONFIG_NF_NAT_PROTO_UDPLITE
64extern const struct nf_nat_l4proto nf_nat_l4proto_udplite;
65#endif
57 66
58bool nf_nat_l4proto_in_range(const struct nf_conntrack_tuple *tuple,67bool nf_nat_l4proto_in_range(const struct nf_conntrack_tuple *tuple,
59 enum nf_nat_manip_type maniptype,68 enum nf_nat_manip_type maniptype,
include/net/netfilter/nf_tables.h+100−1
@@ -259,7 +259,8 @@ struct nft_expr; · 258 unmodified lines
259 * @lookup: look up an element within the set259 * @lookup: look up an element within the set
260 * @insert: insert new element into set260 * @insert: insert new element into set
261 * @activate: activate new element in the next generation261 * @activate: activate new element in the next generation
262 * @deactivate: deactivate element in the next generation262 * @deactivate: lookup for element and deactivate it in the next generation
263 * @deactivate_one: deactivate element in the next generation
263 * @remove: remove element from set264 * @remove: remove element from set
264 * @walk: iterate over all set elemeennts265 * @walk: iterate over all set elemeennts
265 * @privsize: function to return size of set private data266 * @privsize: function to return size of set private data
@@ -294,6 +295,9 @@ struct nft_set_ops { · 28 unmodified lines
294 void * (*deactivate)(const struct net *net,295 void * (*deactivate)(const struct net *net,
295 const struct nft_set *set,296 const struct nft_set *set,
296 const struct nft_set_elem *elem);297 const struct nft_set_elem *elem);
298 bool (*deactivate_one)(const struct net *net,
299 const struct nft_set *set,
300 void *priv);
297 void (*remove)(const struct nft_set *set,301 void (*remove)(const struct nft_set *set,
298 const struct nft_set_elem *elem);302 const struct nft_set_elem *elem);
299 void (*walk)(const struct nft_ctx *ctx,303 void (*walk)(const struct nft_ctx *ctx,
@@ -326,6 +330,7 @@ void nft_unregister_set(struct nft_set_ops *ops); · 26 unmodified lines
326 * @name: name of the set330 * @name: name of the set
327 * @ktype: key type (numeric type defined by userspace, not used in the kernel)331 * @ktype: key type (numeric type defined by userspace, not used in the kernel)
328 * @dtype: data type (verdict or numeric type defined by userspace)332 * @dtype: data type (verdict or numeric type defined by userspace)
333 * @objtype: object type (see NFT_OBJECT_* definitions)
329 * @size: maximum set size334 * @size: maximum set size
330 * @nelems: number of elements335 * @nelems: number of elements
331 * @ndeact: number of deactivated elements queued for removal336 * @ndeact: number of deactivated elements queued for removal
@@ -347,6 +352,7 @@ struct nft_set { · 15 unmodified lines
347 char name[NFT_SET_MAXNAMELEN];352 char name[NFT_SET_MAXNAMELEN];
348 u32 ktype;353 u32 ktype;
349 u32 dtype;354 u32 dtype;
355 u32 objtype;
350 u32 size;356 u32 size;
351 atomic_t nelems;357 atomic_t nelems;
352 u32 ndeact;358 u32 ndeact;
@@ -416,6 +422,7 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set, · 63 unmodified lines
416 * @NFT_SET_EXT_EXPIRATION: element expiration time422 * @NFT_SET_EXT_EXPIRATION: element expiration time
417 * @NFT_SET_EXT_USERDATA: user data associated with the element423 * @NFT_SET_EXT_USERDATA: user data associated with the element
418 * @NFT_SET_EXT_EXPR: expression assiociated with the element424 * @NFT_SET_EXT_EXPR: expression assiociated with the element
425 * @NFT_SET_EXT_OBJREF: stateful object reference associated with element
419 * @NFT_SET_EXT_NUM: number of extension types426 * @NFT_SET_EXT_NUM: number of extension types
420 */427 */
421enum nft_set_extensions {428enum nft_set_extensions {
@@ -426,6 +433,7 @@ enum nft_set_extensions { · 4 unmodified lines
426 NFT_SET_EXT_EXPIRATION,433 NFT_SET_EXT_EXPIRATION,
427 NFT_SET_EXT_USERDATA,434 NFT_SET_EXT_USERDATA,
428 NFT_SET_EXT_EXPR,435 NFT_SET_EXT_EXPR,
436 NFT_SET_EXT_OBJREF,
429 NFT_SET_EXT_NUM437 NFT_SET_EXT_NUM
430};438};
431 439
@@ -554,6 +562,11 @@ static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set, · 122 unmodified lines
554 return elem + set->ops->elemsize;562 return elem + set->ops->elemsize;
555}563}
556 564
565static inline struct nft_object **nft_set_ext_obj(const struct nft_set_ext *ext)
566{
567 return nft_set_ext(ext, NFT_SET_EXT_OBJREF);
568}
569
557void *nft_set_elem_init(const struct nft_set *set,570void *nft_set_elem_init(const struct nft_set *set,
558 const struct nft_set_ext_tmpl *tmpl,571 const struct nft_set_ext_tmpl *tmpl,
559 const u32 *key, const u32 *data,572 const u32 *key, const u32 *data,
@@ -875,6 +888,7 @@ unsigned int nft_do_chain(struct nft_pktinfo *pkt, void *priv); · 315 unmodified lines
875 * @list: used internally888 * @list: used internally
876 * @chains: chains in the table889 * @chains: chains in the table
877 * @sets: sets in the table890 * @sets: sets in the table
891 * @objects: stateful objects in the table
878 * @hgenerator: handle generator state892 * @hgenerator: handle generator state
879 * @use: number of chain references to this table893 * @use: number of chain references to this table
880 * @flags: table flag (see enum nft_table_flags)894 * @flags: table flag (see enum nft_table_flags)
@@ -885,6 +899,7 @@ struct nft_table { · 4 unmodified lines
885 struct list_head list;899 struct list_head list;
886 struct list_head chains;900 struct list_head chains;
887 struct list_head sets;901 struct list_head sets;
902 struct list_head objects;
888 u64 hgenerator;903 u64 hgenerator;
889 u32 use;904 u32 use;
890 u16 flags:14,905 u16 flags:14,
@@ -934,6 +949,80 @@ void nft_unregister_expr(struct nft_expr_type *); · 43 unmodified lines
934int nft_verdict_dump(struct sk_buff *skb, int type,949int nft_verdict_dump(struct sk_buff *skb, int type,
935 const struct nft_verdict *v);950 const struct nft_verdict *v);
936 951
952/**
953 * struct nft_object - nf_tables stateful object
954 *
955 * @list: table stateful object list node
956 * @table: table this object belongs to
957 * @type: pointer to object type
958 * @data: pointer to object data
959 * @name: name of this stateful object
960 * @genmask: generation mask
961 * @use: number of references to this stateful object
962 * @data: object data, layout depends on type
963 */
964struct nft_object {
965 struct list_head list;
966 char name[NFT_OBJ_MAXNAMELEN];
967 struct nft_table *table;
968 u32 genmask:2,
969 use:30;
970 /* runtime data below here */
971 const struct nft_object_type *type ____cacheline_aligned;
972 unsigned char data[]
973 __attribute__((aligned(__alignof__(u64))));
974};
975
976static inline void *nft_obj_data(const struct nft_object *obj)
977{
978 return (void *)obj->data;
979}
980
981#define nft_expr_obj(expr) *((struct nft_object **)nft_expr_priv(expr))
982
983struct nft_object *nf_tables_obj_lookup(const struct nft_table *table,
984 const struct nlattr *nla, u32 objtype,
985 u8 genmask);
986
987int nft_obj_notify(struct net *net, struct nft_table *table,
988 struct nft_object *obj, u32 portid, u32 seq,
989 int event, int family, int report, gfp_t gfp);
990
991/**
992 * struct nft_object_type - stateful object type
993 *
994 * @eval: stateful object evaluation function
995 * @list: list node in list of object types
996 * @type: stateful object numeric type
997 * @size: stateful object size
998 * @owner: module owner
999 * @maxattr: maximum netlink attribute
1000 * @policy: netlink attribute policy
1001 * @init: initialize object from netlink attributes
1002 * @destroy: release existing stateful object
1003 * @dump: netlink dump stateful object
1004 */
1005struct nft_object_type {
1006 void (*eval)(struct nft_object *obj,
1007 struct nft_regs *regs,
1008 const struct nft_pktinfo *pkt);
1009 struct list_head list;
1010 u32 type;
1011 unsigned int size;
1012 unsigned int maxattr;
1013 struct module *owner;
1014 const struct nla_policy *policy;
1015 int (*init)(const struct nlattr * const tb[],
1016 struct nft_object *obj);
1017 void (*destroy)(struct nft_object *obj);
1018 int (*dump)(struct sk_buff *skb,
1019 struct nft_object *obj,
1020 bool reset);
1021};
1022
1023int nft_register_obj(struct nft_object_type *obj_type);
1024void nft_unregister_obj(struct nft_object_type *obj_type);
1025
937/**1026/**
938 * struct nft_traceinfo - nft tracing information and state1027 * struct nft_traceinfo - nft tracing information and state
939 *1028 *
@@ -981,6 +1070,9 @@ void nft_trace_notify(struct nft_traceinfo *info); · 41 unmodified lines
981#define MODULE_ALIAS_NFT_SET() \1070#define MODULE_ALIAS_NFT_SET() \
982 MODULE_ALIAS("nft-set")1071 MODULE_ALIAS("nft-set")
983 1072
1073#define MODULE_ALIAS_NFT_OBJ(type) \
1074 MODULE_ALIAS("nft-obj-" __stringify(type))
1075
984/*1076/*
985 * The gencursor defines two generations, the currently active and the1077 * The gencursor defines two generations, the currently active and the
986 * next one. Objects contain a bitmask of 2 bits specifying the generations1078 * next one. Objects contain a bitmask of 2 bits specifying the generations
@@ -1157,4 +1249,11 @@ struct nft_trans_elem { · 170 unmodified lines
1157#define nft_trans_elem(trans) \1249#define nft_trans_elem(trans) \
1158 (((struct nft_trans_elem *)trans->data)->elem)1250 (((struct nft_trans_elem *)trans->data)->elem)
1159 1251
1252struct nft_trans_obj {
1253 struct nft_object *obj;
1254};
1255
1256#define nft_trans_obj(trans) \
1257 (((struct nft_trans_obj *)trans->data)->obj)
1258
1160#endif /* _NET_NF_TABLES_H */1259#endif /* _NET_NF_TABLES_H */
include/net/netfilter/nf_tables_core.h+1−0
@@ -45,6 +45,7 @@ struct nft_payload_set { · 44 unmodified lines
45 enum nft_registers sreg:8;45 enum nft_registers sreg:8;
46 u8 csum_type;46 u8 csum_type;
47 u8 csum_offset;47 u8 csum_offset;
48 u8 csum_flags;
48};49};
49 50
50extern const struct nft_expr_ops nft_payload_fast_ops;51extern const struct nft_expr_ops nft_payload_fast_ops;
include/net/netns/conntrack.h+43−0
@@ -6,6 +6,12 @@ · 5 unmodified lines
6#include <linux/atomic.h>6#include <linux/atomic.h>
7#include <linux/workqueue.h>7#include <linux/workqueue.h>
8#include <linux/netfilter/nf_conntrack_tcp.h>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#include <linux/seqlock.h>15#include <linux/seqlock.h>
10 16
11struct ctl_table_header;17struct ctl_table_header;
@@ -48,12 +54,49 @@ struct nf_icmp_net { · 36 unmodified lines
48 unsigned int timeout;54 unsigned int timeout;
49};55};
50 56
57#ifdef CONFIG_NF_CT_PROTO_DCCP
58struct nf_dccp_net {
59 struct nf_proto_net pn;
60 int dccp_loose;
61 unsigned int dccp_timeout[CT_DCCP_MAX + 1];
62};
63#endif
64
65#ifdef CONFIG_NF_CT_PROTO_SCTP
66struct nf_sctp_net {
67 struct nf_proto_net pn;
68 unsigned int timeouts[SCTP_CONNTRACK_MAX];
69};
70#endif
71
72#ifdef CONFIG_NF_CT_PROTO_UDPLITE
73enum udplite_conntrack {
74 UDPLITE_CT_UNREPLIED,
75 UDPLITE_CT_REPLIED,
76 UDPLITE_CT_MAX
77};
78
79struct nf_udplite_net {
80 struct nf_proto_net pn;
81 unsigned int timeouts[UDPLITE_CT_MAX];
82};
83#endif
84
51struct nf_ip_net {85struct nf_ip_net {
52 struct nf_generic_net generic;86 struct nf_generic_net generic;
53 struct nf_tcp_net tcp;87 struct nf_tcp_net tcp;
54 struct nf_udp_net udp;88 struct nf_udp_net udp;
55 struct nf_icmp_net icmp;89 struct nf_icmp_net icmp;
56 struct nf_icmp_net icmpv6;90 struct nf_icmp_net icmpv6;
91#ifdef CONFIG_NF_CT_PROTO_DCCP
92 struct nf_dccp_net dccp;
93#endif
94#ifdef CONFIG_NF_CT_PROTO_SCTP
95 struct nf_sctp_net sctp;
96#endif
97#ifdef CONFIG_NF_CT_PROTO_UDPLITE
98 struct nf_udplite_net udplite;
99#endif
57};100};
58 101
59struct ct_pcpu {102struct ct_pcpu {
include/net/netns/netfilter.h+6−0
@@ -17,5 +17,11 @@ struct netns_nf { · 16 unmodified lines
17 struct ctl_table_header *nf_log_dir_header;17 struct ctl_table_header *nf_log_dir_header;
18#endif18#endif
19 struct nf_hook_entry __rcu *hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS];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#endif27#endif
include/uapi/linux/netfilter/nf_conntrack_tuple_common.h+3−0
@@ -2,7 +2,10 @@ · 1 unmodified line
2#define _NF_CONNTRACK_TUPLE_COMMON_H2#define _NF_CONNTRACK_TUPLE_COMMON_H
3 3
4#include <linux/types.h>4#include <linux/types.h>
5#ifndef __KERNEL__
5#include <linux/netfilter.h>6#include <linux/netfilter.h>
7#endif
8#include <linux/netfilter/nf_conntrack_common.h> /* IP_CT_IS_REPLY */
6 9
7enum ip_conntrack_dir {10enum ip_conntrack_dir {
8 IP_CT_DIR_ORIGINAL,11 IP_CT_DIR_ORIGINAL,
include/uapi/linux/netfilter/nf_tables.h+70−0
@@ -4,6 +4,7 @@ · 3 unmodified lines
4#define NFT_TABLE_MAXNAMELEN 324#define NFT_TABLE_MAXNAMELEN 32
5#define NFT_CHAIN_MAXNAMELEN 325#define NFT_CHAIN_MAXNAMELEN 32
6#define NFT_SET_MAXNAMELEN 326#define NFT_SET_MAXNAMELEN 32
7#define NFT_OBJ_MAXNAMELEN 32
7#define NFT_USERDATA_MAXLEN 2568#define NFT_USERDATA_MAXLEN 256
8 9
9/**10/**
@@ -85,6 +86,10 @@ enum nft_verdicts { · 75 unmodified lines
85 * @NFT_MSG_NEWGEN: announce a new generation, only for events (enum nft_gen_attributes)86 * @NFT_MSG_NEWGEN: announce a new generation, only for events (enum nft_gen_attributes)
86 * @NFT_MSG_GETGEN: get the rule-set generation (enum nft_gen_attributes)87 * @NFT_MSG_GETGEN: get the rule-set generation (enum nft_gen_attributes)
87 * @NFT_MSG_TRACE: trace event (enum nft_trace_attributes)88 * @NFT_MSG_TRACE: trace event (enum nft_trace_attributes)
89 * @NFT_MSG_NEWOBJ: create a stateful object (enum nft_obj_attributes)
90 * @NFT_MSG_GETOBJ: get a stateful object (enum nft_obj_attributes)
91 * @NFT_MSG_DELOBJ: delete a stateful object (enum nft_obj_attributes)
92 * @NFT_MSG_GETOBJ_RESET: get and reset a stateful object (enum nft_obj_attributes)
88 */93 */
89enum nf_tables_msg_types {94enum nf_tables_msg_types {
90 NFT_MSG_NEWTABLE,95 NFT_MSG_NEWTABLE,
@@ -105,6 +110,10 @@ enum nf_tables_msg_types { · 14 unmodified lines
105 NFT_MSG_NEWGEN,110 NFT_MSG_NEWGEN,
106 NFT_MSG_GETGEN,111 NFT_MSG_GETGEN,
107 NFT_MSG_TRACE,112 NFT_MSG_TRACE,
113 NFT_MSG_NEWOBJ,
114 NFT_MSG_GETOBJ,
115 NFT_MSG_DELOBJ,
116 NFT_MSG_GETOBJ_RESET,
108 NFT_MSG_MAX,117 NFT_MSG_MAX,
109};118};
110 119
@@ -246,6 +255,7 @@ enum nft_rule_compat_attributes { · 135 unmodified lines
246 * @NFT_SET_MAP: set is used as a dictionary255 * @NFT_SET_MAP: set is used as a dictionary
247 * @NFT_SET_TIMEOUT: set uses timeouts256 * @NFT_SET_TIMEOUT: set uses timeouts
248 * @NFT_SET_EVAL: set contains expressions for evaluation257 * @NFT_SET_EVAL: set contains expressions for evaluation
258 * @NFT_SET_OBJECT: set contains stateful objects
249 */259 */
250enum nft_set_flags {260enum nft_set_flags {
251 NFT_SET_ANONYMOUS = 0x1,261 NFT_SET_ANONYMOUS = 0x1,
@@ -254,6 +264,7 @@ enum nft_set_flags { · 2 unmodified lines
254 NFT_SET_MAP = 0x8,264 NFT_SET_MAP = 0x8,
255 NFT_SET_TIMEOUT = 0x10,265 NFT_SET_TIMEOUT = 0x10,
256 NFT_SET_EVAL = 0x20,266 NFT_SET_EVAL = 0x20,
267 NFT_SET_OBJECT = 0x40,
257};268};
258 269
259/**270/**
@@ -295,6 +306,7 @@ enum nft_set_desc_attributes { · 35 unmodified lines
295 * @NFTA_SET_TIMEOUT: default timeout value (NLA_U64)306 * @NFTA_SET_TIMEOUT: default timeout value (NLA_U64)
296 * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32)307 * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32)
297 * @NFTA_SET_USERDATA: user data (NLA_BINARY)308 * @NFTA_SET_USERDATA: user data (NLA_BINARY)
309 * @NFTA_SET_OBJ_TYPE: stateful object type (NLA_U32: NFT_OBJECT_*)
298 */310 */
299enum nft_set_attributes {311enum nft_set_attributes {
300 NFTA_SET_UNSPEC,312 NFTA_SET_UNSPEC,
@@ -312,6 +324,7 @@ enum nft_set_attributes { · 11 unmodified lines
312 NFTA_SET_GC_INTERVAL,324 NFTA_SET_GC_INTERVAL,
313 NFTA_SET_USERDATA,325 NFTA_SET_USERDATA,
314 NFTA_SET_PAD,326 NFTA_SET_PAD,
327 NFTA_SET_OBJ_TYPE,
315 __NFTA_SET_MAX328 __NFTA_SET_MAX
316};329};
317#define NFTA_SET_MAX (__NFTA_SET_MAX - 1)330#define NFTA_SET_MAX (__NFTA_SET_MAX - 1)
@@ -335,6 +348,7 @@ enum nft_set_elem_flags { · 17 unmodified lines
335 * @NFTA_SET_ELEM_EXPIRATION: expiration time (NLA_U64)348 * @NFTA_SET_ELEM_EXPIRATION: expiration time (NLA_U64)
336 * @NFTA_SET_ELEM_USERDATA: user data (NLA_BINARY)349 * @NFTA_SET_ELEM_USERDATA: user data (NLA_BINARY)
337 * @NFTA_SET_ELEM_EXPR: expression (NLA_NESTED: nft_expr_attributes)350 * @NFTA_SET_ELEM_EXPR: expression (NLA_NESTED: nft_expr_attributes)
351 * @NFTA_SET_ELEM_OBJREF: stateful object reference (NLA_STRING)
338 */352 */
339enum nft_set_elem_attributes {353enum nft_set_elem_attributes {
340 NFTA_SET_ELEM_UNSPEC,354 NFTA_SET_ELEM_UNSPEC,
@@ -346,6 +360,7 @@ enum nft_set_elem_attributes { · 5 unmodified lines
346 NFTA_SET_ELEM_USERDATA,360 NFTA_SET_ELEM_USERDATA,
347 NFTA_SET_ELEM_EXPR,361 NFTA_SET_ELEM_EXPR,
348 NFTA_SET_ELEM_PAD,362 NFTA_SET_ELEM_PAD,
363 NFTA_SET_ELEM_OBJREF,
349 __NFTA_SET_ELEM_MAX364 __NFTA_SET_ELEM_MAX
350};365};
351#define NFTA_SET_ELEM_MAX (__NFTA_SET_ELEM_MAX - 1)366#define NFTA_SET_ELEM_MAX (__NFTA_SET_ELEM_MAX - 1)
@@ -659,6 +674,10 @@ enum nft_payload_csum_types { · 307 unmodified lines
659 NFT_PAYLOAD_CSUM_INET,674 NFT_PAYLOAD_CSUM_INET,
660};675};
661 676
677enum nft_payload_csum_flags {
678 NFT_PAYLOAD_L4CSUM_PSEUDOHDR = (1 << 0),
679};
680
662/**681/**
663 * enum nft_payload_attributes - nf_tables payload expression netlink attributes682 * enum nft_payload_attributes - nf_tables payload expression netlink attributes
664 *683 *
@@ -669,6 +688,7 @@ enum nft_payload_csum_types { · 4 unmodified lines
669 * @NFTA_PAYLOAD_SREG: source register to load data from (NLA_U32: nft_registers)688 * @NFTA_PAYLOAD_SREG: source register to load data from (NLA_U32: nft_registers)
670 * @NFTA_PAYLOAD_CSUM_TYPE: checksum type (NLA_U32)689 * @NFTA_PAYLOAD_CSUM_TYPE: checksum type (NLA_U32)
671 * @NFTA_PAYLOAD_CSUM_OFFSET: checksum offset relative to base (NLA_U32)690 * @NFTA_PAYLOAD_CSUM_OFFSET: checksum offset relative to base (NLA_U32)
691 * @NFTA_PAYLOAD_CSUM_FLAGS: checksum flags (NLA_U32)
672 */692 */
673enum nft_payload_attributes {693enum nft_payload_attributes {
674 NFTA_PAYLOAD_UNSPEC,694 NFTA_PAYLOAD_UNSPEC,
@@ -679,6 +699,7 @@ enum nft_payload_attributes { · 4 unmodified lines
679 NFTA_PAYLOAD_SREG,699 NFTA_PAYLOAD_SREG,
680 NFTA_PAYLOAD_CSUM_TYPE,700 NFTA_PAYLOAD_CSUM_TYPE,
681 NFTA_PAYLOAD_CSUM_OFFSET,701 NFTA_PAYLOAD_CSUM_OFFSET,
702 NFTA_PAYLOAD_CSUM_FLAGS,
682 __NFTA_PAYLOAD_MAX703 __NFTA_PAYLOAD_MAX
683};704};
684#define NFTA_PAYLOAD_MAX (__NFTA_PAYLOAD_MAX - 1)705#define NFTA_PAYLOAD_MAX (__NFTA_PAYLOAD_MAX - 1)
@@ -968,6 +989,7 @@ enum nft_queue_attributes { · 283 unmodified lines
968 989
969enum nft_quota_flags {990enum nft_quota_flags {
970 NFT_QUOTA_F_INV = (1 << 0),991 NFT_QUOTA_F_INV = (1 << 0),
992 NFT_QUOTA_F_DEPLETED = (1 << 1),
971};993};
972 994
973/**995/**
@@ -975,12 +997,14 @@ enum nft_quota_flags { · 1 unmodified line
975 *997 *
976 * @NFTA_QUOTA_BYTES: quota in bytes (NLA_U16)998 * @NFTA_QUOTA_BYTES: quota in bytes (NLA_U16)
977 * @NFTA_QUOTA_FLAGS: flags (NLA_U32)999 * @NFTA_QUOTA_FLAGS: flags (NLA_U32)
1000 * @NFTA_QUOTA_CONSUMED: quota already consumed in bytes (NLA_U64)
978 */1001 */
979enum nft_quota_attributes {1002enum nft_quota_attributes {
980 NFTA_QUOTA_UNSPEC,1003 NFTA_QUOTA_UNSPEC,
981 NFTA_QUOTA_BYTES,1004 NFTA_QUOTA_BYTES,
982 NFTA_QUOTA_FLAGS,1005 NFTA_QUOTA_FLAGS,
983 NFTA_QUOTA_PAD,1006 NFTA_QUOTA_PAD,
1007 NFTA_QUOTA_CONSUMED,
984 __NFTA_QUOTA_MAX1008 __NFTA_QUOTA_MAX
985};1009};
986#define NFTA_QUOTA_MAX (__NFTA_QUOTA_MAX - 1)1010#define NFTA_QUOTA_MAX (__NFTA_QUOTA_MAX - 1)
@@ -1124,6 +1148,26 @@ enum nft_fwd_attributes { · 137 unmodified lines
1124};1148};
1125#define NFTA_FWD_MAX (__NFTA_FWD_MAX - 1)1149#define NFTA_FWD_MAX (__NFTA_FWD_MAX - 1)
1126 1150
1151/**
1152 * enum nft_objref_attributes - nf_tables stateful object expression netlink attributes
1153 *
1154 * @NFTA_OBJREF_IMM_TYPE: object type for immediate reference (NLA_U32: nft_register)
1155 * @NFTA_OBJREF_IMM_NAME: object name for immediate reference (NLA_STRING)
1156 * @NFTA_OBJREF_SET_SREG: source register of the data to look for (NLA_U32: nft_registers)
1157 * @NFTA_OBJREF_SET_NAME: name of the set where to look for (NLA_STRING)
1158 * @NFTA_OBJREF_SET_ID: id of the set where to look for in this transaction (NLA_U32)
1159 */
1160enum nft_objref_attributes {
1161 NFTA_OBJREF_UNSPEC,
1162 NFTA_OBJREF_IMM_TYPE,
1163 NFTA_OBJREF_IMM_NAME,
1164 NFTA_OBJREF_SET_SREG,
1165 NFTA_OBJREF_SET_NAME,
1166 NFTA_OBJREF_SET_ID,
1167 __NFTA_OBJREF_MAX
1168};
1169#define NFTA_OBJREF_MAX (__NFTA_OBJREF_MAX - 1)
1170
1127/**1171/**
1128 * enum nft_gen_attributes - nf_tables ruleset generation attributes1172 * enum nft_gen_attributes - nf_tables ruleset generation attributes
1129 *1173 *
@@ -1172,6 +1216,32 @@ enum nft_fib_flags { · 42 unmodified lines
1172 NFTA_FIB_F_OIF = 1 << 4, /* restrict to oif */1216 NFTA_FIB_F_OIF = 1 << 4, /* restrict to oif */
1173};1217};
1174 1218
1219#define NFT_OBJECT_UNSPEC 0
1220#define NFT_OBJECT_COUNTER 1
1221#define NFT_OBJECT_QUOTA 2
1222#define __NFT_OBJECT_MAX 3
1223#define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1)
1224
1225/**
1226 * enum nft_object_attributes - nf_tables stateful object netlink attributes
1227 *
1228 * @NFTA_OBJ_TABLE: name of the table containing the expression (NLA_STRING)
1229 * @NFTA_OBJ_NAME: name of this expression type (NLA_STRING)
1230 * @NFTA_OBJ_TYPE: stateful object type (NLA_U32)
1231 * @NFTA_OBJ_DATA: stateful object data (NLA_NESTED)
1232 * @NFTA_OBJ_USE: number of references to this expression (NLA_U32)
1233 */
1234enum nft_object_attributes {
1235 NFTA_OBJ_UNSPEC,
1236 NFTA_OBJ_TABLE,
1237 NFTA_OBJ_NAME,
1238 NFTA_OBJ_TYPE,
1239 NFTA_OBJ_DATA,
1240 NFTA_OBJ_USE,
1241 __NFTA_OBJ_MAX
1242};
1243#define NFTA_OBJ_MAX (__NFTA_OBJ_MAX - 1)
1244
1175/**1245/**
1176 * enum nft_trace_attributes - nf_tables trace netlink attributes1246 * enum nft_trace_attributes - nf_tables trace netlink attributes
1177 *1247 *
include/uapi/linux/netfilter/xt_bpf.h+21−0
@@ -2,9 +2,11 @@ · 1 unmodified line
2#define _XT_BPF_H2#define _XT_BPF_H
3 3
4#include <linux/filter.h>4#include <linux/filter.h>
5#include <linux/limits.h>
5#include <linux/types.h>6#include <linux/types.h>
6 7
7#define XT_BPF_MAX_NUM_INSTR 648#define XT_BPF_MAX_NUM_INSTR 64
9#define XT_BPF_PATH_MAX (XT_BPF_MAX_NUM_INSTR * sizeof(struct sock_filter))
8 10
9struct bpf_prog;11struct bpf_prog;
10 12
@@ -16,4 +18,23 @@ struct xt_bpf_info { · 5 unmodified lines
16 struct bpf_prog *filter __attribute__((aligned(8)));18 struct bpf_prog *filter __attribute__((aligned(8)));
17};19};
18 20
21enum xt_bpf_modes {
22 XT_BPF_MODE_BYTECODE,
23 XT_BPF_MODE_FD_PINNED,
24 XT_BPF_MODE_FD_ELF,
25};
26
27struct 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 };
35
36 /* only used in the kernel */
37 struct bpf_prog *filter __attribute__((aligned(8)));
38};
39
19#endif /*_XT_BPF_H */40#endif /*_XT_BPF_H */
net/bridge/br_netfilter_hooks.c+4−4
@@ -1008,10 +1008,10 @@ int br_nf_hook_thresh(unsigned int hook, struct net *net, · 1007 unmodified lines
1008 struct nf_hook_state state;1008 struct nf_hook_state state;
1009 int ret;1009 int ret;
1010 1010
1011 elem = rcu_dereference(net->nf.hooks[NFPROTO_BRIDGE][hook]);1011 for (elem = rcu_dereference(net->nf.hooks[NFPROTO_BRIDGE][hook]);
1012 1012 elem && nf_hook_entry_priority(elem) <= NF_BR_PRI_BRNF;
1013 while (elem && (elem->ops.priority <= NF_BR_PRI_BRNF))1013 elem = rcu_dereference(elem->next))
1014 elem = rcu_dereference(elem->next);1014 ;
1015 1015
1016 if (!elem)1016 if (!elem)
1017 return okfn(net, sk, skb);1017 return okfn(net, sk, skb);
net/bridge/netfilter/nf_log_bridge.c+2−1
@@ -24,7 +24,8 @@ static void nf_log_bridge_packet(struct net *net, u_int8_t pf, · 23 unmodified lines
24 const struct nf_loginfo *loginfo,24 const struct nf_loginfo *loginfo,
25 const char *prefix)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
30static struct nf_logger nf_bridge_logger __read_mostly = {31static struct nf_logger nf_bridge_logger __read_mostly = {
net/ipv4/netfilter/arp_tables.c+8−8
@@ -411,17 +411,15 @@ static inline int check_target(struct arpt_entry *e, const char *name) · 410 unmodified lines
411}411}
412 412
413static inline int413static inline int
414find_check_entry(struct arpt_entry *e, const char *name, unsigned int size)414find_check_entry(struct arpt_entry *e, const char *name, unsigned int size,
415 struct xt_percpu_counter_alloc_state *alloc_state)
415{416{
416 struct xt_entry_target *t;417 struct xt_entry_target *t;
417 struct xt_target *target;418 struct xt_target *target;
418 unsigned long pcnt;
419 int ret;419 int ret;
420 420
421 pcnt = xt_percpu_counter_alloc();421 if (!xt_percpu_counter_alloc(alloc_state, &e->counters))
422 if (IS_ERR_VALUE(pcnt))
423 return -ENOMEM;422 return -ENOMEM;
424 e->counters.pcnt = pcnt;
425 423
426 t = arpt_get_target(e);424 t = arpt_get_target(e);
427 target = xt_request_find_target(NFPROTO_ARP, t->u.user.name,425 target = xt_request_find_target(NFPROTO_ARP, t->u.user.name,
@@ -439,7 +437,7 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size) · 11 unmodified lines
439err:437err:
440 module_put(t->u.kernel.target->me);438 module_put(t->u.kernel.target->me);
441out:439out:
442 xt_percpu_counter_free(e->counters.pcnt);440 xt_percpu_counter_free(&e->counters);
443 441
444 return ret;442 return ret;
445}443}
@@ -519,7 +517,7 @@ static inline void cleanup_entry(struct arpt_entry *e) · 73 unmodified lines
519 if (par.target->destroy != NULL)517 if (par.target->destroy != NULL)
520 par.target->destroy(&par);518 par.target->destroy(&par);
521 module_put(par.target->me);519 module_put(par.target->me);
522 xt_percpu_counter_free(e->counters.pcnt);520 xt_percpu_counter_free(&e->counters);
523}521}
524 522
525/* Checks and translates the user-supplied table segment (held in523/* Checks and translates the user-supplied table segment (held in
@@ -528,6 +526,7 @@ static inline void cleanup_entry(struct arpt_entry *e) · 2 unmodified lines
528static int translate_table(struct xt_table_info *newinfo, void *entry0,526static int translate_table(struct xt_table_info *newinfo, void *entry0,
529 const struct arpt_replace *repl)527 const struct arpt_replace *repl)
530{528{
529 struct xt_percpu_counter_alloc_state alloc_state = { 0 };
531 struct arpt_entry *iter;530 struct arpt_entry *iter;
532 unsigned int *offsets;531 unsigned int *offsets;
533 unsigned int i;532 unsigned int i;
@@ -590,7 +589,8 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, · 56 unmodified lines
590 /* Finally, each sanity check must pass */589 /* Finally, each sanity check must pass */
591 i = 0;590 i = 0;
592 xt_entry_foreach(iter, entry0, newinfo->size) {591 xt_entry_foreach(iter, entry0, newinfo->size) {
593 ret = find_check_entry(iter, repl->name, repl->size);592 ret = find_check_entry(iter, repl->name, repl->size,
593 &alloc_state);
594 if (ret != 0)594 if (ret != 0)
595 break;595 break;
596 ++i;596 ++i;
net/ipv4/netfilter/ip_tables.c+8−8
@@ -531,7 +531,8 @@ static int check_target(struct ipt_entry *e, struct net *net, const char *name) · 530 unmodified lines
531 531
532static int532static int
533find_check_entry(struct ipt_entry *e, struct net *net, const char *name,533find_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 struct xt_entry_target *t;537 struct xt_entry_target *t;
537 struct xt_target *target;538 struct xt_target *target;
@@ -539,12 +540,9 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, · 1 unmodified line
539 unsigned int j;540 unsigned int j;
540 struct xt_mtchk_param mtpar;541 struct xt_mtchk_param mtpar;
541 struct xt_entry_match *ematch;542 struct xt_entry_match *ematch;
542 unsigned long pcnt;
543 543
544 pcnt = xt_percpu_counter_alloc();544 if (!xt_percpu_counter_alloc(alloc_state, &e->counters))
545 if (IS_ERR_VALUE(pcnt))
546 return -ENOMEM;545 return -ENOMEM;
547 e->counters.pcnt = pcnt;
548 546
549 j = 0;547 j = 0;
550 mtpar.net = net;548 mtpar.net = net;
@@ -582,7 +580,7 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, · 31 unmodified lines
582 cleanup_match(ematch, net);580 cleanup_match(ematch, net);
583 }581 }
584 582
585 xt_percpu_counter_free(e->counters.pcnt);583 xt_percpu_counter_free(&e->counters);
586 584
587 return ret;585 return ret;
588}586}
@@ -670,7 +668,7 @@ cleanup_entry(struct ipt_entry *e, struct net *net) · 81 unmodified lines
670 if (par.target->destroy != NULL)668 if (par.target->destroy != NULL)
671 par.target->destroy(&par);669 par.target->destroy(&par);
672 module_put(par.target->me);670 module_put(par.target->me);
673 xt_percpu_counter_free(e->counters.pcnt);671 xt_percpu_counter_free(&e->counters);
674}672}
675 673
676/* Checks and translates the user-supplied table segment (held in674/* Checks and translates the user-supplied table segment (held in
@@ -679,6 +677,7 @@ static int · 2 unmodified lines
679translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,677translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,
680 const struct ipt_replace *repl)678 const struct ipt_replace *repl)
681{679{
680 struct xt_percpu_counter_alloc_state alloc_state = { 0 };
682 struct ipt_entry *iter;681 struct ipt_entry *iter;
683 unsigned int *offsets;682 unsigned int *offsets;
684 unsigned int i;683 unsigned int i;
@@ -738,7 +737,8 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, · 53 unmodified lines
738 /* Finally, each sanity check must pass */737 /* Finally, each sanity check must pass */
739 i = 0;738 i = 0;
740 xt_entry_foreach(iter, entry0, newinfo->size) {739 xt_entry_foreach(iter, entry0, newinfo->size) {
741 ret = find_check_entry(iter, net, repl->name, repl->size);740 ret = find_check_entry(iter, net, repl->name, repl->size,
741 &alloc_state);
742 if (ret != 0)742 if (ret != 0)
743 break;743 break;
744 ++i;744 ++i;
net/ipv4/netfilter/ipt_CLUSTERIP.c+2−2
@@ -419,7 +419,7 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par) · 418 unmodified lines
419 }419 }
420 cipinfo->config = config;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 if (ret < 0)423 if (ret < 0)
424 pr_info("cannot load conntrack support for proto=%u\n",424 pr_info("cannot load conntrack support for proto=%u\n",
425 par->family);425 par->family);
@@ -444,7 +444,7 @@ static void clusterip_tg_destroy(const struct xt_tgdtor_param *par) · 18 unmodified lines
444 444
445 clusterip_config_put(cipinfo->config);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#ifdef CONFIG_COMPAT450#ifdef CONFIG_COMPAT
net/ipv4/netfilter/ipt_MASQUERADE.c+7−1
@@ -41,7 +41,7 @@ static int masquerade_tg_check(const struct xt_tgchk_param *par) · 40 unmodified lines
41 pr_debug("bad rangesize %u\n", mr->rangesize);41 pr_debug("bad rangesize %u\n", mr->rangesize);
42 return -EINVAL;42 return -EINVAL;
43 }43 }
44 return 0;44 return nf_ct_netns_get(par->net, par->family);
45}45}
46 46
47static unsigned int47static unsigned int
@@ -59,6 +59,11 @@ masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par) · 11 unmodified lines
59 xt_out(par));59 xt_out(par));
60}60}
61 61
62static void masquerade_tg_destroy(const struct xt_tgdtor_param *par)
63{
64 nf_ct_netns_put(par->net, par->family);
65}
66
62static struct xt_target masquerade_tg_reg __read_mostly = {67static struct xt_target masquerade_tg_reg __read_mostly = {
63 .name = "MASQUERADE",68 .name = "MASQUERADE",
64 .family = NFPROTO_IPV4,69 .family = NFPROTO_IPV4,
@@ -67,6 +72,7 @@ static struct xt_target masquerade_tg_reg __read_mostly = { · 2 unmodified lines
67 .table = "nat",72 .table = "nat",
68 .hooks = 1 << NF_INET_POST_ROUTING,73 .hooks = 1 << NF_INET_POST_ROUTING,
69 .checkentry = masquerade_tg_check,74 .checkentry = masquerade_tg_check,
75 .destroy = masquerade_tg_destroy,
70 .me = THIS_MODULE,76 .me = THIS_MODULE,
71};77};
72 78
net/ipv4/netfilter/ipt_SYNPROXY.c+2−2
@@ -418,12 +418,12 @@ static int synproxy_tg4_check(const struct xt_tgchk_param *par) · 417 unmodified lines
418 e->ip.invflags & XT_INV_PROTO)418 e->ip.invflags & XT_INV_PROTO)
419 return -EINVAL;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
424static void synproxy_tg4_destroy(const struct xt_tgdtor_param *par)424static 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
429static struct xt_target synproxy_tg4_reg __read_mostly = {429static struct xt_target synproxy_tg4_reg __read_mostly = {
net/ipv4/netfilter/ipt_rpfilter.c+5−3
@@ -83,10 +83,12 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) · 82 unmodified lines
83 return true ^ invert;83 return true ^ invert;
84 84
85 iph = ip_hdr(skb);85 iph = ip_hdr(skb);
86 if (ipv4_is_multicast(iph->daddr)) {86 if (ipv4_is_zeronet(iph->saddr)) {
87 if (ipv4_is_zeronet(iph->saddr))87 if (ipv4_is_lbcast(iph->daddr) ||
88 return ipv4_is_local_multicast(iph->daddr) ^ invert;88 ipv4_is_local_multicast(iph->daddr))
89 return true ^ invert;
89 }90 }
91
90 flow.flowi4_iif = LOOPBACK_IFINDEX;92 flow.flowi4_iif = LOOPBACK_IFINDEX;
91 flow.daddr = iph->saddr;93 flow.daddr = iph->saddr;
92 flow.saddr = rpfilter_get_saddr(iph->daddr);94 flow.saddr = rpfilter_get_saddr(iph->daddr);
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c+56−15
@@ -31,6 +31,13 @@ · 30 unmodified lines
31#include <net/netfilter/ipv4/nf_defrag_ipv4.h>31#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
32#include <net/netfilter/nf_log.h>32#include <net/netfilter/nf_log.h>
33 33
34static int conntrack4_net_id __read_mostly;
35static DEFINE_MUTEX(register_ipv4_hooks);
36
37struct conntrack4_net {
38 unsigned int users;
39};
40
34static bool ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,41static bool ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
35 struct nf_conntrack_tuple *tuple)42 struct nf_conntrack_tuple *tuple)
36{43{
@@ -307,9 +314,42 @@ static struct nf_sockopt_ops so_getorigdst = { · 270 unmodified lines
307 .owner = THIS_MODULE,314 .owner = THIS_MODULE,
308};315};
309 316
310static int ipv4_init_net(struct net *net)317static int ipv4_hooks_register(struct net *net)
311{318{
312 return 0;319 struct conntrack4_net *cnet = net_generic(net, conntrack4_net_id);
320 int err = 0;
321
322 mutex_lock(&register_ipv4_hooks);
323
324 cnet->users++;
325 if (cnet->users > 1)
326 goto out_unlock;
327
328 err = nf_defrag_ipv4_enable(net);
329 if (err) {
330 cnet->users = 0;
331 goto out_unlock;
332 }
333
334 err = nf_register_net_hooks(net, ipv4_conntrack_ops,
335 ARRAY_SIZE(ipv4_conntrack_ops));
336
337 if (err)
338 cnet->users = 0;
339 out_unlock:
340 mutex_unlock(&register_ipv4_hooks);
341 return err;
342}
343
344static void ipv4_hooks_unregister(struct net *net)
345{
346 struct conntrack4_net *cnet = net_generic(net, conntrack4_net_id);
347
348 mutex_lock(&register_ipv4_hooks);
349 if (cnet->users && (--cnet->users == 0))
350 nf_unregister_net_hooks(net, ipv4_conntrack_ops,
351 ARRAY_SIZE(ipv4_conntrack_ops));
352 mutex_unlock(&register_ipv4_hooks);
313}353}
314 354
315struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = {355struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = {
@@ -325,7 +365,8 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = { · 9 unmodified lines
325 .nlattr_to_tuple = ipv4_nlattr_to_tuple,365 .nlattr_to_tuple = ipv4_nlattr_to_tuple,
326 .nla_policy = ipv4_nla_policy,366 .nla_policy = ipv4_nla_policy,
327#endif367#endif
328 .init_net = ipv4_init_net,368 .net_ns_get = ipv4_hooks_register,
369 .net_ns_put = ipv4_hooks_unregister,
329 .me = THIS_MODULE,370 .me = THIS_MODULE,
330};371};
331 372
@@ -340,6 +381,15 @@ static struct nf_conntrack_l4proto *builtin_l4proto4[] = { · 8 unmodified lines
340 &nf_conntrack_l4proto_tcp4,381 &nf_conntrack_l4proto_tcp4,
341 &nf_conntrack_l4proto_udp4,382 &nf_conntrack_l4proto_udp4,
342 &nf_conntrack_l4proto_icmp,383 &nf_conntrack_l4proto_icmp,
384#ifdef CONFIG_NF_CT_PROTO_DCCP
385 &nf_conntrack_l4proto_dccp4,
386#endif
387#ifdef CONFIG_NF_CT_PROTO_SCTP
388 &nf_conntrack_l4proto_sctp4,
389#endif
390#ifdef CONFIG_NF_CT_PROTO_UDPLITE
391 &nf_conntrack_l4proto_udplite4,
392#endif
343};393};
344 394
345static int ipv4_net_init(struct net *net)395static int ipv4_net_init(struct net *net)
@@ -369,6 +419,8 @@ static void ipv4_net_exit(struct net *net) · 23 unmodified lines
369static struct pernet_operations ipv4_net_ops = {419static struct pernet_operations ipv4_net_ops = {
370 .init = ipv4_net_init,420 .init = ipv4_net_init,
371 .exit = ipv4_net_exit,421 .exit = ipv4_net_exit,
422 .id = &conntrack4_net_id,
423 .size = sizeof(struct conntrack4_net),
372};424};
373 425
374static int __init nf_conntrack_l3proto_ipv4_init(void)426static int __init nf_conntrack_l3proto_ipv4_init(void)
@@ -376,7 +428,6 @@ static int __init nf_conntrack_l3proto_ipv4_init(void) · 1 unmodified line
376 int ret = 0;428 int ret = 0;
377 429
378 need_conntrack();430 need_conntrack();
379 nf_defrag_ipv4_enable();
380 431
381 ret = nf_register_sockopt(&so_getorigdst);432 ret = nf_register_sockopt(&so_getorigdst);
382 if (ret < 0) {433 if (ret < 0) {
@@ -390,17 +441,10 @@ static int __init nf_conntrack_l3proto_ipv4_init(void) · 7 unmodified lines
390 goto cleanup_sockopt;441 goto cleanup_sockopt;
391 }442 }
392 443
393 ret = nf_register_hooks(ipv4_conntrack_ops,
394 ARRAY_SIZE(ipv4_conntrack_ops));
395 if (ret < 0) {
396 pr_err("nf_conntrack_ipv4: can't register hooks.\n");
397 goto cleanup_pernet;
398 }
399
400 ret = nf_ct_l4proto_register(builtin_l4proto4,444 ret = nf_ct_l4proto_register(builtin_l4proto4,
401 ARRAY_SIZE(builtin_l4proto4));445 ARRAY_SIZE(builtin_l4proto4));
402 if (ret < 0)446 if (ret < 0)
403 goto cleanup_hooks;447 goto cleanup_pernet;
404 448
405 ret = nf_ct_l3proto_register(&nf_conntrack_l3proto_ipv4);449 ret = nf_ct_l3proto_register(&nf_conntrack_l3proto_ipv4);
406 if (ret < 0) {450 if (ret < 0) {
@@ -412,8 +456,6 @@ static int __init nf_conntrack_l3proto_ipv4_init(void) · 5 unmodified lines
412cleanup_l4proto:456cleanup_l4proto:
413 nf_ct_l4proto_unregister(builtin_l4proto4,457 nf_ct_l4proto_unregister(builtin_l4proto4,
414 ARRAY_SIZE(builtin_l4proto4));458 ARRAY_SIZE(builtin_l4proto4));
415 cleanup_hooks:
416 nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
417 cleanup_pernet:459 cleanup_pernet:
418 unregister_pernet_subsys(&ipv4_net_ops);460 unregister_pernet_subsys(&ipv4_net_ops);
419 cleanup_sockopt:461 cleanup_sockopt:
@@ -427,7 +469,6 @@ static void __exit nf_conntrack_l3proto_ipv4_fini(void) · 7 unmodified lines
427 nf_ct_l3proto_unregister(&nf_conntrack_l3proto_ipv4);469 nf_ct_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
428 nf_ct_l4proto_unregister(builtin_l4proto4,470 nf_ct_l4proto_unregister(builtin_l4proto4,
429 ARRAY_SIZE(builtin_l4proto4));471 ARRAY_SIZE(builtin_l4proto4));
430 nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
431 unregister_pernet_subsys(&ipv4_net_ops);472 unregister_pernet_subsys(&ipv4_net_ops);
432 nf_unregister_sockopt(&so_getorigdst);473 nf_unregister_sockopt(&so_getorigdst);
433}474}
net/ipv4/netfilter/nf_defrag_ipv4.c+38−3
@@ -11,6 +11,7 @@ · 10 unmodified lines
11#include <linux/netfilter.h>11#include <linux/netfilter.h>
12#include <linux/module.h>12#include <linux/module.h>
13#include <linux/skbuff.h>13#include <linux/skbuff.h>
14#include <net/netns/generic.h>
14#include <net/route.h>15#include <net/route.h>
15#include <net/ip.h>16#include <net/ip.h>
16 17
@@ -22,6 +23,8 @@ · 5 unmodified lines
22#endif23#endif
23#include <net/netfilter/nf_conntrack_zones.h>24#include <net/netfilter/nf_conntrack_zones.h>
24 25
26static DEFINE_MUTEX(defrag4_mutex);
27
25static int nf_ct_ipv4_gather_frags(struct net *net, struct sk_buff *skb,28static int nf_ct_ipv4_gather_frags(struct net *net, struct sk_buff *skb,
26 u_int32_t user)29 u_int32_t user)
27{30{
@@ -102,18 +105,50 @@ static struct nf_hook_ops ipv4_defrag_ops[] = { · 74 unmodified lines
102 },105 },
103};106};
104 107
108static void __net_exit defrag4_net_exit(struct net *net)
109{
110 if (net->nf.defrag_ipv4) {
111 nf_unregister_net_hooks(net, ipv4_defrag_ops,
112 ARRAY_SIZE(ipv4_defrag_ops));
113 net->nf.defrag_ipv4 = false;
114 }
115}
116
117static struct pernet_operations defrag4_net_ops = {
118 .exit = defrag4_net_exit,
119};
120
105static int __init nf_defrag_init(void)121static int __init nf_defrag_init(void)
106{122{
107 return nf_register_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops));123 return register_pernet_subsys(&defrag4_net_ops);
108}124}
109 125
110static void __exit nf_defrag_fini(void)126static void __exit nf_defrag_fini(void)
111{127{
112 nf_unregister_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops));128 unregister_pernet_subsys(&defrag4_net_ops);
113}129}
114 130
115void nf_defrag_ipv4_enable(void)131int nf_defrag_ipv4_enable(struct net *net)
116{132{
133 int err = 0;
134
135 might_sleep();
136
137 if (net->nf.defrag_ipv4)
138 return 0;
139
140 mutex_lock(&defrag4_mutex);
141 if (net->nf.defrag_ipv4)
142 goto out_unlock;
143
144 err = nf_register_net_hooks(net, ipv4_defrag_ops,
145 ARRAY_SIZE(ipv4_defrag_ops));
146 if (err == 0)
147 net->nf.defrag_ipv4 = true;
148
149 out_unlock:
150 mutex_unlock(&defrag4_mutex);
151 return err;
117}152}
118EXPORT_SYMBOL_GPL(nf_defrag_ipv4_enable);153EXPORT_SYMBOL_GPL(nf_defrag_ipv4_enable);
119 154
net/ipv4/netfilter/nft_fib_ipv4.c+10−7
@@ -101,12 +101,13 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs, · 100 unmodified lines
101 }101 }
102 102
103 iph = ip_hdr(pkt->skb);103 iph = ip_hdr(pkt->skb);
104 if (ipv4_is_multicast(iph->daddr) &&104 if (ipv4_is_zeronet(iph->saddr)) {
105 ipv4_is_zeronet(iph->saddr) &&105 if (ipv4_is_lbcast(iph->daddr) ||
106 ipv4_is_local_multicast(iph->daddr)) {106 ipv4_is_local_multicast(iph->daddr)) {
107 nft_fib_store_result(dest, priv->result, pkt,107 nft_fib_store_result(dest, priv->result, pkt,
108 get_ifindex(pkt->skb->dev));108 get_ifindex(pkt->skb->dev));
109 return;109 return;
110 }
110 }111 }
111 112
112 if (priv->flags & NFTA_FIB_F_MARK)113 if (priv->flags & NFTA_FIB_F_MARK)
@@ -122,6 +123,8 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs, · 9 unmodified lines
122 fl4.saddr = get_saddr(iph->daddr);123 fl4.saddr = get_saddr(iph->daddr);
123 }124 }
124 125
126 *dest = 0;
127
125 if (fib_lookup(nft_net(pkt), &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE))128 if (fib_lookup(nft_net(pkt), &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE))
126 return;129 return;
127 130
@@ -198,7 +201,7 @@ nft_fib4_select_ops(const struct nft_ctx *ctx, · 70 unmodified lines
198 if (!tb[NFTA_FIB_RESULT])201 if (!tb[NFTA_FIB_RESULT])
199 return ERR_PTR(-EINVAL);202 return ERR_PTR(-EINVAL);
200 203
201 result = htonl(nla_get_be32(tb[NFTA_FIB_RESULT]));204 result = ntohl(nla_get_be32(tb[NFTA_FIB_RESULT]));
202 205
203 switch (result) {206 switch (result) {
204 case NFT_FIB_RESULT_OIF:207 case NFT_FIB_RESULT_OIF:
net/ipv4/netfilter/nft_masq_ipv4.c+9−2
@@ -1,5 +1,5 @@
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 * This program is free software; you can redistribute it and/or modify4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as5 * it under the terms of the GNU General Public License version 2 as
@@ -35,12 +35,19 @@ static void nft_masq_ipv4_eval(const struct nft_expr *expr, · 29 unmodified lines
35 &range, nft_out(pkt));35 &range, nft_out(pkt));
36}36}
37 37
38static void
39nft_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
38static struct nft_expr_type nft_masq_ipv4_type;44static struct nft_expr_type nft_masq_ipv4_type;
39static const struct nft_expr_ops nft_masq_ipv4_ops = {45static const struct nft_expr_ops nft_masq_ipv4_ops = {
40 .type = &nft_masq_ipv4_type,46 .type = &nft_masq_ipv4_type,
41 .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)),47 .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)),
42 .eval = nft_masq_ipv4_eval,48 .eval = nft_masq_ipv4_eval,
43 .init = nft_masq_init,49 .init = nft_masq_init,
50 .destroy = nft_masq_ipv4_destroy,
44 .dump = nft_masq_dump,51 .dump = nft_masq_dump,
45 .validate = nft_masq_validate,52 .validate = nft_masq_validate,
46};53};
@@ -77,5 +84,5 @@ module_init(nft_masq_ipv4_module_init); · 30 unmodified lines
77module_exit(nft_masq_ipv4_module_exit);84module_exit(nft_masq_ipv4_module_exit);
78 85
79MODULE_LICENSE("GPL");86MODULE_LICENSE("GPL");
80MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");87MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org");
81MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "masq");88MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "masq");
net/ipv4/netfilter/nft_redir_ipv4.c+9−2
@@ -1,5 +1,5 @@
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 * This program is free software; you can redistribute it and/or modify4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as5 * it under the terms of the GNU General Public License version 2 as
@@ -38,12 +38,19 @@ static void nft_redir_ipv4_eval(const struct nft_expr *expr, · 32 unmodified lines
38 regs->verdict.code = nf_nat_redirect_ipv4(pkt->skb, &mr, nft_hook(pkt));38 regs->verdict.code = nf_nat_redirect_ipv4(pkt->skb, &mr, nft_hook(pkt));
39}39}
40 40
41static void
42nft_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
41static struct nft_expr_type nft_redir_ipv4_type;47static struct nft_expr_type nft_redir_ipv4_type;
42static const struct nft_expr_ops nft_redir_ipv4_ops = {48static const struct nft_expr_ops nft_redir_ipv4_ops = {
43 .type = &nft_redir_ipv4_type,49 .type = &nft_redir_ipv4_type,
44 .size = NFT_EXPR_SIZE(sizeof(struct nft_redir)),50 .size = NFT_EXPR_SIZE(sizeof(struct nft_redir)),
45 .eval = nft_redir_ipv4_eval,51 .eval = nft_redir_ipv4_eval,
46 .init = nft_redir_init,52 .init = nft_redir_init,
53 .destroy = nft_redir_ipv4_destroy,
47 .dump = nft_redir_dump,54 .dump = nft_redir_dump,
48 .validate = nft_redir_validate,55 .validate = nft_redir_validate,
49};56};
@@ -71,5 +78,5 @@ module_init(nft_redir_ipv4_module_init); · 21 unmodified lines
71module_exit(nft_redir_ipv4_module_exit);78module_exit(nft_redir_ipv4_module_exit);
72 79
73MODULE_LICENSE("GPL");80MODULE_LICENSE("GPL");
74MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");81MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
75MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "redir");82MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "redir");
net/ipv6/netfilter/ip6_tables.c+8−9
@@ -562,7 +562,8 @@ static int check_target(struct ip6t_entry *e, struct net *net, const char *name) · 561 unmodified lines
562 562
563static int563static int
564find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,564find_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 struct xt_entry_target *t;568 struct xt_entry_target *t;
568 struct xt_target *target;569 struct xt_target *target;
@@ -570,12 +571,9 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, · 1 unmodified line
570 unsigned int j;571 unsigned int j;
571 struct xt_mtchk_param mtpar;572 struct xt_mtchk_param mtpar;
572 struct xt_entry_match *ematch;573 struct xt_entry_match *ematch;
573 unsigned long pcnt;
574 574
575 pcnt = xt_percpu_counter_alloc();575 if (!xt_percpu_counter_alloc(alloc_state, &e->counters))
576 if (IS_ERR_VALUE(pcnt))
577 return -ENOMEM;576 return -ENOMEM;
578 e->counters.pcnt = pcnt;
579 577
580 j = 0;578 j = 0;
581 mtpar.net = net;579 mtpar.net = net;
@@ -612,7 +610,7 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, · 30 unmodified lines
612 cleanup_match(ematch, net);610 cleanup_match(ematch, net);
613 }611 }
614 612
615 xt_percpu_counter_free(e->counters.pcnt);613 xt_percpu_counter_free(&e->counters);
616 614
617 return ret;615 return ret;
618}616}
@@ -699,8 +697,7 @@ static void cleanup_entry(struct ip6t_entry *e, struct net *net) · 80 unmodified lines
699 if (par.target->destroy != NULL)697 if (par.target->destroy != NULL)
700 par.target->destroy(&par);698 par.target->destroy(&par);
701 module_put(par.target->me);699 module_put(par.target->me);
702 700 xt_percpu_counter_free(&e->counters);
703 xt_percpu_counter_free(e->counters.pcnt);
704}701}
705 702
706/* Checks and translates the user-supplied table segment (held in703/* Checks and translates the user-supplied table segment (held in
@@ -709,6 +706,7 @@ static int · 2 unmodified lines
709translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,706translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,
710 const struct ip6t_replace *repl)707 const struct ip6t_replace *repl)
711{708{
709 struct xt_percpu_counter_alloc_state alloc_state = { 0 };
712 struct ip6t_entry *iter;710 struct ip6t_entry *iter;
713 unsigned int *offsets;711 unsigned int *offsets;
714 unsigned int i;712 unsigned int i;
@@ -768,7 +766,8 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, · 53 unmodified lines
768 /* Finally, each sanity check must pass */766 /* Finally, each sanity check must pass */
769 i = 0;767 i = 0;
770 xt_entry_foreach(iter, entry0, newinfo->size) {768 xt_entry_foreach(iter, entry0, newinfo->size) {
771 ret = find_check_entry(iter, net, repl->name, repl->size);769 ret = find_check_entry(iter, net, repl->name, repl->size,
770 &alloc_state);
772 if (ret != 0)771 if (ret != 0)
773 break;772 break;
774 ++i;773 ++i;
net/ipv6/netfilter/ip6t_SYNPROXY.c+2−2
@@ -440,12 +440,12 @@ static int synproxy_tg6_check(const struct xt_tgchk_param *par) · 439 unmodified lines
440 e->ipv6.invflags & XT_INV_PROTO)440 e->ipv6.invflags & XT_INV_PROTO)
441 return -EINVAL;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
446static void synproxy_tg6_destroy(const struct xt_tgdtor_param *par)446static 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
451static struct xt_target synproxy_tg6_reg __read_mostly = {451static struct xt_target synproxy_tg6_reg __read_mostly = {
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c+57−13
@@ -34,6 +34,13 @@ · 33 unmodified lines
34#include <net/netfilter/ipv6/nf_defrag_ipv6.h>34#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
35#include <net/netfilter/nf_log.h>35#include <net/netfilter/nf_log.h>
36 36
37static int conntrack6_net_id;
38static DEFINE_MUTEX(register_ipv6_hooks);
39
40struct conntrack6_net {
41 unsigned int users;
42};
43
37static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,44static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
38 struct nf_conntrack_tuple *tuple)45 struct nf_conntrack_tuple *tuple)
39{46{
@@ -308,6 +315,42 @@ static int ipv6_nlattr_tuple_size(void) · 268 unmodified lines
308}315}
309#endif316#endif
310 317
318static int ipv6_hooks_register(struct net *net)
319{
320 struct conntrack6_net *cnet = net_generic(net, conntrack6_net_id);
321 int err = 0;
322
323 mutex_lock(&register_ipv6_hooks);
324 cnet->users++;
325 if (cnet->users > 1)
326 goto out_unlock;
327
328 err = nf_defrag_ipv6_enable(net);
329 if (err < 0) {
330 cnet->users = 0;
331 goto out_unlock;
332 }
333
334 err = nf_register_net_hooks(net, ipv6_conntrack_ops,
335 ARRAY_SIZE(ipv6_conntrack_ops));
336 if (err)
337 cnet->users = 0;
338 out_unlock:
339 mutex_unlock(&register_ipv6_hooks);
340 return err;
341}
342
343static void ipv6_hooks_unregister(struct net *net)
344{
345 struct conntrack6_net *cnet = net_generic(net, conntrack6_net_id);
346
347 mutex_lock(&register_ipv6_hooks);
348 if (cnet->users && (--cnet->users == 0))
349 nf_unregister_net_hooks(net, ipv6_conntrack_ops,
350 ARRAY_SIZE(ipv6_conntrack_ops));
351 mutex_unlock(&register_ipv6_hooks);
352}
353
311struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = {354struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = {
312 .l3proto = PF_INET6,355 .l3proto = PF_INET6,
313 .name = "ipv6",356 .name = "ipv6",
@@ -321,6 +364,8 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = { · 7 unmodified lines
321 .nlattr_to_tuple = ipv6_nlattr_to_tuple,364 .nlattr_to_tuple = ipv6_nlattr_to_tuple,
322 .nla_policy = ipv6_nla_policy,365 .nla_policy = ipv6_nla_policy,
323#endif366#endif
367 .net_ns_get = ipv6_hooks_register,
368 .net_ns_put = ipv6_hooks_unregister,
324 .me = THIS_MODULE,369 .me = THIS_MODULE,
325};370};
326 371
@@ -340,6 +385,15 @@ static struct nf_conntrack_l4proto *builtin_l4proto6[] = { · 13 unmodified lines
340 &nf_conntrack_l4proto_tcp6,385 &nf_conntrack_l4proto_tcp6,
341 &nf_conntrack_l4proto_udp6,386 &nf_conntrack_l4proto_udp6,
342 &nf_conntrack_l4proto_icmpv6,387 &nf_conntrack_l4proto_icmpv6,
388#ifdef CONFIG_NF_CT_PROTO_DCCP
389 &nf_conntrack_l4proto_dccp6,
390#endif
391#ifdef CONFIG_NF_CT_PROTO_SCTP
392 &nf_conntrack_l4proto_sctp6,
393#endif
394#ifdef CONFIG_NF_CT_PROTO_UDPLITE
395 &nf_conntrack_l4proto_udplite6,
396#endif
343};397};
344 398
345static int ipv6_net_init(struct net *net)399static int ipv6_net_init(struct net *net)
@@ -370,6 +424,8 @@ static void ipv6_net_exit(struct net *net) · 24 unmodified lines
370static struct pernet_operations ipv6_net_ops = {424static struct pernet_operations ipv6_net_ops = {
371 .init = ipv6_net_init,425 .init = ipv6_net_init,
372 .exit = ipv6_net_exit,426 .exit = ipv6_net_exit,
427 .id = &conntrack6_net_id,
428 .size = sizeof(struct conntrack6_net),
373};429};
374 430
375static int __init nf_conntrack_l3proto_ipv6_init(void)431static int __init nf_conntrack_l3proto_ipv6_init(void)
@@ -377,7 +433,6 @@ static int __init nf_conntrack_l3proto_ipv6_init(void) · 1 unmodified line
377 int ret = 0;433 int ret = 0;
378 434
379 need_conntrack();435 need_conntrack();
380 nf_defrag_ipv6_enable();
381 436
382 ret = nf_register_sockopt(&so_getorigdst6);437 ret = nf_register_sockopt(&so_getorigdst6);
383 if (ret < 0) {438 if (ret < 0) {
@@ -389,18 +444,10 @@ static int __init nf_conntrack_l3proto_ipv6_init(void) · 5 unmodified lines
389 if (ret < 0)444 if (ret < 0)
390 goto cleanup_sockopt;445 goto cleanup_sockopt;
391 446
392 ret = nf_register_hooks(ipv6_conntrack_ops,
393 ARRAY_SIZE(ipv6_conntrack_ops));
394 if (ret < 0) {
395 pr_err("nf_conntrack_ipv6: can't register pre-routing defrag "
396 "hook.\n");
397 goto cleanup_pernet;
398 }
399
400 ret = nf_ct_l4proto_register(builtin_l4proto6,447 ret = nf_ct_l4proto_register(builtin_l4proto6,
401 ARRAY_SIZE(builtin_l4proto6));448 ARRAY_SIZE(builtin_l4proto6));
402 if (ret < 0)449 if (ret < 0)
403 goto cleanup_hooks;450 goto cleanup_pernet;
404 451
405 ret = nf_ct_l3proto_register(&nf_conntrack_l3proto_ipv6);452 ret = nf_ct_l3proto_register(&nf_conntrack_l3proto_ipv6);
406 if (ret < 0) {453 if (ret < 0) {
@@ -411,8 +458,6 @@ static int __init nf_conntrack_l3proto_ipv6_init(void) · 4 unmodified lines
411cleanup_l4proto:458cleanup_l4proto:
412 nf_ct_l4proto_unregister(builtin_l4proto6,459 nf_ct_l4proto_unregister(builtin_l4proto6,
413 ARRAY_SIZE(builtin_l4proto6));460 ARRAY_SIZE(builtin_l4proto6));
414 cleanup_hooks:
415 nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
416 cleanup_pernet:461 cleanup_pernet:
417 unregister_pernet_subsys(&ipv6_net_ops);462 unregister_pernet_subsys(&ipv6_net_ops);
418 cleanup_sockopt:463 cleanup_sockopt:
@@ -426,7 +471,6 @@ static void __exit nf_conntrack_l3proto_ipv6_fini(void) · 7 unmodified lines
426 nf_ct_l3proto_unregister(&nf_conntrack_l3proto_ipv6);471 nf_ct_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
427 nf_ct_l4proto_unregister(builtin_l4proto6,472 nf_ct_l4proto_unregister(builtin_l4proto6,
428 ARRAY_SIZE(builtin_l4proto6));473 ARRAY_SIZE(builtin_l4proto6));
429 nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
430 unregister_pernet_subsys(&ipv6_net_ops);474 unregister_pernet_subsys(&ipv6_net_ops);
431 nf_unregister_sockopt(&so_getorigdst6);475 nf_unregister_sockopt(&so_getorigdst6);
432}476}
net/ipv6/netfilter/nf_defrag_ipv6_hooks.c+38−4
@@ -30,6 +30,8 @@ · 29 unmodified lines
30#include <net/netfilter/nf_conntrack_zones.h>30#include <net/netfilter/nf_conntrack_zones.h>
31#include <net/netfilter/ipv6/nf_defrag_ipv6.h>31#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
32 32
33static DEFINE_MUTEX(defrag6_mutex);
34
33static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,35static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
34 struct sk_buff *skb)36 struct sk_buff *skb)
35{37{
@@ -87,6 +89,19 @@ static struct nf_hook_ops ipv6_defrag_ops[] = { · 51 unmodified lines
87 },89 },
88};90};
89 91
92static void __net_exit defrag6_net_exit(struct net *net)
93{
94 if (net->nf.defrag_ipv6) {
95 nf_unregister_net_hooks(net, ipv6_defrag_ops,
96 ARRAY_SIZE(ipv6_defrag_ops));
97 net->nf.defrag_ipv6 = false;
98 }
99}
100
101static struct pernet_operations defrag6_net_ops = {
102 .exit = defrag6_net_exit,
103};
104
90static int __init nf_defrag_init(void)105static int __init nf_defrag_init(void)
91{106{
92 int ret = 0;107 int ret = 0;
@@ -96,9 +111,9 @@ static int __init nf_defrag_init(void) · 3 unmodified lines
96 pr_err("nf_defrag_ipv6: can't initialize frag6.\n");111 pr_err("nf_defrag_ipv6: can't initialize frag6.\n");
97 return ret;112 return ret;
98 }113 }
99 ret = nf_register_hooks(ipv6_defrag_ops, ARRAY_SIZE(ipv6_defrag_ops));114 ret = register_pernet_subsys(&defrag6_net_ops);
100 if (ret < 0) {115 if (ret < 0) {
101 pr_err("nf_defrag_ipv6: can't register hooks\n");116 pr_err("nf_defrag_ipv6: can't register pernet ops\n");
102 goto cleanup_frag6;117 goto cleanup_frag6;
103 }118 }
104 return ret;119 return ret;
@@ -111,12 +126,31 @@ cleanup_frag6: · 6 unmodified lines
111 126
112static void __exit nf_defrag_fini(void)127static void __exit nf_defrag_fini(void)
113{128{
114 nf_unregister_hooks(ipv6_defrag_ops, ARRAY_SIZE(ipv6_defrag_ops));129 unregister_pernet_subsys(&defrag6_net_ops);
115 nf_ct_frag6_cleanup();130 nf_ct_frag6_cleanup();
116}131}
117 132
118void nf_defrag_ipv6_enable(void)133int nf_defrag_ipv6_enable(struct net *net)
119{134{
135 int err = 0;
136
137 might_sleep();
138
139 if (net->nf.defrag_ipv6)
140 return 0;
141
142 mutex_lock(&defrag6_mutex);
143 if (net->nf.defrag_ipv6)
144 goto out_unlock;
145
146 err = nf_register_net_hooks(net, ipv6_defrag_ops,
147 ARRAY_SIZE(ipv6_defrag_ops));
148 if (err == 0)
149 net->nf.defrag_ipv6 = true;
150
151 out_unlock:
152 mutex_unlock(&defrag6_mutex);
153 return err;
120}154}
121EXPORT_SYMBOL_GPL(nf_defrag_ipv6_enable);155EXPORT_SYMBOL_GPL(nf_defrag_ipv6_enable);
122 156
net/ipv6/netfilter/nft_fib_ipv6.c+1−1
@@ -235,7 +235,7 @@ nft_fib6_select_ops(const struct nft_ctx *ctx, · 234 unmodified lines
235 if (!tb[NFTA_FIB_RESULT])235 if (!tb[NFTA_FIB_RESULT])
236 return ERR_PTR(-EINVAL);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 switch (result) {240 switch (result) {
241 case NFT_FIB_RESULT_OIF:241 case NFT_FIB_RESULT_OIF:
net/ipv6/netfilter/nft_masq_ipv6.c+9−2
@@ -1,5 +1,5 @@
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 * This program is free software; you can redistribute it and/or modify4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as5 * it under the terms of the GNU General Public License version 2 as
@@ -36,12 +36,19 @@ static void nft_masq_ipv6_eval(const struct nft_expr *expr, · 30 unmodified lines
36 nft_out(pkt));36 nft_out(pkt));
37}37}
38 38
39static void
40nft_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
39static struct nft_expr_type nft_masq_ipv6_type;45static struct nft_expr_type nft_masq_ipv6_type;
40static const struct nft_expr_ops nft_masq_ipv6_ops = {46static const struct nft_expr_ops nft_masq_ipv6_ops = {
41 .type = &nft_masq_ipv6_type,47 .type = &nft_masq_ipv6_type,
42 .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)),48 .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)),
43 .eval = nft_masq_ipv6_eval,49 .eval = nft_masq_ipv6_eval,
44 .init = nft_masq_init,50 .init = nft_masq_init,
51 .destroy = nft_masq_ipv6_destroy,
45 .dump = nft_masq_dump,52 .dump = nft_masq_dump,
46 .validate = nft_masq_validate,53 .validate = nft_masq_validate,
47};54};
@@ -78,5 +85,5 @@ module_init(nft_masq_ipv6_module_init); · 30 unmodified lines
78module_exit(nft_masq_ipv6_module_exit);85module_exit(nft_masq_ipv6_module_exit);
79 86
80MODULE_LICENSE("GPL");87MODULE_LICENSE("GPL");
81MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");88MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
82MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "masq");89MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "masq");
net/ipv6/netfilter/nft_redir_ipv6.c+9−2
@@ -1,5 +1,5 @@
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 * This program is free software; you can redistribute it and/or modify4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as5 * it under the terms of the GNU General Public License version 2 as
@@ -39,12 +39,19 @@ static void nft_redir_ipv6_eval(const struct nft_expr *expr, · 33 unmodified lines
39 nf_nat_redirect_ipv6(pkt->skb, &range, nft_hook(pkt));39 nf_nat_redirect_ipv6(pkt->skb, &range, nft_hook(pkt));
40}40}
41 41
42static void
43nft_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
42static struct nft_expr_type nft_redir_ipv6_type;48static struct nft_expr_type nft_redir_ipv6_type;
43static const struct nft_expr_ops nft_redir_ipv6_ops = {49static const struct nft_expr_ops nft_redir_ipv6_ops = {
44 .type = &nft_redir_ipv6_type,50 .type = &nft_redir_ipv6_type,
45 .size = NFT_EXPR_SIZE(sizeof(struct nft_redir)),51 .size = NFT_EXPR_SIZE(sizeof(struct nft_redir)),
46 .eval = nft_redir_ipv6_eval,52 .eval = nft_redir_ipv6_eval,
47 .init = nft_redir_init,53 .init = nft_redir_init,
54 .destroy = nft_redir_ipv6_destroy,
48 .dump = nft_redir_dump,55 .dump = nft_redir_dump,
49 .validate = nft_redir_validate,56 .validate = nft_redir_validate,
50};57};
@@ -72,5 +79,5 @@ module_init(nft_redir_ipv6_module_init); · 21 unmodified lines
72module_exit(nft_redir_ipv6_module_exit);79module_exit(nft_redir_ipv6_module_exit);
73 80
74MODULE_LICENSE("GPL");81MODULE_LICENSE("GPL");
75MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");82MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
76MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "redir");83MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "redir");
net/netfilter/Kconfig+18−12
@@ -146,38 +146,38 @@ config NF_CONNTRACK_LABELS · 145 unmodified lines
146 to connection tracking entries. It selected by the connlabel match.146 to connection tracking entries. It selected by the connlabel match.
147 147
148config NF_CT_PROTO_DCCP148config NF_CT_PROTO_DCCP
149 tristate 'DCCP protocol connection tracking support'149 bool 'DCCP protocol connection tracking support'
150 depends on NETFILTER_ADVANCED150 depends on NETFILTER_ADVANCED
151 default IP_DCCP151 default y
152 help152 help
153 With this option enabled, the layer 3 independent connection153 With this option enabled, the layer 3 independent connection
154 tracking code will be able to do state tracking on DCCP connections.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
158config NF_CT_PROTO_GRE158config NF_CT_PROTO_GRE
159 tristate159 tristate
160 160
161config NF_CT_PROTO_SCTP161config NF_CT_PROTO_SCTP
162 tristate 'SCTP protocol connection tracking support'162 bool 'SCTP protocol connection tracking support'
163 depends on NETFILTER_ADVANCED163 depends on NETFILTER_ADVANCED
164 default IP_SCTP164 default y
165 help165 help
166 With this option enabled, the layer 3 independent connection166 With this option enabled, the layer 3 independent connection
167 tracking code will be able to do state tracking on SCTP connections.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 read169 If unsure, say Y.
170 <file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
171 170
172config NF_CT_PROTO_UDPLITE171config NF_CT_PROTO_UDPLITE
173 tristate 'UDP-Lite protocol connection tracking support'172 bool 'UDP-Lite protocol connection tracking support'
174 depends on NETFILTER_ADVANCED173 depends on NETFILTER_ADVANCED
174 default y
175 help175 help
176 With this option enabled, the layer 3 independent connection176 With this option enabled, the layer 3 independent connection
177 tracking code will be able to do state tracking on UDP-Lite177 tracking code will be able to do state tracking on UDP-Lite
178 connections.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
182config NF_CONNTRACK_AMANDA182config NF_CONNTRACK_AMANDA
183 tristate "Amanda backup protocol support"183 tristate "Amanda backup protocol support"
@@ -384,17 +384,17 @@ config NF_NAT_NEEDED · 200 unmodified lines
384 default y384 default y
385 385
386config NF_NAT_PROTO_DCCP386config NF_NAT_PROTO_DCCP
387 tristate387 bool
388 depends on NF_NAT && NF_CT_PROTO_DCCP388 depends on NF_NAT && NF_CT_PROTO_DCCP
389 default NF_NAT && NF_CT_PROTO_DCCP389 default NF_NAT && NF_CT_PROTO_DCCP
390 390
391config NF_NAT_PROTO_UDPLITE391config NF_NAT_PROTO_UDPLITE
392 tristate392 bool
393 depends on NF_NAT && NF_CT_PROTO_UDPLITE393 depends on NF_NAT && NF_CT_PROTO_UDPLITE
394 default NF_NAT && NF_CT_PROTO_UDPLITE394 default NF_NAT && NF_CT_PROTO_UDPLITE
395 395
396config NF_NAT_PROTO_SCTP396config NF_NAT_PROTO_SCTP
397 tristate397 bool
398 default NF_NAT && NF_CT_PROTO_SCTP398 default NF_NAT && NF_CT_PROTO_SCTP
399 depends on NF_NAT && NF_CT_PROTO_SCTP399 depends on NF_NAT && NF_CT_PROTO_SCTP
400 select LIBCRC32C400 select LIBCRC32C
@@ -551,6 +551,12 @@ config NFT_NAT · 150 unmodified lines
551 This option adds the "nat" expression that you can use to perform551 This option adds the "nat" expression that you can use to perform
552 typical Network Address Translation (NAT) packet transformations.552 typical Network Address Translation (NAT) packet transformations.
553 553
554config 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.
559
554config NFT_QUEUE560config NFT_QUEUE
555 depends on NETFILTER_NETLINK_QUEUE561 depends on NETFILTER_NETLINK_QUEUE
556 tristate "Netfilter nf_tables queue module"562 tristate "Netfilter nf_tables queue module"
net/netfilter/Makefile+9−9
@@ -5,6 +5,9 @@ nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMEOUT) += nf_conntrack_timeout.o · 4 unmodified lines
5nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMESTAMP) += nf_conntrack_timestamp.o5nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMESTAMP) += nf_conntrack_timestamp.o
6nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o6nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
7nf_conntrack-$(CONFIG_NF_CONNTRACK_LABELS) += nf_conntrack_labels.o7nf_conntrack-$(CONFIG_NF_CONNTRACK_LABELS) += nf_conntrack_labels.o
8nf_conntrack-$(CONFIG_NF_CT_PROTO_DCCP) += nf_conntrack_proto_dccp.o
9nf_conntrack-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
10nf_conntrack-$(CONFIG_NF_CT_PROTO_UDPLITE) += nf_conntrack_proto_udplite.o
8 11
9obj-$(CONFIG_NETFILTER) = netfilter.o12obj-$(CONFIG_NETFILTER) = netfilter.o
10 13
@@ -16,11 +19,7 @@ obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o · 5 unmodified lines
16# connection tracking19# connection tracking
17obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o20obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o
18 21
19# SCTP protocol connection tracking
20obj-$(CONFIG_NF_CT_PROTO_DCCP) += nf_conntrack_proto_dccp.o
21obj-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o22obj-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o
22obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
23obj-$(CONFIG_NF_CT_PROTO_UDPLITE) += nf_conntrack_proto_udplite.o
24 23
25# netlink interface for nf_conntrack24# netlink interface for nf_conntrack
26obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o25obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o
@@ -45,6 +44,11 @@ obj-$(CONFIG_NF_CONNTRACK_TFTP) += nf_conntrack_tftp.o · 18 unmodified lines
45nf_nat-y := nf_nat_core.o nf_nat_proto_unknown.o nf_nat_proto_common.o \44nf_nat-y := nf_nat_core.o nf_nat_proto_unknown.o nf_nat_proto_common.o \
46 nf_nat_proto_udp.o nf_nat_proto_tcp.o nf_nat_helper.o45 nf_nat_proto_udp.o nf_nat_proto_tcp.o nf_nat_helper.o
47 46
47# NAT protocols (nf_nat)
48nf_nat-$(CONFIG_NF_NAT_PROTO_DCCP) += nf_nat_proto_dccp.o
49nf_nat-$(CONFIG_NF_NAT_PROTO_SCTP) += nf_nat_proto_sctp.o
50nf_nat-$(CONFIG_NF_NAT_PROTO_UDPLITE) += nf_nat_proto_udplite.o
51
48# generic transport layer logging52# generic transport layer logging
49obj-$(CONFIG_NF_LOG_COMMON) += nf_log_common.o53obj-$(CONFIG_NF_LOG_COMMON) += nf_log_common.o
50 54
@@ -54,11 +58,6 @@ obj-$(CONFIG_NF_LOG_NETDEV) += nf_log_netdev.o · 3 unmodified lines
54obj-$(CONFIG_NF_NAT) += nf_nat.o58obj-$(CONFIG_NF_NAT) += nf_nat.o
55obj-$(CONFIG_NF_NAT_REDIRECT) += nf_nat_redirect.o59obj-$(CONFIG_NF_NAT_REDIRECT) += nf_nat_redirect.o
56 60
57# NAT protocols (nf_nat)
58obj-$(CONFIG_NF_NAT_PROTO_DCCP) += nf_nat_proto_dccp.o
59obj-$(CONFIG_NF_NAT_PROTO_UDPLITE) += nf_nat_proto_udplite.o
60obj-$(CONFIG_NF_NAT_PROTO_SCTP) += nf_nat_proto_sctp.o
61
62# NAT helpers61# NAT helpers
63obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o62obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o
64obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o63obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o
@@ -89,6 +88,7 @@ obj-$(CONFIG_NFT_NUMGEN) += nft_numgen.o · 24 unmodified lines
89obj-$(CONFIG_NFT_CT) += nft_ct.o88obj-$(CONFIG_NFT_CT) += nft_ct.o
90obj-$(CONFIG_NFT_LIMIT) += nft_limit.o89obj-$(CONFIG_NFT_LIMIT) += nft_limit.o
91obj-$(CONFIG_NFT_NAT) += nft_nat.o90obj-$(CONFIG_NFT_NAT) += nft_nat.o
91obj-$(CONFIG_NFT_OBJREF) += nft_objref.o
92obj-$(CONFIG_NFT_QUEUE) += nft_queue.o92obj-$(CONFIG_NFT_QUEUE) += nft_queue.o
93obj-$(CONFIG_NFT_QUOTA) += nft_quota.o93obj-$(CONFIG_NFT_QUOTA) += nft_quota.o
94obj-$(CONFIG_NFT_REJECT) += nft_reject.o94obj-$(CONFIG_NFT_REJECT) += nft_reject.o
net/netfilter/core.c+6−10
@@ -102,17 +102,14 @@ int nf_register_net_hook(struct net *net, const struct nf_hook_ops *reg) · 101 unmodified lines
102 if (!entry)102 if (!entry)
103 return -ENOMEM;103 return -ENOMEM;
104 104
105 entry->orig_ops = reg;105 nf_hook_entry_init(entry, reg);
106 entry->ops = *reg;
107 entry->next = NULL;
108 106
109 mutex_lock(&nf_hook_mutex);107 mutex_lock(&nf_hook_mutex);
110 108
111 /* Find the spot in the list */109 /* Find the spot in the list */
112 while ((p = nf_entry_dereference(*pp)) != NULL) {110 for (; (p = nf_entry_dereference(*pp)) != NULL; pp = &p->next) {
113 if (reg->priority < p->orig_ops->priority)111 if (reg->priority < nf_hook_entry_priority(p))
114 break;112 break;
115 pp = &p->next;
116 }113 }
117 rcu_assign_pointer(entry->next, p);114 rcu_assign_pointer(entry->next, p);
118 rcu_assign_pointer(*pp, entry);115 rcu_assign_pointer(*pp, entry);
@@ -139,12 +136,11 @@ void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg) · 20 unmodified lines
139 return;136 return;
140 137
141 mutex_lock(&nf_hook_mutex);138 mutex_lock(&nf_hook_mutex);
142 while ((p = nf_entry_dereference(*pp)) != NULL) {139 for (; (p = nf_entry_dereference(*pp)) != NULL; pp = &p->next) {
143 if (p->orig_ops == reg) {140 if (nf_hook_entry_ops(p) == reg) {
144 rcu_assign_pointer(*pp, p->next);141 rcu_assign_pointer(*pp, p->next);
145 break;142 break;
146 }143 }
147 pp = &p->next;
148 }144 }
149 mutex_unlock(&nf_hook_mutex);145 mutex_unlock(&nf_hook_mutex);
150 if (!p) {146 if (!p) {
@@ -311,7 +307,7 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state, · 160 unmodified lines
311 int ret;307 int ret;
312 308
313 do {309 do {
314 verdict = entry->ops.hook(entry->ops.priv, skb, state);310 verdict = nf_hook_entry_hookfn(entry, skb, state);
315 switch (verdict & NF_VERDICT_MASK) {311 switch (verdict & NF_VERDICT_MASK) {
316 case NF_ACCEPT:312 case NF_ACCEPT:
317 entry = rcu_dereference(entry->next);313 entry = rcu_dereference(entry->next);
net/netfilter/ipvs/ip_vs_ctl.c+1−1
@@ -3260,7 +3260,7 @@ static int ip_vs_genl_dump_dests(struct sk_buff *skb, · 3259 unmodified lines
3260 3260
3261 3261
3262 svc = ip_vs_genl_find_service(ipvs, attrs[IPVS_CMD_ATTR_SERVICE]);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 goto out_err;3264 goto out_err;
3265 3265
3266 /* Dump the destinations */3266 /* Dump the destinations */
net/netfilter/ipvs/ip_vs_xmit.c+54−0
@@ -254,6 +254,54 @@ static inline bool ensure_mtu_is_adequate(struct netns_ipvs *ipvs, int skb_af, · 253 unmodified lines
254 return true;254 return true;
255}255}
256 256
257static 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/* Get route to destination or remote server */305/* Get route to destination or remote server */
258static int306static int
259__ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,307__ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
@@ -326,6 +374,9 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb, · 66 unmodified lines
326 return local;374 return local;
327 }375 }
328 376
377 if (!decrement_ttl(ipvs, skb_af, skb))
378 goto err_put;
379
329 if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL))) {380 if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL))) {
330 mtu = dst_mtu(&rt->dst);381 mtu = dst_mtu(&rt->dst);
331 } else {382 } else {
@@ -473,6 +524,9 @@ __ip_vs_get_out_rt_v6(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb, · 141 unmodified lines
473 return local;524 return local;
474 }525 }
475 526
527 if (!decrement_ttl(ipvs, skb_af, skb))
528 goto err_put;
529
476 /* MTU checking */530 /* MTU checking */
477 if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL)))531 if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL)))
478 mtu = dst_mtu(&rt->dst);532 mtu = dst_mtu(&rt->dst);
net/netfilter/nf_conntrack_proto.c+65−8
@@ -125,6 +125,54 @@ void nf_ct_l3proto_module_put(unsigned short l3proto) · 124 unmodified lines
125}125}
126EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put);126EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put);
127 127
128int 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}
153EXPORT_SYMBOL_GPL(nf_ct_netns_get);
154
155void 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}
174EXPORT_SYMBOL_GPL(nf_ct_netns_put);
175
128struct nf_conntrack_l4proto *176struct nf_conntrack_l4proto *
129nf_ct_l4proto_find_get(u_int16_t l3num, u_int8_t l4num)177nf_ct_l4proto_find_get(u_int16_t l3num, u_int8_t l4num)
130{178{
@@ -190,20 +238,19 @@ out_unlock: · 59 unmodified lines
190}238}
191EXPORT_SYMBOL_GPL(nf_ct_l3proto_register);239EXPORT_SYMBOL_GPL(nf_ct_l3proto_register);
192 240
241#ifdef CONFIG_SYSCTL
242extern unsigned int nf_conntrack_default_on;
243
193int nf_ct_l3proto_pernet_register(struct net *net,244int nf_ct_l3proto_pernet_register(struct net *net,
194 struct nf_conntrack_l3proto *proto)245 struct nf_conntrack_l3proto *proto)
195{246{
196 int ret;247 if (nf_conntrack_default_on == 0)
197 248 return 0;
198 if (proto->init_net) {
199 ret = proto->init_net(net);
200 if (ret < 0)
201 return ret;
202 }
203 249
204 return 0;250 return proto->net_ns_get ? proto->net_ns_get(net) : 0;
205}251}
206EXPORT_SYMBOL_GPL(nf_ct_l3proto_pernet_register);252EXPORT_SYMBOL_GPL(nf_ct_l3proto_pernet_register);
253#endif
207 254
208void nf_ct_l3proto_unregister(struct nf_conntrack_l3proto *proto)255void nf_ct_l3proto_unregister(struct nf_conntrack_l3proto *proto)
209{256{
@@ -224,6 +271,16 @@ EXPORT_SYMBOL_GPL(nf_ct_l3proto_unregister); · 14 unmodified lines
224void nf_ct_l3proto_pernet_unregister(struct net *net,271void nf_ct_l3proto_pernet_unregister(struct net *net,
225 struct nf_conntrack_l3proto *proto)272 struct nf_conntrack_l3proto *proto)
226{273{
274 /*
275 * nf_conntrack_default_on *might* have registered hooks.
276 * ->net_ns_put must cope with more puts() than get(), i.e.
277 * if nf_conntrack_default_on was 0 at time of
278 * nf_ct_l3proto_pernet_register invocation this net_ns_put()
279 * should be a noop.
280 */
281 if (proto->net_ns_put)
282 proto->net_ns_put(net);
283
227 /* Remove all contrack entries for this protocol */284 /* Remove all contrack entries for this protocol */
228 nf_ct_iterate_cleanup(net, kill_l3proto, proto, 0, 0);285 nf_ct_iterate_cleanup(net, kill_l3proto, proto, 0, 0);
229}286}
net/netfilter/nf_conntrack_proto_dccp.c+10−69
@@ -9,7 +9,6 @@ · 8 unmodified lines
9 *9 *
10 */10 */
11#include <linux/kernel.h>11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/init.h>12#include <linux/init.h>
14#include <linux/sysctl.h>13#include <linux/sysctl.h>
15#include <linux/spinlock.h>14#include <linux/spinlock.h>
@@ -384,17 +383,9 @@ dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] = · 368 unmodified lines
384 },383 },
385};384};
386 385
387/* this module per-net specifics */386static inline struct nf_dccp_net *dccp_pernet(struct net *net)
388static unsigned int dccp_net_id __read_mostly;
389struct dccp_net {
390 struct nf_proto_net pn;
391 int dccp_loose;
392 unsigned int dccp_timeout[CT_DCCP_MAX + 1];
393};
394
395static inline struct dccp_net *dccp_pernet(struct net *net)
396{387{
397 return net_generic(net, dccp_net_id);388 return &net->ct.nf_ct_proto.dccp;
398}389}
399 390
400static bool dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,391static bool dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
@@ -424,7 +415,7 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, · 23 unmodified lines
424 unsigned int dataoff, unsigned int *timeouts)415 unsigned int dataoff, unsigned int *timeouts)
425{416{
426 struct net *net = nf_ct_net(ct);417 struct net *net = nf_ct_net(ct);
427 struct dccp_net *dn;418 struct nf_dccp_net *dn;
428 struct dccp_hdr _dh, *dh;419 struct dccp_hdr _dh, *dh;
429 const char *msg;420 const char *msg;
430 u_int8_t state;421 u_int8_t state;
@@ -719,7 +710,7 @@ static int dccp_nlattr_size(void) · 288 unmodified lines
719static int dccp_timeout_nlattr_to_obj(struct nlattr *tb[],710static int dccp_timeout_nlattr_to_obj(struct nlattr *tb[],
720 struct net *net, void *data)711 struct net *net, void *data)
721{712{
722 struct dccp_net *dn = dccp_pernet(net);713 struct nf_dccp_net *dn = dccp_pernet(net);
723 unsigned int *timeouts = data;714 unsigned int *timeouts = data;
724 int i;715 int i;
725 716
@@ -820,7 +811,7 @@ static struct ctl_table dccp_sysctl_table[] = { · 94 unmodified lines
820#endif /* CONFIG_SYSCTL */811#endif /* CONFIG_SYSCTL */
821 812
822static int dccp_kmemdup_sysctl_table(struct net *net, struct nf_proto_net *pn,813static int dccp_kmemdup_sysctl_table(struct net *net, struct nf_proto_net *pn,
823 struct dccp_net *dn)814 struct nf_dccp_net *dn)
824{815{
825#ifdef CONFIG_SYSCTL816#ifdef CONFIG_SYSCTL
826 if (pn->ctl_table)817 if (pn->ctl_table)
@@ -850,7 +841,7 @@ static int dccp_kmemdup_sysctl_table(struct net *net, struct nf_proto_net *pn, · 23 unmodified lines
850 841
851static int dccp_init_net(struct net *net, u_int16_t proto)842static int dccp_init_net(struct net *net, u_int16_t proto)
852{843{
853 struct dccp_net *dn = dccp_pernet(net);844 struct nf_dccp_net *dn = dccp_pernet(net);
854 struct nf_proto_net *pn = &dn->pn;845 struct nf_proto_net *pn = &dn->pn;
855 846
856 if (!pn->users) {847 if (!pn->users) {
@@ -868,7 +859,7 @@ static int dccp_init_net(struct net *net, u_int16_t proto) · 11 unmodified lines
868 return dccp_kmemdup_sysctl_table(net, pn, dn);859 return dccp_kmemdup_sysctl_table(net, pn, dn);
869}860}
870 861
871static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = {862struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4 __read_mostly = {
872 .l3proto = AF_INET,863 .l3proto = AF_INET,
873 .l4proto = IPPROTO_DCCP,864 .l4proto = IPPROTO_DCCP,
874 .name = "dccp",865 .name = "dccp",
@@ -898,11 +889,11 @@ static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = { · 23 unmodified lines
898 .nla_policy = dccp_timeout_nla_policy,889 .nla_policy = dccp_timeout_nla_policy,
899 },890 },
900#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */891#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
901 .net_id = &dccp_net_id,
902 .init_net = dccp_init_net,892 .init_net = dccp_init_net,
903};893};
894EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_dccp4);
904 895
905static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = {896struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6 __read_mostly = {
906 .l3proto = AF_INET6,897 .l3proto = AF_INET6,
907 .l4proto = IPPROTO_DCCP,898 .l4proto = IPPROTO_DCCP,
908 .name = "dccp",899 .name = "dccp",
@@ -932,56 +923,6 @@ static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = { · 23 unmodified lines
932 .nla_policy = dccp_timeout_nla_policy,923 .nla_policy = dccp_timeout_nla_policy,
933 },924 },
934#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */925#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
935 .net_id = &dccp_net_id,
936 .init_net = dccp_init_net,926 .init_net = dccp_init_net,
937};927};
938 928EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_dccp6);
939static struct nf_conntrack_l4proto *dccp_proto[] = {
940 &dccp_proto4,
941 &dccp_proto6,
942};
943
944static __net_init int dccp_net_init(struct net *net)
945{
946 return nf_ct_l4proto_pernet_register(net, dccp_proto,
947 ARRAY_SIZE(dccp_proto));
948}
949
950static __net_exit void dccp_net_exit(struct net *net)
951{
952 nf_ct_l4proto_pernet_unregister(net, dccp_proto,
953 ARRAY_SIZE(dccp_proto));
954}
955
956static struct pernet_operations dccp_net_ops = {
957 .init = dccp_net_init,
958 .exit = dccp_net_exit,
959 .id = &dccp_net_id,
960 .size = sizeof(struct dccp_net),
961};
962
963static int __init nf_conntrack_proto_dccp_init(void)
964{
965 int ret;
966
967 ret = register_pernet_subsys(&dccp_net_ops);
968 if (ret < 0)
969 return ret;
970 ret = nf_ct_l4proto_register(dccp_proto, ARRAY_SIZE(dccp_proto));
971 if (ret < 0)
972 unregister_pernet_subsys(&dccp_net_ops);
973 return ret;
974}
975
976static void __exit nf_conntrack_proto_dccp_fini(void)
977{
978 nf_ct_l4proto_unregister(dccp_proto, ARRAY_SIZE(dccp_proto));
979 unregister_pernet_subsys(&dccp_net_ops);
980}
981
982module_init(nf_conntrack_proto_dccp_init);
983module_exit(nf_conntrack_proto_dccp_fini);
984
985MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
986MODULE_DESCRIPTION("DCCP connection tracking protocol helper");
987MODULE_LICENSE("GPL");
net/netfilter/nf_conntrack_proto_sctp.c+9−67
@@ -15,7 +15,6 @@ · 14 unmodified lines
15#include <linux/types.h>15#include <linux/types.h>
16#include <linux/timer.h>16#include <linux/timer.h>
17#include <linux/netfilter.h>17#include <linux/netfilter.h>
18#include <linux/module.h>
19#include <linux/in.h>18#include <linux/in.h>
20#include <linux/ip.h>19#include <linux/ip.h>
21#include <linux/sctp.h>20#include <linux/sctp.h>
@@ -144,15 +143,9 @@ static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = { · 122 unmodified lines
144 }143 }
145};144};
146 145
147static unsigned int sctp_net_id __read_mostly;146static inline struct nf_sctp_net *sctp_pernet(struct net *net)
148struct sctp_net {
149 struct nf_proto_net pn;
150 unsigned int timeouts[SCTP_CONNTRACK_MAX];
151};
152
153static inline struct sctp_net *sctp_pernet(struct net *net)
154{147{
155 return net_generic(net, sctp_net_id);148 return &net->ct.nf_ct_proto.sctp;
156}149}
157 150
158static bool sctp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,151static bool sctp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
@@ -600,7 +593,7 @@ static int sctp_timeout_nlattr_to_obj(struct nlattr *tb[], · 441 unmodified lines
600 struct net *net, void *data)593 struct net *net, void *data)
601{594{
602 unsigned int *timeouts = data;595 unsigned int *timeouts = data;
603 struct sctp_net *sn = sctp_pernet(net);596 struct nf_sctp_net *sn = sctp_pernet(net);
604 int i;597 int i;
605 598
606 /* set default SCTP timeouts. */599 /* set default SCTP timeouts. */
@@ -708,7 +701,7 @@ static struct ctl_table sctp_sysctl_table[] = { · 101 unmodified lines
708#endif701#endif
709 702
710static int sctp_kmemdup_sysctl_table(struct nf_proto_net *pn,703static int sctp_kmemdup_sysctl_table(struct nf_proto_net *pn,
711 struct sctp_net *sn)704 struct nf_sctp_net *sn)
712{705{
713#ifdef CONFIG_SYSCTL706#ifdef CONFIG_SYSCTL
714 if (pn->ctl_table)707 if (pn->ctl_table)
@@ -735,7 +728,7 @@ static int sctp_kmemdup_sysctl_table(struct nf_proto_net *pn, · 20 unmodified lines
735 728
736static int sctp_init_net(struct net *net, u_int16_t proto)729static int sctp_init_net(struct net *net, u_int16_t proto)
737{730{
738 struct sctp_net *sn = sctp_pernet(net);731 struct nf_sctp_net *sn = sctp_pernet(net);
739 struct nf_proto_net *pn = &sn->pn;732 struct nf_proto_net *pn = &sn->pn;
740 733
741 if (!pn->users) {734 if (!pn->users) {
@@ -748,7 +741,7 @@ static int sctp_init_net(struct net *net, u_int16_t proto) · 6 unmodified lines
748 return sctp_kmemdup_sysctl_table(pn, sn);741 return sctp_kmemdup_sysctl_table(pn, sn);
749}742}
750 743
751static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {744struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
752 .l3proto = PF_INET,745 .l3proto = PF_INET,
753 .l4proto = IPPROTO_SCTP,746 .l4proto = IPPROTO_SCTP,
754 .name = "sctp",747 .name = "sctp",
@@ -778,11 +771,11 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = { · 23 unmodified lines
778 .nla_policy = sctp_timeout_nla_policy,771 .nla_policy = sctp_timeout_nla_policy,
779 },772 },
780#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */773#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
781 .net_id = &sctp_net_id,
782 .init_net = sctp_init_net,774 .init_net = sctp_init_net,
783};775};
776EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_sctp4);
784 777
785static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {778struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
786 .l3proto = PF_INET6,779 .l3proto = PF_INET6,
787 .l4proto = IPPROTO_SCTP,780 .l4proto = IPPROTO_SCTP,
788 .name = "sctp",781 .name = "sctp",
@@ -812,57 +805,6 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = { · 23 unmodified lines
812 },805 },
813#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */806#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
814#endif807#endif
815 .net_id = &sctp_net_id,
816 .init_net = sctp_init_net,808 .init_net = sctp_init_net,
817};809};
818 810EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_sctp6);
819static struct nf_conntrack_l4proto *sctp_proto[] = {
820 &nf_conntrack_l4proto_sctp4,
821 &nf_conntrack_l4proto_sctp6,
822};
823
824static int sctp_net_init(struct net *net)
825{
826 return nf_ct_l4proto_pernet_register(net, sctp_proto,
827 ARRAY_SIZE(sctp_proto));
828}
829
830static void sctp_net_exit(struct net *net)
831{
832 nf_ct_l4proto_pernet_unregister(net, sctp_proto,
833 ARRAY_SIZE(sctp_proto));
834}
835
836static struct pernet_operations sctp_net_ops = {
837 .init = sctp_net_init,
838 .exit = sctp_net_exit,
839 .id = &sctp_net_id,
840 .size = sizeof(struct sctp_net),
841};
842
843static int __init nf_conntrack_proto_sctp_init(void)
844{
845 int ret;
846
847 ret = register_pernet_subsys(&sctp_net_ops);
848 if (ret < 0)
849 return ret;
850 ret = nf_ct_l4proto_register(sctp_proto, ARRAY_SIZE(sctp_proto));
851 if (ret < 0)
852 unregister_pernet_subsys(&sctp_net_ops);
853 return ret;
854}
855
856static void __exit nf_conntrack_proto_sctp_fini(void)
857{
858 nf_ct_l4proto_unregister(sctp_proto, ARRAY_SIZE(sctp_proto));
859 unregister_pernet_subsys(&sctp_net_ops);
860}
861
862module_init(nf_conntrack_proto_sctp_init);
863module_exit(nf_conntrack_proto_sctp_fini);
864
865MODULE_LICENSE("GPL");
866MODULE_AUTHOR("Kiran Kumar Immidi");
867MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
868MODULE_ALIAS("ip_conntrack_proto_sctp");
net/netfilter/nf_conntrack_proto_udplite.c+9−70
@@ -9,7 +9,6 @@ · 8 unmodified lines
9 9
10#include <linux/types.h>10#include <linux/types.h>
11#include <linux/timer.h>11#include <linux/timer.h>
12#include <linux/module.h>
13#include <linux/udp.h>12#include <linux/udp.h>
14#include <linux/seq_file.h>13#include <linux/seq_file.h>
15#include <linux/skbuff.h>14#include <linux/skbuff.h>
@@ -24,26 +23,14 @@ · 8 unmodified lines
24#include <net/netfilter/nf_conntrack_ecache.h>23#include <net/netfilter/nf_conntrack_ecache.h>
25#include <net/netfilter/nf_log.h>24#include <net/netfilter/nf_log.h>
26 25
27enum udplite_conntrack {
28 UDPLITE_CT_UNREPLIED,
29 UDPLITE_CT_REPLIED,
30 UDPLITE_CT_MAX
31};
32
33static unsigned int udplite_timeouts[UDPLITE_CT_MAX] = {26static unsigned int udplite_timeouts[UDPLITE_CT_MAX] = {
34 [UDPLITE_CT_UNREPLIED] = 30*HZ,27 [UDPLITE_CT_UNREPLIED] = 30*HZ,
35 [UDPLITE_CT_REPLIED] = 180*HZ,28 [UDPLITE_CT_REPLIED] = 180*HZ,
36};29};
37 30
38static unsigned int udplite_net_id __read_mostly;31static inline struct nf_udplite_net *udplite_pernet(struct net *net)
39struct udplite_net {
40 struct nf_proto_net pn;
41 unsigned int timeouts[UDPLITE_CT_MAX];
42};
43
44static inline struct udplite_net *udplite_pernet(struct net *net)
45{32{
46 return net_generic(net, udplite_net_id);33 return &net->ct.nf_ct_proto.udplite;
47}34}
48 35
49static bool udplite_pkt_to_tuple(const struct sk_buff *skb,36static bool udplite_pkt_to_tuple(const struct sk_buff *skb,
@@ -178,7 +165,7 @@ static int udplite_timeout_nlattr_to_obj(struct nlattr *tb[], · 128 unmodified lines
178 struct net *net, void *data)165 struct net *net, void *data)
179{166{
180 unsigned int *timeouts = data;167 unsigned int *timeouts = data;
181 struct udplite_net *un = udplite_pernet(net);168 struct nf_udplite_net *un = udplite_pernet(net);
182 169
183 /* set default timeouts for UDPlite. */170 /* set default timeouts for UDPlite. */
184 timeouts[UDPLITE_CT_UNREPLIED] = un->timeouts[UDPLITE_CT_UNREPLIED];171 timeouts[UDPLITE_CT_UNREPLIED] = un->timeouts[UDPLITE_CT_UNREPLIED];
@@ -237,7 +224,7 @@ static struct ctl_table udplite_sysctl_table[] = { · 52 unmodified lines
237#endif /* CONFIG_SYSCTL */224#endif /* CONFIG_SYSCTL */
238 225
239static int udplite_kmemdup_sysctl_table(struct nf_proto_net *pn,226static int udplite_kmemdup_sysctl_table(struct nf_proto_net *pn,
240 struct udplite_net *un)227 struct nf_udplite_net *un)
241{228{
242#ifdef CONFIG_SYSCTL229#ifdef CONFIG_SYSCTL
243 if (pn->ctl_table)230 if (pn->ctl_table)
@@ -257,7 +244,7 @@ static int udplite_kmemdup_sysctl_table(struct nf_proto_net *pn, · 13 unmodified lines
257 244
258static int udplite_init_net(struct net *net, u_int16_t proto)245static int udplite_init_net(struct net *net, u_int16_t proto)
259{246{
260 struct udplite_net *un = udplite_pernet(net);247 struct nf_udplite_net *un = udplite_pernet(net);
261 struct nf_proto_net *pn = &un->pn;248 struct nf_proto_net *pn = &un->pn;
262 249
263 if (!pn->users) {250 if (!pn->users) {
@@ -270,7 +257,7 @@ static int udplite_init_net(struct net *net, u_int16_t proto) · 6 unmodified lines
270 return udplite_kmemdup_sysctl_table(pn, un);257 return udplite_kmemdup_sysctl_table(pn, un);
271}258}
272 259
273static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly =260struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly =
274{261{
275 .l3proto = PF_INET,262 .l3proto = PF_INET,
276 .l4proto = IPPROTO_UDPLITE,263 .l4proto = IPPROTO_UDPLITE,
@@ -299,11 +286,11 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly = · 22 unmodified lines
299 .nla_policy = udplite_timeout_nla_policy,286 .nla_policy = udplite_timeout_nla_policy,
300 },287 },
301#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */288#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
302 .net_id = &udplite_net_id,
303 .init_net = udplite_init_net,289 .init_net = udplite_init_net,
304};290};
291EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udplite4);
305 292
306static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =293struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
307{294{
308 .l3proto = PF_INET6,295 .l3proto = PF_INET6,
309 .l4proto = IPPROTO_UDPLITE,296 .l4proto = IPPROTO_UDPLITE,
@@ -332,54 +319,6 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly = · 22 unmodified lines
332 .nla_policy = udplite_timeout_nla_policy,319 .nla_policy = udplite_timeout_nla_policy,
333 },320 },
334#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */321#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
335 .net_id = &udplite_net_id,
336 .init_net = udplite_init_net,322 .init_net = udplite_init_net,
337};323};
338 324EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udplite6);
339static struct nf_conntrack_l4proto *udplite_proto[] = {
340 &nf_conntrack_l4proto_udplite4,
341 &nf_conntrack_l4proto_udplite6,
342};
343
344static int udplite_net_init(struct net *net)
345{
346 return nf_ct_l4proto_pernet_register(net, udplite_proto,
347 ARRAY_SIZE(udplite_proto));
348}
349
350static void udplite_net_exit(struct net *net)
351{
352 nf_ct_l4proto_pernet_unregister(net, udplite_proto,
353 ARRAY_SIZE(udplite_proto));
354}
355
356static struct pernet_operations udplite_net_ops = {
357 .init = udplite_net_init,
358 .exit = udplite_net_exit,
359 .id = &udplite_net_id,
360 .size = sizeof(struct udplite_net),
361};
362
363static int __init nf_conntrack_proto_udplite_init(void)
364{
365 int ret;
366
367 ret = register_pernet_subsys(&udplite_net_ops);
368 if (ret < 0)
369 return ret;
370 ret = nf_ct_l4proto_register(udplite_proto, ARRAY_SIZE(udplite_proto));
371 if (ret < 0)
372 unregister_pernet_subsys(&udplite_net_ops);
373 return ret;
374}
375
376static void __exit nf_conntrack_proto_udplite_exit(void)
377{
378 nf_ct_l4proto_unregister(udplite_proto, ARRAY_SIZE(udplite_proto));
379 unregister_pernet_subsys(&udplite_net_ops);
380}
381
382module_init(nf_conntrack_proto_udplite_init);
383module_exit(nf_conntrack_proto_udplite_exit);
384
385MODULE_LICENSE("GPL");
net/netfilter/nf_conntrack_standalone.c+10−0
@@ -452,6 +452,9 @@ static int log_invalid_proto_max __read_mostly = 255; · 451 unmodified lines
452/* size the user *wants to set */452/* size the user *wants to set */
453static unsigned int nf_conntrack_htable_size_user __read_mostly;453static unsigned int nf_conntrack_htable_size_user __read_mostly;
454 454
455extern unsigned int nf_conntrack_default_on;
456unsigned int nf_conntrack_default_on __read_mostly = 1;
457
455static int458static int
456nf_conntrack_hash_sysctl(struct ctl_table *table, int write,459nf_conntrack_hash_sysctl(struct ctl_table *table, int write,
457 void __user *buffer, size_t *lenp, loff_t *ppos)460 void __user *buffer, size_t *lenp, loff_t *ppos)
@@ -517,6 +520,13 @@ static struct ctl_table nf_ct_sysctl_table[] = { · 59 unmodified lines
517 .mode = 0644,520 .mode = 0644,
518 .proc_handler = proc_dointvec,521 .proc_handler = proc_dointvec,
519 },522 },
523 {
524 .procname = "nf_conntrack_default_on",
525 .data = &nf_conntrack_default_on,
526 .maxlen = sizeof(unsigned int),
527 .mode = 0644,
528 .proc_handler = proc_dointvec,
529 },
520 { }530 { }
521};531};
522 532
net/netfilter/nf_dup_netdev.c+25−8
@@ -14,6 +14,29 @@ · 13 unmodified lines
14#include <linux/netfilter/nf_tables.h>14#include <linux/netfilter/nf_tables.h>
15#include <net/netfilter/nf_tables.h>15#include <net/netfilter/nf_tables.h>
16 16
17static 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
26void 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}
38EXPORT_SYMBOL_GPL(nf_fwd_netdev_egress);
39
17void nf_dup_netdev_egress(const struct nft_pktinfo *pkt, int oif)40void nf_dup_netdev_egress(const struct nft_pktinfo *pkt, int oif)
18{41{
19 struct net_device *dev;42 struct net_device *dev;
@@ -24,14 +47,8 @@ void nf_dup_netdev_egress(const struct nft_pktinfo *pkt, int oif) · 4 unmodified lines
24 return;47 return;
25 48
26 skb = skb_clone(pkt->skb, GFP_ATOMIC);49 skb = skb_clone(pkt->skb, GFP_ATOMIC);
27 if (skb == NULL)50 if (skb)
28 return;51 nf_do_netdev_egress(skb, dev);
29
30 if (skb_mac_header_was_set(skb))
31 skb_push(skb, skb->mac_len);
32
33 skb->dev = dev;
34 dev_queue_xmit(skb);
35}52}
36EXPORT_SYMBOL_GPL(nf_dup_netdev_egress);53EXPORT_SYMBOL_GPL(nf_dup_netdev_egress);
37 54
net/netfilter/nf_log_common.c+2−1
@@ -177,6 +177,7 @@ EXPORT_SYMBOL_GPL(nf_log_dump_packet_common); · 176 unmodified lines
177 177
178/* bridge and netdev logging families share this code. */178/* bridge and netdev logging families share this code. */
179void nf_log_l2packet(struct net *net, u_int8_t pf,179void nf_log_l2packet(struct net *net, u_int8_t pf,
180 __be16 protocol,
180 unsigned int hooknum,181 unsigned int hooknum,
181 const struct sk_buff *skb,182 const struct sk_buff *skb,
182 const struct net_device *in,183 const struct net_device *in,
@@ -184,7 +185,7 @@ void nf_log_l2packet(struct net *net, u_int8_t pf, · 1 unmodified line
184 const struct nf_loginfo *loginfo,185 const struct nf_loginfo *loginfo,
185 const char *prefix)186 const char *prefix)
186{187{
187 switch (eth_hdr(skb)->h_proto) {188 switch (protocol) {
188 case htons(ETH_P_IP):189 case htons(ETH_P_IP):
189 nf_log_packet(net, NFPROTO_IPV4, hooknum, skb, in, out,190 nf_log_packet(net, NFPROTO_IPV4, hooknum, skb, in, out,
190 loginfo, "%s", prefix);191 loginfo, "%s", prefix);
net/netfilter/nf_log_netdev.c+2−1
@@ -23,7 +23,8 @@ static void nf_log_netdev_packet(struct net *net, u_int8_t pf, · 22 unmodified lines
23 const struct nf_loginfo *loginfo,23 const struct nf_loginfo *loginfo,
24 const char *prefix)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
29static struct nf_logger nf_netdev_logger __read_mostly = {30static struct nf_logger nf_netdev_logger __read_mostly = {
net/netfilter/nf_nat_core.c+12−0
@@ -682,6 +682,18 @@ int nf_nat_l3proto_register(const struct nf_nat_l3proto *l3proto) · 681 unmodified lines
682 &nf_nat_l4proto_tcp);682 &nf_nat_l4proto_tcp);
683 RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_UDP],683 RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_UDP],
684 &nf_nat_l4proto_udp);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 mutex_unlock(&nf_nat_proto_mutex);697 mutex_unlock(&nf_nat_proto_mutex);
686 698
687 RCU_INIT_POINTER(nf_nat_l3protos[l3proto->l3proto], l3proto);699 RCU_INIT_POINTER(nf_nat_l3protos[l3proto->l3proto], l3proto);
net/netfilter/nf_nat_proto_dccp.c+1−35
@@ -10,8 +10,6 @@ · 9 unmodified lines
10 */10 */
11 11
12#include <linux/kernel.h>12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/skbuff.h>13#include <linux/skbuff.h>
16#include <linux/dccp.h>14#include <linux/dccp.h>
17 15
@@ -73,7 +71,7 @@ dccp_manip_pkt(struct sk_buff *skb, · 55 unmodified lines
73 return true;71 return true;
74}72}
75 73
76static const struct nf_nat_l4proto nf_nat_l4proto_dccp = {74const struct nf_nat_l4proto nf_nat_l4proto_dccp = {
77 .l4proto = IPPROTO_DCCP,75 .l4proto = IPPROTO_DCCP,
78 .manip_pkt = dccp_manip_pkt,76 .manip_pkt = dccp_manip_pkt,
79 .in_range = nf_nat_l4proto_in_range,77 .in_range = nf_nat_l4proto_in_range,
@@ -82,35 +80,3 @@ static const struct nf_nat_l4proto nf_nat_l4proto_dccp = { · 2 unmodified lines
82 .nlattr_to_range = nf_nat_l4proto_nlattr_to_range,80 .nlattr_to_range = nf_nat_l4proto_nlattr_to_range,
83#endif81#endif
84};82};
85
86static int __init nf_nat_proto_dccp_init(void)
87{
88 int err;
89
90 err = nf_nat_l4proto_register(NFPROTO_IPV4, &nf_nat_l4proto_dccp);
91 if (err < 0)
92 goto err1;
93 err = nf_nat_l4proto_register(NFPROTO_IPV6, &nf_nat_l4proto_dccp);
94 if (err < 0)
95 goto err2;
96 return 0;
97
98err2:
99 nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_dccp);
100err1:
101 return err;
102}
103
104static void __exit nf_nat_proto_dccp_fini(void)
105{
106 nf_nat_l4proto_unregister(NFPROTO_IPV6, &nf_nat_l4proto_dccp);
107 nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_dccp);
108
109}
110
111module_init(nf_nat_proto_dccp_init);
112module_exit(nf_nat_proto_dccp_fini);
113
114MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
115MODULE_DESCRIPTION("DCCP NAT protocol helper");
116MODULE_LICENSE("GPL");
net/netfilter/nf_nat_proto_sctp.c+5−35
@@ -7,9 +7,7 @@ · 6 unmodified lines
7 */7 */
8 8
9#include <linux/types.h>9#include <linux/types.h>
10#include <linux/init.h>
11#include <linux/sctp.h>10#include <linux/sctp.h>
12#include <linux/module.h>
13#include <net/sctp/checksum.h>11#include <net/sctp/checksum.h>
14 12
15#include <net/netfilter/nf_nat_l4proto.h>13#include <net/netfilter/nf_nat_l4proto.h>
@@ -49,12 +47,15 @@ sctp_manip_pkt(struct sk_buff *skb, · 33 unmodified lines
49 hdr->dest = tuple->dst.u.sctp.port;47 hdr->dest = tuple->dst.u.sctp.port;
50 }48 }
51 49
52 hdr->checksum = sctp_compute_cksum(skb, hdroff);50 if (skb->ip_summed != CHECKSUM_PARTIAL) {
51 hdr->checksum = sctp_compute_cksum(skb, hdroff);
52 skb->ip_summed = CHECKSUM_NONE;
53 }
53 54
54 return true;55 return true;
55}56}
56 57
57static const struct nf_nat_l4proto nf_nat_l4proto_sctp = {58const struct nf_nat_l4proto nf_nat_l4proto_sctp = {
58 .l4proto = IPPROTO_SCTP,59 .l4proto = IPPROTO_SCTP,
59 .manip_pkt = sctp_manip_pkt,60 .manip_pkt = sctp_manip_pkt,
60 .in_range = nf_nat_l4proto_in_range,61 .in_range = nf_nat_l4proto_in_range,
@@ -63,34 +64,3 @@ static const struct nf_nat_l4proto nf_nat_l4proto_sctp = { · 2 unmodified lines
63 .nlattr_to_range = nf_nat_l4proto_nlattr_to_range,64 .nlattr_to_range = nf_nat_l4proto_nlattr_to_range,
64#endif65#endif
65};66};
66
67static int __init nf_nat_proto_sctp_init(void)
68{
69 int err;
70
71 err = nf_nat_l4proto_register(NFPROTO_IPV4, &nf_nat_l4proto_sctp);
72 if (err < 0)
73 goto err1;
74 err = nf_nat_l4proto_register(NFPROTO_IPV6, &nf_nat_l4proto_sctp);
75 if (err < 0)
76 goto err2;
77 return 0;
78
79err2:
80 nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_sctp);
81err1:
82 return err;
83}
84
85static void __exit nf_nat_proto_sctp_exit(void)
86{
87 nf_nat_l4proto_unregister(NFPROTO_IPV6, &nf_nat_l4proto_sctp);
88 nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_sctp);
89}
90
91module_init(nf_nat_proto_sctp_init);
92module_exit(nf_nat_proto_sctp_exit);
93
94MODULE_LICENSE("GPL");
95MODULE_DESCRIPTION("SCTP NAT protocol helper");
96MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
net/netfilter/nf_nat_proto_udplite.c+1−34
@@ -8,11 +8,9 @@ · 7 unmodified lines
8 */8 */
9 9
10#include <linux/types.h>10#include <linux/types.h>
11#include <linux/init.h>
12#include <linux/udp.h>11#include <linux/udp.h>
13 12
14#include <linux/netfilter.h>13#include <linux/netfilter.h>
15#include <linux/module.h>
16#include <net/netfilter/nf_nat.h>14#include <net/netfilter/nf_nat.h>
17#include <net/netfilter/nf_nat_l3proto.h>15#include <net/netfilter/nf_nat_l3proto.h>
18#include <net/netfilter/nf_nat_l4proto.h>16#include <net/netfilter/nf_nat_l4proto.h>
@@ -64,7 +62,7 @@ udplite_manip_pkt(struct sk_buff *skb, · 45 unmodified lines
64 return true;62 return true;
65}63}
66 64
67static const struct nf_nat_l4proto nf_nat_l4proto_udplite = {65const struct nf_nat_l4proto nf_nat_l4proto_udplite = {
68 .l4proto = IPPROTO_UDPLITE,66 .l4proto = IPPROTO_UDPLITE,
69 .manip_pkt = udplite_manip_pkt,67 .manip_pkt = udplite_manip_pkt,
70 .in_range = nf_nat_l4proto_in_range,68 .in_range = nf_nat_l4proto_in_range,
@@ -73,34 +71,3 @@ static const struct nf_nat_l4proto nf_nat_l4proto_udplite = { · 2 unmodified lines
73 .nlattr_to_range = nf_nat_l4proto_nlattr_to_range,71 .nlattr_to_range = nf_nat_l4proto_nlattr_to_range,
74#endif72#endif
75};73};
76
77static int __init nf_nat_proto_udplite_init(void)
78{
79 int err;
80
81 err = nf_nat_l4proto_register(NFPROTO_IPV4, &nf_nat_l4proto_udplite);
82 if (err < 0)
83 goto err1;
84 err = nf_nat_l4proto_register(NFPROTO_IPV6, &nf_nat_l4proto_udplite);
85 if (err < 0)
86 goto err2;
87 return 0;
88
89err2:
90 nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_udplite);
91err1:
92 return err;
93}
94
95static void __exit nf_nat_proto_udplite_fini(void)
96{
97 nf_nat_l4proto_unregister(NFPROTO_IPV6, &nf_nat_l4proto_udplite);
98 nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_udplite);
99}
100
101module_init(nf_nat_proto_udplite_init);
102module_exit(nf_nat_proto_udplite_fini);
103
104MODULE_LICENSE("GPL");
105MODULE_DESCRIPTION("UDP-Lite NAT protocol helper");
106MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
net/netfilter/nf_queue.c+2−3
@@ -185,7 +185,7 @@ static unsigned int nf_iterate(struct sk_buff *skb, · 184 unmodified lines
185 185
186 do {186 do {
187repeat:187repeat:
188 verdict = (*entryp)->ops.hook((*entryp)->ops.priv, skb, state);188 verdict = nf_hook_entry_hookfn((*entryp), skb, state);
189 if (verdict != NF_ACCEPT) {189 if (verdict != NF_ACCEPT) {
190 if (verdict != NF_REPEAT)190 if (verdict != NF_REPEAT)
191 return verdict;191 return verdict;
@@ -200,7 +200,6 @@ repeat: · 8 unmodified lines
200void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)200void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
201{201{
202 struct nf_hook_entry *hook_entry = entry->hook;202 struct nf_hook_entry *hook_entry = entry->hook;
203 struct nf_hook_ops *elem = &hook_entry->ops;
204 struct sk_buff *skb = entry->skb;203 struct sk_buff *skb = entry->skb;
205 const struct nf_afinfo *afinfo;204 const struct nf_afinfo *afinfo;
206 int err;205 int err;
@@ -209,7 +208,7 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) · 2 unmodified lines
209 208
210 /* Continue traversal iff userspace said ok... */209 /* Continue traversal iff userspace said ok... */
211 if (verdict == NF_REPEAT)210 if (verdict == NF_REPEAT)
212 verdict = elem->hook(elem->priv, skb, &entry->state);211 verdict = nf_hook_entry_hookfn(hook_entry, skb, &entry->state);
213 212
214 if (verdict == NF_ACCEPT) {213 if (verdict == NF_ACCEPT) {
215 afinfo = nf_get_afinfo(entry->state.pf);214 afinfo = nf_get_afinfo(entry->state.pf);
net/netfilter/nf_tables_api.c+702−16
@@ -22,6 +22,7 @@ · 21 unmodified lines
22#include <net/sock.h>22#include <net/sock.h>
23 23
24static LIST_HEAD(nf_tables_expressions);24static LIST_HEAD(nf_tables_expressions);
25static LIST_HEAD(nf_tables_objects);
25 26
26/**27/**
27 * nft_register_afinfo - register nf_tables address family info28 * nft_register_afinfo - register nf_tables address family info
@@ -110,12 +111,12 @@ static void nft_ctx_init(struct nft_ctx *ctx, · 82 unmodified lines
110 ctx->seq = nlh->nlmsg_seq;111 ctx->seq = nlh->nlmsg_seq;
111}112}
112 113
113static struct nft_trans *nft_trans_alloc(struct nft_ctx *ctx, int msg_type,114static struct nft_trans *nft_trans_alloc_gfp(const struct nft_ctx *ctx,
114 u32 size)115 int msg_type, u32 size, gfp_t gfp)
115{116{
116 struct nft_trans *trans;117 struct nft_trans *trans;
117 118
118 trans = kzalloc(sizeof(struct nft_trans) + size, GFP_KERNEL);119 trans = kzalloc(sizeof(struct nft_trans) + size, gfp);
119 if (trans == NULL)120 if (trans == NULL)
120 return NULL;121 return NULL;
121 122
@@ -125,6 +126,12 @@ static struct nft_trans *nft_trans_alloc(struct nft_ctx *ctx, int msg_type, · 3 unmodified lines
125 return trans;126 return trans;
126}127}
127 128
129static struct nft_trans *nft_trans_alloc(const struct nft_ctx *ctx,
130 int msg_type, u32 size)
131{
132 return nft_trans_alloc_gfp(ctx, msg_type, size, GFP_KERNEL);
133}
134
128static void nft_trans_destroy(struct nft_trans *trans)135static void nft_trans_destroy(struct nft_trans *trans)
129{136{
130 list_del(&trans->list);137 list_del(&trans->list);
@@ -304,6 +311,38 @@ static int nft_delset(struct nft_ctx *ctx, struct nft_set *set) · 173 unmodified lines
304 return err;311 return err;
305}312}
306 313
314static int nft_trans_obj_add(struct nft_ctx *ctx, int msg_type,
315 struct nft_object *obj)
316{
317 struct nft_trans *trans;
318
319 trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_obj));
320 if (trans == NULL)
321 return -ENOMEM;
322
323 if (msg_type == NFT_MSG_NEWOBJ)
324 nft_activate_next(ctx->net, obj);
325
326 nft_trans_obj(trans) = obj;
327 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
328
329 return 0;
330}
331
332static int nft_delobj(struct nft_ctx *ctx, struct nft_object *obj)
333{
334 int err;
335
336 err = nft_trans_obj_add(ctx, NFT_MSG_DELOBJ, obj);
337 if (err < 0)
338 return err;
339
340 nft_deactivate_next(ctx->net, obj);
341 ctx->table->use--;
342
343 return err;
344}
345
307/*346/*
308 * Tables347 * Tables
309 */348 */
@@ -688,6 +727,7 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk, · 378 unmodified lines
688 nla_strlcpy(table->name, name, NFT_TABLE_MAXNAMELEN);727 nla_strlcpy(table->name, name, NFT_TABLE_MAXNAMELEN);
689 INIT_LIST_HEAD(&table->chains);728 INIT_LIST_HEAD(&table->chains);
690 INIT_LIST_HEAD(&table->sets);729 INIT_LIST_HEAD(&table->sets);
730 INIT_LIST_HEAD(&table->objects);
691 table->flags = flags;731 table->flags = flags;
692 732
693 nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);733 nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
@@ -709,6 +749,7 @@ static int nft_flush_table(struct nft_ctx *ctx) · 15 unmodified lines
709{749{
710 int err;750 int err;
711 struct nft_chain *chain, *nc;751 struct nft_chain *chain, *nc;
752 struct nft_object *obj, *ne;
712 struct nft_set *set, *ns;753 struct nft_set *set, *ns;
713 754
714 list_for_each_entry(chain, &ctx->table->chains, list) {755 list_for_each_entry(chain, &ctx->table->chains, list) {
@@ -735,6 +776,12 @@ static int nft_flush_table(struct nft_ctx *ctx) · 20 unmodified lines
735 goto out;776 goto out;
736 }777 }
737 778
779 list_for_each_entry_safe(obj, ne, &ctx->table->objects, list) {
780 err = nft_delobj(ctx, obj);
781 if (err < 0)
782 goto out;
783 }
784
738 list_for_each_entry_safe(chain, nc, &ctx->table->chains, list) {785 list_for_each_entry_safe(chain, nc, &ctx->table->chains, list) {
739 if (!nft_is_active_next(ctx->net, chain))786 if (!nft_is_active_next(ctx->net, chain))
740 continue;787 continue;
@@ -2411,6 +2458,7 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = { · 1670 unmodified lines
2411 [NFTA_SET_GC_INTERVAL] = { .type = NLA_U32 },2458 [NFTA_SET_GC_INTERVAL] = { .type = NLA_U32 },
2412 [NFTA_SET_USERDATA] = { .type = NLA_BINARY,2459 [NFTA_SET_USERDATA] = { .type = NLA_BINARY,
2413 .len = NFT_USERDATA_MAXLEN },2460 .len = NFT_USERDATA_MAXLEN },
2461 [NFTA_SET_OBJ_TYPE] = { .type = NLA_U32 },
2414};2462};
2415 2463
2416static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = {2464static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = {
@@ -2462,6 +2510,7 @@ struct nft_set *nf_tables_set_lookup(const struct nft_table *table, · 45 unmodified lines
2462 }2510 }
2463 return ERR_PTR(-ENOENT);2511 return ERR_PTR(-ENOENT);
2464}2512}
2513EXPORT_SYMBOL_GPL(nf_tables_set_lookup);
2465 2514
2466struct nft_set *nf_tables_set_lookup_byid(const struct net *net,2515struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
2467 const struct nlattr *nla,2516 const struct nlattr *nla,
@@ -2480,6 +2529,7 @@ struct nft_set *nf_tables_set_lookup_byid(const struct net *net, · 12 unmodified lines
2480 }2529 }
2481 return ERR_PTR(-ENOENT);2530 return ERR_PTR(-ENOENT);
2482}2531}
2532EXPORT_SYMBOL_GPL(nf_tables_set_lookup_byid);
2483 2533
2484static int nf_tables_set_alloc_name(struct nft_ctx *ctx, struct nft_set *set,2534static int nf_tables_set_alloc_name(struct nft_ctx *ctx, struct nft_set *set,
2485 const char *name)2535 const char *name)
@@ -2568,6 +2618,9 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx, · 82 unmodified lines
2568 if (nla_put_be32(skb, NFTA_SET_DATA_LEN, htonl(set->dlen)))2618 if (nla_put_be32(skb, NFTA_SET_DATA_LEN, htonl(set->dlen)))
2569 goto nla_put_failure;2619 goto nla_put_failure;
2570 }2620 }
2621 if (set->flags & NFT_SET_OBJECT &&
2622 nla_put_be32(skb, NFTA_SET_OBJ_TYPE, htonl(set->objtype)))
2623 goto nla_put_failure;
2571 2624
2572 if (set->timeout &&2625 if (set->timeout &&
2573 nla_put_be64(skb, NFTA_SET_TIMEOUT,2626 nla_put_be64(skb, NFTA_SET_TIMEOUT,
@@ -2797,7 +2850,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk, · 223 unmodified lines
2797 unsigned int size;2850 unsigned int size;
2798 bool create;2851 bool create;
2799 u64 timeout;2852 u64 timeout;
2800 u32 ktype, dtype, flags, policy, gc_int;2853 u32 ktype, dtype, flags, policy, gc_int, objtype;
2801 struct nft_set_desc desc;2854 struct nft_set_desc desc;
2802 unsigned char *udata;2855 unsigned char *udata;
2803 u16 udlen;2856 u16 udlen;
@@ -2827,11 +2880,12 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk, · 23 unmodified lines
2827 flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS]));2880 flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS]));
2828 if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT |2881 if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT |
2829 NFT_SET_INTERVAL | NFT_SET_TIMEOUT |2882 NFT_SET_INTERVAL | NFT_SET_TIMEOUT |
2830 NFT_SET_MAP | NFT_SET_EVAL))2883 NFT_SET_MAP | NFT_SET_EVAL |
2884 NFT_SET_OBJECT))
2831 return -EINVAL;2885 return -EINVAL;
2832 /* Only one of both operations is supported */2886 /* Only one of these operations is supported */
2833 if ((flags & (NFT_SET_MAP | NFT_SET_EVAL)) ==2887 if ((flags & (NFT_SET_MAP | NFT_SET_EVAL | NFT_SET_OBJECT)) ==
2834 (NFT_SET_MAP | NFT_SET_EVAL))2888 (NFT_SET_MAP | NFT_SET_EVAL | NFT_SET_OBJECT))
2835 return -EOPNOTSUPP;2889 return -EOPNOTSUPP;
2836 }2890 }
2837 2891
@@ -2856,6 +2910,19 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk, · 18 unmodified lines
2856 } else if (flags & NFT_SET_MAP)2910 } else if (flags & NFT_SET_MAP)
2857 return -EINVAL;2911 return -EINVAL;
2858 2912
2913 if (nla[NFTA_SET_OBJ_TYPE] != NULL) {
2914 if (!(flags & NFT_SET_OBJECT))
2915 return -EINVAL;
2916
2917 objtype = ntohl(nla_get_be32(nla[NFTA_SET_OBJ_TYPE]));
2918 if (objtype == NFT_OBJECT_UNSPEC ||
2919 objtype > NFT_OBJECT_MAX)
2920 return -EINVAL;
2921 } else if (flags & NFT_SET_OBJECT)
2922 return -EINVAL;
2923 else
2924 objtype = NFT_OBJECT_UNSPEC;
2925
2859 timeout = 0;2926 timeout = 0;
2860 if (nla[NFTA_SET_TIMEOUT] != NULL) {2927 if (nla[NFTA_SET_TIMEOUT] != NULL) {
2861 if (!(flags & NFT_SET_TIMEOUT))2928 if (!(flags & NFT_SET_TIMEOUT))
@@ -2943,6 +3010,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk, · 81 unmodified lines
2943 set->ktype = ktype;3010 set->ktype = ktype;
2944 set->klen = desc.klen;3011 set->klen = desc.klen;
2945 set->dtype = dtype;3012 set->dtype = dtype;
3013 set->objtype = objtype;
2946 set->dlen = desc.dlen;3014 set->dlen = desc.dlen;
2947 set->flags = flags;3015 set->flags = flags;
2948 set->size = desc.size;3016 set->size = desc.size;
@@ -3064,6 +3132,7 @@ bind: · 115 unmodified lines
3064 list_add_tail_rcu(&binding->list, &set->bindings);3132 list_add_tail_rcu(&binding->list, &set->bindings);
3065 return 0;3133 return 0;
3066}3134}
3135EXPORT_SYMBOL_GPL(nf_tables_bind_set);
3067 3136
3068void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,3137void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
3069 struct nft_set_binding *binding)3138 struct nft_set_binding *binding)
@@ -3074,6 +3143,7 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set, · 4 unmodified lines
3074 nft_is_active(ctx->net, set))3143 nft_is_active(ctx->net, set))
3075 nf_tables_set_destroy(ctx, set);3144 nf_tables_set_destroy(ctx, set);
3076}3145}
3146EXPORT_SYMBOL_GPL(nf_tables_unbind_set);
3077 3147
3078const struct nft_set_ext_type nft_set_ext_types[] = {3148const struct nft_set_ext_type nft_set_ext_types[] = {
3079 [NFT_SET_EXT_KEY] = {3149 [NFT_SET_EXT_KEY] = {
@@ -3085,6 +3155,10 @@ const struct nft_set_ext_type nft_set_ext_types[] = { · 5 unmodified lines
3085 [NFT_SET_EXT_EXPR] = {3155 [NFT_SET_EXT_EXPR] = {
3086 .align = __alignof__(struct nft_expr),3156 .align = __alignof__(struct nft_expr),
3087 },3157 },
3158 [NFT_SET_EXT_OBJREF] = {
3159 .len = sizeof(struct nft_object *),
3160 .align = __alignof__(struct nft_object *),
3161 },
3088 [NFT_SET_EXT_FLAGS] = {3162 [NFT_SET_EXT_FLAGS] = {
3089 .len = sizeof(u8),3163 .len = sizeof(u8),
3090 .align = __alignof__(u8),3164 .align = __alignof__(u8),
@@ -3173,6 +3247,11 @@ static int nf_tables_fill_setelem(struct sk_buff *skb, · 82 unmodified lines
3173 nft_expr_dump(skb, NFTA_SET_ELEM_EXPR, nft_set_ext_expr(ext)) < 0)3247 nft_expr_dump(skb, NFTA_SET_ELEM_EXPR, nft_set_ext_expr(ext)) < 0)
3174 goto nla_put_failure;3248 goto nla_put_failure;
3175 3249
3250 if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) &&
3251 nla_put_string(skb, NFTA_SET_ELEM_OBJREF,
3252 (*nft_set_ext_obj(ext))->name) < 0)
3253 goto nla_put_failure;
3254
3176 if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) &&3255 if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) &&
3177 nla_put_be32(skb, NFTA_SET_ELEM_FLAGS,3256 nla_put_be32(skb, NFTA_SET_ELEM_FLAGS,
3178 htonl(*nft_set_ext_flags(ext))))3257 htonl(*nft_set_ext_flags(ext))))
@@ -3467,7 +3546,8 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem, · 288 unmodified lines
3467 nft_data_uninit(nft_set_ext_data(ext), set->dtype);3546 nft_data_uninit(nft_set_ext_data(ext), set->dtype);
3468 if (destroy_expr && nft_set_ext_exists(ext, NFT_SET_EXT_EXPR))3547 if (destroy_expr && nft_set_ext_exists(ext, NFT_SET_EXT_EXPR))
3469 nf_tables_expr_destroy(NULL, nft_set_ext_expr(ext));3548 nf_tables_expr_destroy(NULL, nft_set_ext_expr(ext));
3470 3549 if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
3550 (*nft_set_ext_obj(ext))->use--;
3471 kfree(elem);3551 kfree(elem);
3472}3552}
3473EXPORT_SYMBOL_GPL(nft_set_elem_destroy);3553EXPORT_SYMBOL_GPL(nft_set_elem_destroy);
@@ -3492,11 +3572,13 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, · 18 unmodified lines
3492 const struct nlattr *attr, u32 nlmsg_flags)3572 const struct nlattr *attr, u32 nlmsg_flags)
3493{3573{
3494 struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];3574 struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
3575 u8 genmask = nft_genmask_next(ctx->net);
3495 struct nft_data_desc d1, d2;3576 struct nft_data_desc d1, d2;
3496 struct nft_set_ext_tmpl tmpl;3577 struct nft_set_ext_tmpl tmpl;
3497 struct nft_set_ext *ext, *ext2;3578 struct nft_set_ext *ext, *ext2;
3498 struct nft_set_elem elem;3579 struct nft_set_elem elem;
3499 struct nft_set_binding *binding;3580 struct nft_set_binding *binding;
3581 struct nft_object *obj = NULL;
3500 struct nft_userdata *udata;3582 struct nft_userdata *udata;
3501 struct nft_data data;3583 struct nft_data data;
3502 enum nft_registers dreg;3584 enum nft_registers dreg;
@@ -3559,6 +3641,20 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, · 56 unmodified lines
3559 nft_set_ext_add(&tmpl, NFT_SET_EXT_TIMEOUT);3641 nft_set_ext_add(&tmpl, NFT_SET_EXT_TIMEOUT);
3560 }3642 }
3561 3643
3644 if (nla[NFTA_SET_ELEM_OBJREF] != NULL) {
3645 if (!(set->flags & NFT_SET_OBJECT)) {
3646 err = -EINVAL;
3647 goto err2;
3648 }
3649 obj = nf_tables_obj_lookup(ctx->table, nla[NFTA_SET_ELEM_OBJREF],
3650 set->objtype, genmask);
3651 if (IS_ERR(obj)) {
3652 err = PTR_ERR(obj);
3653 goto err2;
3654 }
3655 nft_set_ext_add(&tmpl, NFT_SET_EXT_OBJREF);
3656 }
3657
3562 if (nla[NFTA_SET_ELEM_DATA] != NULL) {3658 if (nla[NFTA_SET_ELEM_DATA] != NULL) {
3563 err = nft_data_init(ctx, &data, sizeof(data), &d2,3659 err = nft_data_init(ctx, &data, sizeof(data), &d2,
3564 nla[NFTA_SET_ELEM_DATA]);3660 nla[NFTA_SET_ELEM_DATA]);
@@ -3617,6 +3713,10 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, · 52 unmodified lines
3617 udata->len = ulen - 1;3713 udata->len = ulen - 1;
3618 nla_memcpy(&udata->data, nla[NFTA_SET_ELEM_USERDATA], ulen);3714 nla_memcpy(&udata->data, nla[NFTA_SET_ELEM_USERDATA], ulen);
3619 }3715 }
3716 if (obj) {
3717 *nft_set_ext_obj(ext) = obj;
3718 obj->use++;
3719 }
3620 3720
3621 trans = nft_trans_elem_alloc(ctx, NFT_MSG_NEWSETELEM, set);3721 trans = nft_trans_elem_alloc(ctx, NFT_MSG_NEWSETELEM, set);
3622 if (trans == NULL)3722 if (trans == NULL)
@@ -3626,10 +3726,13 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, · 3 unmodified lines
3626 err = set->ops->insert(ctx->net, set, &elem, &ext2);3726 err = set->ops->insert(ctx->net, set, &elem, &ext2);
3627 if (err) {3727 if (err) {
3628 if (err == -EEXIST) {3728 if (err == -EEXIST) {
3629 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA) &&3729 if ((nft_set_ext_exists(ext, NFT_SET_EXT_DATA) &&
3630 nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) &&3730 nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) &&
3631 memcmp(nft_set_ext_data(ext),3731 memcmp(nft_set_ext_data(ext),
3632 nft_set_ext_data(ext2), set->dlen) != 0)3732 nft_set_ext_data(ext2), set->dlen) != 0) ||
3733 (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) &&
3734 nft_set_ext_exists(ext2, NFT_SET_EXT_OBJREF) &&
3735 *nft_set_ext_obj(ext) != *nft_set_ext_obj(ext2)))
3633 err = -EBUSY;3736 err = -EBUSY;
3634 else if (!(nlmsg_flags & NLM_F_EXCL))3737 else if (!(nlmsg_flags & NLM_F_EXCL))
3635 err = 0;3738 err = 0;
@@ -3779,6 +3882,34 @@ err1: · 143 unmodified lines
3779 return err;3882 return err;
3780}3883}
3781 3884
3885static int nft_flush_set(const struct nft_ctx *ctx,
3886 const struct nft_set *set,
3887 const struct nft_set_iter *iter,
3888 const struct nft_set_elem *elem)
3889{
3890 struct nft_trans *trans;
3891 int err;
3892
3893 trans = nft_trans_alloc_gfp(ctx, NFT_MSG_DELSETELEM,
3894 sizeof(struct nft_trans_elem), GFP_ATOMIC);
3895 if (!trans)
3896 return -ENOMEM;
3897
3898 if (!set->ops->deactivate_one(ctx->net, set, elem->priv)) {
3899 err = -ENOENT;
3900 goto err1;
3901 }
3902
3903 nft_trans_elem_set(trans) = (struct nft_set *)set;
3904 nft_trans_elem(trans) = *((struct nft_set_elem *)elem);
3905 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
3906
3907 return 0;
3908err1:
3909 kfree(trans);
3910 return err;
3911}
3912
3782static int nf_tables_delsetelem(struct net *net, struct sock *nlsk,3913static int nf_tables_delsetelem(struct net *net, struct sock *nlsk,
3783 struct sk_buff *skb, const struct nlmsghdr *nlh,3914 struct sk_buff *skb, const struct nlmsghdr *nlh,
3784 const struct nlattr * const nla[])3915 const struct nlattr * const nla[])
@@ -3789,9 +3920,6 @@ static int nf_tables_delsetelem(struct net *net, struct sock *nlsk, · 4 unmodified lines
3789 struct nft_ctx ctx;3920 struct nft_ctx ctx;
3790 int rem, err = 0;3921 int rem, err = 0;
3791 3922
3792 if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL)
3793 return -EINVAL;
3794
3795 err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, genmask);3923 err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, genmask);
3796 if (err < 0)3924 if (err < 0)
3797 return err;3925 return err;
@@ -3803,6 +3931,18 @@ static int nf_tables_delsetelem(struct net *net, struct sock *nlsk, · 5 unmodified lines
3803 if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)3931 if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
3804 return -EBUSY;3932 return -EBUSY;
3805 3933
3934 if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL) {
3935 struct nft_set_dump_args args = {
3936 .iter = {
3937 .genmask = genmask,
3938 .fn = nft_flush_set,
3939 },
3940 };
3941 set->ops->walk(&ctx, set, &args.iter);
3942
3943 return args.iter.err;
3944 }
3945
3806 nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {3946 nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
3807 err = nft_del_setelem(&ctx, set, attr);3947 err = nft_del_setelem(&ctx, set, attr);
3808 if (err < 0)3948 if (err < 0)
@@ -3838,6 +3978,500 @@ struct nft_set_gc_batch *nft_set_gc_batch_alloc(const struct nft_set *set, · 29 unmodified lines
3838}3978}
3839EXPORT_SYMBOL_GPL(nft_set_gc_batch_alloc);3979EXPORT_SYMBOL_GPL(nft_set_gc_batch_alloc);
3840 3980
3981/*
3982 * Stateful objects
3983 */
3984
3985/**
3986 * nft_register_obj- register nf_tables stateful object type
3987 * @obj: object type
3988 *
3989 * Registers the object type for use with nf_tables. Returns zero on
3990 * success or a negative errno code otherwise.
3991 */
3992int nft_register_obj(struct nft_object_type *obj_type)
3993{
3994 if (obj_type->type == NFT_OBJECT_UNSPEC)
3995 return -EINVAL;
3996
3997 nfnl_lock(NFNL_SUBSYS_NFTABLES);
3998 list_add_rcu(&obj_type->list, &nf_tables_objects);
3999 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
4000 return 0;
4001}
4002EXPORT_SYMBOL_GPL(nft_register_obj);
4003
4004/**
4005 * nft_unregister_obj - unregister nf_tables object type
4006 * @obj: object type
4007 *
4008 * Unregisters the object type for use with nf_tables.
4009 */
4010void nft_unregister_obj(struct nft_object_type *obj_type)
4011{
4012 nfnl_lock(NFNL_SUBSYS_NFTABLES);
4013 list_del_rcu(&obj_type->list);
4014 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
4015}
4016EXPORT_SYMBOL_GPL(nft_unregister_obj);
4017
4018struct nft_object *nf_tables_obj_lookup(const struct nft_table *table,
4019 const struct nlattr *nla,
4020 u32 objtype, u8 genmask)
4021{
4022 struct nft_object *obj;
4023
4024 list_for_each_entry(obj, &table->objects, list) {
4025 if (!nla_strcmp(nla, obj->name) &&
4026 objtype == obj->type->type &&
4027 nft_active_genmask(obj, genmask))
4028 return obj;
4029 }
4030 return ERR_PTR(-ENOENT);
4031}
4032EXPORT_SYMBOL_GPL(nf_tables_obj_lookup);
4033
4034static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = {
4035 [NFTA_OBJ_TABLE] = { .type = NLA_STRING },
4036 [NFTA_OBJ_NAME] = { .type = NLA_STRING },
4037 [NFTA_OBJ_TYPE] = { .type = NLA_U32 },
4038 [NFTA_OBJ_DATA] = { .type = NLA_NESTED },
4039};
4040
4041static struct nft_object *nft_obj_init(const struct nft_object_type *type,
4042 const struct nlattr *attr)
4043{
4044 struct nlattr *tb[type->maxattr + 1];
4045 struct nft_object *obj;
4046 int err;
4047
4048 if (attr) {
4049 err = nla_parse_nested(tb, type->maxattr, attr, type->policy);
4050 if (err < 0)
4051 goto err1;
4052 } else {
4053 memset(tb, 0, sizeof(tb[0]) * (type->maxattr + 1));
4054 }
4055
4056 err = -ENOMEM;
4057 obj = kzalloc(sizeof(struct nft_object) + type->size, GFP_KERNEL);
4058 if (obj == NULL)
4059 goto err1;
4060
4061 err = type->init((const struct nlattr * const *)tb, obj);
4062 if (err < 0)
4063 goto err2;
4064
4065 obj->type = type;
4066 return obj;
4067err2:
4068 kfree(obj);
4069err1:
4070 return ERR_PTR(err);
4071}
4072
4073static int nft_object_dump(struct sk_buff *skb, unsigned int attr,
4074 struct nft_object *obj, bool reset)
4075{
4076 struct nlattr *nest;
4077
4078 nest = nla_nest_start(skb, attr);
4079 if (!nest)
4080 goto nla_put_failure;
4081 if (obj->type->dump(skb, obj, reset) < 0)
4082 goto nla_put_failure;
4083 nla_nest_end(skb, nest);
4084 return 0;
4085
4086nla_put_failure:
4087 return -1;
4088}
4089
4090static const struct nft_object_type *__nft_obj_type_get(u32 objtype)
4091{
4092 const struct nft_object_type *type;
4093
4094 list_for_each_entry(type, &nf_tables_objects, list) {
4095 if (objtype == type->type)
4096 return type;
4097 }
4098 return NULL;
4099}
4100
4101static const struct nft_object_type *nft_obj_type_get(u32 objtype)
4102{
4103 const struct nft_object_type *type;
4104
4105 type = __nft_obj_type_get(objtype);
4106 if (type != NULL && try_module_get(type->owner))
4107 return type;
4108
4109#ifdef CONFIG_MODULES
4110 if (type == NULL) {
4111 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
4112 request_module("nft-obj-%u", objtype);
4113 nfnl_lock(NFNL_SUBSYS_NFTABLES);
4114 if (__nft_obj_type_get(objtype))
4115 return ERR_PTR(-EAGAIN);
4116 }
4117#endif
4118 return ERR_PTR(-ENOENT);
4119}
4120
4121static int nf_tables_newobj(struct net *net, struct sock *nlsk,
4122 struct sk_buff *skb, const struct nlmsghdr *nlh,
4123 const struct nlattr * const nla[])
4124{
4125 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
4126 const struct nft_object_type *type;
4127 u8 genmask = nft_genmask_next(net);
4128 int family = nfmsg->nfgen_family;
4129 struct nft_af_info *afi;
4130 struct nft_table *table;
4131 struct nft_object *obj;
4132 struct nft_ctx ctx;
4133 u32 objtype;
4134 int err;
4135
4136 if (!nla[NFTA_OBJ_TYPE] ||
4137 !nla[NFTA_OBJ_NAME] ||
4138 !nla[NFTA_OBJ_DATA])
4139 return -EINVAL;
4140
4141 afi = nf_tables_afinfo_lookup(net, family, true);
4142 if (IS_ERR(afi))
4143 return PTR_ERR(afi);
4144
4145 table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask);
4146 if (IS_ERR(table))
4147 return PTR_ERR(table);
4148
4149 objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
4150 obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask);
4151 if (IS_ERR(obj)) {
4152 err = PTR_ERR(obj);
4153 if (err != -ENOENT)
4154 return err;
4155
4156 obj = NULL;
4157 }
4158
4159 if (obj != NULL) {
4160 if (nlh->nlmsg_flags & NLM_F_EXCL)
4161 return -EEXIST;
4162
4163 return 0;
4164 }
4165
4166 nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
4167
4168 type = nft_obj_type_get(objtype);
4169 if (IS_ERR(type))
4170 return PTR_ERR(type);
4171
4172 obj = nft_obj_init(type, nla[NFTA_OBJ_DATA]);
4173 if (IS_ERR(obj)) {
4174 err = PTR_ERR(obj);
4175 goto err1;
4176 }
4177 obj->table = table;
4178 nla_strlcpy(obj->name, nla[NFTA_OBJ_NAME], NFT_OBJ_MAXNAMELEN);
4179
4180 err = nft_trans_obj_add(&ctx, NFT_MSG_NEWOBJ, obj);
4181 if (err < 0)
4182 goto err2;
4183
4184 list_add_tail_rcu(&obj->list, &table->objects);
4185 table->use++;
4186 return 0;
4187err2:
4188 if (obj->type->destroy)
4189 obj->type->destroy(obj);
4190 kfree(obj);
4191err1:
4192 module_put(type->owner);
4193 return err;
4194}
4195
4196static int nf_tables_fill_obj_info(struct sk_buff *skb, struct net *net,
4197 u32 portid, u32 seq, int event, u32 flags,
4198 int family, const struct nft_table *table,
4199 struct nft_object *obj, bool reset)
4200{
4201 struct nfgenmsg *nfmsg;
4202 struct nlmsghdr *nlh;
4203
4204 event |= NFNL_SUBSYS_NFTABLES << 8;
4205 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), flags);
4206 if (nlh == NULL)
4207 goto nla_put_failure;
4208
4209 nfmsg = nlmsg_data(nlh);
4210 nfmsg->nfgen_family = family;
4211 nfmsg->version = NFNETLINK_V0;
4212 nfmsg->res_id = htons(net->nft.base_seq & 0xffff);
4213
4214 if (nla_put_string(skb, NFTA_OBJ_TABLE, table->name) ||
4215 nla_put_string(skb, NFTA_OBJ_NAME, obj->name) ||
4216 nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->type->type)) ||
4217 nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) ||
4218 nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset))
4219 goto nla_put_failure;
4220
4221 nlmsg_end(skb, nlh);
4222 return 0;
4223
4224nla_put_failure:
4225 nlmsg_trim(skb, nlh);
4226 return -1;
4227}
4228
4229struct nft_obj_filter {
4230 char table[NFT_OBJ_MAXNAMELEN];
4231 u32 type;
4232};
4233
4234static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
4235{
4236 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
4237 const struct nft_af_info *afi;
4238 const struct nft_table *table;
4239 unsigned int idx = 0, s_idx = cb->args[0];
4240 struct nft_obj_filter *filter = cb->data;
4241 struct net *net = sock_net(skb->sk);
4242 int family = nfmsg->nfgen_family;
4243 struct nft_object *obj;
4244 bool reset = false;
4245
4246 if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
4247 reset = true;
4248
4249 rcu_read_lock();
4250 cb->seq = net->nft.base_seq;
4251
4252 list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
4253 if (family != NFPROTO_UNSPEC && family != afi->family)
4254 continue;
4255
4256 list_for_each_entry_rcu(table, &afi->tables, list) {
4257 list_for_each_entry_rcu(obj, &table->objects, list) {
4258 if (!nft_is_active(net, obj))
4259 goto cont;
4260 if (idx < s_idx)
4261 goto cont;
4262 if (idx > s_idx)
4263 memset(&cb->args[1], 0,
4264 sizeof(cb->args) - sizeof(cb->args[0]));
4265 if (filter->table[0] &&
4266 strcmp(filter->table, table->name))
4267 goto cont;
4268 if (filter->type != NFT_OBJECT_UNSPEC &&
4269 obj->type->type != filter->type)
4270 goto cont;
4271
4272 if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid,
4273 cb->nlh->nlmsg_seq,
4274 NFT_MSG_NEWOBJ,
4275 NLM_F_MULTI | NLM_F_APPEND,
4276 afi->family, table, obj, reset) < 0)
4277 goto done;
4278
4279 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
4280cont:
4281 idx++;
4282 }
4283 }
4284 }
4285done:
4286 rcu_read_unlock();
4287
4288 cb->args[0] = idx;
4289 return skb->len;
4290}
4291
4292static int nf_tables_dump_obj_done(struct netlink_callback *cb)
4293{
4294 kfree(cb->data);
4295
4296 return 0;
4297}
4298
4299static struct nft_obj_filter *
4300nft_obj_filter_alloc(const struct nlattr * const nla[])
4301{
4302 struct nft_obj_filter *filter;
4303
4304 filter = kzalloc(sizeof(*filter), GFP_KERNEL);
4305 if (!filter)
4306 return ERR_PTR(-ENOMEM);
4307
4308 if (nla[NFTA_OBJ_TABLE])
4309 nla_strlcpy(filter->table, nla[NFTA_OBJ_TABLE],
4310 NFT_TABLE_MAXNAMELEN);
4311 if (nla[NFTA_OBJ_TYPE])
4312 filter->type = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
4313
4314 return filter;
4315}
4316
4317static int nf_tables_getobj(struct net *net, struct sock *nlsk,
4318 struct sk_buff *skb, const struct nlmsghdr *nlh,
4319 const struct nlattr * const nla[])
4320{
4321 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
4322 u8 genmask = nft_genmask_cur(net);
4323 int family = nfmsg->nfgen_family;
4324 const struct nft_af_info *afi;
4325 const struct nft_table *table;
4326 struct nft_object *obj;
4327 struct sk_buff *skb2;
4328 bool reset = false;
4329 u32 objtype;
4330 int err;
4331
4332 if (nlh->nlmsg_flags & NLM_F_DUMP) {
4333 struct netlink_dump_control c = {
4334 .dump = nf_tables_dump_obj,
4335 .done = nf_tables_dump_obj_done,
4336 };
4337
4338 if (nla[NFTA_OBJ_TABLE] ||
4339 nla[NFTA_OBJ_TYPE]) {
4340 struct nft_obj_filter *filter;
4341
4342 filter = nft_obj_filter_alloc(nla);
4343 if (IS_ERR(filter))
4344 return -ENOMEM;
4345
4346 c.data = filter;
4347 }
4348 return netlink_dump_start(nlsk, skb, nlh, &c);
4349 }
4350
4351 if (!nla[NFTA_OBJ_NAME] ||
4352 !nla[NFTA_OBJ_TYPE])
4353 return -EINVAL;
4354
4355 afi = nf_tables_afinfo_lookup(net, family, false);
4356 if (IS_ERR(afi))
4357 return PTR_ERR(afi);
4358
4359 table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask);
4360 if (IS_ERR(table))
4361 return PTR_ERR(table);
4362
4363 objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
4364 obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask);
4365 if (IS_ERR(obj))
4366 return PTR_ERR(obj);
4367
4368 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
4369 if (!skb2)
4370 return -ENOMEM;
4371
4372 if (NFNL_MSG_TYPE(nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
4373 reset = true;
4374
4375 err = nf_tables_fill_obj_info(skb2, net, NETLINK_CB(skb).portid,
4376 nlh->nlmsg_seq, NFT_MSG_NEWOBJ, 0,
4377 family, table, obj, reset);
4378 if (err < 0)
4379 goto err;
4380
4381 return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
4382err:
4383 kfree_skb(skb2);
4384 return err;
4385
4386 return 0;
4387}
4388
4389static void nft_obj_destroy(struct nft_object *obj)
4390{
4391 if (obj->type->destroy)
4392 obj->type->destroy(obj);
4393
4394 module_put(obj->type->owner);
4395 kfree(obj);
4396}
4397
4398static int nf_tables_delobj(struct net *net, struct sock *nlsk,
4399 struct sk_buff *skb, const struct nlmsghdr *nlh,
4400 const struct nlattr * const nla[])
4401{
4402 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
4403 u8 genmask = nft_genmask_next(net);
4404 int family = nfmsg->nfgen_family;
4405 struct nft_af_info *afi;
4406 struct nft_table *table;
4407 struct nft_object *obj;
4408 struct nft_ctx ctx;
4409 u32 objtype;
4410
4411 if (!nla[NFTA_OBJ_TYPE] ||
4412 !nla[NFTA_OBJ_NAME])
4413 return -EINVAL;
4414
4415 afi = nf_tables_afinfo_lookup(net, family, true);
4416 if (IS_ERR(afi))
4417 return PTR_ERR(afi);
4418
4419 table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask);
4420 if (IS_ERR(table))
4421 return PTR_ERR(table);
4422
4423 objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
4424 obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask);
4425 if (IS_ERR(obj))
4426 return PTR_ERR(obj);
4427 if (obj->use > 0)
4428 return -EBUSY;
4429
4430 nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
4431
4432 return nft_delobj(&ctx, obj);
4433}
4434
4435int nft_obj_notify(struct net *net, struct nft_table *table,
4436 struct nft_object *obj, u32 portid, u32 seq, int event,
4437 int family, int report, gfp_t gfp)
4438{
4439 struct sk_buff *skb;
4440 int err;
4441
4442 if (!report &&
4443 !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
4444 return 0;
4445
4446 err = -ENOBUFS;
4447 skb = nlmsg_new(NLMSG_GOODSIZE, gfp);
4448 if (skb == NULL)
4449 goto err;
4450
4451 err = nf_tables_fill_obj_info(skb, net, portid, seq, event, 0, family,
4452 table, obj, false);
4453 if (err < 0) {
4454 kfree_skb(skb);
4455 goto err;
4456 }
4457
4458 err = nfnetlink_send(skb, net, portid, NFNLGRP_NFTABLES, report, gfp);
4459err:
4460 if (err < 0) {
4461 nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, err);
4462 }
4463 return err;
4464}
4465EXPORT_SYMBOL_GPL(nft_obj_notify);
4466
4467static int nf_tables_obj_notify(const struct nft_ctx *ctx,
4468 struct nft_object *obj, int event)
4469{
4470 return nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid,
4471 ctx->seq, event, ctx->afi->family, ctx->report,
4472 GFP_KERNEL);
4473}
4474
3841static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net,4475static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net,
3842 u32 portid, u32 seq)4476 u32 portid, u32 seq)
3843{4477{
@@ -3998,6 +4632,26 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { · 154 unmodified lines
3998 [NFT_MSG_GETGEN] = {4632 [NFT_MSG_GETGEN] = {
3999 .call = nf_tables_getgen,4633 .call = nf_tables_getgen,
4000 },4634 },
4635 [NFT_MSG_NEWOBJ] = {
4636 .call_batch = nf_tables_newobj,
4637 .attr_count = NFTA_OBJ_MAX,
4638 .policy = nft_obj_policy,
4639 },
4640 [NFT_MSG_GETOBJ] = {
4641 .call = nf_tables_getobj,
4642 .attr_count = NFTA_OBJ_MAX,
4643 .policy = nft_obj_policy,
4644 },
4645 [NFT_MSG_DELOBJ] = {
4646 .call_batch = nf_tables_delobj,
4647 .attr_count = NFTA_OBJ_MAX,
4648 .policy = nft_obj_policy,
4649 },
4650 [NFT_MSG_GETOBJ_RESET] = {
4651 .call = nf_tables_getobj,
4652 .attr_count = NFTA_OBJ_MAX,
4653 .policy = nft_obj_policy,
4654 },
4001};4655};
4002 4656
4003static void nft_chain_commit_update(struct nft_trans *trans)4657static void nft_chain_commit_update(struct nft_trans *trans)
@@ -4040,6 +4694,9 @@ static void nf_tables_commit_release(struct nft_trans *trans) · 36 unmodified lines
4040 nft_set_elem_destroy(nft_trans_elem_set(trans),4694 nft_set_elem_destroy(nft_trans_elem_set(trans),
4041 nft_trans_elem(trans).priv, true);4695 nft_trans_elem(trans).priv, true);
4042 break;4696 break;
4697 case NFT_MSG_DELOBJ:
4698 nft_obj_destroy(nft_trans_obj(trans));
4699 break;
4043 }4700 }
4044 kfree(trans);4701 kfree(trans);
4045}4702}
@@ -4147,6 +4804,17 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) · 101 unmodified lines
4147 atomic_dec(&te->set->nelems);4804 atomic_dec(&te->set->nelems);
4148 te->set->ndeact--;4805 te->set->ndeact--;
4149 break;4806 break;
4807 case NFT_MSG_NEWOBJ:
4808 nft_clear(net, nft_trans_obj(trans));
4809 nf_tables_obj_notify(&trans->ctx, nft_trans_obj(trans),
4810 NFT_MSG_NEWOBJ);
4811 nft_trans_destroy(trans);
4812 break;
4813 case NFT_MSG_DELOBJ:
4814 list_del_rcu(&nft_trans_obj(trans)->list);
4815 nf_tables_obj_notify(&trans->ctx, nft_trans_obj(trans),
4816 NFT_MSG_DELOBJ);
4817 break;
4150 }4818 }
4151 }4819 }
4152 4820
@@ -4181,6 +4849,9 @@ static void nf_tables_abort_release(struct nft_trans *trans) · 28 unmodified lines
4181 nft_set_elem_destroy(nft_trans_elem_set(trans),4849 nft_set_elem_destroy(nft_trans_elem_set(trans),
4182 nft_trans_elem(trans).priv, true);4850 nft_trans_elem(trans).priv, true);
4183 break;4851 break;
4852 case NFT_MSG_NEWOBJ:
4853 nft_obj_destroy(nft_trans_obj(trans));
4854 break;
4184 }4855 }
4185 kfree(trans);4856 kfree(trans);
4186}4857}
@@ -4259,6 +4930,15 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb) · 72 unmodified lines
4259 te->set->ops->activate(net, te->set, &te->elem);4930 te->set->ops->activate(net, te->set, &te->elem);
4260 te->set->ndeact--;4931 te->set->ndeact--;
4261 4932
4933 nft_trans_destroy(trans);
4934 break;
4935 case NFT_MSG_NEWOBJ:
4936 trans->ctx.table->use--;
4937 list_del_rcu(&nft_trans_obj(trans)->list);
4938 break;
4939 case NFT_MSG_DELOBJ:
4940 trans->ctx.table->use++;
4941 nft_clear(trans->ctx.net, nft_trans_obj(trans));
4262 nft_trans_destroy(trans);4942 nft_trans_destroy(trans);
4263 break;4943 break;
4264 }4944 }
@@ -4807,6 +5487,7 @@ static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi) · 542 unmodified lines
4807{5487{
4808 struct nft_table *table, *nt;5488 struct nft_table *table, *nt;
4809 struct nft_chain *chain, *nc;5489 struct nft_chain *chain, *nc;
5490 struct nft_object *obj, *ne;
4810 struct nft_rule *rule, *nr;5491 struct nft_rule *rule, *nr;
4811 struct nft_set *set, *ns;5492 struct nft_set *set, *ns;
4812 struct nft_ctx ctx = {5493 struct nft_ctx ctx = {
@@ -4833,6 +5514,11 @@ static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi) · 20 unmodified lines
4833 table->use--;5514 table->use--;
4834 nft_set_destroy(set);5515 nft_set_destroy(set);
4835 }5516 }
5517 list_for_each_entry_safe(obj, ne, &table->objects, list) {
5518 list_del(&obj->list);
5519 table->use--;
5520 nft_obj_destroy(obj);
5521 }
4836 list_for_each_entry_safe(chain, nc, &table->chains, list) {5522 list_for_each_entry_safe(chain, nc, &table->chains, list) {
4837 list_del(&chain->list);5523 list_del(&chain->list);
4838 table->use--;5524 table->use--;
net/netfilter/nfnetlink_log.c+1−0
@@ -1152,6 +1152,7 @@ MODULE_ALIAS_NF_LOGGER(AF_INET, 1); · 1151 unmodified lines
1152MODULE_ALIAS_NF_LOGGER(AF_INET6, 1);1152MODULE_ALIAS_NF_LOGGER(AF_INET6, 1);
1153MODULE_ALIAS_NF_LOGGER(AF_BRIDGE, 1);1153MODULE_ALIAS_NF_LOGGER(AF_BRIDGE, 1);
1154MODULE_ALIAS_NF_LOGGER(3, 1); /* NFPROTO_ARP */1154MODULE_ALIAS_NF_LOGGER(3, 1); /* NFPROTO_ARP */
1155MODULE_ALIAS_NF_LOGGER(5, 1); /* NFPROTO_NETDEV */
1155 1156
1156module_init(nfnetlink_log_init);1157module_init(nfnetlink_log_init);
1157module_exit(nfnetlink_log_fini);1158module_exit(nfnetlink_log_fini);
net/netfilter/nft_counter.c+156−30
@@ -31,11 +31,10 @@ struct nft_counter_percpu_priv { · 30 unmodified lines
31 struct nft_counter_percpu __percpu *counter;31 struct nft_counter_percpu __percpu *counter;
32};32};
33 33
34static void nft_counter_eval(const struct nft_expr *expr,34static inline void nft_counter_do_eval(struct nft_counter_percpu_priv *priv,
35 struct nft_regs *regs,35 struct nft_regs *regs,
36 const struct nft_pktinfo *pkt)36 const struct nft_pktinfo *pkt)
37{37{
38 struct nft_counter_percpu_priv *priv = nft_expr_priv(expr);
39 struct nft_counter_percpu *this_cpu;38 struct nft_counter_percpu *this_cpu;
40 39
41 local_bh_disable();40 local_bh_disable();
@@ -47,10 +46,64 @@ static void nft_counter_eval(const struct nft_expr *expr, · 5 unmodified lines
47 local_bh_enable();46 local_bh_enable();
48}47}
49 48
50static void nft_counter_fetch(const struct nft_counter_percpu __percpu *counter,49static inline void nft_counter_obj_eval(struct nft_object *obj,
50 struct nft_regs *regs,
51 const struct nft_pktinfo *pkt)
52{
53 struct nft_counter_percpu_priv *priv = nft_obj_data(obj);
54
55 nft_counter_do_eval(priv, regs, pkt);
56}
57
58static int nft_counter_do_init(const struct nlattr * const tb[],
59 struct nft_counter_percpu_priv *priv)
60{
61 struct nft_counter_percpu __percpu *cpu_stats;
62 struct nft_counter_percpu *this_cpu;
63
64 cpu_stats = netdev_alloc_pcpu_stats(struct nft_counter_percpu);
65 if (cpu_stats == NULL)
66 return -ENOMEM;
67
68 preempt_disable();
69 this_cpu = this_cpu_ptr(cpu_stats);
70 if (tb[NFTA_COUNTER_PACKETS]) {
71 this_cpu->counter.packets =
72 be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_PACKETS]));
73 }
74 if (tb[NFTA_COUNTER_BYTES]) {
75 this_cpu->counter.bytes =
76 be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_BYTES]));
77 }
78 preempt_enable();
79 priv->counter = cpu_stats;
80 return 0;
81}
82
83static int nft_counter_obj_init(const struct nlattr * const tb[],
84 struct nft_object *obj)
85{
86 struct nft_counter_percpu_priv *priv = nft_obj_data(obj);
87
88 return nft_counter_do_init(tb, priv);
89}
90
91static void nft_counter_do_destroy(struct nft_counter_percpu_priv *priv)
92{
93 free_percpu(priv->counter);
94}
95
96static void nft_counter_obj_destroy(struct nft_object *obj)
97{
98 struct nft_counter_percpu_priv *priv = nft_obj_data(obj);
99
100 nft_counter_do_destroy(priv);
101}
102
103static void nft_counter_fetch(struct nft_counter_percpu __percpu *counter,
51 struct nft_counter *total)104 struct nft_counter *total)
52{105{
53 const struct nft_counter_percpu *cpu_stats;106 struct nft_counter_percpu *cpu_stats;
54 u64 bytes, packets;107 u64 bytes, packets;
55 unsigned int seq;108 unsigned int seq;
56 int cpu;109 int cpu;
@@ -69,12 +122,52 @@ static void nft_counter_fetch(const struct nft_counter_percpu __percpu *counter, · 12 unmodified lines
69 }122 }
70}123}
71 124
72static int nft_counter_dump(struct sk_buff *skb, const struct nft_expr *expr)125static u64 __nft_counter_reset(u64 *counter)
126{
127 u64 ret, old;
128
129 do {
130 old = *counter;
131 ret = cmpxchg64(counter, old, 0);
132 } while (ret != old);
133
134 return ret;
135}
136
137static void nft_counter_reset(struct nft_counter_percpu __percpu *counter,
138 struct nft_counter *total)
139{
140 struct nft_counter_percpu *cpu_stats;
141 u64 bytes, packets;
142 unsigned int seq;
143 int cpu;
144
145 memset(total, 0, sizeof(*total));
146 for_each_possible_cpu(cpu) {
147 bytes = packets = 0;
148
149 cpu_stats = per_cpu_ptr(counter, cpu);
150 do {
151 seq = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
152 packets += __nft_counter_reset(&cpu_stats->counter.packets);
153 bytes += __nft_counter_reset(&cpu_stats->counter.bytes);
154 } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, seq));
155
156 total->packets += packets;
157 total->bytes += bytes;
158 }
159}
160
161static int nft_counter_do_dump(struct sk_buff *skb,
162 const struct nft_counter_percpu_priv *priv,
163 bool reset)
73{164{
74 struct nft_counter_percpu_priv *priv = nft_expr_priv(expr);
75 struct nft_counter total;165 struct nft_counter total;
76 166
77 nft_counter_fetch(priv->counter, &total);167 if (reset)
168 nft_counter_reset(priv->counter, &total);
169 else
170 nft_counter_fetch(priv->counter, &total);
78 171
79 if (nla_put_be64(skb, NFTA_COUNTER_BYTES, cpu_to_be64(total.bytes),172 if (nla_put_be64(skb, NFTA_COUNTER_BYTES, cpu_to_be64(total.bytes),
80 NFTA_COUNTER_PAD) ||173 NFTA_COUNTER_PAD) ||
@@ -87,36 +180,54 @@ nla_put_failure: · 6 unmodified lines
87 return -1;180 return -1;
88}181}
89 182
183static int nft_counter_obj_dump(struct sk_buff *skb,
184 struct nft_object *obj, bool reset)
185{
186 struct nft_counter_percpu_priv *priv = nft_obj_data(obj);
187
188 return nft_counter_do_dump(skb, priv, reset);
189}
190
90static const struct nla_policy nft_counter_policy[NFTA_COUNTER_MAX + 1] = {191static const struct nla_policy nft_counter_policy[NFTA_COUNTER_MAX + 1] = {
91 [NFTA_COUNTER_PACKETS] = { .type = NLA_U64 },192 [NFTA_COUNTER_PACKETS] = { .type = NLA_U64 },
92 [NFTA_COUNTER_BYTES] = { .type = NLA_U64 },193 [NFTA_COUNTER_BYTES] = { .type = NLA_U64 },
93};194};
94 195
196static struct nft_object_type nft_counter_obj __read_mostly = {
197 .type = NFT_OBJECT_COUNTER,
198 .size = sizeof(struct nft_counter_percpu_priv),
199 .maxattr = NFTA_COUNTER_MAX,
200 .policy = nft_counter_policy,
201 .eval = nft_counter_obj_eval,
202 .init = nft_counter_obj_init,
203 .destroy = nft_counter_obj_destroy,
204 .dump = nft_counter_obj_dump,
205 .owner = THIS_MODULE,
206};
207
208static void nft_counter_eval(const struct nft_expr *expr,
209 struct nft_regs *regs,
210 const struct nft_pktinfo *pkt)
211{
212 struct nft_counter_percpu_priv *priv = nft_expr_priv(expr);
213
214 nft_counter_do_eval(priv, regs, pkt);
215}
216
217static int nft_counter_dump(struct sk_buff *skb, const struct nft_expr *expr)
218{
219 const struct nft_counter_percpu_priv *priv = nft_expr_priv(expr);
220
221 return nft_counter_do_dump(skb, priv, false);
222}
223
95static int nft_counter_init(const struct nft_ctx *ctx,224static int nft_counter_init(const struct nft_ctx *ctx,
96 const struct nft_expr *expr,225 const struct nft_expr *expr,
97 const struct nlattr * const tb[])226 const struct nlattr * const tb[])
98{227{
99 struct nft_counter_percpu_priv *priv = nft_expr_priv(expr);228 struct nft_counter_percpu_priv *priv = nft_expr_priv(expr);
100 struct nft_counter_percpu __percpu *cpu_stats;
101 struct nft_counter_percpu *this_cpu;
102 229
103 cpu_stats = netdev_alloc_pcpu_stats(struct nft_counter_percpu);230 return nft_counter_do_init(tb, priv);
104 if (cpu_stats == NULL)
105 return -ENOMEM;
106
107 preempt_disable();
108 this_cpu = this_cpu_ptr(cpu_stats);
109 if (tb[NFTA_COUNTER_PACKETS]) {
110 this_cpu->counter.packets =
111 be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_PACKETS]));
112 }
113 if (tb[NFTA_COUNTER_BYTES]) {
114 this_cpu->counter.bytes =
115 be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_BYTES]));
116 }
117 preempt_enable();
118 priv->counter = cpu_stats;
119 return 0;
120}231}
121 232
122static void nft_counter_destroy(const struct nft_ctx *ctx,233static void nft_counter_destroy(const struct nft_ctx *ctx,
@@ -124,7 +235,7 @@ static void nft_counter_destroy(const struct nft_ctx *ctx, · 1 unmodified line
124{235{
125 struct nft_counter_percpu_priv *priv = nft_expr_priv(expr);236 struct nft_counter_percpu_priv *priv = nft_expr_priv(expr);
126 237
127 free_percpu(priv->counter);238 nft_counter_do_destroy(priv);
128}239}
129 240
130static int nft_counter_clone(struct nft_expr *dst, const struct nft_expr *src)241static int nft_counter_clone(struct nft_expr *dst, const struct nft_expr *src)
@@ -174,12 +285,26 @@ static struct nft_expr_type nft_counter_type __read_mostly = { · 43 unmodified lines
174 285
175static int __init nft_counter_module_init(void)286static int __init nft_counter_module_init(void)
176{287{
177 return nft_register_expr(&nft_counter_type);288 int err;
289
290 err = nft_register_obj(&nft_counter_obj);
291 if (err < 0)
292 return err;
293
294 err = nft_register_expr(&nft_counter_type);
295 if (err < 0)
296 goto err1;
297
298 return 0;
299err1:
300 nft_unregister_obj(&nft_counter_obj);
301 return err;
178}302}
179 303
180static void __exit nft_counter_module_exit(void)304static void __exit nft_counter_module_exit(void)
181{305{
182 nft_unregister_expr(&nft_counter_type);306 nft_unregister_expr(&nft_counter_type);
307 nft_unregister_obj(&nft_counter_obj);
183}308}
184 309
185module_init(nft_counter_module_init);310module_init(nft_counter_module_init);
@@ -188,3 +313,4 @@ module_exit(nft_counter_module_exit); · 2 unmodified lines
188MODULE_LICENSE("GPL");313MODULE_LICENSE("GPL");
189MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");314MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
190MODULE_ALIAS_NFT_EXPR("counter");315MODULE_ALIAS_NFT_EXPR("counter");
316MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_COUNTER);
net/netfilter/nft_ct.c+13−13
@@ -208,37 +208,37 @@ static const struct nla_policy nft_ct_policy[NFTA_CT_MAX + 1] = { · 207 unmodified lines
208 [NFTA_CT_SREG] = { .type = NLA_U32 },208 [NFTA_CT_SREG] = { .type = NLA_U32 },
209};209};
210 210
211static int nft_ct_l3proto_try_module_get(uint8_t family)211static int nft_ct_netns_get(struct net *net, uint8_t family)
212{212{
213 int err;213 int err;
214 214
215 if (family == NFPROTO_INET) {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 if (err < 0)217 if (err < 0)
218 goto err1;218 goto err1;
219 err = nf_ct_l3proto_try_module_get(NFPROTO_IPV6);219 err = nf_ct_netns_get(net, NFPROTO_IPV6);
220 if (err < 0)220 if (err < 0)
221 goto err2;221 goto err2;
222 } else {222 } else {
223 err = nf_ct_l3proto_try_module_get(family);223 err = nf_ct_netns_get(net, family);
224 if (err < 0)224 if (err < 0)
225 goto err1;225 goto err1;
226 }226 }
227 return 0;227 return 0;
228 228
229err2:229err2:
230 nf_ct_l3proto_module_put(NFPROTO_IPV4);230 nf_ct_netns_put(net, NFPROTO_IPV4);
231err1:231err1:
232 return err;232 return err;
233}233}
234 234
235static void nft_ct_l3proto_module_put(uint8_t family)235static void nft_ct_netns_put(struct net *net, uint8_t family)
236{236{
237 if (family == NFPROTO_INET) {237 if (family == NFPROTO_INET) {
238 nf_ct_l3proto_module_put(NFPROTO_IPV4);238 nf_ct_netns_put(net, NFPROTO_IPV4);
239 nf_ct_l3proto_module_put(NFPROTO_IPV6);239 nf_ct_netns_put(net, NFPROTO_IPV6);
240 } else240 } else
241 nf_ct_l3proto_module_put(family);241 nf_ct_netns_put(net, family);
242}242}
243 243
244static int nft_ct_get_init(const struct nft_ctx *ctx,244static int nft_ct_get_init(const struct nft_ctx *ctx,
@@ -342,7 +342,7 @@ static int nft_ct_get_init(const struct nft_ctx *ctx, · 97 unmodified lines
342 if (err < 0)342 if (err < 0)
343 return err;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 if (err < 0)346 if (err < 0)
347 return err;347 return err;
348 348
@@ -390,7 +390,7 @@ static int nft_ct_set_init(const struct nft_ctx *ctx, · 41 unmodified lines
390 if (err < 0)390 if (err < 0)
391 goto err1;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 if (err < 0)394 if (err < 0)
395 goto err1;395 goto err1;
396 396
@@ -405,7 +405,7 @@ err1: · 8 unmodified lines
405static void nft_ct_get_destroy(const struct nft_ctx *ctx,405static void nft_ct_get_destroy(const struct nft_ctx *ctx,
406 const struct nft_expr *expr)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
411static void nft_ct_set_destroy(const struct nft_ctx *ctx,411static void nft_ct_set_destroy(const struct nft_ctx *ctx,
@@ -423,7 +423,7 @@ static void nft_ct_set_destroy(const struct nft_ctx *ctx, · 11 unmodified lines
423 break;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
429static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr)429static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr)
net/netfilter/nft_fib.c+1−1
@@ -86,7 +86,7 @@ int nft_fib_init(const struct nft_ctx *ctx, const struct nft_expr *expr, · 85 unmodified lines
86 if ((priv->flags & (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR)) == 0)86 if ((priv->flags & (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR)) == 0)
87 return -EINVAL;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 priv->dreg = nft_parse_register(tb[NFTA_FIB_DREG]);90 priv->dreg = nft_parse_register(tb[NFTA_FIB_DREG]);
91 91
92 switch (priv->result) {92 switch (priv->result) {
net/netfilter/nft_fwd_netdev.c+2−2
@@ -26,8 +26,8 @@ static void nft_fwd_netdev_eval(const struct nft_expr *expr, · 25 unmodified lines
26 struct nft_fwd_netdev *priv = nft_expr_priv(expr);26 struct nft_fwd_netdev *priv = nft_expr_priv(expr);
27 int oif = regs->data[priv->sreg_dev];27 int oif = regs->data[priv->sreg_dev];
28 28
29 nf_dup_netdev_egress(pkt, oif);29 nf_fwd_netdev_egress(pkt, oif);
30 regs->verdict.code = NF_DROP;30 regs->verdict.code = NF_STOLEN;
31}31}
32 32
33static const struct nla_policy nft_fwd_netdev_policy[NFTA_FWD_MAX + 1] = {33static const struct nla_policy nft_fwd_netdev_policy[NFTA_FWD_MAX + 1] = {
net/netfilter/nft_masq.c+3−3
@@ -1,5 +1,5 @@
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 * This program is free software; you can redistribute it and/or modify4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as5 * it under the terms of the GNU General Public License version 2 as
@@ -77,7 +77,7 @@ int nft_masq_init(const struct nft_ctx *ctx, · 71 unmodified lines
77 }77 }
78 }78 }
79 79
80 return 0;80 return nf_ct_netns_get(ctx->net, ctx->afi->family);
81}81}
82EXPORT_SYMBOL_GPL(nft_masq_init);82EXPORT_SYMBOL_GPL(nft_masq_init);
83 83
@@ -105,4 +105,4 @@ nla_put_failure: · 21 unmodified lines
105EXPORT_SYMBOL_GPL(nft_masq_dump);105EXPORT_SYMBOL_GPL(nft_masq_dump);
106 106
107MODULE_LICENSE("GPL");107MODULE_LICENSE("GPL");
108MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");108MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
net/netfilter/nft_nat.c+10−1
@@ -209,7 +209,7 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, · 208 unmodified lines
209 return -EINVAL;209 return -EINVAL;
210 }210 }
211 211
212 return 0;212 return nf_ct_netns_get(ctx->net, family);
213}213}
214 214
215static int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr)215static int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr)
@@ -257,12 +257,21 @@ nla_put_failure: · 41 unmodified lines
257 return -1;257 return -1;
258}258}
259 259
260static void
261nft_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
260static struct nft_expr_type nft_nat_type;268static struct nft_expr_type nft_nat_type;
261static const struct nft_expr_ops nft_nat_ops = {269static const struct nft_expr_ops nft_nat_ops = {
262 .type = &nft_nat_type,270 .type = &nft_nat_type,
263 .size = NFT_EXPR_SIZE(sizeof(struct nft_nat)),271 .size = NFT_EXPR_SIZE(sizeof(struct nft_nat)),
264 .eval = nft_nat_eval,272 .eval = nft_nat_eval,
265 .init = nft_nat_init,273 .init = nft_nat_init,
274 .destroy = nft_nat_destroy,
266 .dump = nft_nat_dump,275 .dump = nft_nat_dump,
267 .validate = nft_nat_validate,276 .validate = nft_nat_validate,
268};277};
net/netfilter/nft_objref.c+226−0
@@ -0,0 +1,226 @@
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
19static 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
28static 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
52static 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
62nla_put_failure:
63 return -1;
64}
65
66static 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
74static struct nft_expr_type nft_objref_type;
75static 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
84struct nft_objref_map {
85 struct nft_set *set;
86 enum nft_registers sreg:8;
87 struct nft_set_binding binding;
88};
89
90static 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
110static 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
148static 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
158nla_put_failure:
159 return -1;
160}
161
162static 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
170static struct nft_expr_type nft_objref_type;
171static 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
180static const struct nft_expr_ops *
181nft_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
195static 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
203static 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
211static int __init nft_objref_module_init(void)
212{
213 return nft_register_expr(&nft_objref_type);
214}
215
216static void __exit nft_objref_module_exit(void)
217{
218 nft_unregister_expr(&nft_objref_type);
219}
220
221module_init(nft_objref_module_init);
222module_exit(nft_objref_module_exit);
223
224MODULE_LICENSE("GPL");
225MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
226MODULE_ALIAS_NFT_EXPR("objref");
net/netfilter/nft_payload.c+102−5
@@ -1,5 +1,6 @@
1/*1/*
2 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>2 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
3 * Copyright (c) 2016 Pablo Neira Ayuso <pablo@netfilter.org>
3 *4 *
4 * This program is free software; you can redistribute it and/or modify5 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as6 * it under the terms of the GNU General Public License version 2 as
@@ -17,6 +18,10 @@ · 11 unmodified lines
17#include <linux/netfilter/nf_tables.h>18#include <linux/netfilter/nf_tables.h>
18#include <net/netfilter/nf_tables_core.h>19#include <net/netfilter/nf_tables_core.h>
19#include <net/netfilter/nf_tables.h>20#include <net/netfilter/nf_tables.h>
21/* For layer 4 checksum field offset. */
22#include <linux/tcp.h>
23#include <linux/udp.h>
24#include <linux/icmpv6.h>
20 25
21/* add vlan header into the user buffer for if tag was removed by offloads */26/* add vlan header into the user buffer for if tag was removed by offloads */
22static bool27static bool
@@ -164,6 +169,87 @@ const struct nft_expr_ops nft_payload_fast_ops = { · 141 unmodified lines
164 .dump = nft_payload_dump,169 .dump = nft_payload_dump,
165};170};
166 171
172static inline void nft_csum_replace(__sum16 *sum, __wsum fsum, __wsum tsum)
173{
174 *sum = csum_fold(csum_add(csum_sub(~csum_unfold(*sum), fsum), tsum));
175 if (*sum == 0)
176 *sum = CSUM_MANGLED_0;
177}
178
179static bool nft_payload_udp_checksum(struct sk_buff *skb, unsigned int thoff)
180{
181 struct udphdr *uh, _uh;
182
183 uh = skb_header_pointer(skb, thoff, sizeof(_uh), &_uh);
184 if (!uh)
185 return false;
186
187 return uh->check;
188}
189
190static int nft_payload_l4csum_offset(const struct nft_pktinfo *pkt,
191 struct sk_buff *skb,
192 unsigned int *l4csum_offset)
193{
194 switch (pkt->tprot) {
195 case IPPROTO_TCP:
196 *l4csum_offset = offsetof(struct tcphdr, check);
197 break;
198 case IPPROTO_UDP:
199 if (!nft_payload_udp_checksum(skb, pkt->xt.thoff))
200 return -1;
201 /* Fall through. */
202 case IPPROTO_UDPLITE:
203 *l4csum_offset = offsetof(struct udphdr, check);
204 break;
205 case IPPROTO_ICMPV6:
206 *l4csum_offset = offsetof(struct icmp6hdr, icmp6_cksum);
207 break;
208 default:
209 return -1;
210 }
211
212 *l4csum_offset += pkt->xt.thoff;
213 return 0;
214}
215
216static int nft_payload_l4csum_update(const struct nft_pktinfo *pkt,
217 struct sk_buff *skb,
218 __wsum fsum, __wsum tsum)
219{
220 int l4csum_offset;
221 __sum16 sum;
222
223 /* If we cannot determine layer 4 checksum offset or this packet doesn't
224 * require layer 4 checksum recalculation, skip this packet.
225 */
226 if (nft_payload_l4csum_offset(pkt, skb, &l4csum_offset) < 0)
227 return 0;
228
229 if (skb_copy_bits(skb, l4csum_offset, &sum, sizeof(sum)) < 0)
230 return -1;
231
232 /* Checksum mangling for an arbitrary amount of bytes, based on
233 * inet_proto_csum_replace*() functions.
234 */
235 if (skb->ip_summed != CHECKSUM_PARTIAL) {
236 nft_csum_replace(&sum, fsum, tsum);
237 if (skb->ip_summed == CHECKSUM_COMPLETE) {
238 skb->csum = ~csum_add(csum_sub(~(skb->csum), fsum),
239 tsum);
240 }
241 } else {
242 sum = ~csum_fold(csum_add(csum_sub(csum_unfold(sum), fsum),
243 tsum));
244 }
245
246 if (!skb_make_writable(skb, l4csum_offset + sizeof(sum)) ||
247 skb_store_bits(skb, l4csum_offset, &sum, sizeof(sum)) < 0)
248 return -1;
249
250 return 0;
251}
252
167static void nft_payload_set_eval(const struct nft_expr *expr,253static void nft_payload_set_eval(const struct nft_expr *expr,
168 struct nft_regs *regs,254 struct nft_regs *regs,
169 const struct nft_pktinfo *pkt)255 const struct nft_pktinfo *pkt)
@@ -204,14 +290,15 @@ static void nft_payload_set_eval(const struct nft_expr *expr, · 34 unmodified lines
204 290
205 fsum = skb_checksum(skb, offset, priv->len, 0);291 fsum = skb_checksum(skb, offset, priv->len, 0);
206 tsum = csum_partial(src, priv->len, 0);292 tsum = csum_partial(src, priv->len, 0);
207 sum = csum_fold(csum_add(csum_sub(~csum_unfold(sum), fsum),293 nft_csum_replace(&sum, fsum, tsum);
208 tsum));
209 if (sum == 0)
210 sum = CSUM_MANGLED_0;
211 294
212 if (!skb_make_writable(skb, csum_offset + sizeof(sum)) ||295 if (!skb_make_writable(skb, csum_offset + sizeof(sum)) ||
213 skb_store_bits(skb, csum_offset, &sum, sizeof(sum)) < 0)296 skb_store_bits(skb, csum_offset, &sum, sizeof(sum)) < 0)
214 goto err;297 goto err;
298
299 if (priv->csum_flags &&
300 nft_payload_l4csum_update(pkt, skb, fsum, tsum) < 0)
301 goto err;
215 }302 }
216 303
217 if (!skb_make_writable(skb, max(offset + priv->len, 0)) ||304 if (!skb_make_writable(skb, max(offset + priv->len, 0)) ||
@@ -240,6 +327,15 @@ static int nft_payload_set_init(const struct nft_ctx *ctx, · 22 unmodified lines
240 if (tb[NFTA_PAYLOAD_CSUM_OFFSET])327 if (tb[NFTA_PAYLOAD_CSUM_OFFSET])
241 priv->csum_offset =328 priv->csum_offset =
242 ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_OFFSET]));329 ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_OFFSET]));
330 if (tb[NFTA_PAYLOAD_CSUM_FLAGS]) {
331 u32 flags;
332
333 flags = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_FLAGS]));
334 if (flags & ~NFT_PAYLOAD_L4CSUM_PSEUDOHDR)
335 return -EINVAL;
336
337 priv->csum_flags = flags;
338 }
243 339
244 switch (priv->csum_type) {340 switch (priv->csum_type) {
245 case NFT_PAYLOAD_CSUM_NONE:341 case NFT_PAYLOAD_CSUM_NONE:
@@ -262,7 +358,8 @@ static int nft_payload_set_dump(struct sk_buff *skb, const struct nft_expr *expr · 16 unmodified lines
262 nla_put_be32(skb, NFTA_PAYLOAD_LEN, htonl(priv->len)) ||358 nla_put_be32(skb, NFTA_PAYLOAD_LEN, htonl(priv->len)) ||
263 nla_put_be32(skb, NFTA_PAYLOAD_CSUM_TYPE, htonl(priv->csum_type)) ||359 nla_put_be32(skb, NFTA_PAYLOAD_CSUM_TYPE, htonl(priv->csum_type)) ||
264 nla_put_be32(skb, NFTA_PAYLOAD_CSUM_OFFSET,360 nla_put_be32(skb, NFTA_PAYLOAD_CSUM_OFFSET,
265 htonl(priv->csum_offset)))361 htonl(priv->csum_offset)) ||
362 nla_put_be32(skb, NFTA_PAYLOAD_CSUM_FLAGS, htonl(priv->csum_flags)))
266 goto nla_put_failure;363 goto nla_put_failure;
267 return 0;364 return 0;
268 365
net/netfilter/nft_quota.c+136−22
@@ -17,38 +17,59 @@ · 16 unmodified lines
17 17
18struct nft_quota {18struct nft_quota {
19 u64 quota;19 u64 quota;
20 bool invert;20 unsigned long flags;
21 atomic64_t remain;21 atomic64_t consumed;
22};22};
23 23
24static inline bool nft_overquota(struct nft_quota *priv,24static 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
30static void nft_quota_eval(const struct nft_expr *expr,30static inline bool nft_quota_invert(struct nft_quota *priv)
31 struct nft_regs *regs,
32 const struct nft_pktinfo *pkt)
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)35static 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 regs->verdict.code = NFT_BREAK;40 regs->verdict.code = NFT_BREAK;
38}41}
39 42
40static const struct nla_policy nft_quota_policy[NFTA_QUOTA_MAX + 1] = {43static const struct nla_policy nft_quota_policy[NFTA_QUOTA_MAX + 1] = {
41 [NFTA_QUOTA_BYTES] = { .type = NLA_U64 },44 [NFTA_QUOTA_BYTES] = { .type = NLA_U64 },
42 [NFTA_QUOTA_FLAGS] = { .type = NLA_U32 },45 [NFTA_QUOTA_FLAGS] = { .type = NLA_U32 },
46 [NFTA_QUOTA_CONSUMED] = { .type = NLA_U64 },
43};47};
44 48
45static int nft_quota_init(const struct nft_ctx *ctx,49#define NFT_QUOTA_DEPLETED_BIT 1 /* From NFT_QUOTA_F_DEPLETED. */
46 const struct nft_expr *expr,50
47 const struct nlattr * const tb[])51static 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);55 struct nft_quota *priv = nft_obj_data(obj);
50 u32 flags = 0;56 bool overquota;
51 u64 quota;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
68static 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 if (!tb[NFTA_QUOTA_BYTES])74 if (!tb[NFTA_QUOTA_BYTES])
54 return -EINVAL;75 return -EINVAL;
@@ -57,26 +78,60 @@ static int nft_quota_init(const struct nft_ctx *ctx, · 2 unmodified lines
57 if (quota > S64_MAX)78 if (quota > S64_MAX)
58 return -EOVERFLOW;79 return -EOVERFLOW;
59 80
81 if (tb[NFTA_QUOTA_CONSUMED]) {
82 consumed = be64_to_cpu(nla_get_be64(tb[NFTA_QUOTA_CONSUMED]));
83 if (consumed > quota)
84 return -EINVAL;
85 }
86
60 if (tb[NFTA_QUOTA_FLAGS]) {87 if (tb[NFTA_QUOTA_FLAGS]) {
61 flags = ntohl(nla_get_be32(tb[NFTA_QUOTA_FLAGS]));88 flags = ntohl(nla_get_be32(tb[NFTA_QUOTA_FLAGS]));
62 if (flags & ~NFT_QUOTA_F_INV)89 if (flags & ~NFT_QUOTA_F_INV)
63 return -EINVAL;90 return -EINVAL;
91 if (flags & NFT_QUOTA_F_DEPLETED)
92 return -EOPNOTSUPP;
64 }93 }
65 94
66 priv->quota = quota;95 priv->quota = quota;
67 priv->invert = (flags & NFT_QUOTA_F_INV) ? true : false;96 priv->flags = flags;
68 atomic64_set(&priv->remain, quota);97 atomic64_set(&priv->consumed, consumed);
69 98
70 return 0;99 return 0;
71}100}
72 101
73static int nft_quota_dump(struct sk_buff *skb, const struct nft_expr *expr)102static int nft_quota_obj_init(const struct nlattr * const tb[],
103 struct nft_object *obj)
104{
105 struct nft_quota *priv = nft_obj_data(obj);
106
107 return nft_quota_do_init(tb, priv);
108}
109
110static int nft_quota_do_dump(struct sk_buff *skb, struct nft_quota *priv,
111 bool reset)
74{112{
75 const struct nft_quota *priv = nft_expr_priv(expr);113 u32 flags = priv->flags;
76 u32 flags = priv->invert ? NFT_QUOTA_F_INV : 0;114 u64 consumed;
115
116 if (reset) {
117 consumed = atomic64_xchg(&priv->consumed, 0);
118 if (test_and_clear_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags))
119 flags |= NFT_QUOTA_F_DEPLETED;
120 } else {
121 consumed = atomic64_read(&priv->consumed);
122 }
123
124 /* Since we inconditionally increment consumed quota for each packet
125 * that we see, don't go over the quota boundary in what we send to
126 * userspace.
127 */
128 if (consumed > priv->quota)
129 consumed = priv->quota;
77 130
78 if (nla_put_be64(skb, NFTA_QUOTA_BYTES, cpu_to_be64(priv->quota),131 if (nla_put_be64(skb, NFTA_QUOTA_BYTES, cpu_to_be64(priv->quota),
79 NFTA_QUOTA_PAD) ||132 NFTA_QUOTA_PAD) ||
133 nla_put_be64(skb, NFTA_QUOTA_CONSUMED, cpu_to_be64(consumed),
134 NFTA_QUOTA_PAD) ||
80 nla_put_be32(skb, NFTA_QUOTA_FLAGS, htonl(flags)))135 nla_put_be32(skb, NFTA_QUOTA_FLAGS, htonl(flags)))
81 goto nla_put_failure;136 goto nla_put_failure;
82 return 0;137 return 0;
@@ -85,6 +140,50 @@ nla_put_failure: · 2 unmodified lines
85 return -1;140 return -1;
86}141}
87 142
143static int nft_quota_obj_dump(struct sk_buff *skb, struct nft_object *obj,
144 bool reset)
145{
146 struct nft_quota *priv = nft_obj_data(obj);
147
148 return nft_quota_do_dump(skb, priv, reset);
149}
150
151static struct nft_object_type nft_quota_obj __read_mostly = {
152 .type = NFT_OBJECT_QUOTA,
153 .size = sizeof(struct nft_quota),
154 .maxattr = NFTA_QUOTA_MAX,
155 .policy = nft_quota_policy,
156 .init = nft_quota_obj_init,
157 .eval = nft_quota_obj_eval,
158 .dump = nft_quota_obj_dump,
159 .owner = THIS_MODULE,
160};
161
162static void nft_quota_eval(const struct nft_expr *expr,
163 struct nft_regs *regs,
164 const struct nft_pktinfo *pkt)
165{
166 struct nft_quota *priv = nft_expr_priv(expr);
167
168 nft_quota_do_eval(priv, regs, pkt);
169}
170
171static int nft_quota_init(const struct nft_ctx *ctx,
172 const struct nft_expr *expr,
173 const struct nlattr * const tb[])
174{
175 struct nft_quota *priv = nft_expr_priv(expr);
176
177 return nft_quota_do_init(tb, priv);
178}
179
180static int nft_quota_dump(struct sk_buff *skb, const struct nft_expr *expr)
181{
182 struct nft_quota *priv = nft_expr_priv(expr);
183
184 return nft_quota_do_dump(skb, priv, false);
185}
186
88static struct nft_expr_type nft_quota_type;187static struct nft_expr_type nft_quota_type;
89static const struct nft_expr_ops nft_quota_ops = {188static const struct nft_expr_ops nft_quota_ops = {
90 .type = &nft_quota_type,189 .type = &nft_quota_type,
@@ -105,12 +204,26 @@ static struct nft_expr_type nft_quota_type __read_mostly = { · 14 unmodified lines
105 204
106static int __init nft_quota_module_init(void)205static int __init nft_quota_module_init(void)
107{206{
108 return nft_register_expr(&nft_quota_type);207 int err;
208
209 err = nft_register_obj(&nft_quota_obj);
210 if (err < 0)
211 return err;
212
213 err = nft_register_expr(&nft_quota_type);
214 if (err < 0)
215 goto err1;
216
217 return 0;
218err1:
219 nft_unregister_obj(&nft_quota_obj);
220 return err;
109}221}
110 222
111static void __exit nft_quota_module_exit(void)223static void __exit nft_quota_module_exit(void)
112{224{
113 nft_unregister_expr(&nft_quota_type);225 nft_unregister_expr(&nft_quota_type);
226 nft_unregister_obj(&nft_quota_obj);
114}227}
115 228
116module_init(nft_quota_module_init);229module_init(nft_quota_module_init);
@@ -119,3 +232,4 @@ module_exit(nft_quota_module_exit); · 2 unmodified lines
119MODULE_LICENSE("GPL");232MODULE_LICENSE("GPL");
120MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");233MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
121MODULE_ALIAS_NFT_EXPR("quota");234MODULE_ALIAS_NFT_EXPR("quota");
235MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_QUOTA);
net/netfilter/nft_redir.c+3−3
@@ -1,5 +1,5 @@
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 * This program is free software; you can redistribute it and/or modify4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as5 * it under the terms of the GNU General Public License version 2 as
@@ -79,7 +79,7 @@ int nft_redir_init(const struct nft_ctx *ctx, · 73 unmodified lines
79 return -EINVAL;79 return -EINVAL;
80 }80 }
81 81
82 return 0;82 return nf_ct_netns_get(ctx->net, ctx->afi->family);
83}83}
84EXPORT_SYMBOL_GPL(nft_redir_init);84EXPORT_SYMBOL_GPL(nft_redir_init);
85 85
@@ -108,4 +108,4 @@ nla_put_failure: · 22 unmodified lines
108EXPORT_SYMBOL_GPL(nft_redir_dump);108EXPORT_SYMBOL_GPL(nft_redir_dump);
109 109
110MODULE_LICENSE("GPL");110MODULE_LICENSE("GPL");
111MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");111MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
net/netfilter/nft_set_hash.c+18−7
@@ -167,6 +167,19 @@ static void nft_hash_activate(const struct net *net, const struct nft_set *set, · 166 unmodified lines
167 nft_set_elem_clear_busy(&he->ext);167 nft_set_elem_clear_busy(&he->ext);
168}168}
169 169
170static 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
170static void *nft_hash_deactivate(const struct net *net,183static void *nft_hash_deactivate(const struct net *net,
171 const struct nft_set *set,184 const struct nft_set *set,
172 const struct nft_set_elem *elem)185 const struct nft_set_elem *elem)
@@ -181,13 +194,10 @@ static void *nft_hash_deactivate(const struct net *net, · 8 unmodified lines
181 194
182 rcu_read_lock();195 rcu_read_lock();
183 he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params);196 he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params);
184 if (he != NULL) {197 if (he != NULL &&
185 if (!nft_set_elem_mark_busy(&he->ext) ||198 !nft_hash_deactivate_one(net, set, he))
186 !nft_is_active(net, &he->ext))199 he = NULL;
187 nft_set_elem_change_active(net, set, &he->ext);200
188 else
189 he = NULL;
190 }
191 rcu_read_unlock();201 rcu_read_unlock();
192 202
193 return he;203 return he;
@@ -387,6 +397,7 @@ static struct nft_set_ops nft_hash_ops __read_mostly = { · 193 unmodified lines
387 .insert = nft_hash_insert,397 .insert = nft_hash_insert,
388 .activate = nft_hash_activate,398 .activate = nft_hash_activate,
389 .deactivate = nft_hash_deactivate,399 .deactivate = nft_hash_deactivate,
400 .deactivate_one = nft_hash_deactivate_one,
390 .remove = nft_hash_remove,401 .remove = nft_hash_remove,
391 .lookup = nft_hash_lookup,402 .lookup = nft_hash_lookup,
392 .update = nft_hash_update,403 .update = nft_hash_update,
net/netfilter/nft_set_rbtree.c+11−1
@@ -171,6 +171,15 @@ static void nft_rbtree_activate(const struct net *net, · 170 unmodified lines
171 nft_set_elem_change_active(net, set, &rbe->ext);171 nft_set_elem_change_active(net, set, &rbe->ext);
172}172}
173 173
174static 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
174static void *nft_rbtree_deactivate(const struct net *net,183static void *nft_rbtree_deactivate(const struct net *net,
175 const struct nft_set *set,184 const struct nft_set *set,
176 const struct nft_set_elem *elem)185 const struct nft_set_elem *elem)
@@ -204,7 +213,7 @@ static void *nft_rbtree_deactivate(const struct net *net, · 27 unmodified lines
204 parent = parent->rb_right;213 parent = parent->rb_right;
205 continue;214 continue;
206 }215 }
207 nft_set_elem_change_active(net, set, &rbe->ext);216 nft_rbtree_deactivate_one(net, set, rbe);
208 return rbe;217 return rbe;
209 }218 }
210 }219 }
@@ -295,6 +304,7 @@ static struct nft_set_ops nft_rbtree_ops __read_mostly = { · 84 unmodified lines
295 .insert = nft_rbtree_insert,304 .insert = nft_rbtree_insert,
296 .remove = nft_rbtree_remove,305 .remove = nft_rbtree_remove,
297 .deactivate = nft_rbtree_deactivate,306 .deactivate = nft_rbtree_deactivate,
307 .deactivate_one = nft_rbtree_deactivate_one,
298 .activate = nft_rbtree_activate,308 .activate = nft_rbtree_activate,
299 .lookup = nft_rbtree_lookup,309 .lookup = nft_rbtree_lookup,
300 .walk = nft_rbtree_walk,310 .walk = nft_rbtree_walk,
net/netfilter/x_tables.c+57−1
@@ -40,6 +40,7 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); · 39 unmodified lines
40MODULE_DESCRIPTION("{ip,ip6,arp,eb}_tables backend module");40MODULE_DESCRIPTION("{ip,ip6,arp,eb}_tables backend module");
41 41
42#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))42#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
43#define XT_PCPU_BLOCK_SIZE 4096
43 44
44struct compat_delta {45struct compat_delta {
45 unsigned int offset; /* offset in kernel */46 unsigned int offset; /* offset in kernel */
@@ -958,7 +959,9 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size) · 912 unmodified lines
958 if (sz <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER))959 if (sz <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER))
959 info = kmalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);960 info = kmalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
960 if (!info) {961 if (!info) {
961 info = vmalloc(sz);962 info = __vmalloc(sz, GFP_KERNEL | __GFP_NOWARN |
963 __GFP_NORETRY | __GFP_HIGHMEM,
964 PAGE_KERNEL);
962 if (!info)965 if (!info)
963 return NULL;966 return NULL;
964 }967 }
@@ -1615,6 +1618,59 @@ void xt_proto_fini(struct net *net, u_int8_t af) · 650 unmodified lines
1615}1618}
1616EXPORT_SYMBOL_GPL(xt_proto_fini);1619EXPORT_SYMBOL_GPL(xt_proto_fini);
1617 1620
1621/**
1622 * xt_percpu_counter_alloc - allocate x_tables rule counter
1623 *
1624 * @state: pointer to xt_percpu allocation state
1625 * @counter: pointer to counter struct inside the ip(6)/arpt_entry struct
1626 *
1627 * On SMP, the packet counter [ ip(6)t_entry->counters.pcnt ] will then
1628 * contain the address of the real (percpu) counter.
1629 *
1630 * Rule evaluation needs to use xt_get_this_cpu_counter() helper
1631 * to fetch the real percpu counter.
1632 *
1633 * To speed up allocation and improve data locality, a 4kb block is
1634 * allocated.
1635 *
1636 * xt_percpu_counter_alloc_state contains the base address of the
1637 * allocated page and the current sub-offset.
1638 *
1639 * returns false on error.
1640 */
1641bool xt_percpu_counter_alloc(struct xt_percpu_counter_alloc_state *state,
1642 struct xt_counters *counter)
1643{
1644 BUILD_BUG_ON(XT_PCPU_BLOCK_SIZE < (sizeof(*counter) * 2));
1645
1646 if (nr_cpu_ids <= 1)
1647 return true;
1648
1649 if (!state->mem) {
1650 state->mem = __alloc_percpu(XT_PCPU_BLOCK_SIZE,
1651 XT_PCPU_BLOCK_SIZE);
1652 if (!state->mem)
1653 return false;
1654 }
1655 counter->pcnt = (__force unsigned long)(state->mem + state->off);
1656 state->off += sizeof(*counter);
1657 if (state->off > (XT_PCPU_BLOCK_SIZE - sizeof(*counter))) {
1658 state->mem = NULL;
1659 state->off = 0;
1660 }
1661 return true;
1662}
1663EXPORT_SYMBOL_GPL(xt_percpu_counter_alloc);
1664
1665void xt_percpu_counter_free(struct xt_counters *counters)
1666{
1667 unsigned long pcnt = counters->pcnt;
1668
1669 if (nr_cpu_ids > 1 && (pcnt & (XT_PCPU_BLOCK_SIZE - 1)) == 0)
1670 free_percpu((void __percpu *)pcnt);
1671}
1672EXPORT_SYMBOL_GPL(xt_percpu_counter_free);
1673
1618static int __net_init xt_net_init(struct net *net)1674static int __net_init xt_net_init(struct net *net)
1619{1675{
1620 int i;1676 int i;
net/netfilter/xt_CONNSECMARK.c+2−2
@@ -106,7 +106,7 @@ static int connsecmark_tg_check(const struct xt_tgchk_param *par) · 105 unmodified lines
106 return -EINVAL;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 if (ret < 0)110 if (ret < 0)
111 pr_info("cannot load conntrack support for proto=%u\n",111 pr_info("cannot load conntrack support for proto=%u\n",
112 par->family);112 par->family);
@@ -115,7 +115,7 @@ static int connsecmark_tg_check(const struct xt_tgchk_param *par) · 2 unmodified lines
115 115
116static void connsecmark_tg_destroy(const struct xt_tgdtor_param *par)116static 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
121static struct xt_target connsecmark_tg_reg __read_mostly = {121static struct xt_target connsecmark_tg_reg __read_mostly = {
net/netfilter/xt_CT.c+3−3
@@ -216,7 +216,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par, · 215 unmodified lines
216 goto err1;216 goto err1;
217#endif217#endif
218 218
219 ret = nf_ct_l3proto_try_module_get(par->family);219 ret = nf_ct_netns_get(par->net, par->family);
220 if (ret < 0)220 if (ret < 0)
221 goto err1;221 goto err1;
222 222
@@ -260,7 +260,7 @@ out: · 37 unmodified lines
260err3:260err3:
261 nf_ct_tmpl_free(ct);261 nf_ct_tmpl_free(ct);
262err2:262err2:
263 nf_ct_l3proto_module_put(par->family);263 nf_ct_netns_put(par->net, par->family);
264err1:264err1:
265 return ret;265 return ret;
266}266}
@@ -341,7 +341,7 @@ static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par, · 74 unmodified lines
341 if (help)341 if (help)
342 module_put(help->helper->me);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 xt_ct_destroy_timeout(ct);346 xt_ct_destroy_timeout(ct);
347 nf_ct_put(info->ct);347 nf_ct_put(info->ct);
net/netfilter/xt_NETMAP.c+9−2
@@ -60,7 +60,12 @@ static int netmap_tg6_checkentry(const struct xt_tgchk_param *par) · 59 unmodified lines
60 60
61 if (!(range->flags & NF_NAT_RANGE_MAP_IPS))61 if (!(range->flags & NF_NAT_RANGE_MAP_IPS))
62 return -EINVAL;62 return -EINVAL;
63 return 0;63 return nf_ct_netns_get(par->net, par->family);
64}
65
66static void netmap_tg_destroy(const struct xt_tgdtor_param *par)
67{
68 nf_ct_netns_put(par->net, par->family);
64}69}
65 70
66static unsigned int71static unsigned int
@@ -111,7 +116,7 @@ static int netmap_tg4_check(const struct xt_tgchk_param *par) · 44 unmodified lines
111 pr_debug("bad rangesize %u.\n", mr->rangesize);116 pr_debug("bad rangesize %u.\n", mr->rangesize);
112 return -EINVAL;117 return -EINVAL;
113 }118 }
114 return 0;119 return nf_ct_netns_get(par->net, par->family);
115}120}
116 121
117static struct xt_target netmap_tg_reg[] __read_mostly = {122static struct xt_target netmap_tg_reg[] __read_mostly = {
@@ -127,6 +132,7 @@ static struct xt_target netmap_tg_reg[] __read_mostly = { · 9 unmodified lines
127 (1 << NF_INET_LOCAL_OUT) |132 (1 << NF_INET_LOCAL_OUT) |
128 (1 << NF_INET_LOCAL_IN),133 (1 << NF_INET_LOCAL_IN),
129 .checkentry = netmap_tg6_checkentry,134 .checkentry = netmap_tg6_checkentry,
135 .destroy = netmap_tg_destroy,
130 .me = THIS_MODULE,136 .me = THIS_MODULE,
131 },137 },
132 {138 {
@@ -141,6 +147,7 @@ static struct xt_target netmap_tg_reg[] __read_mostly = { · 8 unmodified lines
141 (1 << NF_INET_LOCAL_OUT) |147 (1 << NF_INET_LOCAL_OUT) |
142 (1 << NF_INET_LOCAL_IN),148 (1 << NF_INET_LOCAL_IN),
143 .checkentry = netmap_tg4_check,149 .checkentry = netmap_tg4_check,
150 .destroy = netmap_tg_destroy,
144 .me = THIS_MODULE,151 .me = THIS_MODULE,
145 },152 },
146};153};
net/netfilter/xt_REDIRECT.c+10−2
@@ -40,7 +40,13 @@ static int redirect_tg6_checkentry(const struct xt_tgchk_param *par) · 39 unmodified lines
40 40
41 if (range->flags & NF_NAT_RANGE_MAP_IPS)41 if (range->flags & NF_NAT_RANGE_MAP_IPS)
42 return -EINVAL;42 return -EINVAL;
43 return 0;43
44 return nf_ct_netns_get(par->net, par->family);
45}
46
47static 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/* FIXME: Take multiple ranges --RR */52/* FIXME: Take multiple ranges --RR */
@@ -56,7 +62,7 @@ static int redirect_tg4_check(const struct xt_tgchk_param *par) · 9 unmodified lines
56 pr_debug("bad rangesize %u.\n", mr->rangesize);62 pr_debug("bad rangesize %u.\n", mr->rangesize);
57 return -EINVAL;63 return -EINVAL;
58 }64 }
59 return 0;65 return nf_ct_netns_get(par->net, par->family);
60}66}
61 67
62static unsigned int68static unsigned int
@@ -72,6 +78,7 @@ static struct xt_target redirect_tg_reg[] __read_mostly = { · 9 unmodified lines
72 .revision = 0,78 .revision = 0,
73 .table = "nat",79 .table = "nat",
74 .checkentry = redirect_tg6_checkentry,80 .checkentry = redirect_tg6_checkentry,
81 .destroy = redirect_tg_destroy,
75 .target = redirect_tg6,82 .target = redirect_tg6,
76 .targetsize = sizeof(struct nf_nat_range),83 .targetsize = sizeof(struct nf_nat_range),
77 .hooks = (1 << NF_INET_PRE_ROUTING) |84 .hooks = (1 << NF_INET_PRE_ROUTING) |
@@ -85,6 +92,7 @@ static struct xt_target redirect_tg_reg[] __read_mostly = { · 7 unmodified lines
85 .table = "nat",92 .table = "nat",
86 .target = redirect_tg4,93 .target = redirect_tg4,
87 .checkentry = redirect_tg4_check,94 .checkentry = redirect_tg4_check,
95 .destroy = redirect_tg_destroy,
88 .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),96 .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),
89 .hooks = (1 << NF_INET_PRE_ROUTING) |97 .hooks = (1 << NF_INET_PRE_ROUTING) |
90 (1 << NF_INET_LOCAL_OUT),98 (1 << NF_INET_LOCAL_OUT),
net/netfilter/xt_TPROXY.c+10−5
@@ -531,6 +531,11 @@ tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par) · 530 unmodified lines
531static int tproxy_tg6_check(const struct xt_tgchk_param *par)531static int tproxy_tg6_check(const struct xt_tgchk_param *par)
532{532{
533 const struct ip6t_ip6 *i = par->entryinfo;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 if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP) &&540 if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP) &&
536 !(i->invflags & IP6T_INV_PROTO))541 !(i->invflags & IP6T_INV_PROTO))
@@ -545,6 +550,11 @@ static int tproxy_tg6_check(const struct xt_tgchk_param *par) · 8 unmodified lines
545static int tproxy_tg4_check(const struct xt_tgchk_param *par)550static int tproxy_tg4_check(const struct xt_tgchk_param *par)
546{551{
547 const struct ipt_ip *i = par->entryinfo;552 const struct ipt_ip *i = par->entryinfo;
553 int err;
554
555 err = nf_defrag_ipv4_enable(par->net);
556 if (err)
557 return err;
548 558
549 if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP)559 if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP)
550 && !(i->invflags & IPT_INV_PROTO))560 && !(i->invflags & IPT_INV_PROTO))
@@ -596,11 +606,6 @@ static struct xt_target tproxy_tg_reg[] __read_mostly = { · 45 unmodified lines
596 606
597static int __init tproxy_tg_init(void)607static int __init tproxy_tg_init(void)
598{608{
599 nf_defrag_ipv4_enable();
600#ifdef XT_TPROXY_HAVE_IPV6
601 nf_defrag_ipv6_enable();
602#endif
603
604 return xt_register_targets(tproxy_tg_reg, ARRAY_SIZE(tproxy_tg_reg));609 return xt_register_targets(tproxy_tg_reg, ARRAY_SIZE(tproxy_tg_reg));
605}610}
606 611
net/netfilter/xt_bpf.c+80−16
@@ -10,6 +10,7 @@ · 9 unmodified lines
10#include <linux/module.h>10#include <linux/module.h>
11#include <linux/skbuff.h>11#include <linux/skbuff.h>
12#include <linux/filter.h>12#include <linux/filter.h>
13#include <linux/bpf.h>
13 14
14#include <linux/netfilter/xt_bpf.h>15#include <linux/netfilter/xt_bpf.h>
15#include <linux/netfilter/x_tables.h>16#include <linux/netfilter/x_tables.h>
@@ -20,15 +21,15 @@ MODULE_LICENSE("GPL"); · 4 unmodified lines
20MODULE_ALIAS("ipt_bpf");21MODULE_ALIAS("ipt_bpf");
21MODULE_ALIAS("ip6t_bpf");22MODULE_ALIAS("ip6t_bpf");
22 23
23static int bpf_mt_check(const struct xt_mtchk_param *par)24static int __bpf_mt_check_bytecode(struct sock_filter *insns, __u16 len,
25 struct bpf_prog **ret)
24{26{
25 struct xt_bpf_info *info = par->matchinfo;
26 struct sock_fprog_kern program;27 struct sock_fprog_kern program;
27 28
28 program.len = info->bpf_program_num_elem;29 program.len = len;
29 program.filter = info->bpf_program;30 program.filter = insns;
30 31
31 if (bpf_prog_create(&info->filter, &program)) {32 if (bpf_prog_create(ret, &program)) {
32 pr_info("bpf: check failed: parse error\n");33 pr_info("bpf: check failed: parse error\n");
33 return -EINVAL;34 return -EINVAL;
34 }35 }
@@ -36,6 +37,42 @@ static int bpf_mt_check(const struct xt_mtchk_param *par) · 1 unmodified line
36 return 0;37 return 0;
37}38}
38 39
40static int __bpf_mt_check_fd(int fd, struct bpf_prog **ret)
41{
42 struct bpf_prog *prog;
43
44 prog = bpf_prog_get_type(fd, BPF_PROG_TYPE_SOCKET_FILTER);
45 if (IS_ERR(prog))
46 return PTR_ERR(prog);
47
48 *ret = prog;
49 return 0;
50}
51
52static int bpf_mt_check(const struct xt_mtchk_param *par)
53{
54 struct xt_bpf_info *info = par->matchinfo;
55
56 return __bpf_mt_check_bytecode(info->bpf_program,
57 info->bpf_program_num_elem,
58 &info->filter);
59}
60
61static int bpf_mt_check_v1(const struct xt_mtchk_param *par)
62{
63 struct xt_bpf_info_v1 *info = par->matchinfo;
64
65 if (info->mode == XT_BPF_MODE_BYTECODE)
66 return __bpf_mt_check_bytecode(info->bpf_program,
67 info->bpf_program_num_elem,
68 &info->filter);
69 else if (info->mode == XT_BPF_MODE_FD_PINNED ||
70 info->mode == XT_BPF_MODE_FD_ELF)
71 return __bpf_mt_check_fd(info->fd, &info->filter);
72 else
73 return -EINVAL;
74}
75
39static bool bpf_mt(const struct sk_buff *skb, struct xt_action_param *par)76static bool bpf_mt(const struct sk_buff *skb, struct xt_action_param *par)
40{77{
41 const struct xt_bpf_info *info = par->matchinfo;78 const struct xt_bpf_info *info = par->matchinfo;
@@ -43,31 +80,58 @@ static bool bpf_mt(const struct sk_buff *skb, struct xt_action_param *par) · 1 unmodified line
43 return BPF_PROG_RUN(info->filter, skb);80 return BPF_PROG_RUN(info->filter, skb);
44}81}
45 82
83static bool bpf_mt_v1(const struct sk_buff *skb, struct xt_action_param *par)
84{
85 const struct xt_bpf_info_v1 *info = par->matchinfo;
86
87 return !!bpf_prog_run_save_cb(info->filter, (struct sk_buff *) skb);
88}
89
46static void bpf_mt_destroy(const struct xt_mtdtor_param *par)90static void bpf_mt_destroy(const struct xt_mtdtor_param *par)
47{91{
48 const struct xt_bpf_info *info = par->matchinfo;92 const struct xt_bpf_info *info = par->matchinfo;
93
94 bpf_prog_destroy(info->filter);
95}
96
97static void bpf_mt_destroy_v1(const struct xt_mtdtor_param *par)
98{
99 const struct xt_bpf_info_v1 *info = par->matchinfo;
100
49 bpf_prog_destroy(info->filter);101 bpf_prog_destroy(info->filter);
50}102}
51 103
52static struct xt_match bpf_mt_reg __read_mostly = {104static struct xt_match bpf_mt_reg[] __read_mostly = {
53 .name = "bpf",105 {
54 .revision = 0,106 .name = "bpf",
55 .family = NFPROTO_UNSPEC,107 .revision = 0,
56 .checkentry = bpf_mt_check,108 .family = NFPROTO_UNSPEC,
57 .match = bpf_mt,109 .checkentry = bpf_mt_check,
58 .destroy = bpf_mt_destroy,110 .match = bpf_mt,
59 .matchsize = sizeof(struct xt_bpf_info),111 .destroy = bpf_mt_destroy,
60 .me = THIS_MODULE,112 .matchsize = sizeof(struct xt_bpf_info),
113 .me = THIS_MODULE,
114 },
115 {
116 .name = "bpf",
117 .revision = 1,
118 .family = NFPROTO_UNSPEC,
119 .checkentry = bpf_mt_check_v1,
120 .match = bpf_mt_v1,
121 .destroy = bpf_mt_destroy_v1,
122 .matchsize = sizeof(struct xt_bpf_info_v1),
123 .me = THIS_MODULE,
124 },
61};125};
62 126
63static int __init bpf_mt_init(void)127static int __init bpf_mt_init(void)
64{128{
65 return xt_register_match(&bpf_mt_reg);129 return xt_register_matches(bpf_mt_reg, ARRAY_SIZE(bpf_mt_reg));
66}130}
67 131
68static void __exit bpf_mt_exit(void)132static void __exit bpf_mt_exit(void)
69{133{
70 xt_unregister_match(&bpf_mt_reg);134 xt_unregister_matches(bpf_mt_reg, ARRAY_SIZE(bpf_mt_reg));
71}135}
72 136
73module_init(bpf_mt_init);137module_init(bpf_mt_init);
net/netfilter/xt_connbytes.c+2−2
@@ -110,7 +110,7 @@ static int connbytes_mt_check(const struct xt_mtchk_param *par) · 109 unmodified lines
110 sinfo->direction != XT_CONNBYTES_DIR_BOTH)110 sinfo->direction != XT_CONNBYTES_DIR_BOTH)
111 return -EINVAL;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 if (ret < 0)114 if (ret < 0)
115 pr_info("cannot load conntrack support for proto=%u\n",115 pr_info("cannot load conntrack support for proto=%u\n",
116 par->family);116 par->family);
@@ -129,7 +129,7 @@ static int connbytes_mt_check(const struct xt_mtchk_param *par) · 12 unmodified lines
129 129
130static void connbytes_mt_destroy(const struct xt_mtdtor_param *par)130static 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
135static struct xt_match connbytes_mt_reg __read_mostly = {135static struct xt_match connbytes_mt_reg __read_mostly = {
net/netfilter/xt_connlabel.c+3−3
@@ -61,7 +61,7 @@ static int connlabel_mt_check(const struct xt_mtchk_param *par) · 60 unmodified lines
61 return -EINVAL;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 if (ret < 0) {65 if (ret < 0) {
66 pr_info("cannot load conntrack support for proto=%u\n",66 pr_info("cannot load conntrack support for proto=%u\n",
67 par->family);67 par->family);
@@ -70,14 +70,14 @@ static int connlabel_mt_check(const struct xt_mtchk_param *par) · 2 unmodified lines
70 70
71 ret = nf_connlabels_get(par->net, info->bit);71 ret = nf_connlabels_get(par->net, info->bit);
72 if (ret < 0)72 if (ret < 0)
73 nf_ct_l3proto_module_put(par->family);73 nf_ct_netns_put(par->net, par->family);
74 return ret;74 return ret;
75}75}
76 76
77static void connlabel_mt_destroy(const struct xt_mtdtor_param *par)77static void connlabel_mt_destroy(const struct xt_mtdtor_param *par)
78{78{
79 nf_connlabels_put(par->net);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
83static struct xt_match connlabels_mt_reg __read_mostly = {83static struct xt_match connlabels_mt_reg __read_mostly = {
net/netfilter/xt_connlimit.c+3−3
@@ -368,7 +368,7 @@ static int connlimit_mt_check(const struct xt_mtchk_param *par) · 367 unmodified lines
368 368
369 net_get_random_once(&connlimit_rnd, sizeof(connlimit_rnd));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 if (ret < 0) {372 if (ret < 0) {
373 pr_info("cannot load conntrack support for "373 pr_info("cannot load conntrack support for "
374 "address family %u\n", par->family);374 "address family %u\n", par->family);
@@ -378,7 +378,7 @@ static int connlimit_mt_check(const struct xt_mtchk_param *par) · 3 unmodified lines
378 /* init private data */378 /* init private data */
379 info->data = kmalloc(sizeof(struct xt_connlimit_data), GFP_KERNEL);379 info->data = kmalloc(sizeof(struct xt_connlimit_data), GFP_KERNEL);
380 if (info->data == NULL) {380 if (info->data == NULL) {
381 nf_ct_l3proto_module_put(par->family);381 nf_ct_netns_put(par->net, par->family);
382 return -ENOMEM;382 return -ENOMEM;
383 }383 }
384 384
@@ -414,7 +414,7 @@ static void connlimit_mt_destroy(const struct xt_mtdtor_param *par) · 29 unmodified lines
414 const struct xt_connlimit_info *info = par->matchinfo;414 const struct xt_connlimit_info *info = par->matchinfo;
415 unsigned int i;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 for (i = 0; i < ARRAY_SIZE(info->data->climit_root4); ++i)419 for (i = 0; i < ARRAY_SIZE(info->data->climit_root4); ++i)
420 destroy_tree(&info->data->climit_root4[i]);420 destroy_tree(&info->data->climit_root4[i]);
net/netfilter/xt_connmark.c+4−4
@@ -77,7 +77,7 @@ static int connmark_tg_check(const struct xt_tgchk_param *par) · 76 unmodified lines
77{77{
78 int ret;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 if (ret < 0)81 if (ret < 0)
82 pr_info("cannot load conntrack support for proto=%u\n",82 pr_info("cannot load conntrack support for proto=%u\n",
83 par->family);83 par->family);
@@ -86,7 +86,7 @@ static int connmark_tg_check(const struct xt_tgchk_param *par) · 2 unmodified lines
86 86
87static void connmark_tg_destroy(const struct xt_tgdtor_param *par)87static 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
92static bool92static bool
@@ -107,7 +107,7 @@ static int connmark_mt_check(const struct xt_mtchk_param *par) · 14 unmodified lines
107{107{
108 int ret;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 if (ret < 0)111 if (ret < 0)
112 pr_info("cannot load conntrack support for proto=%u\n",112 pr_info("cannot load conntrack support for proto=%u\n",
113 par->family);113 par->family);
@@ -116,7 +116,7 @@ static int connmark_mt_check(const struct xt_mtchk_param *par) · 2 unmodified lines
116 116
117static void connmark_mt_destroy(const struct xt_mtdtor_param *par)117static 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
122static struct xt_target connmark_tg_reg __read_mostly = {122static struct xt_target connmark_tg_reg __read_mostly = {
net/netfilter/xt_conntrack.c+2−2
@@ -271,7 +271,7 @@ static int conntrack_mt_check(const struct xt_mtchk_param *par) · 270 unmodified lines
271{271{
272 int ret;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 if (ret < 0)275 if (ret < 0)
276 pr_info("cannot load conntrack support for proto=%u\n",276 pr_info("cannot load conntrack support for proto=%u\n",
277 par->family);277 par->family);
@@ -280,7 +280,7 @@ static int conntrack_mt_check(const struct xt_mtchk_param *par) · 2 unmodified lines
280 280
281static void conntrack_mt_destroy(const struct xt_mtdtor_param *par)281static 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
286static struct xt_match conntrack_mt_reg[] __read_mostly = {286static struct xt_match conntrack_mt_reg[] __read_mostly = {
net/netfilter/xt_helper.c+2−2
@@ -59,7 +59,7 @@ static int helper_mt_check(const struct xt_mtchk_param *par) · 58 unmodified lines
59 struct xt_helper_info *info = par->matchinfo;59 struct xt_helper_info *info = par->matchinfo;
60 int ret;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 if (ret < 0) {63 if (ret < 0) {
64 pr_info("cannot load conntrack support for proto=%u\n",64 pr_info("cannot load conntrack support for proto=%u\n",
65 par->family);65 par->family);
@@ -71,7 +71,7 @@ static int helper_mt_check(const struct xt_mtchk_param *par) · 5 unmodified lines
71 71
72static void helper_mt_destroy(const struct xt_mtdtor_param *par)72static 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
77static struct xt_match helper_mt_reg __read_mostly = {77static struct xt_match helper_mt_reg __read_mostly = {
net/netfilter/xt_multiport.c+19−7
@@ -44,12 +44,18 @@ ports_match_v1(const struct xt_multiport_v1 *minfo, · 43 unmodified lines
44 44
45 switch (minfo->flags) {45 switch (minfo->flags) {
46 case XT_MULTIPORT_SOURCE: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 case XT_MULTIPORT_DESTINATION: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 case XT_MULTIPORT_EITHER:54 case XT_MULTIPORT_EITHER:
51 return ((dst >= s && dst <= e) ||55 if ((dst >= s && dst <= e) ||
52 (src >= s && src <= e)) ^ minfo->invert;56 (src >= s && src <= e))
57 return true ^ minfo->invert;
58 break;
53 default:59 default:
54 break;60 break;
55 }61 }
@@ -59,11 +65,17 @@ ports_match_v1(const struct xt_multiport_v1 *minfo, · 3 unmodified lines
59 65
60 switch (minfo->flags) {66 switch (minfo->flags) {
61 case XT_MULTIPORT_SOURCE:67 case XT_MULTIPORT_SOURCE:
62 return (src == s) ^ minfo->invert;68 if (src == s)
69 return true ^ minfo->invert;
70 break;
63 case XT_MULTIPORT_DESTINATION:71 case XT_MULTIPORT_DESTINATION:
64 return (dst == s) ^ minfo->invert;72 if (dst == s)
73 return true ^ minfo->invert;
74 break;
65 case XT_MULTIPORT_EITHER:75 case XT_MULTIPORT_EITHER:
66 return (src == s || dst == s) ^ minfo->invert;76 if (src == s || dst == s)
77 return true ^ minfo->invert;
78 break;
67 default:79 default:
68 break;80 break;
69 }81 }
net/netfilter/xt_nat.c+17−1
@@ -23,7 +23,17 @@ static int xt_nat_checkentry_v0(const struct xt_tgchk_param *par) · 22 unmodified lines
23 par->target->name);23 par->target->name);
24 return -EINVAL;24 return -EINVAL;
25 }25 }
26 return 0;26 return nf_ct_netns_get(par->net, par->family);
27}
28
29static int xt_nat_checkentry(const struct xt_tgchk_param *par)
30{
31 return nf_ct_netns_get(par->net, par->family);
32}
33
34static void xt_nat_destroy(const struct xt_tgdtor_param *par)
35{
36 nf_ct_netns_put(par->net, par->family);
27}37}
28 38
29static void xt_nat_convert_range(struct nf_nat_range *dst,39static void xt_nat_convert_range(struct nf_nat_range *dst,
@@ -106,6 +116,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { · 76 unmodified lines
106 .name = "SNAT",116 .name = "SNAT",
107 .revision = 0,117 .revision = 0,
108 .checkentry = xt_nat_checkentry_v0,118 .checkentry = xt_nat_checkentry_v0,
119 .destroy = xt_nat_destroy,
109 .target = xt_snat_target_v0,120 .target = xt_snat_target_v0,
110 .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),121 .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),
111 .family = NFPROTO_IPV4,122 .family = NFPROTO_IPV4,
@@ -118,6 +129,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { · 6 unmodified lines
118 .name = "DNAT",129 .name = "DNAT",
119 .revision = 0,130 .revision = 0,
120 .checkentry = xt_nat_checkentry_v0,131 .checkentry = xt_nat_checkentry_v0,
132 .destroy = xt_nat_destroy,
121 .target = xt_dnat_target_v0,133 .target = xt_dnat_target_v0,
122 .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),134 .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),
123 .family = NFPROTO_IPV4,135 .family = NFPROTO_IPV4,
@@ -129,6 +141,8 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { · 5 unmodified lines
129 {141 {
130 .name = "SNAT",142 .name = "SNAT",
131 .revision = 1,143 .revision = 1,
144 .checkentry = xt_nat_checkentry,
145 .destroy = xt_nat_destroy,
132 .target = xt_snat_target_v1,146 .target = xt_snat_target_v1,
133 .targetsize = sizeof(struct nf_nat_range),147 .targetsize = sizeof(struct nf_nat_range),
134 .table = "nat",148 .table = "nat",
@@ -139,6 +153,8 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { · 4 unmodified lines
139 {153 {
140 .name = "DNAT",154 .name = "DNAT",
141 .revision = 1,155 .revision = 1,
156 .checkentry = xt_nat_checkentry,
157 .destroy = xt_nat_destroy,
142 .target = xt_dnat_target_v1,158 .target = xt_dnat_target_v1,
143 .targetsize = sizeof(struct nf_nat_range),159 .targetsize = sizeof(struct nf_nat_range),
144 .table = "nat",160 .table = "nat",
net/netfilter/xt_socket.c+28−5
@@ -147,9 +147,28 @@ socket_mt6_v1_v2_v3(const struct sk_buff *skb, struct xt_action_param *par) · 146 unmodified lines
147}147}
148#endif148#endif
149 149
150static 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
150static int socket_mt_v1_check(const struct xt_mtchk_param *par)164static int socket_mt_v1_check(const struct xt_mtchk_param *par)
151{165{
152 const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo;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 if (info->flags & ~XT_SOCKET_FLAGS_V1) {173 if (info->flags & ~XT_SOCKET_FLAGS_V1) {
155 pr_info("unknown flags 0x%x\n", info->flags & ~XT_SOCKET_FLAGS_V1);174 pr_info("unknown flags 0x%x\n", info->flags & ~XT_SOCKET_FLAGS_V1);
@@ -161,6 +180,11 @@ static int socket_mt_v1_check(const struct xt_mtchk_param *par) · 5 unmodified lines
161static int socket_mt_v2_check(const struct xt_mtchk_param *par)180static int socket_mt_v2_check(const struct xt_mtchk_param *par)
162{181{
163 const struct xt_socket_mtinfo2 *info = (struct xt_socket_mtinfo2 *) par->matchinfo;182 const struct xt_socket_mtinfo2 *info = (struct xt_socket_mtinfo2 *) par->matchinfo;
183 int err;
184
185 err = socket_mt_enable_defrag(par->net, par->family);
186 if (err)
187 return err;
164 188
165 if (info->flags & ~XT_SOCKET_FLAGS_V2) {189 if (info->flags & ~XT_SOCKET_FLAGS_V2) {
166 pr_info("unknown flags 0x%x\n", info->flags & ~XT_SOCKET_FLAGS_V2);190 pr_info("unknown flags 0x%x\n", info->flags & ~XT_SOCKET_FLAGS_V2);
@@ -173,7 +197,11 @@ static int socket_mt_v3_check(const struct xt_mtchk_param *par) · 6 unmodified lines
173{197{
174 const struct xt_socket_mtinfo3 *info =198 const struct xt_socket_mtinfo3 *info =
175 (struct xt_socket_mtinfo3 *)par->matchinfo;199 (struct xt_socket_mtinfo3 *)par->matchinfo;
200 int err;
176 201
202 err = socket_mt_enable_defrag(par->net, par->family);
203 if (err)
204 return err;
177 if (info->flags & ~XT_SOCKET_FLAGS_V3) {205 if (info->flags & ~XT_SOCKET_FLAGS_V3) {
178 pr_info("unknown flags 0x%x\n",206 pr_info("unknown flags 0x%x\n",
179 info->flags & ~XT_SOCKET_FLAGS_V3);207 info->flags & ~XT_SOCKET_FLAGS_V3);
@@ -268,11 +296,6 @@ static struct xt_match socket_mt_reg[] __read_mostly = { · 88 unmodified lines
268 296
269static int __init socket_mt_init(void)297static int __init socket_mt_init(void)
270{298{
271 nf_defrag_ipv4_enable();
272#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
273 nf_defrag_ipv6_enable();
274#endif
275
276 return xt_register_matches(socket_mt_reg, ARRAY_SIZE(socket_mt_reg));299 return xt_register_matches(socket_mt_reg, ARRAY_SIZE(socket_mt_reg));
277}300}
278 301
net/netfilter/xt_state.c+2−2
@@ -43,7 +43,7 @@ static int state_mt_check(const struct xt_mtchk_param *par) · 42 unmodified lines
43{43{
44 int ret;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 if (ret < 0)47 if (ret < 0)
48 pr_info("cannot load conntrack support for proto=%u\n",48 pr_info("cannot load conntrack support for proto=%u\n",
49 par->family);49 par->family);
@@ -52,7 +52,7 @@ static int state_mt_check(const struct xt_mtchk_param *par) · 2 unmodified lines
52 52
53static void state_mt_destroy(const struct xt_mtdtor_param *par)53static 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
58static struct xt_match state_mt_reg __read_mostly = {58static struct xt_match state_mt_reg __read_mostly = {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t