linux/net/netfilter/nfnetlink_cttimeout.c
<<
>>
Prefs
   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(void *timeouts, struct nf_conntrack_l4proto *l4proto,
  53                          struct net *net, const struct nlattr *attr)
  54{
  55        int ret = 0;
  56
  57        if (likely(l4proto->ctnl_timeout.nlattr_to_obj)) {
  58                struct nlattr *tb[l4proto->ctnl_timeout.nlattr_max+1];
  59
  60                ret = nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max,
  61                                       attr, l4proto->ctnl_timeout.nla_policy);
  62                if (ret < 0)
  63                        return ret;
  64
  65                ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, net, timeouts);
  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->data,
 124                                                        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->data, 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) {
 224                        if (cur != last)
 225                                continue;
 226
 227                        last = NULL;
 228                }
 229                if (ctnl_timeout_fill_info(skb, NETLINK_CB(cb->skb).portid,
 230                                           cb->nlh->nlmsg_seq,
 231                                           NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
 232                                           IPCTNL_MSG_TIMEOUT_NEW, cur) < 0) {
 233                        cb->args[1] = (unsigned long)cur;
 234                        break;
 235                }
 236        }
 237        if (!cb->args[1])
 238                cb->args[2] = 1;
 239        rcu_read_unlock();
 240        return skb->len;
 241}
 242
 243static int
 244cttimeout_get_timeout(struct sock *ctnl, struct sk_buff *skb,
 245                      const struct nlmsghdr *nlh,
 246                      const struct nlattr * const cda[])
 247{
 248        int ret = -ENOENT;
 249        char *name;
 250        struct ctnl_timeout *cur;
 251
 252        if (nlh->nlmsg_flags & NLM_F_DUMP) {
 253                struct netlink_dump_control c = {
 254                        .dump = ctnl_timeout_dump,
 255                };
 256                return netlink_dump_start(ctnl, skb, nlh, &c);
 257        }
 258
 259        if (!cda[CTA_TIMEOUT_NAME])
 260                return -EINVAL;
 261        name = nla_data(cda[CTA_TIMEOUT_NAME]);
 262
 263        list_for_each_entry(cur, &cttimeout_list, head) {
 264                struct sk_buff *skb2;
 265
 266                if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
 267                        continue;
 268
 269                skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 270                if (skb2 == NULL) {
 271                        ret = -ENOMEM;
 272                        break;
 273                }
 274
 275                ret = ctnl_timeout_fill_info(skb2, NETLINK_CB(skb).portid,
 276                                             nlh->nlmsg_seq,
 277                                             NFNL_MSG_TYPE(nlh->nlmsg_type),
 278                                             IPCTNL_MSG_TIMEOUT_NEW, cur);
 279                if (ret <= 0) {
 280                        kfree_skb(skb2);
 281                        break;
 282                }
 283                ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid,
 284                                        MSG_DONTWAIT);
 285                if (ret > 0)
 286                        ret = 0;
 287
 288                /* this avoids a loop in nfnetlink. */
 289                return ret == -EAGAIN ? -ENOBUFS : ret;
 290        }
 291        return ret;
 292}
 293
 294/* try to delete object, fail if it is still in use. */
 295static int ctnl_timeout_try_del(struct ctnl_timeout *timeout)
 296{
 297        int ret = 0;
 298
 299        /* we want to avoid races with nf_ct_timeout_find_get. */
 300        if (atomic_dec_and_test(&timeout->refcnt)) {
 301                /* We are protected by nfnl mutex. */
 302                list_del_rcu(&timeout->head);
 303                nf_ct_l4proto_put(timeout->l4proto);
 304                kfree_rcu(timeout, rcu_head);
 305        } else {
 306                /* still in use, restore reference counter. */
 307                atomic_inc(&timeout->refcnt);
 308                ret = -EBUSY;
 309        }
 310        return ret;
 311}
 312
 313static int
 314cttimeout_del_timeout(struct sock *ctnl, struct sk_buff *skb,
 315                      const struct nlmsghdr *nlh,
 316                      const struct nlattr * const cda[])
 317{
 318        char *name;
 319        struct ctnl_timeout *cur;
 320        int ret = -ENOENT;
 321
 322        if (!cda[CTA_TIMEOUT_NAME]) {
 323                list_for_each_entry(cur, &cttimeout_list, head)
 324                        ctnl_timeout_try_del(cur);
 325
 326                return 0;
 327        }
 328        name = nla_data(cda[CTA_TIMEOUT_NAME]);
 329
 330        list_for_each_entry(cur, &cttimeout_list, head) {
 331                if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
 332                        continue;
 333
 334                ret = ctnl_timeout_try_del(cur);
 335                if (ret < 0)
 336                        return ret;
 337
 338                break;
 339        }
 340        return ret;
 341}
 342
 343static int
 344cttimeout_default_set(struct sock *ctnl, struct sk_buff *skb,
 345                      const struct nlmsghdr *nlh,
 346                      const struct nlattr * const cda[])
 347{
 348        __u16 l3num;
 349        __u8 l4num;
 350        struct nf_conntrack_l4proto *l4proto;
 351        struct net *net = sock_net(skb->sk);
 352        unsigned int *timeouts;
 353        int ret;
 354
 355        if (!cda[CTA_TIMEOUT_L3PROTO] ||
 356            !cda[CTA_TIMEOUT_L4PROTO] ||
 357            !cda[CTA_TIMEOUT_DATA])
 358                return -EINVAL;
 359
 360        l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
 361        l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
 362        l4proto = nf_ct_l4proto_find_get(l3num, l4num);
 363
 364        /* This protocol is not supported, skip. */
 365        if (l4proto->l4proto != l4num) {
 366                ret = -EOPNOTSUPP;
 367                goto err;
 368        }
 369
 370        timeouts = l4proto->get_timeouts(net);
 371
 372        ret = ctnl_timeout_parse_policy(timeouts, l4proto, net,
 373                                        cda[CTA_TIMEOUT_DATA]);
 374        if (ret < 0)
 375                goto err;
 376
 377        nf_ct_l4proto_put(l4proto);
 378        return 0;
 379err:
 380        nf_ct_l4proto_put(l4proto);
 381        return ret;
 382}
 383
 384static int
 385cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid,
 386                            u32 seq, u32 type, int event,
 387                            struct nf_conntrack_l4proto *l4proto)
 388{
 389        struct nlmsghdr *nlh;
 390        struct nfgenmsg *nfmsg;
 391        unsigned int flags = portid ? NLM_F_MULTI : 0;
 392
 393        event |= NFNL_SUBSYS_CTNETLINK_TIMEOUT << 8;
 394        nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
 395        if (nlh == NULL)
 396                goto nlmsg_failure;
 397
 398        nfmsg = nlmsg_data(nlh);
 399        nfmsg->nfgen_family = AF_UNSPEC;
 400        nfmsg->version = NFNETLINK_V0;
 401        nfmsg->res_id = 0;
 402
 403        if (nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(l4proto->l3proto)) ||
 404            nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, l4proto->l4proto))
 405                goto nla_put_failure;
 406
 407        if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) {
 408                struct nlattr *nest_parms;
 409                unsigned int *timeouts = l4proto->get_timeouts(net);
 410                int ret;
 411
 412                nest_parms = nla_nest_start(skb,
 413                                            CTA_TIMEOUT_DATA | NLA_F_NESTED);
 414                if (!nest_parms)
 415                        goto nla_put_failure;
 416
 417                ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, timeouts);
 418                if (ret < 0)
 419                        goto nla_put_failure;
 420
 421                nla_nest_end(skb, nest_parms);
 422        }
 423
 424        nlmsg_end(skb, nlh);
 425        return skb->len;
 426
 427nlmsg_failure:
 428nla_put_failure:
 429        nlmsg_cancel(skb, nlh);
 430        return -1;
 431}
 432
 433static int cttimeout_default_get(struct sock *ctnl, struct sk_buff *skb,
 434                                 const struct nlmsghdr *nlh,
 435                                 const struct nlattr * const cda[])
 436{
 437        __u16 l3num;
 438        __u8 l4num;
 439        struct nf_conntrack_l4proto *l4proto;
 440        struct net *net = sock_net(skb->sk);
 441        struct sk_buff *skb2;
 442        int ret, err;
 443
 444        if (!cda[CTA_TIMEOUT_L3PROTO] || !cda[CTA_TIMEOUT_L4PROTO])
 445                return -EINVAL;
 446
 447        l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
 448        l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
 449        l4proto = nf_ct_l4proto_find_get(l3num, l4num);
 450
 451        /* This protocol is not supported, skip. */
 452        if (l4proto->l4proto != l4num) {
 453                err = -EOPNOTSUPP;
 454                goto err;
 455        }
 456
 457        skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 458        if (skb2 == NULL) {
 459                err = -ENOMEM;
 460                goto err;
 461        }
 462
 463        ret = cttimeout_default_fill_info(net, skb2, NETLINK_CB(skb).portid,
 464                                          nlh->nlmsg_seq,
 465                                          NFNL_MSG_TYPE(nlh->nlmsg_type),
 466                                          IPCTNL_MSG_TIMEOUT_DEFAULT_SET,
 467                                          l4proto);
 468        if (ret <= 0) {
 469                kfree_skb(skb2);
 470                err = -ENOMEM;
 471                goto err;
 472        }
 473        ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
 474        if (ret > 0)
 475                ret = 0;
 476
 477        /* this avoids a loop in nfnetlink. */
 478        return ret == -EAGAIN ? -ENOBUFS : ret;
 479err:
 480        nf_ct_l4proto_put(l4proto);
 481        return err;
 482}
 483
 484#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
 485static struct ctnl_timeout *ctnl_timeout_find_get(const char *name)
 486{
 487        struct ctnl_timeout *timeout, *matching = NULL;
 488
 489        rcu_read_lock();
 490        list_for_each_entry_rcu(timeout, &cttimeout_list, head) {
 491                if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
 492                        continue;
 493
 494                if (!try_module_get(THIS_MODULE))
 495                        goto err;
 496
 497                if (!atomic_inc_not_zero(&timeout->refcnt)) {
 498                        module_put(THIS_MODULE);
 499                        goto err;
 500                }
 501                matching = timeout;
 502                break;
 503        }
 504err:
 505        rcu_read_unlock();
 506        return matching;
 507}
 508
 509static void ctnl_timeout_put(struct ctnl_timeout *timeout)
 510{
 511        atomic_dec(&timeout->refcnt);
 512        module_put(THIS_MODULE);
 513}
 514#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
 515
 516static const struct nfnl_callback cttimeout_cb[IPCTNL_MSG_TIMEOUT_MAX] = {
 517        [IPCTNL_MSG_TIMEOUT_NEW]        = { .call = cttimeout_new_timeout,
 518                                            .attr_count = CTA_TIMEOUT_MAX,
 519                                            .policy = cttimeout_nla_policy },
 520        [IPCTNL_MSG_TIMEOUT_GET]        = { .call = cttimeout_get_timeout,
 521                                            .attr_count = CTA_TIMEOUT_MAX,
 522                                            .policy = cttimeout_nla_policy },
 523        [IPCTNL_MSG_TIMEOUT_DELETE]     = { .call = cttimeout_del_timeout,
 524                                            .attr_count = CTA_TIMEOUT_MAX,
 525                                            .policy = cttimeout_nla_policy },
 526        [IPCTNL_MSG_TIMEOUT_DEFAULT_SET]= { .call = cttimeout_default_set,
 527                                            .attr_count = CTA_TIMEOUT_MAX,
 528                                            .policy = cttimeout_nla_policy },
 529        [IPCTNL_MSG_TIMEOUT_DEFAULT_GET]= { .call = cttimeout_default_get,
 530                                            .attr_count = CTA_TIMEOUT_MAX,
 531                                            .policy = cttimeout_nla_policy },
 532};
 533
 534static const struct nfnetlink_subsystem cttimeout_subsys = {
 535        .name                           = "conntrack_timeout",
 536        .subsys_id                      = NFNL_SUBSYS_CTNETLINK_TIMEOUT,
 537        .cb_count                       = IPCTNL_MSG_TIMEOUT_MAX,
 538        .cb                             = cttimeout_cb,
 539};
 540
 541MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_TIMEOUT);
 542
 543static int __init cttimeout_init(void)
 544{
 545        int ret;
 546
 547        ret = nfnetlink_subsys_register(&cttimeout_subsys);
 548        if (ret < 0) {
 549                pr_err("cttimeout_init: cannot register cttimeout with "
 550                        "nfnetlink.\n");
 551                goto err_out;
 552        }
 553#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
 554        RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, ctnl_timeout_find_get);
 555        RCU_INIT_POINTER(nf_ct_timeout_put_hook, ctnl_timeout_put);
 556#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
 557        return 0;
 558
 559err_out:
 560        return ret;
 561}
 562
 563static void __exit cttimeout_exit(void)
 564{
 565        struct ctnl_timeout *cur, *tmp;
 566
 567        pr_info("cttimeout: unregistering from nfnetlink.\n");
 568
 569        nfnetlink_subsys_unregister(&cttimeout_subsys);
 570        list_for_each_entry_safe(cur, tmp, &cttimeout_list, head) {
 571                list_del_rcu(&cur->head);
 572                /* We are sure that our objects have no clients at this point,
 573                 * it's safe to release them all without checking refcnt.
 574                 */
 575                nf_ct_l4proto_put(cur->l4proto);
 576                kfree_rcu(cur, rcu_head);
 577        }
 578#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
 579        RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, NULL);
 580        RCU_INIT_POINTER(nf_ct_timeout_put_hook, NULL);
 581#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
 582}
 583
 584module_init(cttimeout_init);
 585module_exit(cttimeout_exit);
 586