nfnetlink_cttimeout.c revision 15e473046cb6e5d18a4d0057e61d76315230382b
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#include <net/netfilter/nf_conntrack_timeout.h> 33 34#include <linux/netfilter/nfnetlink.h> 35#include <linux/netfilter/nfnetlink_cttimeout.h> 36 37MODULE_LICENSE("GPL"); 38MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); 39MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tuning"); 40 41static LIST_HEAD(cttimeout_list); 42 43static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = { 44 [CTA_TIMEOUT_NAME] = { .type = NLA_NUL_STRING }, 45 [CTA_TIMEOUT_L3PROTO] = { .type = NLA_U16 }, 46 [CTA_TIMEOUT_L4PROTO] = { .type = NLA_U8 }, 47 [CTA_TIMEOUT_DATA] = { .type = NLA_NESTED }, 48}; 49 50static int 51ctnl_timeout_parse_policy(struct ctnl_timeout *timeout, 52 struct nf_conntrack_l4proto *l4proto, 53 struct net *net, 54 const struct nlattr *attr) 55{ 56 int ret = 0; 57 58 if (likely(l4proto->ctnl_timeout.nlattr_to_obj)) { 59 struct nlattr *tb[l4proto->ctnl_timeout.nlattr_max+1]; 60 61 nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max, 62 attr, l4proto->ctnl_timeout.nla_policy); 63 64 ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, net, 65 &timeout->data); 66 } 67 return ret; 68} 69 70static int 71cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb, 72 const struct nlmsghdr *nlh, 73 const struct nlattr * const cda[]) 74{ 75 __u16 l3num; 76 __u8 l4num; 77 struct nf_conntrack_l4proto *l4proto; 78 struct ctnl_timeout *timeout, *matching = NULL; 79 struct net *net = sock_net(skb->sk); 80 char *name; 81 int ret; 82 83 if (!cda[CTA_TIMEOUT_NAME] || 84 !cda[CTA_TIMEOUT_L3PROTO] || 85 !cda[CTA_TIMEOUT_L4PROTO] || 86 !cda[CTA_TIMEOUT_DATA]) 87 return -EINVAL; 88 89 name = nla_data(cda[CTA_TIMEOUT_NAME]); 90 l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO])); 91 l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]); 92 93 list_for_each_entry(timeout, &cttimeout_list, head) { 94 if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) 95 continue; 96 97 if (nlh->nlmsg_flags & NLM_F_EXCL) 98 return -EEXIST; 99 100 matching = timeout; 101 break; 102 } 103 104 l4proto = nf_ct_l4proto_find_get(l3num, l4num); 105 106 /* This protocol is not supportted, skip. */ 107 if (l4proto->l4proto != l4num) { 108 ret = -EOPNOTSUPP; 109 goto err_proto_put; 110 } 111 112 if (matching) { 113 if (nlh->nlmsg_flags & NLM_F_REPLACE) { 114 /* You cannot replace one timeout policy by another of 115 * different kind, sorry. 116 */ 117 if (matching->l3num != l3num || 118 matching->l4proto->l4proto != l4num) { 119 ret = -EINVAL; 120 goto err_proto_put; 121 } 122 123 ret = ctnl_timeout_parse_policy(matching, l4proto, net, 124 cda[CTA_TIMEOUT_DATA]); 125 return ret; 126 } 127 ret = -EBUSY; 128 goto err_proto_put; 129 } 130 131 timeout = kzalloc(sizeof(struct ctnl_timeout) + 132 l4proto->ctnl_timeout.obj_size, GFP_KERNEL); 133 if (timeout == NULL) { 134 ret = -ENOMEM; 135 goto err_proto_put; 136 } 137 138 ret = ctnl_timeout_parse_policy(timeout, l4proto, net, 139 cda[CTA_TIMEOUT_DATA]); 140 if (ret < 0) 141 goto err; 142 143 strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME])); 144 timeout->l3num = l3num; 145 timeout->l4proto = l4proto; 146 atomic_set(&timeout->refcnt, 1); 147 list_add_tail_rcu(&timeout->head, &cttimeout_list); 148 149 return 0; 150err: 151 kfree(timeout); 152err_proto_put: 153 nf_ct_l4proto_put(l4proto); 154 return ret; 155} 156 157static int 158ctnl_timeout_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, 159 int event, struct ctnl_timeout *timeout) 160{ 161 struct nlmsghdr *nlh; 162 struct nfgenmsg *nfmsg; 163 unsigned int flags = portid ? NLM_F_MULTI : 0; 164 struct nf_conntrack_l4proto *l4proto = timeout->l4proto; 165 166 event |= NFNL_SUBSYS_CTNETLINK_TIMEOUT << 8; 167 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); 168 if (nlh == NULL) 169 goto nlmsg_failure; 170 171 nfmsg = nlmsg_data(nlh); 172 nfmsg->nfgen_family = AF_UNSPEC; 173 nfmsg->version = NFNETLINK_V0; 174 nfmsg->res_id = 0; 175 176 if (nla_put_string(skb, CTA_TIMEOUT_NAME, timeout->name) || 177 nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num)) || 178 nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4proto->l4proto) || 179 nla_put_be32(skb, CTA_TIMEOUT_USE, 180 htonl(atomic_read(&timeout->refcnt)))) 181 goto nla_put_failure; 182 183 if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) { 184 struct nlattr *nest_parms; 185 int ret; 186 187 nest_parms = nla_nest_start(skb, 188 CTA_TIMEOUT_DATA | NLA_F_NESTED); 189 if (!nest_parms) 190 goto nla_put_failure; 191 192 ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, &timeout->data); 193 if (ret < 0) 194 goto nla_put_failure; 195 196 nla_nest_end(skb, nest_parms); 197 } 198 199 nlmsg_end(skb, nlh); 200 return skb->len; 201 202nlmsg_failure: 203nla_put_failure: 204 nlmsg_cancel(skb, nlh); 205 return -1; 206} 207 208static int 209ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb) 210{ 211 struct ctnl_timeout *cur, *last; 212 213 if (cb->args[2]) 214 return 0; 215 216 last = (struct ctnl_timeout *)cb->args[1]; 217 if (cb->args[1]) 218 cb->args[1] = 0; 219 220 rcu_read_lock(); 221 list_for_each_entry_rcu(cur, &cttimeout_list, head) { 222 if (last && cur != last) 223 continue; 224 225 if (ctnl_timeout_fill_info(skb, NETLINK_CB(cb->skb).portid, 226 cb->nlh->nlmsg_seq, 227 NFNL_MSG_TYPE(cb->nlh->nlmsg_type), 228 IPCTNL_MSG_TIMEOUT_NEW, cur) < 0) { 229 cb->args[1] = (unsigned long)cur; 230 break; 231 } 232 } 233 if (!cb->args[1]) 234 cb->args[2] = 1; 235 rcu_read_unlock(); 236 return skb->len; 237} 238 239static int 240cttimeout_get_timeout(struct sock *ctnl, struct sk_buff *skb, 241 const struct nlmsghdr *nlh, 242 const struct nlattr * const cda[]) 243{ 244 int ret = -ENOENT; 245 char *name; 246 struct ctnl_timeout *cur; 247 248 if (nlh->nlmsg_flags & NLM_F_DUMP) { 249 struct netlink_dump_control c = { 250 .dump = ctnl_timeout_dump, 251 }; 252 return netlink_dump_start(ctnl, skb, nlh, &c); 253 } 254 255 if (!cda[CTA_TIMEOUT_NAME]) 256 return -EINVAL; 257 name = nla_data(cda[CTA_TIMEOUT_NAME]); 258 259 list_for_each_entry(cur, &cttimeout_list, head) { 260 struct sk_buff *skb2; 261 262 if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) 263 continue; 264 265 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 266 if (skb2 == NULL) { 267 ret = -ENOMEM; 268 break; 269 } 270 271 ret = ctnl_timeout_fill_info(skb2, NETLINK_CB(skb).portid, 272 nlh->nlmsg_seq, 273 NFNL_MSG_TYPE(nlh->nlmsg_type), 274 IPCTNL_MSG_TIMEOUT_NEW, cur); 275 if (ret <= 0) { 276 kfree_skb(skb2); 277 break; 278 } 279 ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, 280 MSG_DONTWAIT); 281 if (ret > 0) 282 ret = 0; 283 284 /* this avoids a loop in nfnetlink. */ 285 return ret == -EAGAIN ? -ENOBUFS : ret; 286 } 287 return ret; 288} 289 290/* try to delete object, fail if it is still in use. */ 291static int ctnl_timeout_try_del(struct ctnl_timeout *timeout) 292{ 293 int ret = 0; 294 295 /* we want to avoid races with nf_ct_timeout_find_get. */ 296 if (atomic_dec_and_test(&timeout->refcnt)) { 297 /* We are protected by nfnl mutex. */ 298 list_del_rcu(&timeout->head); 299 nf_ct_l4proto_put(timeout->l4proto); 300 kfree_rcu(timeout, rcu_head); 301 } else { 302 /* still in use, restore reference counter. */ 303 atomic_inc(&timeout->refcnt); 304 ret = -EBUSY; 305 } 306 return ret; 307} 308 309static int 310cttimeout_del_timeout(struct sock *ctnl, struct sk_buff *skb, 311 const struct nlmsghdr *nlh, 312 const struct nlattr * const cda[]) 313{ 314 char *name; 315 struct ctnl_timeout *cur; 316 int ret = -ENOENT; 317 318 if (!cda[CTA_TIMEOUT_NAME]) { 319 list_for_each_entry(cur, &cttimeout_list, head) 320 ctnl_timeout_try_del(cur); 321 322 return 0; 323 } 324 name = nla_data(cda[CTA_TIMEOUT_NAME]); 325 326 list_for_each_entry(cur, &cttimeout_list, head) { 327 if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) 328 continue; 329 330 ret = ctnl_timeout_try_del(cur); 331 if (ret < 0) 332 return ret; 333 334 break; 335 } 336 return ret; 337} 338 339#ifdef CONFIG_NF_CONNTRACK_TIMEOUT 340static struct ctnl_timeout *ctnl_timeout_find_get(const char *name) 341{ 342 struct ctnl_timeout *timeout, *matching = NULL; 343 344 rcu_read_lock(); 345 list_for_each_entry_rcu(timeout, &cttimeout_list, head) { 346 if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) 347 continue; 348 349 if (!try_module_get(THIS_MODULE)) 350 goto err; 351 352 if (!atomic_inc_not_zero(&timeout->refcnt)) { 353 module_put(THIS_MODULE); 354 goto err; 355 } 356 matching = timeout; 357 break; 358 } 359err: 360 rcu_read_unlock(); 361 return matching; 362} 363 364static void ctnl_timeout_put(struct ctnl_timeout *timeout) 365{ 366 atomic_dec(&timeout->refcnt); 367 module_put(THIS_MODULE); 368} 369#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ 370 371static const struct nfnl_callback cttimeout_cb[IPCTNL_MSG_TIMEOUT_MAX] = { 372 [IPCTNL_MSG_TIMEOUT_NEW] = { .call = cttimeout_new_timeout, 373 .attr_count = CTA_TIMEOUT_MAX, 374 .policy = cttimeout_nla_policy }, 375 [IPCTNL_MSG_TIMEOUT_GET] = { .call = cttimeout_get_timeout, 376 .attr_count = CTA_TIMEOUT_MAX, 377 .policy = cttimeout_nla_policy }, 378 [IPCTNL_MSG_TIMEOUT_DELETE] = { .call = cttimeout_del_timeout, 379 .attr_count = CTA_TIMEOUT_MAX, 380 .policy = cttimeout_nla_policy }, 381}; 382 383static const struct nfnetlink_subsystem cttimeout_subsys = { 384 .name = "conntrack_timeout", 385 .subsys_id = NFNL_SUBSYS_CTNETLINK_TIMEOUT, 386 .cb_count = IPCTNL_MSG_TIMEOUT_MAX, 387 .cb = cttimeout_cb, 388}; 389 390MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_TIMEOUT); 391 392static int __init cttimeout_init(void) 393{ 394 int ret; 395 396 ret = nfnetlink_subsys_register(&cttimeout_subsys); 397 if (ret < 0) { 398 pr_err("cttimeout_init: cannot register cttimeout with " 399 "nfnetlink.\n"); 400 goto err_out; 401 } 402#ifdef CONFIG_NF_CONNTRACK_TIMEOUT 403 RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, ctnl_timeout_find_get); 404 RCU_INIT_POINTER(nf_ct_timeout_put_hook, ctnl_timeout_put); 405#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ 406 return 0; 407 408err_out: 409 return ret; 410} 411 412static void __exit cttimeout_exit(void) 413{ 414 struct ctnl_timeout *cur, *tmp; 415 416 pr_info("cttimeout: unregistering from nfnetlink.\n"); 417 418 nfnetlink_subsys_unregister(&cttimeout_subsys); 419 list_for_each_entry_safe(cur, tmp, &cttimeout_list, head) { 420 list_del_rcu(&cur->head); 421 /* We are sure that our objects have no clients at this point, 422 * it's safe to release them all without checking refcnt. 423 */ 424 nf_ct_l4proto_put(cur->l4proto); 425 kfree_rcu(cur, rcu_head); 426 } 427#ifdef CONFIG_NF_CONNTRACK_TIMEOUT 428 RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, NULL); 429 RCU_INIT_POINTER(nf_ct_timeout_put_hook, NULL); 430#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ 431} 432 433module_init(cttimeout_init); 434module_exit(cttimeout_exit); 435