netfilter: nfnetlink: netns support
[safe/jmp/linux-2.6] / net / netfilter / nf_conntrack_netlink.c
index 4e503ad..d4c5d06 100644 (file)
@@ -463,15 +463,16 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
        struct sk_buff *skb;
        unsigned int type;
        unsigned int flags = 0, group;
+       int err;
 
        /* ignore our fake conntrack entry */
        if (ct == &nf_conntrack_untracked)
                return 0;
 
-       if (events & IPCT_DESTROY) {
+       if (events & (1 << IPCT_DESTROY)) {
                type = IPCTNL_MSG_CT_DELETE;
                group = NFNLGRP_CONNTRACK_DESTROY;
-       } else  if (events & (IPCT_NEW | IPCT_RELATED)) {
+       } else  if (events & ((1 << IPCT_NEW) | (1 << IPCT_RELATED))) {
                type = IPCTNL_MSG_CT_NEW;
                flags = NLM_F_CREATE|NLM_F_EXCL;
                group = NFNLGRP_CONNTRACK_NEW;
@@ -481,7 +482,7 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
        } else
                return 0;
 
-       if (!item->report && !nfnetlink_has_listeners(group))
+       if (!item->report && !nfnetlink_has_listeners(&init_net, group))
                return 0;
 
        skb = nlmsg_new(ctnetlink_nlmsg_size(ct), GFP_ATOMIC);
@@ -519,7 +520,7 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
        if (ctnetlink_dump_status(skb, ct) < 0)
                goto nla_put_failure;
 
-       if (events & IPCT_DESTROY) {
+       if (events & (1 << IPCT_DESTROY)) {
                if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
                    ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
                        goto nla_put_failure;
@@ -527,38 +528,42 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
                if (ctnetlink_dump_timeout(skb, ct) < 0)
                        goto nla_put_failure;
 
-               if (events & IPCT_PROTOINFO
+               if (events & (1 << IPCT_PROTOINFO)
                    && ctnetlink_dump_protoinfo(skb, ct) < 0)
                        goto nla_put_failure;
 
-               if ((events & IPCT_HELPER || nfct_help(ct))
+               if ((events & (1 << IPCT_HELPER) || nfct_help(ct))
                    && ctnetlink_dump_helpinfo(skb, ct) < 0)
                        goto nla_put_failure;
 
 #ifdef CONFIG_NF_CONNTRACK_SECMARK
-               if ((events & IPCT_SECMARK || ct->secmark)
+               if ((events & (1 << IPCT_SECMARK) || ct->secmark)
                    && ctnetlink_dump_secmark(skb, ct) < 0)
                        goto nla_put_failure;
 #endif
 
-               if (events & IPCT_RELATED &&
+               if (events & (1 << IPCT_RELATED) &&
                    ctnetlink_dump_master(skb, ct) < 0)
                        goto nla_put_failure;
 
-               if (events & IPCT_NATSEQADJ &&
+               if (events & (1 << IPCT_NATSEQADJ) &&
                    ctnetlink_dump_nat_seq_adj(skb, ct) < 0)
                        goto nla_put_failure;
        }
 
 #ifdef CONFIG_NF_CONNTRACK_MARK
-       if ((events & IPCT_MARK || ct->mark)
+       if ((events & (1 << IPCT_MARK) || ct->mark)
            && ctnetlink_dump_mark(skb, ct) < 0)
                goto nla_put_failure;
 #endif
        rcu_read_unlock();
 
        nlmsg_end(skb, nlh);
-       nfnetlink_send(skb, item->pid, group, item->report, GFP_ATOMIC);
+       err = nfnetlink_send(skb, &init_net, item->pid, group, item->report,
+                            GFP_ATOMIC);
+       if (err == -ENOBUFS || err == -EAGAIN)
+               return -ENOBUFS;
+
        return 0;
 
 nla_put_failure:
@@ -567,7 +572,7 @@ nla_put_failure:
 nlmsg_failure:
        kfree_skb(skb);
 errout:
-       nfnetlink_set_err(0, group, -ENOBUFS);
+       nfnetlink_set_err(&init_net, 0, group, -ENOBUFS);
        return 0;
 }
 #endif /* CONFIG_NF_CONNTRACK_EVENTS */
@@ -700,7 +705,8 @@ ctnetlink_parse_tuple_proto(struct nlattr *attr,
 }
 
 static int
-ctnetlink_parse_tuple(struct nlattr *cda[], struct nf_conntrack_tuple *tuple,
+ctnetlink_parse_tuple(const struct nlattr * const cda[],
+                     struct nf_conntrack_tuple *tuple,
                      enum ctattr_tuple type, u_int8_t l3num)
 {
        struct nlattr *tb[CTA_TUPLE_MAX+1];
@@ -736,7 +742,7 @@ ctnetlink_parse_tuple(struct nlattr *cda[], struct nf_conntrack_tuple *tuple,
 }
 
 static inline int
-ctnetlink_parse_help(struct nlattr *attr, char **helper_name)
+ctnetlink_parse_help(const struct nlattr *attr, char **helper_name)
 {
        struct nlattr *tb[CTA_HELP_MAX+1];
 
@@ -760,7 +766,8 @@ static const struct nla_policy ct_nla_policy[CTA_MAX+1] = {
 
 static int
 ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
-                       struct nlmsghdr *nlh, struct nlattr *cda[])
+                       const struct nlmsghdr *nlh,
+                       const struct nlattr * const cda[])
 {
        struct nf_conntrack_tuple_hash *h;
        struct nf_conntrack_tuple tuple;
@@ -798,10 +805,15 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
                }
        }
 
-       nf_conntrack_event_report(IPCT_DESTROY,
-                                 ct,
-                                 NETLINK_CB(skb).pid,
-                                 nlmsg_report(nlh));
+       if (nf_conntrack_event_report(IPCT_DESTROY, ct,
+                                     NETLINK_CB(skb).pid,
+                                     nlmsg_report(nlh)) < 0) {
+               nf_ct_delete_from_lists(ct);
+               /* we failed to report the event, try later */
+               nf_ct_insert_dying_list(ct);
+               nf_ct_put(ct);
+               return 0;
+       }
 
        /* death_by_timeout would report the event again */
        set_bit(IPS_DYING_BIT, &ct->status);
@@ -814,7 +826,8 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
 
 static int
 ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
-                       struct nlmsghdr *nlh, struct nlattr *cda[])
+                       const struct nlmsghdr *nlh,
+                       const struct nlattr * const cda[])
 {
        struct nf_conntrack_tuple_hash *h;
        struct nf_conntrack_tuple tuple;
@@ -875,7 +888,7 @@ out:
 static int
 ctnetlink_parse_nat_setup(struct nf_conn *ct,
                          enum nf_nat_manip_type manip,
-                         struct nlattr *attr)
+                         const struct nlattr *attr)
 {
        typeof(nfnetlink_parse_nat_setup_hook) parse_nat_setup;
 
@@ -905,7 +918,7 @@ ctnetlink_parse_nat_setup(struct nf_conn *ct,
 #endif
 
 static int
-ctnetlink_change_status(struct nf_conn *ct, struct nlattr *cda[])
+ctnetlink_change_status(struct nf_conn *ct, const struct nlattr * const cda[])
 {
        unsigned long d;
        unsigned int status = ntohl(nla_get_be32(cda[CTA_STATUS]));
@@ -931,7 +944,7 @@ ctnetlink_change_status(struct nf_conn *ct, struct nlattr *cda[])
 }
 
 static int
-ctnetlink_change_nat(struct nf_conn *ct, struct nlattr *cda[])
+ctnetlink_change_nat(struct nf_conn *ct, const struct nlattr * const cda[])
 {
 #ifdef CONFIG_NF_NAT_NEEDED
        int ret;
@@ -957,7 +970,7 @@ ctnetlink_change_nat(struct nf_conn *ct, struct nlattr *cda[])
 }
 
 static inline int
-ctnetlink_change_helper(struct nf_conn *ct, struct nlattr *cda[])
+ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[])
 {
        struct nf_conntrack_helper *helper;
        struct nf_conn_help *help = nfct_help(ct);
@@ -1019,7 +1032,7 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nlattr *cda[])
 }
 
 static inline int
-ctnetlink_change_timeout(struct nf_conn *ct, struct nlattr *cda[])
+ctnetlink_change_timeout(struct nf_conn *ct, const struct nlattr * const cda[])
 {
        u_int32_t timeout = ntohl(nla_get_be32(cda[CTA_TIMEOUT]));
 
@@ -1033,9 +1046,10 @@ ctnetlink_change_timeout(struct nf_conn *ct, struct nlattr *cda[])
 }
 
 static inline int
-ctnetlink_change_protoinfo(struct nf_conn *ct, struct nlattr *cda[])
+ctnetlink_change_protoinfo(struct nf_conn *ct, const struct nlattr * const cda[])
 {
-       struct nlattr *tb[CTA_PROTOINFO_MAX+1], *attr = cda[CTA_PROTOINFO];
+       const struct nlattr *attr = cda[CTA_PROTOINFO];
+       struct nlattr *tb[CTA_PROTOINFO_MAX+1];
        struct nf_conntrack_l4proto *l4proto;
        int err = 0;
 
@@ -1052,7 +1066,7 @@ ctnetlink_change_protoinfo(struct nf_conn *ct, struct nlattr *cda[])
 
 #ifdef CONFIG_NF_NAT_NEEDED
 static inline int
-change_nat_seq_adj(struct nf_nat_seq *natseq, struct nlattr *attr)
+change_nat_seq_adj(struct nf_nat_seq *natseq, const struct nlattr * const attr)
 {
        struct nlattr *cda[CTA_NAT_SEQ_MAX+1];
 
@@ -1080,7 +1094,8 @@ change_nat_seq_adj(struct nf_nat_seq *natseq, struct nlattr *attr)
 }
 
 static int
-ctnetlink_change_nat_seq_adj(struct nf_conn *ct, struct nlattr *cda[])
+ctnetlink_change_nat_seq_adj(struct nf_conn *ct,
+                            const struct nlattr * const cda[])
 {
        int ret = 0;
        struct nf_conn_nat *nat = nfct_nat(ct);
@@ -1111,7 +1126,8 @@ ctnetlink_change_nat_seq_adj(struct nf_conn *ct, struct nlattr *cda[])
 #endif
 
 static int
-ctnetlink_change_conntrack(struct nf_conn *ct, struct nlattr *cda[])
+ctnetlink_change_conntrack(struct nf_conn *ct,
+                          const struct nlattr * const cda[])
 {
        int err;
 
@@ -1160,7 +1176,7 @@ ctnetlink_change_conntrack(struct nf_conn *ct, struct nlattr *cda[])
 }
 
 static struct nf_conn *
-ctnetlink_create_conntrack(struct nlattr *cda[],
+ctnetlink_create_conntrack(const struct nlattr * const cda[],
                           struct nf_conntrack_tuple *otuple,
                           struct nf_conntrack_tuple *rtuple,
                           u8 u3)
@@ -1253,6 +1269,7 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
        }
 
        nf_ct_acct_ext_add(ct, GFP_ATOMIC);
+       nf_ct_ecache_ext_add(ct, GFP_ATOMIC);
 
 #if defined(CONFIG_NF_CONNTRACK_MARK)
        if (cda[CTA_MARK])
@@ -1294,7 +1311,8 @@ err1:
 
 static int
 ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
-                       struct nlmsghdr *nlh, struct nlattr *cda[])
+                       const struct nlmsghdr *nlh,
+                       const struct nlattr * const cda[])
 {
        struct nf_conntrack_tuple otuple, rtuple;
        struct nf_conntrack_tuple_hash *h = NULL;
@@ -1340,13 +1358,13 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
                        else
                                events = IPCT_NEW;
 
-                       nf_conntrack_event_report(IPCT_STATUS |
-                                                 IPCT_HELPER |
-                                                 IPCT_PROTOINFO |
-                                                 IPCT_NATSEQADJ |
-                                                 IPCT_MARK | events,
-                                                 ct, NETLINK_CB(skb).pid,
-                                                 nlmsg_report(nlh));
+                       nf_conntrack_eventmask_report((1 << IPCT_STATUS) |
+                                                     (1 << IPCT_HELPER) |
+                                                     (1 << IPCT_PROTOINFO) |
+                                                     (1 << IPCT_NATSEQADJ) |
+                                                     (1 << IPCT_MARK) | events,
+                                                     ct, NETLINK_CB(skb).pid,
+                                                     nlmsg_report(nlh));
                        nf_ct_put(ct);
                } else
                        spin_unlock_bh(&nf_conntrack_lock);
@@ -1365,13 +1383,13 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
                if (err == 0) {
                        nf_conntrack_get(&ct->ct_general);
                        spin_unlock_bh(&nf_conntrack_lock);
-                       nf_conntrack_event_report(IPCT_STATUS |
-                                                 IPCT_HELPER |
-                                                 IPCT_PROTOINFO |
-                                                 IPCT_NATSEQADJ |
-                                                 IPCT_MARK,
-                                                 ct, NETLINK_CB(skb).pid,
-                                                 nlmsg_report(nlh));
+                       nf_conntrack_eventmask_report((1 << IPCT_STATUS) |
+                                                     (1 << IPCT_HELPER) |
+                                                     (1 << IPCT_PROTOINFO) |
+                                                     (1 << IPCT_NATSEQADJ) |
+                                                     (1 << IPCT_MARK),
+                                                     ct, NETLINK_CB(skb).pid,
+                                                     nlmsg_report(nlh));
                        nf_ct_put(ct);
                } else
                        spin_unlock_bh(&nf_conntrack_lock);
@@ -1515,14 +1533,14 @@ ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item)
        unsigned int type;
        int flags = 0;
 
-       if (events & IPEXP_NEW) {
+       if (events & (1 << IPEXP_NEW)) {
                type = IPCTNL_MSG_EXP_NEW;
                flags = NLM_F_CREATE|NLM_F_EXCL;
        } else
                return 0;
 
        if (!item->report &&
-           !nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW))
+           !nfnetlink_has_listeners(&init_net, NFNLGRP_CONNTRACK_EXP_NEW))
                return 0;
 
        skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
@@ -1545,7 +1563,7 @@ ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item)
        rcu_read_unlock();
 
        nlmsg_end(skb, nlh);
-       nfnetlink_send(skb, item->pid, NFNLGRP_CONNTRACK_EXP_NEW,
+       nfnetlink_send(skb, &init_net, item->pid, NFNLGRP_CONNTRACK_EXP_NEW,
                       item->report, GFP_ATOMIC);
        return 0;
 
@@ -1555,7 +1573,7 @@ nla_put_failure:
 nlmsg_failure:
        kfree_skb(skb);
 errout:
-       nfnetlink_set_err(0, 0, -ENOBUFS);
+       nfnetlink_set_err(&init_net, 0, 0, -ENOBUFS);
        return 0;
 }
 #endif
@@ -1619,7 +1637,8 @@ static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
 
 static int
 ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
-                    struct nlmsghdr *nlh, struct nlattr *cda[])
+                    const struct nlmsghdr *nlh,
+                    const struct nlattr * const cda[])
 {
        struct nf_conntrack_tuple tuple;
        struct nf_conntrack_expect *exp;
@@ -1679,7 +1698,8 @@ out:
 
 static int
 ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
-                    struct nlmsghdr *nlh, struct nlattr *cda[])
+                    const struct nlmsghdr *nlh,
+                    const struct nlattr * const cda[])
 {
        struct nf_conntrack_expect *exp;
        struct nf_conntrack_tuple tuple;
@@ -1757,13 +1777,15 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
        return 0;
 }
 static int
-ctnetlink_change_expect(struct nf_conntrack_expect *x, struct nlattr *cda[])
+ctnetlink_change_expect(struct nf_conntrack_expect *x,
+                       const struct nlattr * const cda[])
 {
        return -EOPNOTSUPP;
 }
 
 static int
-ctnetlink_create_expect(struct nlattr *cda[], u_int8_t u3, u32 pid, int report)
+ctnetlink_create_expect(const struct nlattr * const cda[], u_int8_t u3,
+                       u32 pid, int report)
 {
        struct nf_conntrack_tuple tuple, mask, master_tuple;
        struct nf_conntrack_tuple_hash *h = NULL;
@@ -1821,7 +1843,8 @@ out:
 
 static int
 ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
-                    struct nlmsghdr *nlh, struct nlattr *cda[])
+                    const struct nlmsghdr *nlh,
+                    const struct nlattr * const cda[])
 {
        struct nf_conntrack_tuple tuple;
        struct nf_conntrack_expect *exp;