]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - net/netfilter/nfnetlink_cttimeout.c
netfilter: nf_ct_ext: add timeout extension
[mirror_ubuntu-artful-kernel.git] / net / netfilter / nfnetlink_cttimeout.c
1 /*
2 * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
3 * (C) 2012 by Vyatta Inc. <http://www.vyatta.com>
4 *
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
7 * published by the Free Software Foundation (or any later at your option).
8 */
9 #include <linux/init.h>
10 #include <linux/module.h>
11 #include <linux/kernel.h>
12 #include <linux/rculist.h>
13 #include <linux/rculist_nulls.h>
14 #include <linux/types.h>
15 #include <linux/timer.h>
16 #include <linux/security.h>
17 #include <linux/skbuff.h>
18 #include <linux/errno.h>
19 #include <linux/netlink.h>
20 #include <linux/spinlock.h>
21 #include <linux/interrupt.h>
22 #include <linux/slab.h>
23
24 #include <linux/netfilter.h>
25 #include <net/netlink.h>
26 #include <net/sock.h>
27 #include <net/netfilter/nf_conntrack.h>
28 #include <net/netfilter/nf_conntrack_core.h>
29 #include <net/netfilter/nf_conntrack_l3proto.h>
30 #include <net/netfilter/nf_conntrack_l4proto.h>
31 #include <net/netfilter/nf_conntrack_tuple.h>
32
33 #include <linux/netfilter/nfnetlink.h>
34 #include <linux/netfilter/nfnetlink_cttimeout.h>
35
36 MODULE_LICENSE("GPL");
37 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
38 MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tuning");
39
40 static LIST_HEAD(cttimeout_list);
41
42 static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = {
43 [CTA_TIMEOUT_NAME] = { .type = NLA_NUL_STRING },
44 [CTA_TIMEOUT_L3PROTO] = { .type = NLA_U16 },
45 [CTA_TIMEOUT_L4PROTO] = { .type = NLA_U8 },
46 [CTA_TIMEOUT_DATA] = { .type = NLA_NESTED },
47 };
48
49 static int
50 ctnl_timeout_parse_policy(struct ctnl_timeout *timeout,
51 struct nf_conntrack_l4proto *l4proto,
52 const struct nlattr *attr)
53 {
54 int ret = 0;
55
56 if (likely(l4proto->ctnl_timeout.nlattr_to_obj)) {
57 struct nlattr *tb[l4proto->ctnl_timeout.nlattr_max+1];
58
59 nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max,
60 attr, l4proto->ctnl_timeout.nla_policy);
61
62 ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, &timeout->data);
63 }
64 return ret;
65 }
66
67 static int
68 cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb,
69 const struct nlmsghdr *nlh,
70 const struct nlattr * const cda[])
71 {
72 __u16 l3num;
73 __u8 l4num;
74 struct nf_conntrack_l4proto *l4proto;
75 struct ctnl_timeout *timeout, *matching = NULL;
76 char *name;
77 int ret;
78
79 if (!cda[CTA_TIMEOUT_NAME] ||
80 !cda[CTA_TIMEOUT_L3PROTO] ||
81 !cda[CTA_TIMEOUT_L4PROTO] ||
82 !cda[CTA_TIMEOUT_DATA])
83 return -EINVAL;
84
85 name = nla_data(cda[CTA_TIMEOUT_NAME]);
86 l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
87 l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
88
89 list_for_each_entry(timeout, &cttimeout_list, head) {
90 if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
91 continue;
92
93 if (nlh->nlmsg_flags & NLM_F_EXCL)
94 return -EEXIST;
95
96 matching = timeout;
97 break;
98 }
99
100 l4proto = __nf_ct_l4proto_find(l3num, l4num);
101
102 /* This protocol is not supportted, skip. */
103 if (l4proto->l4proto != l4num)
104 return -EOPNOTSUPP;
105
106 if (matching) {
107 if (nlh->nlmsg_flags & NLM_F_REPLACE) {
108 /* You cannot replace one timeout policy by another of
109 * different kind, sorry.
110 */
111 if (matching->l3num != l3num ||
112 matching->l4num != l4num)
113 return -EINVAL;
114
115 ret = ctnl_timeout_parse_policy(matching, l4proto,
116 cda[CTA_TIMEOUT_DATA]);
117 return ret;
118 }
119 return -EBUSY;
120 }
121
122 timeout = kzalloc(sizeof(struct ctnl_timeout) +
123 l4proto->ctnl_timeout.obj_size, GFP_KERNEL);
124 if (timeout == NULL)
125 return -ENOMEM;
126
127 ret = ctnl_timeout_parse_policy(timeout, l4proto,
128 cda[CTA_TIMEOUT_DATA]);
129 if (ret < 0)
130 goto err;
131
132 strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME]));
133 timeout->l3num = l3num;
134 timeout->l4num = l4num;
135 atomic_set(&timeout->refcnt, 1);
136 list_add_tail_rcu(&timeout->head, &cttimeout_list);
137
138 return 0;
139 err:
140 kfree(timeout);
141 return ret;
142 }
143
144 static int
145 ctnl_timeout_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type,
146 int event, struct ctnl_timeout *timeout)
147 {
148 struct nlmsghdr *nlh;
149 struct nfgenmsg *nfmsg;
150 unsigned int flags = pid ? NLM_F_MULTI : 0;
151 struct nf_conntrack_l4proto *l4proto;
152
153 event |= NFNL_SUBSYS_CTNETLINK_TIMEOUT << 8;
154 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags);
155 if (nlh == NULL)
156 goto nlmsg_failure;
157
158 nfmsg = nlmsg_data(nlh);
159 nfmsg->nfgen_family = AF_UNSPEC;
160 nfmsg->version = NFNETLINK_V0;
161 nfmsg->res_id = 0;
162
163 NLA_PUT_STRING(skb, CTA_TIMEOUT_NAME, timeout->name);
164 NLA_PUT_BE16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num));
165 NLA_PUT_U8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4num);
166 NLA_PUT_BE32(skb, CTA_TIMEOUT_USE,
167 htonl(atomic_read(&timeout->refcnt)));
168
169 l4proto = __nf_ct_l4proto_find(timeout->l3num, timeout->l4num);
170
171 /* If the timeout object does not match the layer 4 protocol tracker,
172 * then skip dumping the data part since we don't know how to
173 * interpret it. This may happen for UPDlite, SCTP and DCCP since
174 * you can unload the module.
175 */
176 if (timeout->l4num != l4proto->l4proto)
177 goto out;
178
179 if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) {
180 struct nlattr *nest_parms;
181 int ret;
182
183 nest_parms = nla_nest_start(skb,
184 CTA_TIMEOUT_DATA | NLA_F_NESTED);
185 if (!nest_parms)
186 goto nla_put_failure;
187
188 ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, &timeout->data);
189 if (ret < 0)
190 goto nla_put_failure;
191
192 nla_nest_end(skb, nest_parms);
193 }
194 out:
195 nlmsg_end(skb, nlh);
196 return skb->len;
197
198 nlmsg_failure:
199 nla_put_failure:
200 nlmsg_cancel(skb, nlh);
201 return -1;
202 }
203
204 static int
205 ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb)
206 {
207 struct ctnl_timeout *cur, *last;
208
209 if (cb->args[2])
210 return 0;
211
212 last = (struct ctnl_timeout *)cb->args[1];
213 if (cb->args[1])
214 cb->args[1] = 0;
215
216 rcu_read_lock();
217 list_for_each_entry_rcu(cur, &cttimeout_list, head) {
218 if (last && cur != last)
219 continue;
220
221 if (ctnl_timeout_fill_info(skb, NETLINK_CB(cb->skb).pid,
222 cb->nlh->nlmsg_seq,
223 NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
224 IPCTNL_MSG_TIMEOUT_NEW, cur) < 0) {
225 cb->args[1] = (unsigned long)cur;
226 break;
227 }
228 }
229 if (!cb->args[1])
230 cb->args[2] = 1;
231 rcu_read_unlock();
232 return skb->len;
233 }
234
235 static int
236 cttimeout_get_timeout(struct sock *ctnl, struct sk_buff *skb,
237 const struct nlmsghdr *nlh,
238 const struct nlattr * const cda[])
239 {
240 int ret = -ENOENT;
241 char *name;
242 struct ctnl_timeout *cur;
243
244 if (nlh->nlmsg_flags & NLM_F_DUMP) {
245 struct netlink_dump_control c = {
246 .dump = ctnl_timeout_dump,
247 };
248 return netlink_dump_start(ctnl, skb, nlh, &c);
249 }
250
251 if (!cda[CTA_TIMEOUT_NAME])
252 return -EINVAL;
253 name = nla_data(cda[CTA_TIMEOUT_NAME]);
254
255 list_for_each_entry(cur, &cttimeout_list, head) {
256 struct sk_buff *skb2;
257
258 if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
259 continue;
260
261 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
262 if (skb2 == NULL) {
263 ret = -ENOMEM;
264 break;
265 }
266
267 ret = ctnl_timeout_fill_info(skb2, NETLINK_CB(skb).pid,
268 nlh->nlmsg_seq,
269 NFNL_MSG_TYPE(nlh->nlmsg_type),
270 IPCTNL_MSG_TIMEOUT_NEW, cur);
271 if (ret <= 0) {
272 kfree_skb(skb2);
273 break;
274 }
275 ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid,
276 MSG_DONTWAIT);
277 if (ret > 0)
278 ret = 0;
279
280 /* this avoids a loop in nfnetlink. */
281 return ret == -EAGAIN ? -ENOBUFS : ret;
282 }
283 return ret;
284 }
285
286 /* try to delete object, fail if it is still in use. */
287 static int ctnl_timeout_try_del(struct ctnl_timeout *timeout)
288 {
289 int ret = 0;
290
291 /* we want to avoid races with nf_ct_timeout_find_get. */
292 if (atomic_dec_and_test(&timeout->refcnt)) {
293 /* We are protected by nfnl mutex. */
294 list_del_rcu(&timeout->head);
295 kfree_rcu(timeout, rcu_head);
296 } else {
297 /* still in use, restore reference counter. */
298 atomic_inc(&timeout->refcnt);
299 ret = -EBUSY;
300 }
301 return ret;
302 }
303
304 static int
305 cttimeout_del_timeout(struct sock *ctnl, struct sk_buff *skb,
306 const struct nlmsghdr *nlh,
307 const struct nlattr * const cda[])
308 {
309 char *name;
310 struct ctnl_timeout *cur;
311 int ret = -ENOENT;
312
313 if (!cda[CTA_TIMEOUT_NAME]) {
314 list_for_each_entry(cur, &cttimeout_list, head)
315 ctnl_timeout_try_del(cur);
316
317 return 0;
318 }
319 name = nla_data(cda[CTA_TIMEOUT_NAME]);
320
321 list_for_each_entry(cur, &cttimeout_list, head) {
322 if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
323 continue;
324
325 ret = ctnl_timeout_try_del(cur);
326 if (ret < 0)
327 return ret;
328
329 break;
330 }
331 return ret;
332 }
333
334 static const struct nfnl_callback cttimeout_cb[IPCTNL_MSG_TIMEOUT_MAX] = {
335 [IPCTNL_MSG_TIMEOUT_NEW] = { .call = cttimeout_new_timeout,
336 .attr_count = CTA_TIMEOUT_MAX,
337 .policy = cttimeout_nla_policy },
338 [IPCTNL_MSG_TIMEOUT_GET] = { .call = cttimeout_get_timeout,
339 .attr_count = CTA_TIMEOUT_MAX,
340 .policy = cttimeout_nla_policy },
341 [IPCTNL_MSG_TIMEOUT_DELETE] = { .call = cttimeout_del_timeout,
342 .attr_count = CTA_TIMEOUT_MAX,
343 .policy = cttimeout_nla_policy },
344 };
345
346 static const struct nfnetlink_subsystem cttimeout_subsys = {
347 .name = "conntrack_timeout",
348 .subsys_id = NFNL_SUBSYS_CTNETLINK_TIMEOUT,
349 .cb_count = IPCTNL_MSG_TIMEOUT_MAX,
350 .cb = cttimeout_cb,
351 };
352
353 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_TIMEOUT);
354
355 static int __init cttimeout_init(void)
356 {
357 int ret;
358
359 ret = nfnetlink_subsys_register(&cttimeout_subsys);
360 if (ret < 0) {
361 pr_err("cttimeout_init: cannot register cttimeout with "
362 "nfnetlink.\n");
363 goto err_out;
364 }
365 return 0;
366
367 err_out:
368 return ret;
369 }
370
371 static void __exit cttimeout_exit(void)
372 {
373 struct ctnl_timeout *cur, *tmp;
374
375 pr_info("cttimeout: unregistering from nfnetlink.\n");
376
377 nfnetlink_subsys_unregister(&cttimeout_subsys);
378 list_for_each_entry_safe(cur, tmp, &cttimeout_list, head) {
379 list_del_rcu(&cur->head);
380 /* We are sure that our objects have no clients at this point,
381 * it's safe to release them all without checking refcnt.
382 */
383 kfree_rcu(cur, rcu_head);
384 }
385 }
386
387 module_init(cttimeout_init);
388 module_exit(cttimeout_exit);