aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-08-10 13:33:08 -0400
committerDavid S. Miller <davem@davemloft.net>2018-08-10 13:33:08 -0400
commitfd685657cd5441e504113db1928196d030c8c414 (patch)
tree947d6d4401a9f34659f8954fcd5e2e8eda1efbb4
parentebddd97afb89cb1e88cc037aef2913ad4723a59f (diff)
parente7ea2a52ffaf60a211edc0df97dcf194d1257714 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
Pablo Neira Ayuso says: ==================== Netfilter updates for net-next The following batch contains netfilter updates for your net-next tree: 1) Expose NFT_OSF_MAXGENRELEN maximum OS name length from the new OS passive fingerprint matching extension, from Fernando Fernandez. 2) Add extension to support for fine grain conntrack timeout policies from nf_tables. As preparation works, this patchset moves nf_ct_untimeout() to nf_conntrack_timeout and it also decouples the timeout policy from the ctnl_timeout object, most work done by Harsha Sharma. 3) Enable connection tracking when conntrack helper is in place. 4) Missing enumeration in uapi header when splitting original xt_osf to nfnetlink_osf, also from Fernando. 5) Fix a sparse warning due to incorrect typing in the nf_osf_find(), from Wei Yongjun. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netfilter/nfnetlink_osf.h12
-rw-r--r--include/net/netfilter/nf_conntrack_l4proto.h2
-rw-r--r--include/net/netfilter/nf_conntrack_timeout.h21
-rw-r--r--include/uapi/linux/netfilter/nf_tables.h15
-rw-r--r--include/uapi/linux/netfilter/nfnetlink_osf.h12
-rw-r--r--include/uapi/linux/netfilter/xt_osf.h1
-rw-r--r--net/netfilter/nf_conntrack_timeout.c21
-rw-r--r--net/netfilter/nfnetlink_cttimeout.c55
-rw-r--r--net/netfilter/nfnetlink_osf.c2
-rw-r--r--net/netfilter/nft_ct.c218
-rw-r--r--net/netfilter/nft_osf.c8
-rw-r--r--net/netfilter/xt_CT.c4
12 files changed, 304 insertions, 67 deletions
diff --git a/include/linux/netfilter/nfnetlink_osf.h b/include/linux/netfilter/nfnetlink_osf.h
index a7311bc03d3a..ecf7dab81e9e 100644
--- a/include/linux/netfilter/nfnetlink_osf.h
+++ b/include/linux/netfilter/nfnetlink_osf.h
@@ -4,18 +4,6 @@
4 4
5#include <uapi/linux/netfilter/nfnetlink_osf.h> 5#include <uapi/linux/netfilter/nfnetlink_osf.h>
6 6
7/* Initial window size option state machine: multiple of mss, mtu or
8 * plain numeric value. Can also be made as plain numeric value which
9 * is not a multiple of specified value.
10 */
11enum nf_osf_window_size_options {
12 OSF_WSS_PLAIN = 0,
13 OSF_WSS_MSS,
14 OSF_WSS_MTU,
15 OSF_WSS_MODULO,
16 OSF_WSS_MAX,
17};
18
19enum osf_fmatch_states { 7enum osf_fmatch_states {
20 /* Packet does not match the fingerprint */ 8 /* Packet does not match the fingerprint */
21 FMATCH_WRONG = 0, 9 FMATCH_WRONG = 0,
diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
index 6068c6da3eac..8465263b297d 100644
--- a/include/net/netfilter/nf_conntrack_l4proto.h
+++ b/include/net/netfilter/nf_conntrack_l4proto.h
@@ -77,7 +77,6 @@ struct nf_conntrack_l4proto {
77 struct nf_conntrack_tuple *t); 77 struct nf_conntrack_tuple *t);
78 const struct nla_policy *nla_policy; 78 const struct nla_policy *nla_policy;
79 79
80#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
81 struct { 80 struct {
82 int (*nlattr_to_obj)(struct nlattr *tb[], 81 int (*nlattr_to_obj)(struct nlattr *tb[],
83 struct net *net, void *data); 82 struct net *net, void *data);
@@ -87,7 +86,6 @@ struct nf_conntrack_l4proto {
87 u16 nlattr_max; 86 u16 nlattr_max;
88 const struct nla_policy *nla_policy; 87 const struct nla_policy *nla_policy;
89 } ctnl_timeout; 88 } ctnl_timeout;
90#endif
91#ifdef CONFIG_NF_CONNTRACK_PROCFS 89#ifdef CONFIG_NF_CONNTRACK_PROCFS
92 /* Print out the private part of the conntrack. */ 90 /* Print out the private part of the conntrack. */
93 void (*print_conntrack)(struct seq_file *s, struct nf_conn *); 91 void (*print_conntrack)(struct seq_file *s, struct nf_conn *);
diff --git a/include/net/netfilter/nf_conntrack_timeout.h b/include/net/netfilter/nf_conntrack_timeout.h
index 80ceb3d0291d..d5f62cc6c2ae 100644
--- a/include/net/netfilter/nf_conntrack_timeout.h
+++ b/include/net/netfilter/nf_conntrack_timeout.h
@@ -11,24 +11,28 @@
11 11
12#define CTNL_TIMEOUT_NAME_MAX 32 12#define CTNL_TIMEOUT_NAME_MAX 32
13 13
14struct nf_ct_timeout {
15 __u16 l3num;
16 const struct nf_conntrack_l4proto *l4proto;
17 char data[0];
18};
19
14struct ctnl_timeout { 20struct ctnl_timeout {
15 struct list_head head; 21 struct list_head head;
16 struct rcu_head rcu_head; 22 struct rcu_head rcu_head;
17 refcount_t refcnt; 23 refcount_t refcnt;
18 char name[CTNL_TIMEOUT_NAME_MAX]; 24 char name[CTNL_TIMEOUT_NAME_MAX];
19 __u16 l3num; 25 struct nf_ct_timeout timeout;
20 const struct nf_conntrack_l4proto *l4proto;
21 char data[0];
22}; 26};
23 27
24struct nf_conn_timeout { 28struct nf_conn_timeout {
25 struct ctnl_timeout __rcu *timeout; 29 struct nf_ct_timeout __rcu *timeout;
26}; 30};
27 31
28static inline unsigned int * 32static inline unsigned int *
29nf_ct_timeout_data(struct nf_conn_timeout *t) 33nf_ct_timeout_data(struct nf_conn_timeout *t)
30{ 34{
31 struct ctnl_timeout *timeout; 35 struct nf_ct_timeout *timeout;
32 36
33 timeout = rcu_dereference(t->timeout); 37 timeout = rcu_dereference(t->timeout);
34 if (timeout == NULL) 38 if (timeout == NULL)
@@ -49,7 +53,7 @@ struct nf_conn_timeout *nf_ct_timeout_find(const struct nf_conn *ct)
49 53
50static inline 54static inline
51struct nf_conn_timeout *nf_ct_timeout_ext_add(struct nf_conn *ct, 55struct nf_conn_timeout *nf_ct_timeout_ext_add(struct nf_conn *ct,
52 struct ctnl_timeout *timeout, 56 struct nf_ct_timeout *timeout,
53 gfp_t gfp) 57 gfp_t gfp)
54{ 58{
55#ifdef CONFIG_NF_CONNTRACK_TIMEOUT 59#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
@@ -83,6 +87,7 @@ static inline unsigned int *nf_ct_timeout_lookup(const struct nf_conn *ct)
83#ifdef CONFIG_NF_CONNTRACK_TIMEOUT 87#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
84int nf_conntrack_timeout_init(void); 88int nf_conntrack_timeout_init(void);
85void nf_conntrack_timeout_fini(void); 89void nf_conntrack_timeout_fini(void);
90void nf_ct_untimeout(struct net *net, struct nf_ct_timeout *timeout);
86#else 91#else
87static inline int nf_conntrack_timeout_init(void) 92static inline int nf_conntrack_timeout_init(void)
88{ 93{
@@ -96,8 +101,8 @@ static inline void nf_conntrack_timeout_fini(void)
96#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ 101#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
97 102
98#ifdef CONFIG_NF_CONNTRACK_TIMEOUT 103#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
99extern struct ctnl_timeout *(*nf_ct_timeout_find_get_hook)(struct net *net, const char *name); 104extern struct nf_ct_timeout *(*nf_ct_timeout_find_get_hook)(struct net *net, const char *name);
100extern void (*nf_ct_timeout_put_hook)(struct ctnl_timeout *timeout); 105extern void (*nf_ct_timeout_put_hook)(struct nf_ct_timeout *timeout);
101#endif 106#endif
102 107
103#endif /* _NF_CONNTRACK_TIMEOUT_H */ 108#endif /* _NF_CONNTRACK_TIMEOUT_H */
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 357862d948de..e23290ffdc77 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -8,6 +8,7 @@
8#define NFT_SET_MAXNAMELEN NFT_NAME_MAXLEN 8#define NFT_SET_MAXNAMELEN NFT_NAME_MAXLEN
9#define NFT_OBJ_MAXNAMELEN NFT_NAME_MAXLEN 9#define NFT_OBJ_MAXNAMELEN NFT_NAME_MAXLEN
10#define NFT_USERDATA_MAXLEN 256 10#define NFT_USERDATA_MAXLEN 256
11#define NFT_OSF_MAXGENRELEN 16
11 12
12/** 13/**
13 * enum nft_registers - nf_tables registers 14 * enum nft_registers - nf_tables registers
@@ -957,6 +958,7 @@ enum nft_socket_keys {
957 * @NFT_CT_DST_IP: conntrack layer 3 protocol destination (IPv4 address) 958 * @NFT_CT_DST_IP: conntrack layer 3 protocol destination (IPv4 address)
958 * @NFT_CT_SRC_IP6: conntrack layer 3 protocol source (IPv6 address) 959 * @NFT_CT_SRC_IP6: conntrack layer 3 protocol source (IPv6 address)
959 * @NFT_CT_DST_IP6: conntrack layer 3 protocol destination (IPv6 address) 960 * @NFT_CT_DST_IP6: conntrack layer 3 protocol destination (IPv6 address)
961 * @NFT_CT_TIMEOUT: connection tracking timeout policy assigned to conntrack
960 */ 962 */
961enum nft_ct_keys { 963enum nft_ct_keys {
962 NFT_CT_STATE, 964 NFT_CT_STATE,
@@ -982,6 +984,7 @@ enum nft_ct_keys {
982 NFT_CT_DST_IP, 984 NFT_CT_DST_IP,
983 NFT_CT_SRC_IP6, 985 NFT_CT_SRC_IP6,
984 NFT_CT_DST_IP6, 986 NFT_CT_DST_IP6,
987 NFT_CT_TIMEOUT,
985 __NFT_CT_MAX 988 __NFT_CT_MAX
986}; 989};
987#define NFT_CT_MAX (__NFT_CT_MAX - 1) 990#define NFT_CT_MAX (__NFT_CT_MAX - 1)
@@ -1410,6 +1413,15 @@ enum nft_ct_helper_attributes {
1410}; 1413};
1411#define NFTA_CT_HELPER_MAX (__NFTA_CT_HELPER_MAX - 1) 1414#define NFTA_CT_HELPER_MAX (__NFTA_CT_HELPER_MAX - 1)
1412 1415
1416enum nft_ct_timeout_timeout_attributes {
1417 NFTA_CT_TIMEOUT_UNSPEC,
1418 NFTA_CT_TIMEOUT_L3PROTO,
1419 NFTA_CT_TIMEOUT_L4PROTO,
1420 NFTA_CT_TIMEOUT_DATA,
1421 __NFTA_CT_TIMEOUT_MAX,
1422};
1423#define NFTA_CT_TIMEOUT_MAX (__NFTA_CT_TIMEOUT_MAX - 1)
1424
1413#define NFT_OBJECT_UNSPEC 0 1425#define NFT_OBJECT_UNSPEC 0
1414#define NFT_OBJECT_COUNTER 1 1426#define NFT_OBJECT_COUNTER 1
1415#define NFT_OBJECT_QUOTA 2 1427#define NFT_OBJECT_QUOTA 2
@@ -1417,7 +1429,8 @@ enum nft_ct_helper_attributes {
1417#define NFT_OBJECT_LIMIT 4 1429#define NFT_OBJECT_LIMIT 4
1418#define NFT_OBJECT_CONNLIMIT 5 1430#define NFT_OBJECT_CONNLIMIT 5
1419#define NFT_OBJECT_TUNNEL 6 1431#define NFT_OBJECT_TUNNEL 6
1420#define __NFT_OBJECT_MAX 7 1432#define NFT_OBJECT_CT_TIMEOUT 7
1433#define __NFT_OBJECT_MAX 8
1421#define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1) 1434#define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1)
1422 1435
1423/** 1436/**
diff --git a/include/uapi/linux/netfilter/nfnetlink_osf.h b/include/uapi/linux/netfilter/nfnetlink_osf.h
index 3b93fbb9fc24..76a3527df5dd 100644
--- a/include/uapi/linux/netfilter/nfnetlink_osf.h
+++ b/include/uapi/linux/netfilter/nfnetlink_osf.h
@@ -88,6 +88,18 @@ enum iana_options {
88 OSFOPT_EMPTY = 255, 88 OSFOPT_EMPTY = 255,
89}; 89};
90 90
91/* Initial window size option state machine: multiple of mss, mtu or
92 * plain numeric value. Can also be made as plain numeric value which
93 * is not a multiple of specified value.
94 */
95enum nf_osf_window_size_options {
96 OSF_WSS_PLAIN = 0,
97 OSF_WSS_MSS,
98 OSF_WSS_MTU,
99 OSF_WSS_MODULO,
100 OSF_WSS_MAX,
101};
102
91enum nf_osf_attr_type { 103enum nf_osf_attr_type {
92 OSF_ATTR_UNSPEC, 104 OSF_ATTR_UNSPEC,
93 OSF_ATTR_FINGER, 105 OSF_ATTR_FINGER,
diff --git a/include/uapi/linux/netfilter/xt_osf.h b/include/uapi/linux/netfilter/xt_osf.h
index c56c59605c2b..24102b5286ec 100644
--- a/include/uapi/linux/netfilter/xt_osf.h
+++ b/include/uapi/linux/netfilter/xt_osf.h
@@ -46,6 +46,7 @@
46#define xt_osf_finger nf_osf_finger 46#define xt_osf_finger nf_osf_finger
47#define xt_osf_nlmsg nf_osf_nlmsg 47#define xt_osf_nlmsg nf_osf_nlmsg
48 48
49#define xt_osf_window_size_options nf_osf_window_size_options
49#define xt_osf_attr_type nf_osf_attr_type 50#define xt_osf_attr_type nf_osf_attr_type
50#define xt_osf_msg_types nf_osf_msg_types 51#define xt_osf_msg_types nf_osf_msg_types
51 52
diff --git a/net/netfilter/nf_conntrack_timeout.c b/net/netfilter/nf_conntrack_timeout.c
index 46aee65f339b..91fbd183da2d 100644
--- a/net/netfilter/nf_conntrack_timeout.c
+++ b/net/netfilter/nf_conntrack_timeout.c
@@ -24,13 +24,30 @@
24#include <net/netfilter/nf_conntrack_extend.h> 24#include <net/netfilter/nf_conntrack_extend.h>
25#include <net/netfilter/nf_conntrack_timeout.h> 25#include <net/netfilter/nf_conntrack_timeout.h>
26 26
27struct ctnl_timeout * 27struct nf_ct_timeout *
28(*nf_ct_timeout_find_get_hook)(struct net *net, const char *name) __read_mostly; 28(*nf_ct_timeout_find_get_hook)(struct net *net, const char *name) __read_mostly;
29EXPORT_SYMBOL_GPL(nf_ct_timeout_find_get_hook); 29EXPORT_SYMBOL_GPL(nf_ct_timeout_find_get_hook);
30 30
31void (*nf_ct_timeout_put_hook)(struct ctnl_timeout *timeout) __read_mostly; 31void (*nf_ct_timeout_put_hook)(struct nf_ct_timeout *timeout) __read_mostly;
32EXPORT_SYMBOL_GPL(nf_ct_timeout_put_hook); 32EXPORT_SYMBOL_GPL(nf_ct_timeout_put_hook);
33 33
34static int untimeout(struct nf_conn *ct, void *timeout)
35{
36 struct nf_conn_timeout *timeout_ext = nf_ct_timeout_find(ct);
37
38 if (timeout_ext && (!timeout || timeout_ext->timeout == timeout))
39 RCU_INIT_POINTER(timeout_ext->timeout, NULL);
40
41 /* We are not intended to delete this conntrack. */
42 return 0;
43}
44
45void nf_ct_untimeout(struct net *net, struct nf_ct_timeout *timeout)
46{
47 nf_ct_iterate_cleanup_net(net, untimeout, timeout, 0, 0);
48}
49EXPORT_SYMBOL_GPL(nf_ct_untimeout);
50
34static const struct nf_ct_ext_type timeout_extend = { 51static const struct nf_ct_ext_type timeout_extend = {
35 .len = sizeof(struct nf_conn_timeout), 52 .len = sizeof(struct nf_conn_timeout),
36 .align = __alignof__(struct nf_conn_timeout), 53 .align = __alignof__(struct nf_conn_timeout),
diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c
index 4199e5300575..d46a236cdf31 100644
--- a/net/netfilter/nfnetlink_cttimeout.c
+++ b/net/netfilter/nfnetlink_cttimeout.c
@@ -113,13 +113,13 @@ static int cttimeout_new_timeout(struct net *net, struct sock *ctnl,
113 /* You cannot replace one timeout policy by another of 113 /* You cannot replace one timeout policy by another of
114 * different kind, sorry. 114 * different kind, sorry.
115 */ 115 */
116 if (matching->l3num != l3num || 116 if (matching->timeout.l3num != l3num ||
117 matching->l4proto->l4proto != l4num) 117 matching->timeout.l4proto->l4proto != l4num)
118 return -EINVAL; 118 return -EINVAL;
119 119
120 return ctnl_timeout_parse_policy(&matching->data, 120 return ctnl_timeout_parse_policy(&matching->timeout.data,
121 matching->l4proto, net, 121 matching->timeout.l4proto,
122 cda[CTA_TIMEOUT_DATA]); 122 net, cda[CTA_TIMEOUT_DATA]);
123 } 123 }
124 124
125 return -EBUSY; 125 return -EBUSY;
@@ -140,14 +140,14 @@ static int cttimeout_new_timeout(struct net *net, struct sock *ctnl,
140 goto err_proto_put; 140 goto err_proto_put;
141 } 141 }
142 142
143 ret = ctnl_timeout_parse_policy(&timeout->data, l4proto, net, 143 ret = ctnl_timeout_parse_policy(&timeout->timeout.data, l4proto, net,
144 cda[CTA_TIMEOUT_DATA]); 144 cda[CTA_TIMEOUT_DATA]);
145 if (ret < 0) 145 if (ret < 0)
146 goto err; 146 goto err;
147 147
148 strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME])); 148 strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME]));
149 timeout->l3num = l3num; 149 timeout->timeout.l3num = l3num;
150 timeout->l4proto = l4proto; 150 timeout->timeout.l4proto = l4proto;
151 refcount_set(&timeout->refcnt, 1); 151 refcount_set(&timeout->refcnt, 1);
152 list_add_tail_rcu(&timeout->head, &net->nfct_timeout_list); 152 list_add_tail_rcu(&timeout->head, &net->nfct_timeout_list);
153 153
@@ -166,7 +166,7 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
166 struct nlmsghdr *nlh; 166 struct nlmsghdr *nlh;
167 struct nfgenmsg *nfmsg; 167 struct nfgenmsg *nfmsg;
168 unsigned int flags = portid ? NLM_F_MULTI : 0; 168 unsigned int flags = portid ? NLM_F_MULTI : 0;
169 const struct nf_conntrack_l4proto *l4proto = timeout->l4proto; 169 const struct nf_conntrack_l4proto *l4proto = timeout->timeout.l4proto;
170 170
171 event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_TIMEOUT, event); 171 event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_TIMEOUT, event);
172 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); 172 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
@@ -179,8 +179,9 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
179 nfmsg->res_id = 0; 179 nfmsg->res_id = 0;
180 180
181 if (nla_put_string(skb, CTA_TIMEOUT_NAME, timeout->name) || 181 if (nla_put_string(skb, CTA_TIMEOUT_NAME, timeout->name) ||
182 nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num)) || 182 nla_put_be16(skb, CTA_TIMEOUT_L3PROTO,
183 nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4proto->l4proto) || 183 htons(timeout->timeout.l3num)) ||
184 nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, l4proto->l4proto) ||
184 nla_put_be32(skb, CTA_TIMEOUT_USE, 185 nla_put_be32(skb, CTA_TIMEOUT_USE,
185 htonl(refcount_read(&timeout->refcnt)))) 186 htonl(refcount_read(&timeout->refcnt))))
186 goto nla_put_failure; 187 goto nla_put_failure;
@@ -194,7 +195,8 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
194 if (!nest_parms) 195 if (!nest_parms)
195 goto nla_put_failure; 196 goto nla_put_failure;
196 197
197 ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, &timeout->data); 198 ret = l4proto->ctnl_timeout.obj_to_nlattr(skb,
199 &timeout->timeout.data);
198 if (ret < 0) 200 if (ret < 0)
199 goto nla_put_failure; 201 goto nla_put_failure;
200 202
@@ -297,22 +299,6 @@ static int cttimeout_get_timeout(struct net *net, struct sock *ctnl,
297 return ret; 299 return ret;
298} 300}
299 301
300static int untimeout(struct nf_conn *ct, void *timeout)
301{
302 struct nf_conn_timeout *timeout_ext = nf_ct_timeout_find(ct);
303
304 if (timeout_ext && (!timeout || timeout_ext->timeout == timeout))
305 RCU_INIT_POINTER(timeout_ext->timeout, NULL);
306
307 /* We are not intended to delete this conntrack. */
308 return 0;
309}
310
311static void ctnl_untimeout(struct net *net, struct ctnl_timeout *timeout)
312{
313 nf_ct_iterate_cleanup_net(net, untimeout, timeout, 0, 0);
314}
315
316/* try to delete object, fail if it is still in use. */ 302/* try to delete object, fail if it is still in use. */
317static int ctnl_timeout_try_del(struct net *net, struct ctnl_timeout *timeout) 303static int ctnl_timeout_try_del(struct net *net, struct ctnl_timeout *timeout)
318{ 304{
@@ -324,8 +310,8 @@ static int ctnl_timeout_try_del(struct net *net, struct ctnl_timeout *timeout)
324 if (refcount_dec_if_one(&timeout->refcnt)) { 310 if (refcount_dec_if_one(&timeout->refcnt)) {
325 /* We are protected by nfnl mutex. */ 311 /* We are protected by nfnl mutex. */
326 list_del_rcu(&timeout->head); 312 list_del_rcu(&timeout->head);
327 nf_ct_l4proto_put(timeout->l4proto); 313 nf_ct_l4proto_put(timeout->timeout.l4proto);
328 ctnl_untimeout(net, timeout); 314 nf_ct_untimeout(net, &timeout->timeout);
329 kfree_rcu(timeout, rcu_head); 315 kfree_rcu(timeout, rcu_head);
330 } else { 316 } else {
331 ret = -EBUSY; 317 ret = -EBUSY;
@@ -526,8 +512,11 @@ err:
526 return matching; 512 return matching;
527} 513}
528 514
529static void ctnl_timeout_put(struct ctnl_timeout *timeout) 515static void ctnl_timeout_put(struct nf_ct_timeout *t)
530{ 516{
517 struct ctnl_timeout *timeout =
518 container_of(t, struct ctnl_timeout, timeout);
519
531 if (refcount_dec_and_test(&timeout->refcnt)) 520 if (refcount_dec_and_test(&timeout->refcnt))
532 kfree_rcu(timeout, rcu_head); 521 kfree_rcu(timeout, rcu_head);
533 522
@@ -573,11 +562,11 @@ static void __net_exit cttimeout_net_exit(struct net *net)
573 struct ctnl_timeout *cur, *tmp; 562 struct ctnl_timeout *cur, *tmp;
574 563
575 nf_ct_unconfirmed_destroy(net); 564 nf_ct_unconfirmed_destroy(net);
576 ctnl_untimeout(net, NULL); 565 nf_ct_untimeout(net, NULL);
577 566
578 list_for_each_entry_safe(cur, tmp, &net->nfct_timeout_list, head) { 567 list_for_each_entry_safe(cur, tmp, &net->nfct_timeout_list, head) {
579 list_del_rcu(&cur->head); 568 list_del_rcu(&cur->head);
580 nf_ct_l4proto_put(cur->l4proto); 569 nf_ct_l4proto_put(cur->timeout.l4proto);
581 570
582 if (refcount_dec_and_test(&cur->refcnt)) 571 if (refcount_dec_and_test(&cur->refcnt))
583 kfree_rcu(cur, rcu_head); 572 kfree_rcu(cur, rcu_head);
diff --git a/net/netfilter/nfnetlink_osf.c b/net/netfilter/nfnetlink_osf.c
index f9dba62c450f..00db27dfd2ff 100644
--- a/net/netfilter/nfnetlink_osf.c
+++ b/net/netfilter/nfnetlink_osf.c
@@ -271,7 +271,7 @@ const char *nf_osf_find(const struct sk_buff *skb,
271 271
272 tcp = nf_osf_hdr_ctx_init(&ctx, skb, ip, opts); 272 tcp = nf_osf_hdr_ctx_init(&ctx, skb, ip, opts);
273 if (!tcp) 273 if (!tcp)
274 return false; 274 return NULL;
275 275
276 list_for_each_entry_rcu(kf, &nf_osf_fingers[ctx.df], finger_entry) { 276 list_for_each_entry_rcu(kf, &nf_osf_fingers[ctx.df], finger_entry) {
277 f = &kf->finger; 277 f = &kf->finger;
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
index 3bc82ee5464d..4855d4ce1c8f 100644
--- a/net/netfilter/nft_ct.c
+++ b/net/netfilter/nft_ct.c
@@ -22,6 +22,8 @@
22#include <net/netfilter/nf_conntrack_helper.h> 22#include <net/netfilter/nf_conntrack_helper.h>
23#include <net/netfilter/nf_conntrack_ecache.h> 23#include <net/netfilter/nf_conntrack_ecache.h>
24#include <net/netfilter/nf_conntrack_labels.h> 24#include <net/netfilter/nf_conntrack_labels.h>
25#include <net/netfilter/nf_conntrack_timeout.h>
26#include <net/netfilter/nf_conntrack_l4proto.h>
25 27
26struct nft_ct { 28struct nft_ct {
27 enum nft_ct_keys key:8; 29 enum nft_ct_keys key:8;
@@ -765,6 +767,194 @@ static struct nft_expr_type nft_notrack_type __read_mostly = {
765 .owner = THIS_MODULE, 767 .owner = THIS_MODULE,
766}; 768};
767 769
770#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
771static int
772nft_ct_timeout_parse_policy(void *timeouts,
773 const struct nf_conntrack_l4proto *l4proto,
774 struct net *net, const struct nlattr *attr)
775{
776 struct nlattr **tb;
777 int ret = 0;
778
779 if (!l4proto->ctnl_timeout.nlattr_to_obj)
780 return 0;
781
782 tb = kcalloc(l4proto->ctnl_timeout.nlattr_max + 1, sizeof(*tb),
783 GFP_KERNEL);
784
785 if (!tb)
786 return -ENOMEM;
787
788 ret = nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max,
789 attr, l4proto->ctnl_timeout.nla_policy,
790 NULL);
791 if (ret < 0)
792 goto err;
793
794 ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, net, timeouts);
795
796err:
797 kfree(tb);
798 return ret;
799}
800
801struct nft_ct_timeout_obj {
802 struct nf_conn *tmpl;
803 u8 l4proto;
804};
805
806static void nft_ct_timeout_obj_eval(struct nft_object *obj,
807 struct nft_regs *regs,
808 const struct nft_pktinfo *pkt)
809{
810 const struct nft_ct_timeout_obj *priv = nft_obj_data(obj);
811 struct nf_conn *ct = (struct nf_conn *)skb_nfct(pkt->skb);
812 struct sk_buff *skb = pkt->skb;
813
814 if (ct ||
815 priv->l4proto != pkt->tprot)
816 return;
817
818 nf_ct_set(skb, priv->tmpl, IP_CT_NEW);
819}
820
821static int nft_ct_timeout_obj_init(const struct nft_ctx *ctx,
822 const struct nlattr * const tb[],
823 struct nft_object *obj)
824{
825 const struct nf_conntrack_zone *zone = &nf_ct_zone_dflt;
826 struct nft_ct_timeout_obj *priv = nft_obj_data(obj);
827 const struct nf_conntrack_l4proto *l4proto;
828 struct nf_conn_timeout *timeout_ext;
829 struct nf_ct_timeout *timeout;
830 int l3num = ctx->family;
831 struct nf_conn *tmpl;
832 __u8 l4num;
833 int ret;
834
835 if (!tb[NFTA_CT_TIMEOUT_L3PROTO] ||
836 !tb[NFTA_CT_TIMEOUT_L4PROTO] ||
837 !tb[NFTA_CT_TIMEOUT_DATA])
838 return -EINVAL;
839
840 l3num = ntohs(nla_get_be16(tb[NFTA_CT_TIMEOUT_L3PROTO]));
841 l4num = nla_get_u8(tb[NFTA_CT_TIMEOUT_L4PROTO]);
842 priv->l4proto = l4num;
843
844 l4proto = nf_ct_l4proto_find_get(l3num, l4num);
845
846 if (l4proto->l4proto != l4num) {
847 ret = -EOPNOTSUPP;
848 goto err_proto_put;
849 }
850
851 timeout = kzalloc(sizeof(struct nf_ct_timeout) +
852 l4proto->ctnl_timeout.obj_size, GFP_KERNEL);
853 if (timeout == NULL) {
854 ret = -ENOMEM;
855 goto err_proto_put;
856 }
857
858 ret = nft_ct_timeout_parse_policy(&timeout->data, l4proto, ctx->net,
859 tb[NFTA_CT_TIMEOUT_DATA]);
860 if (ret < 0)
861 goto err_free_timeout;
862
863 timeout->l3num = l3num;
864 timeout->l4proto = l4proto;
865 tmpl = nf_ct_tmpl_alloc(ctx->net, zone, GFP_ATOMIC);
866 if (!tmpl) {
867 ret = -ENOMEM;
868 goto err_free_timeout;
869 }
870
871 timeout_ext = nf_ct_timeout_ext_add(tmpl, timeout, GFP_ATOMIC);
872 if (!timeout_ext) {
873 ret = -ENOMEM;
874 goto err_free_tmpl;
875 }
876
877 ret = nf_ct_netns_get(ctx->net, ctx->family);
878 if (ret < 0)
879 goto err_free_tmpl;
880
881 priv->tmpl = tmpl;
882
883 return 0;
884
885err_free_tmpl:
886 nf_ct_tmpl_free(tmpl);
887err_free_timeout:
888 kfree(timeout);
889err_proto_put:
890 nf_ct_l4proto_put(l4proto);
891 return ret;
892}
893
894static void nft_ct_timeout_obj_destroy(const struct nft_ctx *ctx,
895 struct nft_object *obj)
896{
897 struct nft_ct_timeout_obj *priv = nft_obj_data(obj);
898 struct nf_conn_timeout *t = nf_ct_timeout_find(priv->tmpl);
899 struct nf_ct_timeout *timeout;
900
901 timeout = rcu_dereference_raw(t->timeout);
902 nf_ct_untimeout(ctx->net, timeout);
903 nf_ct_l4proto_put(timeout->l4proto);
904 nf_ct_netns_put(ctx->net, ctx->family);
905 nf_ct_tmpl_free(priv->tmpl);
906}
907
908static int nft_ct_timeout_obj_dump(struct sk_buff *skb,
909 struct nft_object *obj, bool reset)
910{
911 const struct nft_ct_timeout_obj *priv = nft_obj_data(obj);
912 const struct nf_conn_timeout *t = nf_ct_timeout_find(priv->tmpl);
913 const struct nf_ct_timeout *timeout = rcu_dereference_raw(t->timeout);
914 struct nlattr *nest_params;
915 int ret;
916
917 if (nla_put_u8(skb, NFTA_CT_TIMEOUT_L4PROTO, timeout->l4proto->l4proto) ||
918 nla_put_be16(skb, NFTA_CT_TIMEOUT_L3PROTO, htons(timeout->l3num)))
919 return -1;
920
921 nest_params = nla_nest_start(skb, NFTA_CT_TIMEOUT_DATA | NLA_F_NESTED);
922 if (!nest_params)
923 return -1;
924
925 ret = timeout->l4proto->ctnl_timeout.obj_to_nlattr(skb, &timeout->data);
926 if (ret < 0)
927 return -1;
928 nla_nest_end(skb, nest_params);
929 return 0;
930}
931
932static const struct nla_policy nft_ct_timeout_policy[NFTA_CT_TIMEOUT_MAX + 1] = {
933 [NFTA_CT_TIMEOUT_L3PROTO] = {.type = NLA_U16 },
934 [NFTA_CT_TIMEOUT_L4PROTO] = {.type = NLA_U8 },
935 [NFTA_CT_TIMEOUT_DATA] = {.type = NLA_NESTED },
936};
937
938static struct nft_object_type nft_ct_timeout_obj_type;
939
940static const struct nft_object_ops nft_ct_timeout_obj_ops = {
941 .type = &nft_ct_timeout_obj_type,
942 .size = sizeof(struct nft_ct_timeout_obj),
943 .eval = nft_ct_timeout_obj_eval,
944 .init = nft_ct_timeout_obj_init,
945 .destroy = nft_ct_timeout_obj_destroy,
946 .dump = nft_ct_timeout_obj_dump,
947};
948
949static struct nft_object_type nft_ct_timeout_obj_type __read_mostly = {
950 .type = NFT_OBJECT_CT_TIMEOUT,
951 .ops = &nft_ct_timeout_obj_ops,
952 .maxattr = NFTA_CT_TIMEOUT_MAX,
953 .policy = nft_ct_timeout_policy,
954 .owner = THIS_MODULE,
955};
956#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
957
768static int nft_ct_helper_obj_init(const struct nft_ctx *ctx, 958static int nft_ct_helper_obj_init(const struct nft_ctx *ctx,
769 const struct nlattr * const tb[], 959 const struct nlattr * const tb[],
770 struct nft_object *obj) 960 struct nft_object *obj)
@@ -773,6 +963,7 @@ static int nft_ct_helper_obj_init(const struct nft_ctx *ctx,
773 struct nf_conntrack_helper *help4, *help6; 963 struct nf_conntrack_helper *help4, *help6;
774 char name[NF_CT_HELPER_NAME_LEN]; 964 char name[NF_CT_HELPER_NAME_LEN];
775 int family = ctx->family; 965 int family = ctx->family;
966 int err;
776 967
777 if (!tb[NFTA_CT_HELPER_NAME] || !tb[NFTA_CT_HELPER_L4PROTO]) 968 if (!tb[NFTA_CT_HELPER_NAME] || !tb[NFTA_CT_HELPER_L4PROTO])
778 return -EINVAL; 969 return -EINVAL;
@@ -823,7 +1014,18 @@ static int nft_ct_helper_obj_init(const struct nft_ctx *ctx,
823 priv->helper4 = help4; 1014 priv->helper4 = help4;
824 priv->helper6 = help6; 1015 priv->helper6 = help6;
825 1016
1017 err = nf_ct_netns_get(ctx->net, ctx->family);
1018 if (err < 0)
1019 goto err_put_helper;
1020
826 return 0; 1021 return 0;
1022
1023err_put_helper:
1024 if (priv->helper4)
1025 nf_conntrack_helper_put(priv->helper4);
1026 if (priv->helper6)
1027 nf_conntrack_helper_put(priv->helper6);
1028 return err;
827} 1029}
828 1030
829static void nft_ct_helper_obj_destroy(const struct nft_ctx *ctx, 1031static void nft_ct_helper_obj_destroy(const struct nft_ctx *ctx,
@@ -835,6 +1037,8 @@ static void nft_ct_helper_obj_destroy(const struct nft_ctx *ctx,
835 nf_conntrack_helper_put(priv->helper4); 1037 nf_conntrack_helper_put(priv->helper4);
836 if (priv->helper6) 1038 if (priv->helper6)
837 nf_conntrack_helper_put(priv->helper6); 1039 nf_conntrack_helper_put(priv->helper6);
1040
1041 nf_ct_netns_put(ctx->net, ctx->family);
838} 1042}
839 1043
840static void nft_ct_helper_obj_eval(struct nft_object *obj, 1044static void nft_ct_helper_obj_eval(struct nft_object *obj,
@@ -949,9 +1153,17 @@ static int __init nft_ct_module_init(void)
949 err = nft_register_obj(&nft_ct_helper_obj_type); 1153 err = nft_register_obj(&nft_ct_helper_obj_type);
950 if (err < 0) 1154 if (err < 0)
951 goto err2; 1155 goto err2;
952 1156#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
1157 err = nft_register_obj(&nft_ct_timeout_obj_type);
1158 if (err < 0)
1159 goto err3;
1160#endif
953 return 0; 1161 return 0;
954 1162
1163#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
1164err3:
1165 nft_unregister_obj(&nft_ct_helper_obj_type);
1166#endif
955err2: 1167err2:
956 nft_unregister_expr(&nft_notrack_type); 1168 nft_unregister_expr(&nft_notrack_type);
957err1: 1169err1:
@@ -961,6 +1173,9 @@ err1:
961 1173
962static void __exit nft_ct_module_exit(void) 1174static void __exit nft_ct_module_exit(void)
963{ 1175{
1176#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
1177 nft_unregister_obj(&nft_ct_timeout_obj_type);
1178#endif
964 nft_unregister_obj(&nft_ct_helper_obj_type); 1179 nft_unregister_obj(&nft_ct_helper_obj_type);
965 nft_unregister_expr(&nft_notrack_type); 1180 nft_unregister_expr(&nft_notrack_type);
966 nft_unregister_expr(&nft_ct_type); 1181 nft_unregister_expr(&nft_ct_type);
@@ -974,3 +1189,4 @@ MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
974MODULE_ALIAS_NFT_EXPR("ct"); 1189MODULE_ALIAS_NFT_EXPR("ct");
975MODULE_ALIAS_NFT_EXPR("notrack"); 1190MODULE_ALIAS_NFT_EXPR("notrack");
976MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_CT_HELPER); 1191MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_CT_HELPER);
1192MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_CT_TIMEOUT);
diff --git a/net/netfilter/nft_osf.c b/net/netfilter/nft_osf.c
index 9b2f3de7be4f..5af74b37f423 100644
--- a/net/netfilter/nft_osf.c
+++ b/net/netfilter/nft_osf.c
@@ -4,8 +4,6 @@
4#include <net/netfilter/nf_tables.h> 4#include <net/netfilter/nf_tables.h>
5#include <linux/netfilter/nfnetlink_osf.h> 5#include <linux/netfilter/nfnetlink_osf.h>
6 6
7#define OSF_GENRE_SIZE 32
8
9struct nft_osf { 7struct nft_osf {
10 enum nft_registers dreg:8; 8 enum nft_registers dreg:8;
11}; 9};
@@ -37,9 +35,9 @@ static void nft_osf_eval(const struct nft_expr *expr, struct nft_regs *regs,
37 35
38 os_name = nf_osf_find(skb, nf_osf_fingers); 36 os_name = nf_osf_find(skb, nf_osf_fingers);
39 if (!os_name) 37 if (!os_name)
40 strncpy((char *)dest, "unknown", IFNAMSIZ); 38 strncpy((char *)dest, "unknown", NFT_OSF_MAXGENRELEN);
41 else 39 else
42 strncpy((char *)dest, os_name, IFNAMSIZ); 40 strncpy((char *)dest, os_name, NFT_OSF_MAXGENRELEN);
43} 41}
44 42
45static int nft_osf_init(const struct nft_ctx *ctx, 43static int nft_osf_init(const struct nft_ctx *ctx,
@@ -51,7 +49,7 @@ static int nft_osf_init(const struct nft_ctx *ctx,
51 49
52 priv->dreg = nft_parse_register(tb[NFTA_OSF_DREG]); 50 priv->dreg = nft_parse_register(tb[NFTA_OSF_DREG]);
53 err = nft_validate_register_store(ctx, priv->dreg, NULL, 51 err = nft_validate_register_store(ctx, priv->dreg, NULL,
54 NFTA_DATA_VALUE, OSF_GENRE_SIZE); 52 NFTA_DATA_VALUE, NFT_OSF_MAXGENRELEN);
55 if (err < 0) 53 if (err < 0)
56 return err; 54 return err;
57 55
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index 7ba454e9e3fa..89457efd2e00 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -104,7 +104,7 @@ xt_ct_set_helper(struct nf_conn *ct, const char *helper_name,
104} 104}
105 105
106#ifdef CONFIG_NF_CONNTRACK_TIMEOUT 106#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
107static void __xt_ct_tg_timeout_put(struct ctnl_timeout *timeout) 107static void __xt_ct_tg_timeout_put(struct nf_ct_timeout *timeout)
108{ 108{
109 typeof(nf_ct_timeout_put_hook) timeout_put; 109 typeof(nf_ct_timeout_put_hook) timeout_put;
110 110
@@ -121,7 +121,7 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
121#ifdef CONFIG_NF_CONNTRACK_TIMEOUT 121#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
122 typeof(nf_ct_timeout_find_get_hook) timeout_find_get; 122 typeof(nf_ct_timeout_find_get_hook) timeout_find_get;
123 const struct nf_conntrack_l4proto *l4proto; 123 const struct nf_conntrack_l4proto *l4proto;
124 struct ctnl_timeout *timeout; 124 struct nf_ct_timeout *timeout;
125 struct nf_conn_timeout *timeout_ext; 125 struct nf_conn_timeout *timeout_ext;
126 const char *errmsg = NULL; 126 const char *errmsg = NULL;
127 int ret = 0; 127 int ret = 0;