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