]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorDavid S. Miller <davem@davemloft.net>
Wed, 15 Oct 2008 06:19:16 +0000 (23:19 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 15 Oct 2008 06:19:16 +0000 (23:19 -0700)
Documentation/networking/phonet.txt
include/linux/netfilter/nfnetlink.h
include/net/netfilter/nf_nat_core.h
net/bridge/netfilter/Kconfig
net/core/net_namespace.c
net/ipv4/netfilter/nf_defrag_ipv4.c
net/ipv4/netfilter/nf_nat_core.c
net/ipv6/netfilter.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nfnetlink.c

index 0e6e592f4f55b876c06b48ceae531b3cfdd6b421..6a07e45d4a9307aa208b88ae84cd97ab490fd0ac 100644 (file)
@@ -146,8 +146,8 @@ WARNING:
 When polling a connected pipe socket for writability, there is an
 intrinsic race condition whereby writability might be lost between the
 polling and the writing system calls. In this case, the socket will
-block until write because possible again, unless non-blocking mode
-becomes enabled.
+block until write becomes possible again, unless non-blocking mode
+is enabled.
 
 
 The pipe protocol provides two socket options at the SOL_PNPIPE level:
index 0d8424f76899f11d5c96dce8d525c1f54fbe4b1a..7d8e0455ccacb101e79cb9e6a940ccf7f5c41615 100644 (file)
@@ -78,6 +78,9 @@ extern int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group,
                          int echo);
 extern int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags);
 
+extern void nfnl_lock(void);
+extern void nfnl_unlock(void);
+
 #define MODULE_ALIAS_NFNL_SUBSYS(subsys) \
        MODULE_ALIAS("nfnetlink-subsys-" __stringify(subsys))
 
index f29eeb9777e0d8282c174c1f00c9a4e9423ce55e..58684066388c45750e1f5a21199ccc8a2557670b 100644 (file)
@@ -25,4 +25,12 @@ static inline int nf_nat_initialized(struct nf_conn *ct,
        else
                return test_bit(IPS_DST_NAT_DONE_BIT, &ct->status);
 }
+
+struct nlattr;
+
+extern int
+(*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct,
+                                 enum nf_nat_manip_type manip,
+                                 struct nlattr *attr);
+
 #endif /* _NF_NAT_CORE_H */
index 366d3e9d51f8ed49dbac3708c90c2de28d5c9f3a..ba6f73eb06c60c1a7f44e90eacfe5c130819ddd8 100644 (file)
@@ -4,6 +4,7 @@
 
 menuconfig BRIDGE_NF_EBTABLES
        tristate "Ethernet Bridge tables (ebtables) support"
+       depends on BRIDGE && BRIDGE_NETFILTER
        select NETFILTER_XTABLES
        help
          ebtables is a general, extensible frame/packet identification
index b0dc818a91d7fadafb9ea7308fa66f1140ca45a4..f1d07b5c1e17257c21f6669588946a0df08b77a4 100644 (file)
@@ -96,7 +96,7 @@ static void net_free(struct net *net)
                return;
        }
 #endif
-
+       kfree(net->gen);
        kmem_cache_free(net_cachep, net);
 }
 
index aa2c50a180f7ea0d194992321dd60797e7859812..fa2d6b6fc3e581524181d88a1402df6289eb42c8 100644 (file)
@@ -41,12 +41,13 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
                                          int (*okfn)(struct sk_buff *))
 {
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#if !defined(CONFIG_NF_NAT) && !defined(CONFIG_NF_NAT_MODULE)
        /* Previously seen (loopback)?  Ignore.  Do this before
           fragment check. */
        if (skb->nfct)
                return NF_ACCEPT;
 #endif
-
+#endif
        /* Gather fragments. */
        if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
                if (nf_ct_ipv4_gather_frags(skb,
index 2ac9eaf1a8c92bfbcf546ae26c81a09aeb899551..a65cf692359fbc803032a2d9a18dead804747bc0 100644 (file)
@@ -584,6 +584,98 @@ static struct nf_ct_ext_type nat_extend __read_mostly = {
        .flags          = NF_CT_EXT_F_PREALLOC,
 };
 
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
+
+static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = {
+       [CTA_PROTONAT_PORT_MIN] = { .type = NLA_U16 },
+       [CTA_PROTONAT_PORT_MAX] = { .type = NLA_U16 },
+};
+
+static int nfnetlink_parse_nat_proto(struct nlattr *attr,
+                                    const struct nf_conn *ct,
+                                    struct nf_nat_range *range)
+{
+       struct nlattr *tb[CTA_PROTONAT_MAX+1];
+       const struct nf_nat_protocol *npt;
+       int err;
+
+       err = nla_parse_nested(tb, CTA_PROTONAT_MAX, attr, protonat_nla_policy);
+       if (err < 0)
+               return err;
+
+       npt = nf_nat_proto_find_get(nf_ct_protonum(ct));
+       if (npt->nlattr_to_range)
+               err = npt->nlattr_to_range(tb, range);
+       nf_nat_proto_put(npt);
+       return err;
+}
+
+static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = {
+       [CTA_NAT_MINIP]         = { .type = NLA_U32 },
+       [CTA_NAT_MAXIP]         = { .type = NLA_U32 },
+};
+
+static int
+nfnetlink_parse_nat(struct nlattr *nat,
+                   const struct nf_conn *ct, struct nf_nat_range *range)
+{
+       struct nlattr *tb[CTA_NAT_MAX+1];
+       int err;
+
+       memset(range, 0, sizeof(*range));
+
+       err = nla_parse_nested(tb, CTA_NAT_MAX, nat, nat_nla_policy);
+       if (err < 0)
+               return err;
+
+       if (tb[CTA_NAT_MINIP])
+               range->min_ip = nla_get_be32(tb[CTA_NAT_MINIP]);
+
+       if (!tb[CTA_NAT_MAXIP])
+               range->max_ip = range->min_ip;
+       else
+               range->max_ip = nla_get_be32(tb[CTA_NAT_MAXIP]);
+
+       if (range->min_ip)
+               range->flags |= IP_NAT_RANGE_MAP_IPS;
+
+       if (!tb[CTA_NAT_PROTO])
+               return 0;
+
+       err = nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO], ct, range);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int
+nfnetlink_parse_nat_setup(struct nf_conn *ct,
+                         enum nf_nat_manip_type manip,
+                         struct nlattr *attr)
+{
+       struct nf_nat_range range;
+
+       if (nfnetlink_parse_nat(attr, ct, &range) < 0)
+               return -EINVAL;
+       if (nf_nat_initialized(ct, manip))
+               return -EEXIST;
+
+       return nf_nat_setup_info(ct, &range, manip);
+}
+#else
+static int
+nfnetlink_parse_nat_setup(struct nf_conn *ct,
+                         enum nf_nat_manip_type manip,
+                         struct nlattr *attr)
+{
+       return -EOPNOTSUPP;
+}
+#endif
+
 static int __net_init nf_nat_net_init(struct net *net)
 {
        net->ipv4.nat_bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size,
@@ -654,6 +746,9 @@ static int __init nf_nat_init(void)
 
        BUG_ON(nf_nat_seq_adjust_hook != NULL);
        rcu_assign_pointer(nf_nat_seq_adjust_hook, nf_nat_seq_adjust);
+       BUG_ON(nfnetlink_parse_nat_setup_hook != NULL);
+       rcu_assign_pointer(nfnetlink_parse_nat_setup_hook,
+                          nfnetlink_parse_nat_setup);
        return 0;
 
  cleanup_extend:
@@ -667,10 +762,12 @@ static void __exit nf_nat_cleanup(void)
        nf_ct_l3proto_put(l3proto);
        nf_ct_extend_unregister(&nat_extend);
        rcu_assign_pointer(nf_nat_seq_adjust_hook, NULL);
+       rcu_assign_pointer(nfnetlink_parse_nat_setup_hook, NULL);
        synchronize_net();
 }
 
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("nf-nat-ipv4");
 
 module_init(nf_nat_init);
 module_exit(nf_nat_cleanup);
index 6b29b03925f1f08ec7013a969c64511a8c228f13..fd5b3a4e332988056119748ae1c636dff72b53b9 100644 (file)
@@ -12,6 +12,7 @@
 
 int ip6_route_me_harder(struct sk_buff *skb)
 {
+       struct net *net = dev_net(skb->dst->dev);
        struct ipv6hdr *iph = ipv6_hdr(skb);
        struct dst_entry *dst;
        struct flowi fl = {
@@ -23,7 +24,7 @@ int ip6_route_me_harder(struct sk_buff *skb)
                    .saddr = iph->saddr, } },
        };
 
-       dst = ip6_route_output(dev_net(skb->dst->dev), skb->sk, &fl);
+       dst = ip6_route_output(net, skb->sk, &fl);
 
 #ifdef CONFIG_XFRM
        if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
@@ -33,8 +34,7 @@ int ip6_route_me_harder(struct sk_buff *skb)
 #endif
 
        if (dst->error) {
-               IP6_INC_STATS(&init_net, ip6_dst_idev(dst),
-                             IPSTATS_MIB_OUTNOROUTES);
+               IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
                LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n");
                dst_release(dst);
                return -EINVAL;
index 27de3c7b006e6fe5bc72e775b62b6a78db886bc3..622d7c671cb78533082f9bf0b655a3bbffcd2f92 100644 (file)
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_conntrack_extend.h>
 #include <net/netfilter/nf_conntrack_acct.h>
+#include <net/netfilter/nf_nat.h>
 
 #define NF_CONNTRACK_VERSION   "0.5.0"
 
+unsigned int
+(*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct,
+                                 enum nf_nat_manip_type manip,
+                                 struct nlattr *attr) __read_mostly;
+EXPORT_SYMBOL_GPL(nfnetlink_parse_nat_setup_hook);
+
 DEFINE_SPINLOCK(nf_conntrack_lock);
 EXPORT_SYMBOL_GPL(nf_conntrack_lock);
 
index cadfd15b44f61457b54ea0291cd7c44e0b405df3..08e82d64eb6f4db6aad440c14f39ad7efd09f29a 100644 (file)
@@ -689,71 +689,6 @@ ctnetlink_parse_tuple(struct nlattr *cda[], struct nf_conntrack_tuple *tuple,
        return 0;
 }
 
-#ifdef CONFIG_NF_NAT_NEEDED
-static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = {
-       [CTA_PROTONAT_PORT_MIN] = { .type = NLA_U16 },
-       [CTA_PROTONAT_PORT_MAX] = { .type = NLA_U16 },
-};
-
-static int nfnetlink_parse_nat_proto(struct nlattr *attr,
-                                    const struct nf_conn *ct,
-                                    struct nf_nat_range *range)
-{
-       struct nlattr *tb[CTA_PROTONAT_MAX+1];
-       const struct nf_nat_protocol *npt;
-       int err;
-
-       err = nla_parse_nested(tb, CTA_PROTONAT_MAX, attr, protonat_nla_policy);
-       if (err < 0)
-               return err;
-
-       npt = nf_nat_proto_find_get(nf_ct_protonum(ct));
-       if (npt->nlattr_to_range)
-               err = npt->nlattr_to_range(tb, range);
-       nf_nat_proto_put(npt);
-       return err;
-}
-
-static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = {
-       [CTA_NAT_MINIP]         = { .type = NLA_U32 },
-       [CTA_NAT_MAXIP]         = { .type = NLA_U32 },
-};
-
-static inline int
-nfnetlink_parse_nat(struct nlattr *nat,
-                   const struct nf_conn *ct, struct nf_nat_range *range)
-{
-       struct nlattr *tb[CTA_NAT_MAX+1];
-       int err;
-
-       memset(range, 0, sizeof(*range));
-
-       err = nla_parse_nested(tb, CTA_NAT_MAX, nat, nat_nla_policy);
-       if (err < 0)
-               return err;
-
-       if (tb[CTA_NAT_MINIP])
-               range->min_ip = nla_get_be32(tb[CTA_NAT_MINIP]);
-
-       if (!tb[CTA_NAT_MAXIP])
-               range->max_ip = range->min_ip;
-       else
-               range->max_ip = nla_get_be32(tb[CTA_NAT_MAXIP]);
-
-       if (range->min_ip)
-               range->flags |= IP_NAT_RANGE_MAP_IPS;
-
-       if (!tb[CTA_NAT_PROTO])
-               return 0;
-
-       err = nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO], ct, range);
-       if (err < 0)
-               return err;
-
-       return 0;
-}
-#endif
-
 static inline int
 ctnetlink_parse_help(struct nlattr *attr, char **helper_name)
 {
@@ -878,6 +813,34 @@ out:
        return err;
 }
 
+static int
+ctnetlink_parse_nat_setup(struct nf_conn *ct,
+                         enum nf_nat_manip_type manip,
+                         struct nlattr *attr)
+{
+       typeof(nfnetlink_parse_nat_setup_hook) parse_nat_setup;
+
+       parse_nat_setup = rcu_dereference(nfnetlink_parse_nat_setup_hook);
+       if (!parse_nat_setup) {
+#ifdef CONFIG_KMOD
+               rcu_read_unlock();
+               nfnl_unlock();
+               if (request_module("nf-nat-ipv4") < 0) {
+                       nfnl_lock();
+                       rcu_read_lock();
+                       return -EOPNOTSUPP;
+               }
+               nfnl_lock();
+               rcu_read_lock();
+               if (nfnetlink_parse_nat_setup_hook)
+                       return -EAGAIN;
+#endif
+               return -EOPNOTSUPP;
+       }
+
+       return parse_nat_setup(ct, manip, attr);
+}
+
 static int
 ctnetlink_change_status(struct nf_conn *ct, struct nlattr *cda[])
 {
@@ -897,31 +860,6 @@ ctnetlink_change_status(struct nf_conn *ct, struct nlattr *cda[])
                /* ASSURED bit can only be set */
                return -EBUSY;
 
-       if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) {
-#ifndef CONFIG_NF_NAT_NEEDED
-               return -EOPNOTSUPP;
-#else
-               struct nf_nat_range range;
-
-               if (cda[CTA_NAT_DST]) {
-                       if (nfnetlink_parse_nat(cda[CTA_NAT_DST], ct,
-                                               &range) < 0)
-                               return -EINVAL;
-                       if (nf_nat_initialized(ct, IP_NAT_MANIP_DST))
-                               return -EEXIST;
-                       nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST);
-               }
-               if (cda[CTA_NAT_SRC]) {
-                       if (nfnetlink_parse_nat(cda[CTA_NAT_SRC], ct,
-                                               &range) < 0)
-                               return -EINVAL;
-                       if (nf_nat_initialized(ct, IP_NAT_MANIP_SRC))
-                               return -EEXIST;
-                       nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC);
-               }
-#endif
-       }
-
        /* Be careful here, modifying NAT bits can screw up things,
         * so don't let users modify them directly if they don't pass
         * nf_nat_range. */
@@ -929,6 +867,31 @@ ctnetlink_change_status(struct nf_conn *ct, struct nlattr *cda[])
        return 0;
 }
 
+static int
+ctnetlink_change_nat(struct nf_conn *ct, struct nlattr *cda[])
+{
+#ifdef CONFIG_NF_NAT_NEEDED
+       int ret;
+
+       if (cda[CTA_NAT_DST]) {
+               ret = ctnetlink_parse_nat_setup(ct,
+                                               IP_NAT_MANIP_DST,
+                                               cda[CTA_NAT_DST]);
+               if (ret < 0)
+                       return ret;
+       }
+       if (cda[CTA_NAT_SRC]) {
+               ret = ctnetlink_parse_nat_setup(ct,
+                                               IP_NAT_MANIP_SRC,
+                                               cda[CTA_NAT_SRC]);
+               if (ret < 0)
+                       return ret;
+       }
+       return 0;
+#else
+       return -EOPNOTSUPP;
+#endif
+}
 
 static inline int
 ctnetlink_change_helper(struct nf_conn *ct, struct nlattr *cda[])
@@ -1157,6 +1120,14 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
                }
        }
 
+       if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) {
+               err = ctnetlink_change_nat(ct, cda);
+               if (err < 0) {
+                       rcu_read_unlock();
+                       goto err;
+               }
+       }
+
        if (cda[CTA_PROTOINFO]) {
                err = ctnetlink_change_protoinfo(ct, cda);
                if (err < 0) {
index b75c9c4a995d885c1ac12339b0afff9d1d24db31..4739f9f961d8ea7e306021251b1676248318f72a 100644 (file)
@@ -44,15 +44,17 @@ static struct sock *nfnl = NULL;
 static const struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT];
 static DEFINE_MUTEX(nfnl_mutex);
 
-static inline void nfnl_lock(void)
+void nfnl_lock(void)
 {
        mutex_lock(&nfnl_mutex);
 }
+EXPORT_SYMBOL_GPL(nfnl_lock);
 
-static inline void nfnl_unlock(void)
+void nfnl_unlock(void)
 {
        mutex_unlock(&nfnl_mutex);
 }
+EXPORT_SYMBOL_GPL(nfnl_unlock);
 
 int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n)
 {
@@ -132,6 +134,7 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                return 0;
 
        type = nlh->nlmsg_type;
+replay:
        ss = nfnetlink_get_subsys(type);
        if (!ss) {
 #ifdef CONFIG_KMOD
@@ -165,7 +168,10 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                } else
                        return -EINVAL;
 
-               return nc->call(nfnl, skb, nlh, cda);
+               err = nc->call(nfnl, skb, nlh, cda);
+               if (err == -EAGAIN)
+                       goto replay;
+               return err;
        }
 }