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