Commit ea9cf2a55a7bb84ba862a0fc13044a4311c9bbfe

Authored by YueHaibing
Committed by Pablo Neira Ayuso
1 parent 4b87dd54be

netfilter: cttimeout: remove set but not used variable 'l3num'

Fixes gcc '-Wunused-but-set-variable' warning:

net/netfilter/nfnetlink_cttimeout.c: In function 'cttimeout_default_set':
net/netfilter/nfnetlink_cttimeout.c:353:8: warning:
 variable 'l3num' set but not used [-Wunused-but-set-variable]

It not used any more after
commit dd2934a95701 ("netfilter: conntrack: remove l3->l4 mapping information")

Signed-off-by: YueHaibing <yuehaibing@huawei.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

Showing 1 changed file with 0 additions and 2 deletions Inline Diff

net/netfilter/nfnetlink_cttimeout.c
1 /* 1 /*
2 * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org> 2 * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
3 * (C) 2012 by Vyatta Inc. <http://www.vyatta.com> 3 * (C) 2012 by Vyatta Inc. <http://www.vyatta.com>
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as 6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation (or any later at your option). 7 * published by the Free Software Foundation (or any later at your option).
8 */ 8 */
9 #include <linux/init.h> 9 #include <linux/init.h>
10 #include <linux/module.h> 10 #include <linux/module.h>
11 #include <linux/kernel.h> 11 #include <linux/kernel.h>
12 #include <linux/rculist.h> 12 #include <linux/rculist.h>
13 #include <linux/rculist_nulls.h> 13 #include <linux/rculist_nulls.h>
14 #include <linux/types.h> 14 #include <linux/types.h>
15 #include <linux/timer.h> 15 #include <linux/timer.h>
16 #include <linux/security.h> 16 #include <linux/security.h>
17 #include <linux/skbuff.h> 17 #include <linux/skbuff.h>
18 #include <linux/errno.h> 18 #include <linux/errno.h>
19 #include <linux/netlink.h> 19 #include <linux/netlink.h>
20 #include <linux/spinlock.h> 20 #include <linux/spinlock.h>
21 #include <linux/interrupt.h> 21 #include <linux/interrupt.h>
22 #include <linux/slab.h> 22 #include <linux/slab.h>
23 23
24 #include <linux/netfilter.h> 24 #include <linux/netfilter.h>
25 #include <net/netlink.h> 25 #include <net/netlink.h>
26 #include <net/sock.h> 26 #include <net/sock.h>
27 #include <net/netfilter/nf_conntrack.h> 27 #include <net/netfilter/nf_conntrack.h>
28 #include <net/netfilter/nf_conntrack_core.h> 28 #include <net/netfilter/nf_conntrack_core.h>
29 #include <net/netfilter/nf_conntrack_l4proto.h> 29 #include <net/netfilter/nf_conntrack_l4proto.h>
30 #include <net/netfilter/nf_conntrack_tuple.h> 30 #include <net/netfilter/nf_conntrack_tuple.h>
31 #include <net/netfilter/nf_conntrack_timeout.h> 31 #include <net/netfilter/nf_conntrack_timeout.h>
32 32
33 #include <linux/netfilter/nfnetlink.h> 33 #include <linux/netfilter/nfnetlink.h>
34 #include <linux/netfilter/nfnetlink_cttimeout.h> 34 #include <linux/netfilter/nfnetlink_cttimeout.h>
35 35
36 MODULE_LICENSE("GPL"); 36 MODULE_LICENSE("GPL");
37 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); 37 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
38 MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tuning"); 38 MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tuning");
39 39
40 static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = { 40 static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = {
41 [CTA_TIMEOUT_NAME] = { .type = NLA_NUL_STRING, 41 [CTA_TIMEOUT_NAME] = { .type = NLA_NUL_STRING,
42 .len = CTNL_TIMEOUT_NAME_MAX - 1}, 42 .len = CTNL_TIMEOUT_NAME_MAX - 1},
43 [CTA_TIMEOUT_L3PROTO] = { .type = NLA_U16 }, 43 [CTA_TIMEOUT_L3PROTO] = { .type = NLA_U16 },
44 [CTA_TIMEOUT_L4PROTO] = { .type = NLA_U8 }, 44 [CTA_TIMEOUT_L4PROTO] = { .type = NLA_U8 },
45 [CTA_TIMEOUT_DATA] = { .type = NLA_NESTED }, 45 [CTA_TIMEOUT_DATA] = { .type = NLA_NESTED },
46 }; 46 };
47 47
48 static int 48 static int
49 ctnl_timeout_parse_policy(void *timeout, 49 ctnl_timeout_parse_policy(void *timeout,
50 const struct nf_conntrack_l4proto *l4proto, 50 const struct nf_conntrack_l4proto *l4proto,
51 struct net *net, const struct nlattr *attr) 51 struct net *net, const struct nlattr *attr)
52 { 52 {
53 struct nlattr **tb; 53 struct nlattr **tb;
54 int ret = 0; 54 int ret = 0;
55 55
56 tb = kcalloc(l4proto->ctnl_timeout.nlattr_max + 1, sizeof(*tb), 56 tb = kcalloc(l4proto->ctnl_timeout.nlattr_max + 1, sizeof(*tb),
57 GFP_KERNEL); 57 GFP_KERNEL);
58 58
59 if (!tb) 59 if (!tb)
60 return -ENOMEM; 60 return -ENOMEM;
61 61
62 ret = nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max, attr, 62 ret = nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max, attr,
63 l4proto->ctnl_timeout.nla_policy, NULL); 63 l4proto->ctnl_timeout.nla_policy, NULL);
64 if (ret < 0) 64 if (ret < 0)
65 goto err; 65 goto err;
66 66
67 ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, net, timeout); 67 ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, net, timeout);
68 68
69 err: 69 err:
70 kfree(tb); 70 kfree(tb);
71 return ret; 71 return ret;
72 } 72 }
73 73
74 static int cttimeout_new_timeout(struct net *net, struct sock *ctnl, 74 static int cttimeout_new_timeout(struct net *net, struct sock *ctnl,
75 struct sk_buff *skb, 75 struct sk_buff *skb,
76 const struct nlmsghdr *nlh, 76 const struct nlmsghdr *nlh,
77 const struct nlattr * const cda[], 77 const struct nlattr * const cda[],
78 struct netlink_ext_ack *extack) 78 struct netlink_ext_ack *extack)
79 { 79 {
80 __u16 l3num; 80 __u16 l3num;
81 __u8 l4num; 81 __u8 l4num;
82 const struct nf_conntrack_l4proto *l4proto; 82 const struct nf_conntrack_l4proto *l4proto;
83 struct ctnl_timeout *timeout, *matching = NULL; 83 struct ctnl_timeout *timeout, *matching = NULL;
84 char *name; 84 char *name;
85 int ret; 85 int ret;
86 86
87 if (!cda[CTA_TIMEOUT_NAME] || 87 if (!cda[CTA_TIMEOUT_NAME] ||
88 !cda[CTA_TIMEOUT_L3PROTO] || 88 !cda[CTA_TIMEOUT_L3PROTO] ||
89 !cda[CTA_TIMEOUT_L4PROTO] || 89 !cda[CTA_TIMEOUT_L4PROTO] ||
90 !cda[CTA_TIMEOUT_DATA]) 90 !cda[CTA_TIMEOUT_DATA])
91 return -EINVAL; 91 return -EINVAL;
92 92
93 name = nla_data(cda[CTA_TIMEOUT_NAME]); 93 name = nla_data(cda[CTA_TIMEOUT_NAME]);
94 l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO])); 94 l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
95 l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]); 95 l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
96 96
97 list_for_each_entry(timeout, &net->nfct_timeout_list, head) { 97 list_for_each_entry(timeout, &net->nfct_timeout_list, head) {
98 if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) 98 if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
99 continue; 99 continue;
100 100
101 if (nlh->nlmsg_flags & NLM_F_EXCL) 101 if (nlh->nlmsg_flags & NLM_F_EXCL)
102 return -EEXIST; 102 return -EEXIST;
103 103
104 matching = timeout; 104 matching = timeout;
105 break; 105 break;
106 } 106 }
107 107
108 if (matching) { 108 if (matching) {
109 if (nlh->nlmsg_flags & NLM_F_REPLACE) { 109 if (nlh->nlmsg_flags & NLM_F_REPLACE) {
110 /* You cannot replace one timeout policy by another of 110 /* You cannot replace one timeout policy by another of
111 * different kind, sorry. 111 * different kind, sorry.
112 */ 112 */
113 if (matching->timeout.l3num != l3num || 113 if (matching->timeout.l3num != l3num ||
114 matching->timeout.l4proto->l4proto != l4num) 114 matching->timeout.l4proto->l4proto != l4num)
115 return -EINVAL; 115 return -EINVAL;
116 116
117 return ctnl_timeout_parse_policy(&matching->timeout.data, 117 return ctnl_timeout_parse_policy(&matching->timeout.data,
118 matching->timeout.l4proto, 118 matching->timeout.l4proto,
119 net, cda[CTA_TIMEOUT_DATA]); 119 net, cda[CTA_TIMEOUT_DATA]);
120 } 120 }
121 121
122 return -EBUSY; 122 return -EBUSY;
123 } 123 }
124 124
125 l4proto = nf_ct_l4proto_find_get(l4num); 125 l4proto = nf_ct_l4proto_find_get(l4num);
126 126
127 /* This protocol is not supportted, skip. */ 127 /* This protocol is not supportted, skip. */
128 if (l4proto->l4proto != l4num) { 128 if (l4proto->l4proto != l4num) {
129 ret = -EOPNOTSUPP; 129 ret = -EOPNOTSUPP;
130 goto err_proto_put; 130 goto err_proto_put;
131 } 131 }
132 132
133 timeout = kzalloc(sizeof(struct ctnl_timeout) + 133 timeout = kzalloc(sizeof(struct ctnl_timeout) +
134 l4proto->ctnl_timeout.obj_size, GFP_KERNEL); 134 l4proto->ctnl_timeout.obj_size, GFP_KERNEL);
135 if (timeout == NULL) { 135 if (timeout == NULL) {
136 ret = -ENOMEM; 136 ret = -ENOMEM;
137 goto err_proto_put; 137 goto err_proto_put;
138 } 138 }
139 139
140 ret = ctnl_timeout_parse_policy(&timeout->timeout.data, l4proto, net, 140 ret = ctnl_timeout_parse_policy(&timeout->timeout.data, l4proto, net,
141 cda[CTA_TIMEOUT_DATA]); 141 cda[CTA_TIMEOUT_DATA]);
142 if (ret < 0) 142 if (ret < 0)
143 goto err; 143 goto err;
144 144
145 strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME])); 145 strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME]));
146 timeout->timeout.l3num = l3num; 146 timeout->timeout.l3num = l3num;
147 timeout->timeout.l4proto = l4proto; 147 timeout->timeout.l4proto = l4proto;
148 refcount_set(&timeout->refcnt, 1); 148 refcount_set(&timeout->refcnt, 1);
149 list_add_tail_rcu(&timeout->head, &net->nfct_timeout_list); 149 list_add_tail_rcu(&timeout->head, &net->nfct_timeout_list);
150 150
151 return 0; 151 return 0;
152 err: 152 err:
153 kfree(timeout); 153 kfree(timeout);
154 err_proto_put: 154 err_proto_put:
155 nf_ct_l4proto_put(l4proto); 155 nf_ct_l4proto_put(l4proto);
156 return ret; 156 return ret;
157 } 157 }
158 158
159 static int 159 static int
160 ctnl_timeout_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, 160 ctnl_timeout_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
161 int event, struct ctnl_timeout *timeout) 161 int event, struct ctnl_timeout *timeout)
162 { 162 {
163 struct nlmsghdr *nlh; 163 struct nlmsghdr *nlh;
164 struct nfgenmsg *nfmsg; 164 struct nfgenmsg *nfmsg;
165 unsigned int flags = portid ? NLM_F_MULTI : 0; 165 unsigned int flags = portid ? NLM_F_MULTI : 0;
166 const struct nf_conntrack_l4proto *l4proto = timeout->timeout.l4proto; 166 const struct nf_conntrack_l4proto *l4proto = timeout->timeout.l4proto;
167 struct nlattr *nest_parms; 167 struct nlattr *nest_parms;
168 int ret; 168 int ret;
169 169
170 event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_TIMEOUT, event); 170 event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_TIMEOUT, event);
171 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); 171 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
172 if (nlh == NULL) 172 if (nlh == NULL)
173 goto nlmsg_failure; 173 goto nlmsg_failure;
174 174
175 nfmsg = nlmsg_data(nlh); 175 nfmsg = nlmsg_data(nlh);
176 nfmsg->nfgen_family = AF_UNSPEC; 176 nfmsg->nfgen_family = AF_UNSPEC;
177 nfmsg->version = NFNETLINK_V0; 177 nfmsg->version = NFNETLINK_V0;
178 nfmsg->res_id = 0; 178 nfmsg->res_id = 0;
179 179
180 if (nla_put_string(skb, CTA_TIMEOUT_NAME, timeout->name) || 180 if (nla_put_string(skb, CTA_TIMEOUT_NAME, timeout->name) ||
181 nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, 181 nla_put_be16(skb, CTA_TIMEOUT_L3PROTO,
182 htons(timeout->timeout.l3num)) || 182 htons(timeout->timeout.l3num)) ||
183 nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, l4proto->l4proto) || 183 nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, l4proto->l4proto) ||
184 nla_put_be32(skb, CTA_TIMEOUT_USE, 184 nla_put_be32(skb, CTA_TIMEOUT_USE,
185 htonl(refcount_read(&timeout->refcnt)))) 185 htonl(refcount_read(&timeout->refcnt))))
186 goto nla_put_failure; 186 goto nla_put_failure;
187 187
188 nest_parms = nla_nest_start(skb, CTA_TIMEOUT_DATA | NLA_F_NESTED); 188 nest_parms = nla_nest_start(skb, CTA_TIMEOUT_DATA | NLA_F_NESTED);
189 if (!nest_parms) 189 if (!nest_parms)
190 goto nla_put_failure; 190 goto nla_put_failure;
191 191
192 ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, &timeout->timeout.data); 192 ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, &timeout->timeout.data);
193 if (ret < 0) 193 if (ret < 0)
194 goto nla_put_failure; 194 goto nla_put_failure;
195 195
196 nla_nest_end(skb, nest_parms); 196 nla_nest_end(skb, nest_parms);
197 197
198 nlmsg_end(skb, nlh); 198 nlmsg_end(skb, nlh);
199 return skb->len; 199 return skb->len;
200 200
201 nlmsg_failure: 201 nlmsg_failure:
202 nla_put_failure: 202 nla_put_failure:
203 nlmsg_cancel(skb, nlh); 203 nlmsg_cancel(skb, nlh);
204 return -1; 204 return -1;
205 } 205 }
206 206
207 static int 207 static int
208 ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb) 208 ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb)
209 { 209 {
210 struct net *net = sock_net(skb->sk); 210 struct net *net = sock_net(skb->sk);
211 struct ctnl_timeout *cur, *last; 211 struct ctnl_timeout *cur, *last;
212 212
213 if (cb->args[2]) 213 if (cb->args[2])
214 return 0; 214 return 0;
215 215
216 last = (struct ctnl_timeout *)cb->args[1]; 216 last = (struct ctnl_timeout *)cb->args[1];
217 if (cb->args[1]) 217 if (cb->args[1])
218 cb->args[1] = 0; 218 cb->args[1] = 0;
219 219
220 rcu_read_lock(); 220 rcu_read_lock();
221 list_for_each_entry_rcu(cur, &net->nfct_timeout_list, head) { 221 list_for_each_entry_rcu(cur, &net->nfct_timeout_list, head) {
222 if (last) { 222 if (last) {
223 if (cur != last) 223 if (cur != last)
224 continue; 224 continue;
225 225
226 last = NULL; 226 last = NULL;
227 } 227 }
228 if (ctnl_timeout_fill_info(skb, NETLINK_CB(cb->skb).portid, 228 if (ctnl_timeout_fill_info(skb, NETLINK_CB(cb->skb).portid,
229 cb->nlh->nlmsg_seq, 229 cb->nlh->nlmsg_seq,
230 NFNL_MSG_TYPE(cb->nlh->nlmsg_type), 230 NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
231 IPCTNL_MSG_TIMEOUT_NEW, cur) < 0) { 231 IPCTNL_MSG_TIMEOUT_NEW, cur) < 0) {
232 cb->args[1] = (unsigned long)cur; 232 cb->args[1] = (unsigned long)cur;
233 break; 233 break;
234 } 234 }
235 } 235 }
236 if (!cb->args[1]) 236 if (!cb->args[1])
237 cb->args[2] = 1; 237 cb->args[2] = 1;
238 rcu_read_unlock(); 238 rcu_read_unlock();
239 return skb->len; 239 return skb->len;
240 } 240 }
241 241
242 static int cttimeout_get_timeout(struct net *net, struct sock *ctnl, 242 static int cttimeout_get_timeout(struct net *net, struct sock *ctnl,
243 struct sk_buff *skb, 243 struct sk_buff *skb,
244 const struct nlmsghdr *nlh, 244 const struct nlmsghdr *nlh,
245 const struct nlattr * const cda[], 245 const struct nlattr * const cda[],
246 struct netlink_ext_ack *extack) 246 struct netlink_ext_ack *extack)
247 { 247 {
248 int ret = -ENOENT; 248 int ret = -ENOENT;
249 char *name; 249 char *name;
250 struct ctnl_timeout *cur; 250 struct ctnl_timeout *cur;
251 251
252 if (nlh->nlmsg_flags & NLM_F_DUMP) { 252 if (nlh->nlmsg_flags & NLM_F_DUMP) {
253 struct netlink_dump_control c = { 253 struct netlink_dump_control c = {
254 .dump = ctnl_timeout_dump, 254 .dump = ctnl_timeout_dump,
255 }; 255 };
256 return netlink_dump_start(ctnl, skb, nlh, &c); 256 return netlink_dump_start(ctnl, skb, nlh, &c);
257 } 257 }
258 258
259 if (!cda[CTA_TIMEOUT_NAME]) 259 if (!cda[CTA_TIMEOUT_NAME])
260 return -EINVAL; 260 return -EINVAL;
261 name = nla_data(cda[CTA_TIMEOUT_NAME]); 261 name = nla_data(cda[CTA_TIMEOUT_NAME]);
262 262
263 list_for_each_entry(cur, &net->nfct_timeout_list, head) { 263 list_for_each_entry(cur, &net->nfct_timeout_list, head) {
264 struct sk_buff *skb2; 264 struct sk_buff *skb2;
265 265
266 if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) 266 if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
267 continue; 267 continue;
268 268
269 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 269 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
270 if (skb2 == NULL) { 270 if (skb2 == NULL) {
271 ret = -ENOMEM; 271 ret = -ENOMEM;
272 break; 272 break;
273 } 273 }
274 274
275 ret = ctnl_timeout_fill_info(skb2, NETLINK_CB(skb).portid, 275 ret = ctnl_timeout_fill_info(skb2, NETLINK_CB(skb).portid,
276 nlh->nlmsg_seq, 276 nlh->nlmsg_seq,
277 NFNL_MSG_TYPE(nlh->nlmsg_type), 277 NFNL_MSG_TYPE(nlh->nlmsg_type),
278 IPCTNL_MSG_TIMEOUT_NEW, cur); 278 IPCTNL_MSG_TIMEOUT_NEW, cur);
279 if (ret <= 0) { 279 if (ret <= 0) {
280 kfree_skb(skb2); 280 kfree_skb(skb2);
281 break; 281 break;
282 } 282 }
283 ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, 283 ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid,
284 MSG_DONTWAIT); 284 MSG_DONTWAIT);
285 if (ret > 0) 285 if (ret > 0)
286 ret = 0; 286 ret = 0;
287 287
288 /* this avoids a loop in nfnetlink. */ 288 /* this avoids a loop in nfnetlink. */
289 return ret == -EAGAIN ? -ENOBUFS : ret; 289 return ret == -EAGAIN ? -ENOBUFS : ret;
290 } 290 }
291 return ret; 291 return ret;
292 } 292 }
293 293
294 /* try to delete object, fail if it is still in use. */ 294 /* try to delete object, fail if it is still in use. */
295 static int ctnl_timeout_try_del(struct net *net, struct ctnl_timeout *timeout) 295 static int ctnl_timeout_try_del(struct net *net, struct ctnl_timeout *timeout)
296 { 296 {
297 int ret = 0; 297 int ret = 0;
298 298
299 /* We want to avoid races with ctnl_timeout_put. So only when the 299 /* We want to avoid races with ctnl_timeout_put. So only when the
300 * current refcnt is 1, we decrease it to 0. 300 * current refcnt is 1, we decrease it to 0.
301 */ 301 */
302 if (refcount_dec_if_one(&timeout->refcnt)) { 302 if (refcount_dec_if_one(&timeout->refcnt)) {
303 /* We are protected by nfnl mutex. */ 303 /* We are protected by nfnl mutex. */
304 list_del_rcu(&timeout->head); 304 list_del_rcu(&timeout->head);
305 nf_ct_l4proto_put(timeout->timeout.l4proto); 305 nf_ct_l4proto_put(timeout->timeout.l4proto);
306 nf_ct_untimeout(net, &timeout->timeout); 306 nf_ct_untimeout(net, &timeout->timeout);
307 kfree_rcu(timeout, rcu_head); 307 kfree_rcu(timeout, rcu_head);
308 } else { 308 } else {
309 ret = -EBUSY; 309 ret = -EBUSY;
310 } 310 }
311 return ret; 311 return ret;
312 } 312 }
313 313
314 static int cttimeout_del_timeout(struct net *net, struct sock *ctnl, 314 static int cttimeout_del_timeout(struct net *net, struct sock *ctnl,
315 struct sk_buff *skb, 315 struct sk_buff *skb,
316 const struct nlmsghdr *nlh, 316 const struct nlmsghdr *nlh,
317 const struct nlattr * const cda[], 317 const struct nlattr * const cda[],
318 struct netlink_ext_ack *extack) 318 struct netlink_ext_ack *extack)
319 { 319 {
320 struct ctnl_timeout *cur, *tmp; 320 struct ctnl_timeout *cur, *tmp;
321 int ret = -ENOENT; 321 int ret = -ENOENT;
322 char *name; 322 char *name;
323 323
324 if (!cda[CTA_TIMEOUT_NAME]) { 324 if (!cda[CTA_TIMEOUT_NAME]) {
325 list_for_each_entry_safe(cur, tmp, &net->nfct_timeout_list, 325 list_for_each_entry_safe(cur, tmp, &net->nfct_timeout_list,
326 head) 326 head)
327 ctnl_timeout_try_del(net, cur); 327 ctnl_timeout_try_del(net, cur);
328 328
329 return 0; 329 return 0;
330 } 330 }
331 name = nla_data(cda[CTA_TIMEOUT_NAME]); 331 name = nla_data(cda[CTA_TIMEOUT_NAME]);
332 332
333 list_for_each_entry(cur, &net->nfct_timeout_list, head) { 333 list_for_each_entry(cur, &net->nfct_timeout_list, head) {
334 if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) 334 if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
335 continue; 335 continue;
336 336
337 ret = ctnl_timeout_try_del(net, cur); 337 ret = ctnl_timeout_try_del(net, cur);
338 if (ret < 0) 338 if (ret < 0)
339 return ret; 339 return ret;
340 340
341 break; 341 break;
342 } 342 }
343 return ret; 343 return ret;
344 } 344 }
345 345
346 static int cttimeout_default_set(struct net *net, struct sock *ctnl, 346 static int cttimeout_default_set(struct net *net, struct sock *ctnl,
347 struct sk_buff *skb, 347 struct sk_buff *skb,
348 const struct nlmsghdr *nlh, 348 const struct nlmsghdr *nlh,
349 const struct nlattr * const cda[], 349 const struct nlattr * const cda[],
350 struct netlink_ext_ack *extack) 350 struct netlink_ext_ack *extack)
351 { 351 {
352 const struct nf_conntrack_l4proto *l4proto; 352 const struct nf_conntrack_l4proto *l4proto;
353 __u16 l3num;
354 __u8 l4num; 353 __u8 l4num;
355 int ret; 354 int ret;
356 355
357 if (!cda[CTA_TIMEOUT_L3PROTO] || 356 if (!cda[CTA_TIMEOUT_L3PROTO] ||
358 !cda[CTA_TIMEOUT_L4PROTO] || 357 !cda[CTA_TIMEOUT_L4PROTO] ||
359 !cda[CTA_TIMEOUT_DATA]) 358 !cda[CTA_TIMEOUT_DATA])
360 return -EINVAL; 359 return -EINVAL;
361 360
362 l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
363 l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]); 361 l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
364 l4proto = nf_ct_l4proto_find_get(l4num); 362 l4proto = nf_ct_l4proto_find_get(l4num);
365 363
366 /* This protocol is not supported, skip. */ 364 /* This protocol is not supported, skip. */
367 if (l4proto->l4proto != l4num) { 365 if (l4proto->l4proto != l4num) {
368 ret = -EOPNOTSUPP; 366 ret = -EOPNOTSUPP;
369 goto err; 367 goto err;
370 } 368 }
371 369
372 ret = ctnl_timeout_parse_policy(NULL, l4proto, net, 370 ret = ctnl_timeout_parse_policy(NULL, l4proto, net,
373 cda[CTA_TIMEOUT_DATA]); 371 cda[CTA_TIMEOUT_DATA]);
374 if (ret < 0) 372 if (ret < 0)
375 goto err; 373 goto err;
376 374
377 nf_ct_l4proto_put(l4proto); 375 nf_ct_l4proto_put(l4proto);
378 return 0; 376 return 0;
379 err: 377 err:
380 nf_ct_l4proto_put(l4proto); 378 nf_ct_l4proto_put(l4proto);
381 return ret; 379 return ret;
382 } 380 }
383 381
384 static int 382 static int
385 cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid, 383 cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid,
386 u32 seq, u32 type, int event, u16 l3num, 384 u32 seq, u32 type, int event, u16 l3num,
387 const struct nf_conntrack_l4proto *l4proto) 385 const struct nf_conntrack_l4proto *l4proto)
388 { 386 {
389 struct nlmsghdr *nlh; 387 struct nlmsghdr *nlh;
390 struct nfgenmsg *nfmsg; 388 struct nfgenmsg *nfmsg;
391 unsigned int flags = portid ? NLM_F_MULTI : 0; 389 unsigned int flags = portid ? NLM_F_MULTI : 0;
392 struct nlattr *nest_parms; 390 struct nlattr *nest_parms;
393 int ret; 391 int ret;
394 392
395 event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_TIMEOUT, event); 393 event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_TIMEOUT, event);
396 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); 394 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
397 if (nlh == NULL) 395 if (nlh == NULL)
398 goto nlmsg_failure; 396 goto nlmsg_failure;
399 397
400 nfmsg = nlmsg_data(nlh); 398 nfmsg = nlmsg_data(nlh);
401 nfmsg->nfgen_family = AF_UNSPEC; 399 nfmsg->nfgen_family = AF_UNSPEC;
402 nfmsg->version = NFNETLINK_V0; 400 nfmsg->version = NFNETLINK_V0;
403 nfmsg->res_id = 0; 401 nfmsg->res_id = 0;
404 402
405 if (nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(l3num)) || 403 if (nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(l3num)) ||
406 nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, l4proto->l4proto)) 404 nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, l4proto->l4proto))
407 goto nla_put_failure; 405 goto nla_put_failure;
408 406
409 nest_parms = nla_nest_start(skb, CTA_TIMEOUT_DATA | NLA_F_NESTED); 407 nest_parms = nla_nest_start(skb, CTA_TIMEOUT_DATA | NLA_F_NESTED);
410 if (!nest_parms) 408 if (!nest_parms)
411 goto nla_put_failure; 409 goto nla_put_failure;
412 410
413 ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, NULL); 411 ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, NULL);
414 if (ret < 0) 412 if (ret < 0)
415 goto nla_put_failure; 413 goto nla_put_failure;
416 414
417 nla_nest_end(skb, nest_parms); 415 nla_nest_end(skb, nest_parms);
418 416
419 nlmsg_end(skb, nlh); 417 nlmsg_end(skb, nlh);
420 return skb->len; 418 return skb->len;
421 419
422 nlmsg_failure: 420 nlmsg_failure:
423 nla_put_failure: 421 nla_put_failure:
424 nlmsg_cancel(skb, nlh); 422 nlmsg_cancel(skb, nlh);
425 return -1; 423 return -1;
426 } 424 }
427 425
428 static int cttimeout_default_get(struct net *net, struct sock *ctnl, 426 static int cttimeout_default_get(struct net *net, struct sock *ctnl,
429 struct sk_buff *skb, 427 struct sk_buff *skb,
430 const struct nlmsghdr *nlh, 428 const struct nlmsghdr *nlh,
431 const struct nlattr * const cda[], 429 const struct nlattr * const cda[],
432 struct netlink_ext_ack *extack) 430 struct netlink_ext_ack *extack)
433 { 431 {
434 const struct nf_conntrack_l4proto *l4proto; 432 const struct nf_conntrack_l4proto *l4proto;
435 struct sk_buff *skb2; 433 struct sk_buff *skb2;
436 int ret, err; 434 int ret, err;
437 __u16 l3num; 435 __u16 l3num;
438 __u8 l4num; 436 __u8 l4num;
439 437
440 if (!cda[CTA_TIMEOUT_L3PROTO] || !cda[CTA_TIMEOUT_L4PROTO]) 438 if (!cda[CTA_TIMEOUT_L3PROTO] || !cda[CTA_TIMEOUT_L4PROTO])
441 return -EINVAL; 439 return -EINVAL;
442 440
443 l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO])); 441 l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
444 l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]); 442 l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
445 l4proto = nf_ct_l4proto_find_get(l4num); 443 l4proto = nf_ct_l4proto_find_get(l4num);
446 444
447 /* This protocol is not supported, skip. */ 445 /* This protocol is not supported, skip. */
448 if (l4proto->l4proto != l4num) { 446 if (l4proto->l4proto != l4num) {
449 err = -EOPNOTSUPP; 447 err = -EOPNOTSUPP;
450 goto err; 448 goto err;
451 } 449 }
452 450
453 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 451 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
454 if (skb2 == NULL) { 452 if (skb2 == NULL) {
455 err = -ENOMEM; 453 err = -ENOMEM;
456 goto err; 454 goto err;
457 } 455 }
458 456
459 ret = cttimeout_default_fill_info(net, skb2, NETLINK_CB(skb).portid, 457 ret = cttimeout_default_fill_info(net, skb2, NETLINK_CB(skb).portid,
460 nlh->nlmsg_seq, 458 nlh->nlmsg_seq,
461 NFNL_MSG_TYPE(nlh->nlmsg_type), 459 NFNL_MSG_TYPE(nlh->nlmsg_type),
462 IPCTNL_MSG_TIMEOUT_DEFAULT_SET, 460 IPCTNL_MSG_TIMEOUT_DEFAULT_SET,
463 l3num, 461 l3num,
464 l4proto); 462 l4proto);
465 if (ret <= 0) { 463 if (ret <= 0) {
466 kfree_skb(skb2); 464 kfree_skb(skb2);
467 err = -ENOMEM; 465 err = -ENOMEM;
468 goto err; 466 goto err;
469 } 467 }
470 ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT); 468 ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
471 if (ret > 0) 469 if (ret > 0)
472 ret = 0; 470 ret = 0;
473 471
474 /* this avoids a loop in nfnetlink. */ 472 /* this avoids a loop in nfnetlink. */
475 return ret == -EAGAIN ? -ENOBUFS : ret; 473 return ret == -EAGAIN ? -ENOBUFS : ret;
476 err: 474 err:
477 nf_ct_l4proto_put(l4proto); 475 nf_ct_l4proto_put(l4proto);
478 return err; 476 return err;
479 } 477 }
480 478
481 static struct nf_ct_timeout *ctnl_timeout_find_get(struct net *net, 479 static struct nf_ct_timeout *ctnl_timeout_find_get(struct net *net,
482 const char *name) 480 const char *name)
483 { 481 {
484 struct ctnl_timeout *timeout, *matching = NULL; 482 struct ctnl_timeout *timeout, *matching = NULL;
485 483
486 list_for_each_entry_rcu(timeout, &net->nfct_timeout_list, head) { 484 list_for_each_entry_rcu(timeout, &net->nfct_timeout_list, head) {
487 if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) 485 if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
488 continue; 486 continue;
489 487
490 if (!try_module_get(THIS_MODULE)) 488 if (!try_module_get(THIS_MODULE))
491 goto err; 489 goto err;
492 490
493 if (!refcount_inc_not_zero(&timeout->refcnt)) { 491 if (!refcount_inc_not_zero(&timeout->refcnt)) {
494 module_put(THIS_MODULE); 492 module_put(THIS_MODULE);
495 goto err; 493 goto err;
496 } 494 }
497 matching = timeout; 495 matching = timeout;
498 break; 496 break;
499 } 497 }
500 err: 498 err:
501 return matching ? &matching->timeout : NULL; 499 return matching ? &matching->timeout : NULL;
502 } 500 }
503 501
504 static void ctnl_timeout_put(struct nf_ct_timeout *t) 502 static void ctnl_timeout_put(struct nf_ct_timeout *t)
505 { 503 {
506 struct ctnl_timeout *timeout = 504 struct ctnl_timeout *timeout =
507 container_of(t, struct ctnl_timeout, timeout); 505 container_of(t, struct ctnl_timeout, timeout);
508 506
509 if (refcount_dec_and_test(&timeout->refcnt)) 507 if (refcount_dec_and_test(&timeout->refcnt))
510 kfree_rcu(timeout, rcu_head); 508 kfree_rcu(timeout, rcu_head);
511 509
512 module_put(THIS_MODULE); 510 module_put(THIS_MODULE);
513 } 511 }
514 512
515 static const struct nfnl_callback cttimeout_cb[IPCTNL_MSG_TIMEOUT_MAX] = { 513 static const struct nfnl_callback cttimeout_cb[IPCTNL_MSG_TIMEOUT_MAX] = {
516 [IPCTNL_MSG_TIMEOUT_NEW] = { .call = cttimeout_new_timeout, 514 [IPCTNL_MSG_TIMEOUT_NEW] = { .call = cttimeout_new_timeout,
517 .attr_count = CTA_TIMEOUT_MAX, 515 .attr_count = CTA_TIMEOUT_MAX,
518 .policy = cttimeout_nla_policy }, 516 .policy = cttimeout_nla_policy },
519 [IPCTNL_MSG_TIMEOUT_GET] = { .call = cttimeout_get_timeout, 517 [IPCTNL_MSG_TIMEOUT_GET] = { .call = cttimeout_get_timeout,
520 .attr_count = CTA_TIMEOUT_MAX, 518 .attr_count = CTA_TIMEOUT_MAX,
521 .policy = cttimeout_nla_policy }, 519 .policy = cttimeout_nla_policy },
522 [IPCTNL_MSG_TIMEOUT_DELETE] = { .call = cttimeout_del_timeout, 520 [IPCTNL_MSG_TIMEOUT_DELETE] = { .call = cttimeout_del_timeout,
523 .attr_count = CTA_TIMEOUT_MAX, 521 .attr_count = CTA_TIMEOUT_MAX,
524 .policy = cttimeout_nla_policy }, 522 .policy = cttimeout_nla_policy },
525 [IPCTNL_MSG_TIMEOUT_DEFAULT_SET]= { .call = cttimeout_default_set, 523 [IPCTNL_MSG_TIMEOUT_DEFAULT_SET]= { .call = cttimeout_default_set,
526 .attr_count = CTA_TIMEOUT_MAX, 524 .attr_count = CTA_TIMEOUT_MAX,
527 .policy = cttimeout_nla_policy }, 525 .policy = cttimeout_nla_policy },
528 [IPCTNL_MSG_TIMEOUT_DEFAULT_GET]= { .call = cttimeout_default_get, 526 [IPCTNL_MSG_TIMEOUT_DEFAULT_GET]= { .call = cttimeout_default_get,
529 .attr_count = CTA_TIMEOUT_MAX, 527 .attr_count = CTA_TIMEOUT_MAX,
530 .policy = cttimeout_nla_policy }, 528 .policy = cttimeout_nla_policy },
531 }; 529 };
532 530
533 static const struct nfnetlink_subsystem cttimeout_subsys = { 531 static const struct nfnetlink_subsystem cttimeout_subsys = {
534 .name = "conntrack_timeout", 532 .name = "conntrack_timeout",
535 .subsys_id = NFNL_SUBSYS_CTNETLINK_TIMEOUT, 533 .subsys_id = NFNL_SUBSYS_CTNETLINK_TIMEOUT,
536 .cb_count = IPCTNL_MSG_TIMEOUT_MAX, 534 .cb_count = IPCTNL_MSG_TIMEOUT_MAX,
537 .cb = cttimeout_cb, 535 .cb = cttimeout_cb,
538 }; 536 };
539 537
540 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_TIMEOUT); 538 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_TIMEOUT);
541 539
542 static int __net_init cttimeout_net_init(struct net *net) 540 static int __net_init cttimeout_net_init(struct net *net)
543 { 541 {
544 INIT_LIST_HEAD(&net->nfct_timeout_list); 542 INIT_LIST_HEAD(&net->nfct_timeout_list);
545 543
546 return 0; 544 return 0;
547 } 545 }
548 546
549 static void __net_exit cttimeout_net_exit(struct net *net) 547 static void __net_exit cttimeout_net_exit(struct net *net)
550 { 548 {
551 struct ctnl_timeout *cur, *tmp; 549 struct ctnl_timeout *cur, *tmp;
552 550
553 nf_ct_unconfirmed_destroy(net); 551 nf_ct_unconfirmed_destroy(net);
554 nf_ct_untimeout(net, NULL); 552 nf_ct_untimeout(net, NULL);
555 553
556 list_for_each_entry_safe(cur, tmp, &net->nfct_timeout_list, head) { 554 list_for_each_entry_safe(cur, tmp, &net->nfct_timeout_list, head) {
557 list_del_rcu(&cur->head); 555 list_del_rcu(&cur->head);
558 nf_ct_l4proto_put(cur->timeout.l4proto); 556 nf_ct_l4proto_put(cur->timeout.l4proto);
559 557
560 if (refcount_dec_and_test(&cur->refcnt)) 558 if (refcount_dec_and_test(&cur->refcnt))
561 kfree_rcu(cur, rcu_head); 559 kfree_rcu(cur, rcu_head);
562 } 560 }
563 } 561 }
564 562
565 static struct pernet_operations cttimeout_ops = { 563 static struct pernet_operations cttimeout_ops = {
566 .init = cttimeout_net_init, 564 .init = cttimeout_net_init,
567 .exit = cttimeout_net_exit, 565 .exit = cttimeout_net_exit,
568 }; 566 };
569 567
570 static int __init cttimeout_init(void) 568 static int __init cttimeout_init(void)
571 { 569 {
572 int ret; 570 int ret;
573 571
574 ret = register_pernet_subsys(&cttimeout_ops); 572 ret = register_pernet_subsys(&cttimeout_ops);
575 if (ret < 0) 573 if (ret < 0)
576 return ret; 574 return ret;
577 575
578 ret = nfnetlink_subsys_register(&cttimeout_subsys); 576 ret = nfnetlink_subsys_register(&cttimeout_subsys);
579 if (ret < 0) { 577 if (ret < 0) {
580 pr_err("cttimeout_init: cannot register cttimeout with " 578 pr_err("cttimeout_init: cannot register cttimeout with "
581 "nfnetlink.\n"); 579 "nfnetlink.\n");
582 goto err_out; 580 goto err_out;
583 } 581 }
584 RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, ctnl_timeout_find_get); 582 RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, ctnl_timeout_find_get);
585 RCU_INIT_POINTER(nf_ct_timeout_put_hook, ctnl_timeout_put); 583 RCU_INIT_POINTER(nf_ct_timeout_put_hook, ctnl_timeout_put);
586 return 0; 584 return 0;
587 585
588 err_out: 586 err_out:
589 unregister_pernet_subsys(&cttimeout_ops); 587 unregister_pernet_subsys(&cttimeout_ops);
590 return ret; 588 return ret;
591 } 589 }
592 590
593 static void __exit cttimeout_exit(void) 591 static void __exit cttimeout_exit(void)
594 { 592 {
595 nfnetlink_subsys_unregister(&cttimeout_subsys); 593 nfnetlink_subsys_unregister(&cttimeout_subsys);
596 594
597 unregister_pernet_subsys(&cttimeout_ops); 595 unregister_pernet_subsys(&cttimeout_ops);
598 RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, NULL); 596 RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, NULL);
599 RCU_INIT_POINTER(nf_ct_timeout_put_hook, NULL); 597 RCU_INIT_POINTER(nf_ct_timeout_put_hook, NULL);
600 synchronize_rcu(); 598 synchronize_rcu();
601 } 599 }
602 600
603 module_init(cttimeout_init); 601 module_init(cttimeout_init);
604 module_exit(cttimeout_exit); 602 module_exit(cttimeout_exit);
605 603