linux/net/netfilter/nf_conntrack_netlink.c
<<
>>
Prefs
   1/* Connection tracking via netlink socket. Allows for user space
   2 * protocol helpers and general trouble making from userspace.
   3 *
   4 * (C) 2001 by Jay Schulist <jschlst@samba.org>
   5 * (C) 2002-2006 by Harald Welte <laforge@gnumonks.org>
   6 * (C) 2003 by Patrick Mchardy <kaber@trash.net>
   7 * (C) 2005-2007 by Pablo Neira Ayuso <pablo@netfilter.org>
   8 *
   9 * Initial connection tracking via netlink development funded and
  10 * generally made possible by Network Robots, Inc. (www.networkrobots.com)
  11 *
  12 * Further development of this code funded by Astaro AG (http://www.astaro.com)
  13 *
  14 * This software may be used and distributed according to the terms
  15 * of the GNU General Public License, incorporated herein by reference.
  16 */
  17
  18#include <linux/init.h>
  19#include <linux/module.h>
  20#include <linux/kernel.h>
  21#include <linux/types.h>
  22#include <linux/timer.h>
  23#include <linux/skbuff.h>
  24#include <linux/errno.h>
  25#include <linux/netlink.h>
  26#include <linux/spinlock.h>
  27#include <linux/interrupt.h>
  28#include <linux/notifier.h>
  29
  30#include <linux/netfilter.h>
  31#include <net/netlink.h>
  32#include <net/netfilter/nf_conntrack.h>
  33#include <net/netfilter/nf_conntrack_core.h>
  34#include <net/netfilter/nf_conntrack_expect.h>
  35#include <net/netfilter/nf_conntrack_helper.h>
  36#include <net/netfilter/nf_conntrack_l3proto.h>
  37#include <net/netfilter/nf_conntrack_l4proto.h>
  38#include <net/netfilter/nf_conntrack_tuple.h>
  39#ifdef CONFIG_NF_NAT_NEEDED
  40#include <net/netfilter/nf_nat_core.h>
  41#include <net/netfilter/nf_nat_protocol.h>
  42#endif
  43
  44#include <linux/netfilter/nfnetlink.h>
  45#include <linux/netfilter/nfnetlink_conntrack.h>
  46
  47MODULE_LICENSE("GPL");
  48
  49static char __initdata version[] = "0.93";
  50
  51static inline int
  52ctnetlink_dump_tuples_proto(struct sk_buff *skb,
  53                            const struct nf_conntrack_tuple *tuple,
  54                            struct nf_conntrack_l4proto *l4proto)
  55{
  56        int ret = 0;
  57        struct nlattr *nest_parms;
  58
  59        nest_parms = nla_nest_start(skb, CTA_TUPLE_PROTO | NLA_F_NESTED);
  60        if (!nest_parms)
  61                goto nla_put_failure;
  62        NLA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
  63
  64        if (likely(l4proto->tuple_to_nlattr))
  65                ret = l4proto->tuple_to_nlattr(skb, tuple);
  66
  67        nla_nest_end(skb, nest_parms);
  68
  69        return ret;
  70
  71nla_put_failure:
  72        return -1;
  73}
  74
  75static inline int
  76ctnetlink_dump_tuples_ip(struct sk_buff *skb,
  77                         const struct nf_conntrack_tuple *tuple,
  78                         struct nf_conntrack_l3proto *l3proto)
  79{
  80        int ret = 0;
  81        struct nlattr *nest_parms;
  82
  83        nest_parms = nla_nest_start(skb, CTA_TUPLE_IP | NLA_F_NESTED);
  84        if (!nest_parms)
  85                goto nla_put_failure;
  86
  87        if (likely(l3proto->tuple_to_nlattr))
  88                ret = l3proto->tuple_to_nlattr(skb, tuple);
  89
  90        nla_nest_end(skb, nest_parms);
  91
  92        return ret;
  93
  94nla_put_failure:
  95        return -1;
  96}
  97
  98static inline int
  99ctnetlink_dump_tuples(struct sk_buff *skb,
 100                      const struct nf_conntrack_tuple *tuple)
 101{
 102        int ret;
 103        struct nf_conntrack_l3proto *l3proto;
 104        struct nf_conntrack_l4proto *l4proto;
 105
 106        l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
 107        ret = ctnetlink_dump_tuples_ip(skb, tuple, l3proto);
 108        nf_ct_l3proto_put(l3proto);
 109
 110        if (unlikely(ret < 0))
 111                return ret;
 112
 113        l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum);
 114        ret = ctnetlink_dump_tuples_proto(skb, tuple, l4proto);
 115        nf_ct_l4proto_put(l4proto);
 116
 117        return ret;
 118}
 119
 120static inline int
 121ctnetlink_dump_status(struct sk_buff *skb, const struct nf_conn *ct)
 122{
 123        __be32 status = htonl((u_int32_t) ct->status);
 124        NLA_PUT(skb, CTA_STATUS, sizeof(status), &status);
 125        return 0;
 126
 127nla_put_failure:
 128        return -1;
 129}
 130
 131static inline int
 132ctnetlink_dump_timeout(struct sk_buff *skb, const struct nf_conn *ct)
 133{
 134        long timeout_l = ct->timeout.expires - jiffies;
 135        __be32 timeout;
 136
 137        if (timeout_l < 0)
 138                timeout = 0;
 139        else
 140                timeout = htonl(timeout_l / HZ);
 141
 142        NLA_PUT(skb, CTA_TIMEOUT, sizeof(timeout), &timeout);
 143        return 0;
 144
 145nla_put_failure:
 146        return -1;
 147}
 148
 149static inline int
 150ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct nf_conn *ct)
 151{
 152        struct nf_conntrack_l4proto *l4proto = nf_ct_l4proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
 153        struct nlattr *nest_proto;
 154        int ret;
 155
 156        if (!l4proto->to_nlattr) {
 157                nf_ct_l4proto_put(l4proto);
 158                return 0;
 159        }
 160
 161        nest_proto = nla_nest_start(skb, CTA_PROTOINFO | NLA_F_NESTED);
 162        if (!nest_proto)
 163                goto nla_put_failure;
 164
 165        ret = l4proto->to_nlattr(skb, nest_proto, ct);
 166
 167        nf_ct_l4proto_put(l4proto);
 168
 169        nla_nest_end(skb, nest_proto);
 170
 171        return ret;
 172
 173nla_put_failure:
 174        nf_ct_l4proto_put(l4proto);
 175        return -1;
 176}
 177
 178static inline int
 179ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct)
 180{
 181        struct nlattr *nest_helper;
 182        const struct nf_conn_help *help = nfct_help(ct);
 183        struct nf_conntrack_helper *helper;
 184
 185        if (!help)
 186                return 0;
 187
 188        rcu_read_lock();
 189        helper = rcu_dereference(help->helper);
 190        if (!helper)
 191                goto out;
 192
 193        nest_helper = nla_nest_start(skb, CTA_HELP | NLA_F_NESTED);
 194        if (!nest_helper)
 195                goto nla_put_failure;
 196        NLA_PUT(skb, CTA_HELP_NAME, strlen(helper->name), helper->name);
 197
 198        if (helper->to_nlattr)
 199                helper->to_nlattr(skb, ct);
 200
 201        nla_nest_end(skb, nest_helper);
 202out:
 203        rcu_read_unlock();
 204        return 0;
 205
 206nla_put_failure:
 207        rcu_read_unlock();
 208        return -1;
 209}
 210
 211#ifdef CONFIG_NF_CT_ACCT
 212static inline int
 213ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct,
 214                        enum ip_conntrack_dir dir)
 215{
 216        enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG;
 217        struct nlattr *nest_count;
 218        __be32 tmp;
 219
 220        nest_count = nla_nest_start(skb, type | NLA_F_NESTED);
 221        if (!nest_count)
 222                goto nla_put_failure;
 223
 224        tmp = htonl(ct->counters[dir].packets);
 225        NLA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp);
 226
 227        tmp = htonl(ct->counters[dir].bytes);
 228        NLA_PUT(skb, CTA_COUNTERS32_BYTES, sizeof(u_int32_t), &tmp);
 229
 230        nla_nest_end(skb, nest_count);
 231
 232        return 0;
 233
 234nla_put_failure:
 235        return -1;
 236}
 237#else
 238#define ctnetlink_dump_counters(a, b, c) (0)
 239#endif
 240
 241#ifdef CONFIG_NF_CONNTRACK_MARK
 242static inline int
 243ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct)
 244{
 245        __be32 mark = htonl(ct->mark);
 246
 247        NLA_PUT(skb, CTA_MARK, sizeof(u_int32_t), &mark);
 248        return 0;
 249
 250nla_put_failure:
 251        return -1;
 252}
 253#else
 254#define ctnetlink_dump_mark(a, b) (0)
 255#endif
 256
 257static inline int
 258ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct)
 259{
 260        __be32 id = htonl((unsigned long)ct);
 261        NLA_PUT(skb, CTA_ID, sizeof(u_int32_t), &id);
 262        return 0;
 263
 264nla_put_failure:
 265        return -1;
 266}
 267
 268static inline int
 269ctnetlink_dump_use(struct sk_buff *skb, const struct nf_conn *ct)
 270{
 271        __be32 use = htonl(atomic_read(&ct->ct_general.use));
 272
 273        NLA_PUT(skb, CTA_USE, sizeof(u_int32_t), &use);
 274        return 0;
 275
 276nla_put_failure:
 277        return -1;
 278}
 279
 280#define tuple(ct, dir) (&(ct)->tuplehash[dir].tuple)
 281
 282static int
 283ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
 284                    int event, int nowait,
 285                    const struct nf_conn *ct)
 286{
 287        struct nlmsghdr *nlh;
 288        struct nfgenmsg *nfmsg;
 289        struct nlattr *nest_parms;
 290        unsigned char *b = skb_tail_pointer(skb);
 291
 292        event |= NFNL_SUBSYS_CTNETLINK << 8;
 293        nlh    = NLMSG_PUT(skb, pid, seq, event, sizeof(struct nfgenmsg));
 294        nfmsg  = NLMSG_DATA(nlh);
 295
 296        nlh->nlmsg_flags    = (nowait && pid) ? NLM_F_MULTI : 0;
 297        nfmsg->nfgen_family =
 298                ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
 299        nfmsg->version      = NFNETLINK_V0;
 300        nfmsg->res_id       = 0;
 301
 302        nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG | NLA_F_NESTED);
 303        if (!nest_parms)
 304                goto nla_put_failure;
 305        if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
 306                goto nla_put_failure;
 307        nla_nest_end(skb, nest_parms);
 308
 309        nest_parms = nla_nest_start(skb, CTA_TUPLE_REPLY | NLA_F_NESTED);
 310        if (!nest_parms)
 311                goto nla_put_failure;
 312        if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0)
 313                goto nla_put_failure;
 314        nla_nest_end(skb, nest_parms);
 315
 316        if (ctnetlink_dump_status(skb, ct) < 0 ||
 317            ctnetlink_dump_timeout(skb, ct) < 0 ||
 318            ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
 319            ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0 ||
 320            ctnetlink_dump_protoinfo(skb, ct) < 0 ||
 321            ctnetlink_dump_helpinfo(skb, ct) < 0 ||
 322            ctnetlink_dump_mark(skb, ct) < 0 ||
 323            ctnetlink_dump_id(skb, ct) < 0 ||
 324            ctnetlink_dump_use(skb, ct) < 0)
 325                goto nla_put_failure;
 326
 327        nlh->nlmsg_len = skb_tail_pointer(skb) - b;
 328        return skb->len;
 329
 330nlmsg_failure:
 331nla_put_failure:
 332        nlmsg_trim(skb, b);
 333        return -1;
 334}
 335
 336#ifdef CONFIG_NF_CONNTRACK_EVENTS
 337static int ctnetlink_conntrack_event(struct notifier_block *this,
 338                                     unsigned long events, void *ptr)
 339{
 340        struct nlmsghdr *nlh;
 341        struct nfgenmsg *nfmsg;
 342        struct nlattr *nest_parms;
 343        struct nf_conn *ct = (struct nf_conn *)ptr;
 344        struct sk_buff *skb;
 345        unsigned int type;
 346        sk_buff_data_t b;
 347        unsigned int flags = 0, group;
 348
 349        /* ignore our fake conntrack entry */
 350        if (ct == &nf_conntrack_untracked)
 351                return NOTIFY_DONE;
 352
 353        if (events & IPCT_DESTROY) {
 354                type = IPCTNL_MSG_CT_DELETE;
 355                group = NFNLGRP_CONNTRACK_DESTROY;
 356        } else  if (events & (IPCT_NEW | IPCT_RELATED)) {
 357                type = IPCTNL_MSG_CT_NEW;
 358                flags = NLM_F_CREATE|NLM_F_EXCL;
 359                group = NFNLGRP_CONNTRACK_NEW;
 360        } else  if (events & (IPCT_STATUS | IPCT_PROTOINFO)) {
 361                type = IPCTNL_MSG_CT_NEW;
 362                group = NFNLGRP_CONNTRACK_UPDATE;
 363        } else
 364                return NOTIFY_DONE;
 365
 366        if (!nfnetlink_has_listeners(group))
 367                return NOTIFY_DONE;
 368
 369        skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
 370        if (!skb)
 371                return NOTIFY_DONE;
 372
 373        b = skb->tail;
 374
 375        type |= NFNL_SUBSYS_CTNETLINK << 8;
 376        nlh   = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg));
 377        nfmsg = NLMSG_DATA(nlh);
 378
 379        nlh->nlmsg_flags    = flags;
 380        nfmsg->nfgen_family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
 381        nfmsg->version  = NFNETLINK_V0;
 382        nfmsg->res_id   = 0;
 383
 384        nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG | NLA_F_NESTED);
 385        if (!nest_parms)
 386                goto nla_put_failure;
 387        if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
 388                goto nla_put_failure;
 389        nla_nest_end(skb, nest_parms);
 390
 391        nest_parms = nla_nest_start(skb, CTA_TUPLE_REPLY | NLA_F_NESTED);
 392        if (!nest_parms)
 393                goto nla_put_failure;
 394        if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0)
 395                goto nla_put_failure;
 396        nla_nest_end(skb, nest_parms);
 397
 398        if (events & IPCT_DESTROY) {
 399                if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
 400                    ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
 401                        goto nla_put_failure;
 402        } else {
 403                if (ctnetlink_dump_status(skb, ct) < 0)
 404                        goto nla_put_failure;
 405
 406                if (ctnetlink_dump_timeout(skb, ct) < 0)
 407                        goto nla_put_failure;
 408
 409                if (events & IPCT_PROTOINFO
 410                    && ctnetlink_dump_protoinfo(skb, ct) < 0)
 411                        goto nla_put_failure;
 412
 413                if ((events & IPCT_HELPER || nfct_help(ct))
 414                    && ctnetlink_dump_helpinfo(skb, ct) < 0)
 415                        goto nla_put_failure;
 416
 417#ifdef CONFIG_NF_CONNTRACK_MARK
 418                if ((events & IPCT_MARK || ct->mark)
 419                    && ctnetlink_dump_mark(skb, ct) < 0)
 420                        goto nla_put_failure;
 421#endif
 422
 423                if (events & IPCT_COUNTER_FILLING &&
 424                    (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
 425                     ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0))
 426                        goto nla_put_failure;
 427        }
 428
 429        nlh->nlmsg_len = skb->tail - b;
 430        nfnetlink_send(skb, 0, group, 0);
 431        return NOTIFY_DONE;
 432
 433nlmsg_failure:
 434nla_put_failure:
 435        kfree_skb(skb);
 436        return NOTIFY_DONE;
 437}
 438#endif /* CONFIG_NF_CONNTRACK_EVENTS */
 439
 440static int ctnetlink_done(struct netlink_callback *cb)
 441{
 442        if (cb->args[1])
 443                nf_ct_put((struct nf_conn *)cb->args[1]);
 444        return 0;
 445}
 446
 447#define L3PROTO(ct) ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num
 448
 449static int
 450ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
 451{
 452        struct nf_conn *ct, *last;
 453        struct nf_conntrack_tuple_hash *h;
 454        struct hlist_node *n;
 455        struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
 456        u_int8_t l3proto = nfmsg->nfgen_family;
 457
 458        read_lock_bh(&nf_conntrack_lock);
 459        last = (struct nf_conn *)cb->args[1];
 460        for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) {
 461restart:
 462                hlist_for_each_entry(h, n, &nf_conntrack_hash[cb->args[0]],
 463                                     hnode) {
 464                        if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL)
 465                                continue;
 466                        ct = nf_ct_tuplehash_to_ctrack(h);
 467                        /* Dump entries of a given L3 protocol number.
 468                         * If it is not specified, ie. l3proto == 0,
 469                         * then dump everything. */
 470                        if (l3proto && L3PROTO(ct) != l3proto)
 471                                continue;
 472                        if (cb->args[1]) {
 473                                if (ct != last)
 474                                        continue;
 475                                cb->args[1] = 0;
 476                        }
 477                        if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
 478                                                cb->nlh->nlmsg_seq,
 479                                                IPCTNL_MSG_CT_NEW,
 480                                                1, ct) < 0) {
 481                                nf_conntrack_get(&ct->ct_general);
 482                                cb->args[1] = (unsigned long)ct;
 483                                goto out;
 484                        }
 485#ifdef CONFIG_NF_CT_ACCT
 486                        if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) ==
 487                                                IPCTNL_MSG_CT_GET_CTRZERO)
 488                                memset(&ct->counters, 0, sizeof(ct->counters));
 489#endif
 490                }
 491                if (cb->args[1]) {
 492                        cb->args[1] = 0;
 493                        goto restart;
 494                }
 495        }
 496out:
 497        read_unlock_bh(&nf_conntrack_lock);
 498        if (last)
 499                nf_ct_put(last);
 500
 501        return skb->len;
 502}
 503
 504static inline int
 505ctnetlink_parse_tuple_ip(struct nlattr *attr, struct nf_conntrack_tuple *tuple)
 506{
 507        struct nlattr *tb[CTA_IP_MAX+1];
 508        struct nf_conntrack_l3proto *l3proto;
 509        int ret = 0;
 510
 511        nla_parse_nested(tb, CTA_IP_MAX, attr, NULL);
 512
 513        l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
 514
 515        if (likely(l3proto->nlattr_to_tuple)) {
 516                ret = nla_validate_nested(attr, CTA_IP_MAX,
 517                                          l3proto->nla_policy);
 518                if (ret == 0)
 519                        ret = l3proto->nlattr_to_tuple(tb, tuple);
 520        }
 521
 522        nf_ct_l3proto_put(l3proto);
 523
 524        return ret;
 525}
 526
 527static const struct nla_policy proto_nla_policy[CTA_PROTO_MAX+1] = {
 528        [CTA_PROTO_NUM] = { .type = NLA_U8 },
 529};
 530
 531static inline int
 532ctnetlink_parse_tuple_proto(struct nlattr *attr,
 533                            struct nf_conntrack_tuple *tuple)
 534{
 535        struct nlattr *tb[CTA_PROTO_MAX+1];
 536        struct nf_conntrack_l4proto *l4proto;
 537        int ret = 0;
 538
 539        ret = nla_parse_nested(tb, CTA_PROTO_MAX, attr, proto_nla_policy);
 540        if (ret < 0)
 541                return ret;
 542
 543        if (!tb[CTA_PROTO_NUM])
 544                return -EINVAL;
 545        tuple->dst.protonum = *(u_int8_t *)nla_data(tb[CTA_PROTO_NUM]);
 546
 547        l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum);
 548
 549        if (likely(l4proto->nlattr_to_tuple)) {
 550                ret = nla_validate_nested(attr, CTA_PROTO_MAX,
 551                                          l4proto->nla_policy);
 552                if (ret == 0)
 553                        ret = l4proto->nlattr_to_tuple(tb, tuple);
 554        }
 555
 556        nf_ct_l4proto_put(l4proto);
 557
 558        return ret;
 559}
 560
 561static inline int
 562ctnetlink_parse_tuple(struct nlattr *cda[], struct nf_conntrack_tuple *tuple,
 563                      enum ctattr_tuple type, u_int8_t l3num)
 564{
 565        struct nlattr *tb[CTA_TUPLE_MAX+1];
 566        int err;
 567
 568        memset(tuple, 0, sizeof(*tuple));
 569
 570        nla_parse_nested(tb, CTA_TUPLE_MAX, cda[type], NULL);
 571
 572        if (!tb[CTA_TUPLE_IP])
 573                return -EINVAL;
 574
 575        tuple->src.l3num = l3num;
 576
 577        err = ctnetlink_parse_tuple_ip(tb[CTA_TUPLE_IP], tuple);
 578        if (err < 0)
 579                return err;
 580
 581        if (!tb[CTA_TUPLE_PROTO])
 582                return -EINVAL;
 583
 584        err = ctnetlink_parse_tuple_proto(tb[CTA_TUPLE_PROTO], tuple);
 585        if (err < 0)
 586                return err;
 587
 588        /* orig and expect tuples get DIR_ORIGINAL */
 589        if (type == CTA_TUPLE_REPLY)
 590                tuple->dst.dir = IP_CT_DIR_REPLY;
 591        else
 592                tuple->dst.dir = IP_CT_DIR_ORIGINAL;
 593
 594        return 0;
 595}
 596
 597#ifdef CONFIG_NF_NAT_NEEDED
 598static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = {
 599        [CTA_PROTONAT_PORT_MIN] = { .type = NLA_U16 },
 600        [CTA_PROTONAT_PORT_MAX] = { .type = NLA_U16 },
 601};
 602
 603static int nfnetlink_parse_nat_proto(struct nlattr *attr,
 604                                     const struct nf_conn *ct,
 605                                     struct nf_nat_range *range)
 606{
 607        struct nlattr *tb[CTA_PROTONAT_MAX+1];
 608        struct nf_nat_protocol *npt;
 609        int err;
 610
 611        err = nla_parse_nested(tb, CTA_PROTONAT_MAX, attr, protonat_nla_policy);
 612        if (err < 0)
 613                return err;
 614
 615        npt = nf_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
 616
 617        if (!npt->nlattr_to_range) {
 618                nf_nat_proto_put(npt);
 619                return 0;
 620        }
 621
 622        /* nlattr_to_range returns 1 if it parsed, 0 if not, neg. on error */
 623        if (npt->nlattr_to_range(tb, range) > 0)
 624                range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
 625
 626        nf_nat_proto_put(npt);
 627
 628        return 0;
 629}
 630
 631static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = {
 632        [CTA_NAT_MINIP]         = { .type = NLA_U32 },
 633        [CTA_NAT_MAXIP]         = { .type = NLA_U32 },
 634};
 635
 636static inline int
 637nfnetlink_parse_nat(struct nlattr *nat,
 638                    const struct nf_conn *ct, struct nf_nat_range *range)
 639{
 640        struct nlattr *tb[CTA_NAT_MAX+1];
 641        int err;
 642
 643        memset(range, 0, sizeof(*range));
 644
 645        err = nla_parse_nested(tb, CTA_NAT_MAX, nat, nat_nla_policy);
 646        if (err < 0)
 647                return err;
 648
 649        if (tb[CTA_NAT_MINIP])
 650                range->min_ip = *(__be32 *)nla_data(tb[CTA_NAT_MINIP]);
 651
 652        if (!tb[CTA_NAT_MAXIP])
 653                range->max_ip = range->min_ip;
 654        else
 655                range->max_ip = *(__be32 *)nla_data(tb[CTA_NAT_MAXIP]);
 656
 657        if (range->min_ip)
 658                range->flags |= IP_NAT_RANGE_MAP_IPS;
 659
 660        if (!tb[CTA_NAT_PROTO])
 661                return 0;
 662
 663        err = nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO], ct, range);
 664        if (err < 0)
 665                return err;
 666
 667        return 0;
 668}
 669#endif
 670
 671static inline int
 672ctnetlink_parse_help(struct nlattr *attr, char **helper_name)
 673{
 674        struct nlattr *tb[CTA_HELP_MAX+1];
 675
 676        nla_parse_nested(tb, CTA_HELP_MAX, attr, NULL);
 677
 678        if (!tb[CTA_HELP_NAME])
 679                return -EINVAL;
 680
 681        *helper_name = nla_data(tb[CTA_HELP_NAME]);
 682
 683        return 0;
 684}
 685
 686static const struct nla_policy ct_nla_policy[CTA_MAX+1] = {
 687        [CTA_STATUS]            = { .type = NLA_U32 },
 688        [CTA_TIMEOUT]           = { .type = NLA_U32 },
 689        [CTA_MARK]              = { .type = NLA_U32 },
 690        [CTA_USE]               = { .type = NLA_U32 },
 691        [CTA_ID]                = { .type = NLA_U32 },
 692};
 693
 694static int
 695ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
 696                        struct nlmsghdr *nlh, struct nlattr *cda[])
 697{
 698        struct nf_conntrack_tuple_hash *h;
 699        struct nf_conntrack_tuple tuple;
 700        struct nf_conn *ct;
 701        struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
 702        u_int8_t u3 = nfmsg->nfgen_family;
 703        int err = 0;
 704
 705        if (cda[CTA_TUPLE_ORIG])
 706                err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3);
 707        else if (cda[CTA_TUPLE_REPLY])
 708                err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3);
 709        else {
 710                /* Flush the whole table */
 711                nf_conntrack_flush();
 712                return 0;
 713        }
 714
 715        if (err < 0)
 716                return err;
 717
 718        h = nf_conntrack_find_get(&tuple);
 719        if (!h)
 720                return -ENOENT;
 721
 722        ct = nf_ct_tuplehash_to_ctrack(h);
 723
 724        if (cda[CTA_ID]) {
 725                u_int32_t id = ntohl(*(__be32 *)nla_data(cda[CTA_ID]));
 726                if (id != (u32)(unsigned long)ct) {
 727                        nf_ct_put(ct);
 728                        return -ENOENT;
 729                }
 730        }
 731        if (del_timer(&ct->timeout))
 732                ct->timeout.function((unsigned long)ct);
 733
 734        nf_ct_put(ct);
 735
 736        return 0;
 737}
 738
 739static int
 740ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
 741                        struct nlmsghdr *nlh, struct nlattr *cda[])
 742{
 743        struct nf_conntrack_tuple_hash *h;
 744        struct nf_conntrack_tuple tuple;
 745        struct nf_conn *ct;
 746        struct sk_buff *skb2 = NULL;
 747        struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
 748        u_int8_t u3 = nfmsg->nfgen_family;
 749        int err = 0;
 750
 751        if (nlh->nlmsg_flags & NLM_F_DUMP) {
 752#ifndef CONFIG_NF_CT_ACCT
 753                if (NFNL_MSG_TYPE(nlh->nlmsg_type) == IPCTNL_MSG_CT_GET_CTRZERO)
 754                        return -ENOTSUPP;
 755#endif
 756                return netlink_dump_start(ctnl, skb, nlh, ctnetlink_dump_table,
 757                                          ctnetlink_done);
 758        }
 759
 760        if (cda[CTA_TUPLE_ORIG])
 761                err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3);
 762        else if (cda[CTA_TUPLE_REPLY])
 763                err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3);
 764        else
 765                return -EINVAL;
 766
 767        if (err < 0)
 768                return err;
 769
 770        h = nf_conntrack_find_get(&tuple);
 771        if (!h)
 772                return -ENOENT;
 773
 774        ct = nf_ct_tuplehash_to_ctrack(h);
 775
 776        err = -ENOMEM;
 777        skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
 778        if (!skb2) {
 779                nf_ct_put(ct);
 780                return -ENOMEM;
 781        }
 782
 783        err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq,
 784                                  IPCTNL_MSG_CT_NEW, 1, ct);
 785        nf_ct_put(ct);
 786        if (err <= 0)
 787                goto free;
 788
 789        err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
 790        if (err < 0)
 791                goto out;
 792
 793        return 0;
 794
 795free:
 796        kfree_skb(skb2);
 797out:
 798        return err;
 799}
 800
 801static inline int
 802ctnetlink_change_status(struct nf_conn *ct, struct nlattr *cda[])
 803{
 804        unsigned long d;
 805        unsigned int status = ntohl(*(__be32 *)nla_data(cda[CTA_STATUS]));
 806        d = ct->status ^ status;
 807
 808        if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING))
 809                /* unchangeable */
 810                return -EINVAL;
 811
 812        if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY))
 813                /* SEEN_REPLY bit can only be set */
 814                return -EINVAL;
 815
 816
 817        if (d & IPS_ASSURED && !(status & IPS_ASSURED))
 818                /* ASSURED bit can only be set */
 819                return -EINVAL;
 820
 821        if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) {
 822#ifndef CONFIG_NF_NAT_NEEDED
 823                return -EINVAL;
 824#else
 825                struct nf_nat_range range;
 826
 827                if (cda[CTA_NAT_DST]) {
 828                        if (nfnetlink_parse_nat(cda[CTA_NAT_DST], ct,
 829                                                &range) < 0)
 830                                return -EINVAL;
 831                        if (nf_nat_initialized(ct,
 832                                               HOOK2MANIP(NF_IP_PRE_ROUTING)))
 833                                return -EEXIST;
 834                        nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
 835                }
 836                if (cda[CTA_NAT_SRC]) {
 837                        if (nfnetlink_parse_nat(cda[CTA_NAT_SRC], ct,
 838                                                &range) < 0)
 839                                return -EINVAL;
 840                        if (nf_nat_initialized(ct,
 841                                               HOOK2MANIP(NF_IP_POST_ROUTING)))
 842                                return -EEXIST;
 843                        nf_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
 844                }
 845#endif
 846        }
 847
 848        /* Be careful here, modifying NAT bits can screw up things,
 849         * so don't let users modify them directly if they don't pass
 850         * nf_nat_range. */
 851        ct->status |= status & ~(IPS_NAT_DONE_MASK | IPS_NAT_MASK);
 852        return 0;
 853}
 854
 855
 856static inline int
 857ctnetlink_change_helper(struct nf_conn *ct, struct nlattr *cda[])
 858{
 859        struct nf_conntrack_helper *helper;
 860        struct nf_conn_help *help = nfct_help(ct);
 861        char *helpname;
 862        int err;
 863
 864        /* don't change helper of sibling connections */
 865        if (ct->master)
 866                return -EINVAL;
 867
 868        err = ctnetlink_parse_help(cda[CTA_HELP], &helpname);
 869        if (err < 0)
 870                return err;
 871
 872        if (!strcmp(helpname, "")) {
 873                if (help && help->helper) {
 874                        /* we had a helper before ... */
 875                        nf_ct_remove_expectations(ct);
 876                        rcu_assign_pointer(help->helper, NULL);
 877                }
 878
 879                return 0;
 880        }
 881
 882        helper = __nf_conntrack_helper_find_byname(helpname);
 883        if (helper == NULL)
 884                return -EINVAL;
 885
 886        if (help) {
 887                if (help->helper == helper)
 888                        return 0;
 889                if (help->helper)
 890                        return -EBUSY;
 891                /* need to zero data of old helper */
 892                memset(&help->help, 0, sizeof(help->help));
 893        } else {
 894                help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
 895                if (help == NULL)
 896                        return -ENOMEM;
 897        }
 898
 899        rcu_assign_pointer(help->helper, helper);
 900
 901        return 0;
 902}
 903
 904static inline int
 905ctnetlink_change_timeout(struct nf_conn *ct, struct nlattr *cda[])
 906{
 907        u_int32_t timeout = ntohl(*(__be32 *)nla_data(cda[CTA_TIMEOUT]));
 908
 909        if (!del_timer(&ct->timeout))
 910                return -ETIME;
 911
 912        ct->timeout.expires = jiffies + timeout * HZ;
 913        add_timer(&ct->timeout);
 914
 915        return 0;
 916}
 917
 918static inline int
 919ctnetlink_change_protoinfo(struct nf_conn *ct, struct nlattr *cda[])
 920{
 921        struct nlattr *tb[CTA_PROTOINFO_MAX+1], *attr = cda[CTA_PROTOINFO];
 922        struct nf_conntrack_l4proto *l4proto;
 923        u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
 924        u_int16_t l3num = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
 925        int err = 0;
 926
 927        nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, NULL);
 928
 929        l4proto = nf_ct_l4proto_find_get(l3num, npt);
 930
 931        if (l4proto->from_nlattr)
 932                err = l4proto->from_nlattr(tb, ct);
 933        nf_ct_l4proto_put(l4proto);
 934
 935        return err;
 936}
 937
 938static int
 939ctnetlink_change_conntrack(struct nf_conn *ct, struct nlattr *cda[])
 940{
 941        int err;
 942
 943        if (cda[CTA_HELP]) {
 944                err = ctnetlink_change_helper(ct, cda);
 945                if (err < 0)
 946                        return err;
 947        }
 948
 949        if (cda[CTA_TIMEOUT]) {
 950                err = ctnetlink_change_timeout(ct, cda);
 951                if (err < 0)
 952                        return err;
 953        }
 954
 955        if (cda[CTA_STATUS]) {
 956                err = ctnetlink_change_status(ct, cda);
 957                if (err < 0)
 958                        return err;
 959        }
 960
 961        if (cda[CTA_PROTOINFO]) {
 962                err = ctnetlink_change_protoinfo(ct, cda);
 963                if (err < 0)
 964                        return err;
 965        }
 966
 967#if defined(CONFIG_NF_CONNTRACK_MARK)
 968        if (cda[CTA_MARK])
 969                ct->mark = ntohl(*(__be32 *)nla_data(cda[CTA_MARK]));
 970#endif
 971
 972        return 0;
 973}
 974
 975static int
 976ctnetlink_create_conntrack(struct nlattr *cda[],
 977                           struct nf_conntrack_tuple *otuple,
 978                           struct nf_conntrack_tuple *rtuple,
 979                           struct nf_conn *master_ct)
 980{
 981        struct nf_conn *ct;
 982        int err = -EINVAL;
 983        struct nf_conn_help *help;
 984        struct nf_conntrack_helper *helper;
 985
 986        ct = nf_conntrack_alloc(otuple, rtuple);
 987        if (ct == NULL || IS_ERR(ct))
 988                return -ENOMEM;
 989
 990        if (!cda[CTA_TIMEOUT])
 991                goto err;
 992        ct->timeout.expires = ntohl(*(__be32 *)nla_data(cda[CTA_TIMEOUT]));
 993
 994        ct->timeout.expires = jiffies + ct->timeout.expires * HZ;
 995        ct->status |= IPS_CONFIRMED;
 996
 997        if (cda[CTA_STATUS]) {
 998                err = ctnetlink_change_status(ct, cda);
 999                if (err < 0)
1000                        goto err;
1001        }
1002
1003        if (cda[CTA_PROTOINFO]) {
1004                err = ctnetlink_change_protoinfo(ct, cda);
1005                if (err < 0)
1006                        goto err;
1007        }
1008
1009#if defined(CONFIG_NF_CONNTRACK_MARK)
1010        if (cda[CTA_MARK])
1011                ct->mark = ntohl(*(__be32 *)nla_data(cda[CTA_MARK]));
1012#endif
1013
1014        helper = nf_ct_helper_find_get(rtuple);
1015        if (helper) {
1016                help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
1017                if (help == NULL) {
1018                        nf_ct_helper_put(helper);
1019                        err = -ENOMEM;
1020                        goto err;
1021                }
1022                /* not in hash table yet so not strictly necessary */
1023                rcu_assign_pointer(help->helper, helper);
1024        }
1025
1026        /* setup master conntrack: this is a confirmed expectation */
1027        if (master_ct) {
1028                __set_bit(IPS_EXPECTED_BIT, &ct->status);
1029                ct->master = master_ct;
1030        }
1031
1032        add_timer(&ct->timeout);
1033        nf_conntrack_hash_insert(ct);
1034
1035        if (helper)
1036                nf_ct_helper_put(helper);
1037
1038        return 0;
1039
1040err:
1041        nf_conntrack_free(ct);
1042        return err;
1043}
1044
1045static int
1046ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
1047                        struct nlmsghdr *nlh, struct nlattr *cda[])
1048{
1049        struct nf_conntrack_tuple otuple, rtuple;
1050        struct nf_conntrack_tuple_hash *h = NULL;
1051        struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
1052        u_int8_t u3 = nfmsg->nfgen_family;
1053        int err = 0;
1054
1055        if (cda[CTA_TUPLE_ORIG]) {
1056                err = ctnetlink_parse_tuple(cda, &otuple, CTA_TUPLE_ORIG, u3);
1057                if (err < 0)
1058                        return err;
1059        }
1060
1061        if (cda[CTA_TUPLE_REPLY]) {
1062                err = ctnetlink_parse_tuple(cda, &rtuple, CTA_TUPLE_REPLY, u3);
1063                if (err < 0)
1064                        return err;
1065        }
1066
1067        write_lock_bh(&nf_conntrack_lock);
1068        if (cda[CTA_TUPLE_ORIG])
1069                h = __nf_conntrack_find(&otuple, NULL);
1070        else if (cda[CTA_TUPLE_REPLY])
1071                h = __nf_conntrack_find(&rtuple, NULL);
1072
1073        if (h == NULL) {
1074                struct nf_conntrack_tuple master;
1075                struct nf_conntrack_tuple_hash *master_h = NULL;
1076                struct nf_conn *master_ct = NULL;
1077
1078                if (cda[CTA_TUPLE_MASTER]) {
1079                        err = ctnetlink_parse_tuple(cda,
1080                                                    &master,
1081                                                    CTA_TUPLE_MASTER,
1082                                                    u3);
1083                        if (err < 0)
1084                                return err;
1085
1086                        master_h = __nf_conntrack_find(&master, NULL);
1087                        if (master_h == NULL) {
1088                                err = -ENOENT;
1089                                goto out_unlock;
1090                        }
1091                        master_ct = nf_ct_tuplehash_to_ctrack(master_h);
1092                        atomic_inc(&master_ct->ct_general.use);
1093                }
1094
1095                write_unlock_bh(&nf_conntrack_lock);
1096                err = -ENOENT;
1097                if (nlh->nlmsg_flags & NLM_F_CREATE)
1098                        err = ctnetlink_create_conntrack(cda,
1099                                                         &otuple,
1100                                                         &rtuple,
1101                                                         master_ct);
1102                if (err < 0 && master_ct)
1103                        nf_ct_put(master_ct);
1104
1105                return err;
1106        }
1107        /* implicit 'else' */
1108
1109        /* We manipulate the conntrack inside the global conntrack table lock,
1110         * so there's no need to increase the refcount */
1111        err = -EEXIST;
1112        if (!(nlh->nlmsg_flags & NLM_F_EXCL)) {
1113                /* we only allow nat config for new conntracks */
1114                if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) {
1115                        err = -EINVAL;
1116                        goto out_unlock;
1117                }
1118                /* can't link an existing conntrack to a master */
1119                if (cda[CTA_TUPLE_MASTER]) {
1120                        err = -EINVAL;
1121                        goto out_unlock;
1122                }
1123                err = ctnetlink_change_conntrack(nf_ct_tuplehash_to_ctrack(h),
1124                                                 cda);
1125        }
1126
1127out_unlock:
1128        write_unlock_bh(&nf_conntrack_lock);
1129        return err;
1130}
1131
1132/***********************************************************************
1133 * EXPECT
1134 ***********************************************************************/
1135
1136static inline int
1137ctnetlink_exp_dump_tuple(struct sk_buff *skb,
1138                         const struct nf_conntrack_tuple *tuple,
1139                         enum ctattr_expect type)
1140{
1141        struct nlattr *nest_parms;
1142
1143        nest_parms = nla_nest_start(skb, type | NLA_F_NESTED);
1144        if (!nest_parms)
1145                goto nla_put_failure;
1146        if (ctnetlink_dump_tuples(skb, tuple) < 0)
1147                goto nla_put_failure;
1148        nla_nest_end(skb, nest_parms);
1149
1150        return 0;
1151
1152nla_put_failure:
1153        return -1;
1154}
1155
1156static inline int
1157ctnetlink_exp_dump_mask(struct sk_buff *skb,
1158                        const struct nf_conntrack_tuple *tuple,
1159                        const struct nf_conntrack_tuple_mask *mask)
1160{
1161        int ret;
1162        struct nf_conntrack_l3proto *l3proto;
1163        struct nf_conntrack_l4proto *l4proto;
1164        struct nf_conntrack_tuple m;
1165        struct nlattr *nest_parms;
1166
1167        memset(&m, 0xFF, sizeof(m));
1168        m.src.u.all = mask->src.u.all;
1169        memcpy(&m.src.u3, &mask->src.u3, sizeof(m.src.u3));
1170
1171        nest_parms = nla_nest_start(skb, CTA_EXPECT_MASK | NLA_F_NESTED);
1172        if (!nest_parms)
1173                goto nla_put_failure;
1174
1175        l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
1176        ret = ctnetlink_dump_tuples_ip(skb, &m, l3proto);
1177        nf_ct_l3proto_put(l3proto);
1178
1179        if (unlikely(ret < 0))
1180                goto nla_put_failure;
1181
1182        l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum);
1183        ret = ctnetlink_dump_tuples_proto(skb, &m, l4proto);
1184        nf_ct_l4proto_put(l4proto);
1185        if (unlikely(ret < 0))
1186                goto nla_put_failure;
1187
1188        nla_nest_end(skb, nest_parms);
1189
1190        return 0;
1191
1192nla_put_failure:
1193        return -1;
1194}
1195
1196static inline int
1197ctnetlink_exp_dump_expect(struct sk_buff *skb,
1198                          const struct nf_conntrack_expect *exp)
1199{
1200        struct nf_conn *master = exp->master;
1201        __be32 timeout = htonl((exp->timeout.expires - jiffies) / HZ);
1202        __be32 id = htonl((unsigned long)exp);
1203
1204        if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
1205                goto nla_put_failure;
1206        if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
1207                goto nla_put_failure;
1208        if (ctnetlink_exp_dump_tuple(skb,
1209                                 &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
1210                                 CTA_EXPECT_MASTER) < 0)
1211                goto nla_put_failure;
1212
1213        NLA_PUT(skb, CTA_EXPECT_TIMEOUT, sizeof(timeout), &timeout);
1214        NLA_PUT(skb, CTA_EXPECT_ID, sizeof(u_int32_t), &id);
1215
1216        return 0;
1217
1218nla_put_failure:
1219        return -1;
1220}
1221
1222static int
1223ctnetlink_exp_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
1224                    int event,
1225                    int nowait,
1226                    const struct nf_conntrack_expect *exp)
1227{
1228        struct nlmsghdr *nlh;
1229        struct nfgenmsg *nfmsg;
1230        unsigned char *b = skb_tail_pointer(skb);
1231
1232        event |= NFNL_SUBSYS_CTNETLINK_EXP << 8;
1233        nlh    = NLMSG_PUT(skb, pid, seq, event, sizeof(struct nfgenmsg));
1234        nfmsg  = NLMSG_DATA(nlh);
1235
1236        nlh->nlmsg_flags    = (nowait && pid) ? NLM_F_MULTI : 0;
1237        nfmsg->nfgen_family = exp->tuple.src.l3num;
1238        nfmsg->version      = NFNETLINK_V0;
1239        nfmsg->res_id       = 0;
1240
1241        if (ctnetlink_exp_dump_expect(skb, exp) < 0)
1242                goto nla_put_failure;
1243
1244        nlh->nlmsg_len = skb_tail_pointer(skb) - b;
1245        return skb->len;
1246
1247nlmsg_failure:
1248nla_put_failure:
1249        nlmsg_trim(skb, b);
1250        return -1;
1251}
1252
1253#ifdef CONFIG_NF_CONNTRACK_EVENTS
1254static int ctnetlink_expect_event(struct notifier_block *this,
1255                                  unsigned long events, void *ptr)
1256{
1257        struct nlmsghdr *nlh;
1258        struct nfgenmsg *nfmsg;
1259        struct nf_conntrack_expect *exp = (struct nf_conntrack_expect *)ptr;
1260        struct sk_buff *skb;
1261        unsigned int type;
1262        sk_buff_data_t b;
1263        int flags = 0;
1264
1265        if (events & IPEXP_NEW) {
1266                type = IPCTNL_MSG_EXP_NEW;
1267                flags = NLM_F_CREATE|NLM_F_EXCL;
1268        } else
1269                return NOTIFY_DONE;
1270
1271        if (!nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW))
1272                return NOTIFY_DONE;
1273
1274        skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
1275        if (!skb)
1276                return NOTIFY_DONE;
1277
1278        b = skb->tail;
1279
1280        type |= NFNL_SUBSYS_CTNETLINK_EXP << 8;
1281        nlh   = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg));
1282        nfmsg = NLMSG_DATA(nlh);
1283
1284        nlh->nlmsg_flags    = flags;
1285        nfmsg->nfgen_family = exp->tuple.src.l3num;
1286        nfmsg->version      = NFNETLINK_V0;
1287        nfmsg->res_id       = 0;
1288
1289        if (ctnetlink_exp_dump_expect(skb, exp) < 0)
1290                goto nla_put_failure;
1291
1292        nlh->nlmsg_len = skb->tail - b;
1293        nfnetlink_send(skb, 0, NFNLGRP_CONNTRACK_EXP_NEW, 0);
1294        return NOTIFY_DONE;
1295
1296nlmsg_failure:
1297nla_put_failure:
1298        kfree_skb(skb);
1299        return NOTIFY_DONE;
1300}
1301#endif
1302static int ctnetlink_exp_done(struct netlink_callback *cb)
1303{
1304        if (cb->args[1])
1305                nf_ct_expect_put((struct nf_conntrack_expect *)cb->args[1]);
1306        return 0;
1307}
1308
1309static int
1310ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
1311{
1312        struct nf_conntrack_expect *exp, *last;
1313        struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
1314        struct hlist_node *n;
1315        u_int8_t l3proto = nfmsg->nfgen_family;
1316
1317        read_lock_bh(&nf_conntrack_lock);
1318        last = (struct nf_conntrack_expect *)cb->args[1];
1319        for (; cb->args[0] < nf_ct_expect_hsize; cb->args[0]++) {
1320restart:
1321                hlist_for_each_entry(exp, n, &nf_ct_expect_hash[cb->args[0]],
1322                                     hnode) {
1323                        if (l3proto && exp->tuple.src.l3num != l3proto)
1324                                continue;
1325                        if (cb->args[1]) {
1326                                if (exp != last)
1327                                        continue;
1328                                cb->args[1] = 0;
1329                        }
1330                        if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid,
1331                                                    cb->nlh->nlmsg_seq,
1332                                                    IPCTNL_MSG_EXP_NEW,
1333                                                    1, exp) < 0) {
1334                                atomic_inc(&exp->use);
1335                                cb->args[1] = (unsigned long)exp;
1336                                goto out;
1337                        }
1338                }
1339                if (cb->args[1]) {
1340                        cb->args[1] = 0;
1341                        goto restart;
1342                }
1343        }
1344out:
1345        read_unlock_bh(&nf_conntrack_lock);
1346        if (last)
1347                nf_ct_expect_put(last);
1348
1349        return skb->len;
1350}
1351
1352static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
1353        [CTA_EXPECT_TIMEOUT]    = { .type = NLA_U32 },
1354        [CTA_EXPECT_ID]         = { .type = NLA_U32 },
1355};
1356
1357static int
1358ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
1359                     struct nlmsghdr *nlh, struct nlattr *cda[])
1360{
1361        struct nf_conntrack_tuple tuple;
1362        struct nf_conntrack_expect *exp;
1363        struct sk_buff *skb2;
1364        struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
1365        u_int8_t u3 = nfmsg->nfgen_family;
1366        int err = 0;
1367
1368        if (nlh->nlmsg_flags & NLM_F_DUMP) {
1369                return netlink_dump_start(ctnl, skb, nlh,
1370                                          ctnetlink_exp_dump_table,
1371                                          ctnetlink_exp_done);
1372        }
1373
1374        if (cda[CTA_EXPECT_MASTER])
1375                err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, u3);
1376        else
1377                return -EINVAL;
1378
1379        if (err < 0)
1380                return err;
1381
1382        exp = nf_ct_expect_find_get(&tuple);
1383        if (!exp)
1384                return -ENOENT;
1385
1386        if (cda[CTA_EXPECT_ID]) {
1387                __be32 id = *(__be32 *)nla_data(cda[CTA_EXPECT_ID]);
1388                if (ntohl(id) != (u32)(unsigned long)exp) {
1389                        nf_ct_expect_put(exp);
1390                        return -ENOENT;
1391                }
1392        }
1393
1394        err = -ENOMEM;
1395        skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
1396        if (!skb2)
1397                goto out;
1398
1399        err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid,
1400                                      nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW,
1401                                      1, exp);
1402        if (err <= 0)
1403                goto free;
1404
1405        nf_ct_expect_put(exp);
1406
1407        return netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
1408
1409free:
1410        kfree_skb(skb2);
1411out:
1412        nf_ct_expect_put(exp);
1413        return err;
1414}
1415
1416static int
1417ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
1418                     struct nlmsghdr *nlh, struct nlattr *cda[])
1419{
1420        struct nf_conntrack_expect *exp;
1421        struct nf_conntrack_tuple tuple;
1422        struct nf_conntrack_helper *h;
1423        struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
1424        struct hlist_node *n, *next;
1425        u_int8_t u3 = nfmsg->nfgen_family;
1426        unsigned int i;
1427        int err;
1428
1429        if (cda[CTA_EXPECT_TUPLE]) {
1430                /* delete a single expect by tuple */
1431                err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
1432                if (err < 0)
1433                        return err;
1434
1435                /* bump usage count to 2 */
1436                exp = nf_ct_expect_find_get(&tuple);
1437                if (!exp)
1438                        return -ENOENT;
1439
1440                if (cda[CTA_EXPECT_ID]) {
1441                        __be32 id = *(__be32 *)nla_data(cda[CTA_EXPECT_ID]);
1442                        if (ntohl(id) != (u32)(unsigned long)exp) {
1443                                nf_ct_expect_put(exp);
1444                                return -ENOENT;
1445                        }
1446                }
1447
1448                /* after list removal, usage count == 1 */
1449                nf_ct_unexpect_related(exp);
1450                /* have to put what we 'get' above.
1451                 * after this line usage count == 0 */
1452                nf_ct_expect_put(exp);
1453        } else if (cda[CTA_EXPECT_HELP_NAME]) {
1454                char *name = nla_data(cda[CTA_EXPECT_HELP_NAME]);
1455                struct nf_conn_help *m_help;
1456
1457                /* delete all expectations for this helper */
1458                write_lock_bh(&nf_conntrack_lock);
1459                h = __nf_conntrack_helper_find_byname(name);
1460                if (!h) {
1461                        write_unlock_bh(&nf_conntrack_lock);
1462                        return -EINVAL;
1463                }
1464                for (i = 0; i < nf_ct_expect_hsize; i++) {
1465                        hlist_for_each_entry_safe(exp, n, next,
1466                                                  &nf_ct_expect_hash[i],
1467                                                  hnode) {
1468                                m_help = nfct_help(exp->master);
1469                                if (m_help->helper == h
1470                                    && del_timer(&exp->timeout)) {
1471                                        nf_ct_unlink_expect(exp);
1472                                        nf_ct_expect_put(exp);
1473                                }
1474                        }
1475                }
1476                write_unlock_bh(&nf_conntrack_lock);
1477        } else {
1478                /* This basically means we have to flush everything*/
1479                write_lock_bh(&nf_conntrack_lock);
1480                for (i = 0; i < nf_ct_expect_hsize; i++) {
1481                        hlist_for_each_entry_safe(exp, n, next,
1482                                                  &nf_ct_expect_hash[i],
1483                                                  hnode) {
1484                                if (del_timer(&exp->timeout)) {
1485                                        nf_ct_unlink_expect(exp);
1486                                        nf_ct_expect_put(exp);
1487                                }
1488                        }
1489                }
1490                write_unlock_bh(&nf_conntrack_lock);
1491        }
1492
1493        return 0;
1494}
1495static int
1496ctnetlink_change_expect(struct nf_conntrack_expect *x, struct nlattr *cda[])
1497{
1498        return -EOPNOTSUPP;
1499}
1500
1501static int
1502ctnetlink_create_expect(struct nlattr *cda[], u_int8_t u3)
1503{
1504        struct nf_conntrack_tuple tuple, mask, master_tuple;
1505        struct nf_conntrack_tuple_hash *h = NULL;
1506        struct nf_conntrack_expect *exp;
1507        struct nf_conn *ct;
1508        struct nf_conn_help *help;
1509        int err = 0;
1510
1511        /* caller guarantees that those three CTA_EXPECT_* exist */
1512        err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
1513        if (err < 0)
1514                return err;
1515        err = ctnetlink_parse_tuple(cda, &mask, CTA_EXPECT_MASK, u3);
1516        if (err < 0)
1517                return err;
1518        err = ctnetlink_parse_tuple(cda, &master_tuple, CTA_EXPECT_MASTER, u3);
1519        if (err < 0)
1520                return err;
1521
1522        /* Look for master conntrack of this expectation */
1523        h = nf_conntrack_find_get(&master_tuple);
1524        if (!h)
1525                return -ENOENT;
1526        ct = nf_ct_tuplehash_to_ctrack(h);
1527        help = nfct_help(ct);
1528
1529        if (!help || !help->helper) {
1530                /* such conntrack hasn't got any helper, abort */
1531                err = -EINVAL;
1532                goto out;
1533        }
1534
1535        exp = nf_ct_expect_alloc(ct);
1536        if (!exp) {
1537                err = -ENOMEM;
1538                goto out;
1539        }
1540
1541        exp->expectfn = NULL;
1542        exp->flags = 0;
1543        exp->master = ct;
1544        exp->helper = NULL;
1545        memcpy(&exp->tuple, &tuple, sizeof(struct nf_conntrack_tuple));
1546        memcpy(&exp->mask.src.u3, &mask.src.u3, sizeof(exp->mask.src.u3));
1547        exp->mask.src.u.all = mask.src.u.all;
1548
1549        err = nf_ct_expect_related(exp);
1550        nf_ct_expect_put(exp);
1551
1552out:
1553        nf_ct_put(nf_ct_tuplehash_to_ctrack(h));
1554        return err;
1555}
1556
1557static int
1558ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
1559                     struct nlmsghdr *nlh, struct nlattr *cda[])
1560{
1561        struct nf_conntrack_tuple tuple;
1562        struct nf_conntrack_expect *exp;
1563        struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
1564        u_int8_t u3 = nfmsg->nfgen_family;
1565        int err = 0;
1566
1567        if (!cda[CTA_EXPECT_TUPLE]
1568            || !cda[CTA_EXPECT_MASK]
1569            || !cda[CTA_EXPECT_MASTER])
1570                return -EINVAL;
1571
1572        err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
1573        if (err < 0)
1574                return err;
1575
1576        write_lock_bh(&nf_conntrack_lock);
1577        exp = __nf_ct_expect_find(&tuple);
1578
1579        if (!exp) {
1580                write_unlock_bh(&nf_conntrack_lock);
1581                err = -ENOENT;
1582                if (nlh->nlmsg_flags & NLM_F_CREATE)
1583                        err = ctnetlink_create_expect(cda, u3);
1584                return err;
1585        }
1586
1587        err = -EEXIST;
1588        if (!(nlh->nlmsg_flags & NLM_F_EXCL))
1589                err = ctnetlink_change_expect(exp, cda);
1590        write_unlock_bh(&nf_conntrack_lock);
1591
1592        return err;
1593}
1594
1595#ifdef CONFIG_NF_CONNTRACK_EVENTS
1596static struct notifier_block ctnl_notifier = {
1597        .notifier_call  = ctnetlink_conntrack_event,
1598};
1599
1600static struct notifier_block ctnl_notifier_exp = {
1601        .notifier_call  = ctnetlink_expect_event,
1602};
1603#endif
1604
1605static const struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = {
1606        [IPCTNL_MSG_CT_NEW]             = { .call = ctnetlink_new_conntrack,
1607                                            .attr_count = CTA_MAX,
1608                                            .policy = ct_nla_policy },
1609        [IPCTNL_MSG_CT_GET]             = { .call = ctnetlink_get_conntrack,
1610                                            .attr_count = CTA_MAX,
1611                                            .policy = ct_nla_policy },
1612        [IPCTNL_MSG_CT_DELETE]          = { .call = ctnetlink_del_conntrack,
1613                                            .attr_count = CTA_MAX,
1614                                            .policy = ct_nla_policy },
1615        [IPCTNL_MSG_CT_GET_CTRZERO]     = { .call = ctnetlink_get_conntrack,
1616                                            .attr_count = CTA_MAX,
1617                                            .policy = ct_nla_policy },
1618};
1619
1620static const struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = {
1621        [IPCTNL_MSG_EXP_GET]            = { .call = ctnetlink_get_expect,
1622                                            .attr_count = CTA_EXPECT_MAX,
1623                                            .policy = exp_nla_policy },
1624        [IPCTNL_MSG_EXP_NEW]            = { .call = ctnetlink_new_expect,
1625                                            .attr_count = CTA_EXPECT_MAX,
1626                                            .policy = exp_nla_policy },
1627        [IPCTNL_MSG_EXP_DELETE]         = { .call = ctnetlink_del_expect,
1628                                            .attr_count = CTA_EXPECT_MAX,
1629                                            .policy = exp_nla_policy },
1630};
1631
1632static const struct nfnetlink_subsystem ctnl_subsys = {
1633        .name                           = "conntrack",
1634        .subsys_id                      = NFNL_SUBSYS_CTNETLINK,
1635        .cb_count                       = IPCTNL_MSG_MAX,
1636        .cb                             = ctnl_cb,
1637};
1638
1639static const struct nfnetlink_subsystem ctnl_exp_subsys = {
1640        .name                           = "conntrack_expect",
1641        .subsys_id                      = NFNL_SUBSYS_CTNETLINK_EXP,
1642        .cb_count                       = IPCTNL_MSG_EXP_MAX,
1643        .cb                             = ctnl_exp_cb,
1644};
1645
1646MODULE_ALIAS("ip_conntrack_netlink");
1647MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK);
1648MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP);
1649
1650static int __init ctnetlink_init(void)
1651{
1652        int ret;
1653
1654        printk("ctnetlink v%s: registering with nfnetlink.\n", version);
1655        ret = nfnetlink_subsys_register(&ctnl_subsys);
1656        if (ret < 0) {
1657                printk("ctnetlink_init: cannot register with nfnetlink.\n");
1658                goto err_out;
1659        }
1660
1661        ret = nfnetlink_subsys_register(&ctnl_exp_subsys);
1662        if (ret < 0) {
1663                printk("ctnetlink_init: cannot register exp with nfnetlink.\n");
1664                goto err_unreg_subsys;
1665        }
1666
1667#ifdef CONFIG_NF_CONNTRACK_EVENTS
1668        ret = nf_conntrack_register_notifier(&ctnl_notifier);
1669        if (ret < 0) {
1670                printk("ctnetlink_init: cannot register notifier.\n");
1671                goto err_unreg_exp_subsys;
1672        }
1673
1674        ret = nf_ct_expect_register_notifier(&ctnl_notifier_exp);
1675        if (ret < 0) {
1676                printk("ctnetlink_init: cannot expect register notifier.\n");
1677                goto err_unreg_notifier;
1678        }
1679#endif
1680
1681        return 0;
1682
1683#ifdef CONFIG_NF_CONNTRACK_EVENTS
1684err_unreg_notifier:
1685        nf_conntrack_unregister_notifier(&ctnl_notifier);
1686err_unreg_exp_subsys:
1687        nfnetlink_subsys_unregister(&ctnl_exp_subsys);
1688#endif
1689err_unreg_subsys:
1690        nfnetlink_subsys_unregister(&ctnl_subsys);
1691err_out:
1692        return ret;
1693}
1694
1695static void __exit ctnetlink_exit(void)
1696{
1697        printk("ctnetlink: unregistering from nfnetlink.\n");
1698
1699#ifdef CONFIG_NF_CONNTRACK_EVENTS
1700        nf_ct_expect_unregister_notifier(&ctnl_notifier_exp);
1701        nf_conntrack_unregister_notifier(&ctnl_notifier);
1702#endif
1703
1704        nfnetlink_subsys_unregister(&ctnl_exp_subsys);
1705        nfnetlink_subsys_unregister(&ctnl_subsys);
1706        return;
1707}
1708
1709module_init(ctnetlink_init);
1710module_exit(ctnetlink_exit);
1711