Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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