]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
netfilter: nat: move nlattr parse and xfrm session decode to core
authorFlorian Westphal <fw@strlen.de>
Tue, 19 Feb 2019 16:38:20 +0000 (17:38 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 27 Feb 2019 09:49:42 +0000 (10:49 +0100)
None of these functions calls any external functions, moving them allows
to avoid both the indirection and a need to export these symbols.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/net/netfilter/nf_nat_l3proto.h
net/ipv4/netfilter/nf_nat_l3proto_ipv4.c
net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
net/netfilter/nf_nat_core.c

index d774ca0c4c5ef02012f547a6419f18fdb23cdc78..100972bbd9adfd924399fcc06cdbfafa2cbd49d8 100644 (file)
@@ -18,15 +18,6 @@ struct nf_nat_l3proto {
        void    (*csum_recalc)(struct sk_buff *skb, u8 proto,
                               void *data, __sum16 *check,
                               int datalen, int oldlen);
-
-       void    (*decode_session)(struct sk_buff *skb,
-                                 const struct nf_conn *ct,
-                                 enum ip_conntrack_dir dir,
-                                 unsigned long statusbit,
-                                 struct flowi *fl);
-
-       int     (*nlattr_to_range)(struct nlattr *tb[],
-                                  struct nf_nat_range2 *range);
 };
 
 int nf_nat_l3proto_register(const struct nf_nat_l3proto *);
index 4b07eb8a9b185160ec58c8b377d7c4d52264cb05..36b4f9659ffaadc17251f98d6a0a9c36ef45b92c 100644 (file)
 
 static const struct nf_nat_l3proto nf_nat_l3proto_ipv4;
 
-#ifdef CONFIG_XFRM
-static void nf_nat_ipv4_decode_session(struct sk_buff *skb,
-                                      const struct nf_conn *ct,
-                                      enum ip_conntrack_dir dir,
-                                      unsigned long statusbit,
-                                      struct flowi *fl)
-{
-       const struct nf_conntrack_tuple *t = &ct->tuplehash[dir].tuple;
-       struct flowi4 *fl4 = &fl->u.ip4;
-
-       if (ct->status & statusbit) {
-               fl4->daddr = t->dst.u3.ip;
-               if (t->dst.protonum == IPPROTO_TCP ||
-                   t->dst.protonum == IPPROTO_UDP ||
-                   t->dst.protonum == IPPROTO_UDPLITE ||
-                   t->dst.protonum == IPPROTO_DCCP ||
-                   t->dst.protonum == IPPROTO_SCTP)
-                       fl4->fl4_dport = t->dst.u.all;
-       }
-
-       statusbit ^= IPS_NAT_MASK;
-
-       if (ct->status & statusbit) {
-               fl4->saddr = t->src.u3.ip;
-               if (t->dst.protonum == IPPROTO_TCP ||
-                   t->dst.protonum == IPPROTO_UDP ||
-                   t->dst.protonum == IPPROTO_UDPLITE ||
-                   t->dst.protonum == IPPROTO_DCCP ||
-                   t->dst.protonum == IPPROTO_SCTP)
-                       fl4->fl4_sport = t->src.u.all;
-       }
-}
-#endif /* CONFIG_XFRM */
-
 static bool nf_nat_ipv4_manip_pkt(struct sk_buff *skb,
                                  unsigned int iphdroff,
                                  const struct nf_conntrack_tuple *target,
@@ -127,35 +93,11 @@ static void nf_nat_ipv4_csum_recalc(struct sk_buff *skb,
                                         htons(oldlen), htons(datalen), true);
 }
 
-#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
-static int nf_nat_ipv4_nlattr_to_range(struct nlattr *tb[],
-                                      struct nf_nat_range2 *range)
-{
-       if (tb[CTA_NAT_V4_MINIP]) {
-               range->min_addr.ip = nla_get_be32(tb[CTA_NAT_V4_MINIP]);
-               range->flags |= NF_NAT_RANGE_MAP_IPS;
-       }
-
-       if (tb[CTA_NAT_V4_MAXIP])
-               range->max_addr.ip = nla_get_be32(tb[CTA_NAT_V4_MAXIP]);
-       else
-               range->max_addr.ip = range->min_addr.ip;
-
-       return 0;
-}
-#endif
-
 static const struct nf_nat_l3proto nf_nat_l3proto_ipv4 = {
        .l3proto                = NFPROTO_IPV4,
        .manip_pkt              = nf_nat_ipv4_manip_pkt,
        .csum_update            = nf_nat_ipv4_csum_update,
        .csum_recalc            = nf_nat_ipv4_csum_recalc,
-#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
-       .nlattr_to_range        = nf_nat_ipv4_nlattr_to_range,
-#endif
-#ifdef CONFIG_XFRM
-       .decode_session         = nf_nat_ipv4_decode_session,
-#endif
 };
 
 int nf_nat_icmp_reply_translation(struct sk_buff *skb,
index 490bfd3c916296aeac4c5948ff76938127e5595b..5d667cf9bab867848da3a33e5d215277715eca40 100644 (file)
 
 static const struct nf_nat_l3proto nf_nat_l3proto_ipv6;
 
-#ifdef CONFIG_XFRM
-static void nf_nat_ipv6_decode_session(struct sk_buff *skb,
-                                      const struct nf_conn *ct,
-                                      enum ip_conntrack_dir dir,
-                                      unsigned long statusbit,
-                                      struct flowi *fl)
-{
-       const struct nf_conntrack_tuple *t = &ct->tuplehash[dir].tuple;
-       struct flowi6 *fl6 = &fl->u.ip6;
-
-       if (ct->status & statusbit) {
-               fl6->daddr = t->dst.u3.in6;
-               if (t->dst.protonum == IPPROTO_TCP ||
-                   t->dst.protonum == IPPROTO_UDP ||
-                   t->dst.protonum == IPPROTO_UDPLITE ||
-                   t->dst.protonum == IPPROTO_DCCP ||
-                   t->dst.protonum == IPPROTO_SCTP)
-                       fl6->fl6_dport = t->dst.u.all;
-       }
-
-       statusbit ^= IPS_NAT_MASK;
-
-       if (ct->status & statusbit) {
-               fl6->saddr = t->src.u3.in6;
-               if (t->dst.protonum == IPPROTO_TCP ||
-                   t->dst.protonum == IPPROTO_UDP ||
-                   t->dst.protonum == IPPROTO_UDPLITE ||
-                   t->dst.protonum == IPPROTO_DCCP ||
-                   t->dst.protonum == IPPROTO_SCTP)
-                       fl6->fl6_sport = t->src.u.all;
-       }
-}
-#endif
-
 static bool nf_nat_ipv6_manip_pkt(struct sk_buff *skb,
                                  unsigned int iphdroff,
                                  const struct nf_conntrack_tuple *target,
@@ -136,37 +102,11 @@ static void nf_nat_ipv6_csum_recalc(struct sk_buff *skb,
                                         htons(oldlen), htons(datalen), true);
 }
 
-#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
-static int nf_nat_ipv6_nlattr_to_range(struct nlattr *tb[],
-                                      struct nf_nat_range2 *range)
-{
-       if (tb[CTA_NAT_V6_MINIP]) {
-               nla_memcpy(&range->min_addr.ip6, tb[CTA_NAT_V6_MINIP],
-                          sizeof(struct in6_addr));
-               range->flags |= NF_NAT_RANGE_MAP_IPS;
-       }
-
-       if (tb[CTA_NAT_V6_MAXIP])
-               nla_memcpy(&range->max_addr.ip6, tb[CTA_NAT_V6_MAXIP],
-                          sizeof(struct in6_addr));
-       else
-               range->max_addr = range->min_addr;
-
-       return 0;
-}
-#endif
-
 static const struct nf_nat_l3proto nf_nat_l3proto_ipv6 = {
        .l3proto                = NFPROTO_IPV6,
        .manip_pkt              = nf_nat_ipv6_manip_pkt,
        .csum_update            = nf_nat_ipv6_csum_update,
        .csum_recalc            = nf_nat_ipv6_csum_recalc,
-#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
-       .nlattr_to_range        = nf_nat_ipv6_nlattr_to_range,
-#endif
-#ifdef CONFIG_XFRM
-       .decode_session = nf_nat_ipv6_decode_session,
-#endif
 };
 
 int nf_nat_icmpv6_reply_translation(struct sk_buff *skb,
index 35e61038ae96f6f5868f310dd865d71eb24e7998..0f39ae7a9f34ed3334a2a3598a189c33ddf358e2 100644 (file)
@@ -65,9 +65,74 @@ __nf_nat_l3proto_find(u8 family)
 }
 
 #ifdef CONFIG_XFRM
+static void nf_nat_ipv4_decode_session(struct sk_buff *skb,
+                                      const struct nf_conn *ct,
+                                      enum ip_conntrack_dir dir,
+                                      unsigned long statusbit,
+                                      struct flowi *fl)
+{
+       const struct nf_conntrack_tuple *t = &ct->tuplehash[dir].tuple;
+       struct flowi4 *fl4 = &fl->u.ip4;
+
+       if (ct->status & statusbit) {
+               fl4->daddr = t->dst.u3.ip;
+               if (t->dst.protonum == IPPROTO_TCP ||
+                   t->dst.protonum == IPPROTO_UDP ||
+                   t->dst.protonum == IPPROTO_UDPLITE ||
+                   t->dst.protonum == IPPROTO_DCCP ||
+                   t->dst.protonum == IPPROTO_SCTP)
+                       fl4->fl4_dport = t->dst.u.all;
+       }
+
+       statusbit ^= IPS_NAT_MASK;
+
+       if (ct->status & statusbit) {
+               fl4->saddr = t->src.u3.ip;
+               if (t->dst.protonum == IPPROTO_TCP ||
+                   t->dst.protonum == IPPROTO_UDP ||
+                   t->dst.protonum == IPPROTO_UDPLITE ||
+                   t->dst.protonum == IPPROTO_DCCP ||
+                   t->dst.protonum == IPPROTO_SCTP)
+                       fl4->fl4_sport = t->src.u.all;
+       }
+}
+
+static void nf_nat_ipv6_decode_session(struct sk_buff *skb,
+                                      const struct nf_conn *ct,
+                                      enum ip_conntrack_dir dir,
+                                      unsigned long statusbit,
+                                      struct flowi *fl)
+{
+#if IS_ENABLED(CONFIG_IPV6)
+       const struct nf_conntrack_tuple *t = &ct->tuplehash[dir].tuple;
+       struct flowi6 *fl6 = &fl->u.ip6;
+
+       if (ct->status & statusbit) {
+               fl6->daddr = t->dst.u3.in6;
+               if (t->dst.protonum == IPPROTO_TCP ||
+                   t->dst.protonum == IPPROTO_UDP ||
+                   t->dst.protonum == IPPROTO_UDPLITE ||
+                   t->dst.protonum == IPPROTO_DCCP ||
+                   t->dst.protonum == IPPROTO_SCTP)
+                       fl6->fl6_dport = t->dst.u.all;
+       }
+
+       statusbit ^= IPS_NAT_MASK;
+
+       if (ct->status & statusbit) {
+               fl6->saddr = t->src.u3.in6;
+               if (t->dst.protonum == IPPROTO_TCP ||
+                   t->dst.protonum == IPPROTO_UDP ||
+                   t->dst.protonum == IPPROTO_UDPLITE ||
+                   t->dst.protonum == IPPROTO_DCCP ||
+                   t->dst.protonum == IPPROTO_SCTP)
+                       fl6->fl6_sport = t->src.u.all;
+       }
+#endif
+}
+
 static void __nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl)
 {
-       const struct nf_nat_l3proto *l3proto;
        const struct nf_conn *ct;
        enum ip_conntrack_info ctinfo;
        enum ip_conntrack_dir dir;
@@ -79,17 +144,20 @@ static void __nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl)
                return;
 
        family = nf_ct_l3num(ct);
-       l3proto = __nf_nat_l3proto_find(family);
-       if (l3proto == NULL)
-               return;
-
        dir = CTINFO2DIR(ctinfo);
        if (dir == IP_CT_DIR_ORIGINAL)
                statusbit = IPS_DST_NAT;
        else
                statusbit = IPS_SRC_NAT;
 
-       l3proto->decode_session(skb, ct, dir, statusbit, fl);
+       switch (family) {
+       case NFPROTO_IPV4:
+               nf_nat_ipv4_decode_session(skb, ct, dir, statusbit, fl);
+               return;
+       case NFPROTO_IPV6:
+               nf_nat_ipv6_decode_session(skb, ct, dir, statusbit, fl);
+               return;
+       }
 }
 
 int nf_xfrm_me_harder(struct net *net, struct sk_buff *skb, unsigned int family)
@@ -887,10 +955,43 @@ static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = {
        [CTA_NAT_PROTO]         = { .type = NLA_NESTED },
 };
 
+static int nf_nat_ipv4_nlattr_to_range(struct nlattr *tb[],
+                                      struct nf_nat_range2 *range)
+{
+       if (tb[CTA_NAT_V4_MINIP]) {
+               range->min_addr.ip = nla_get_be32(tb[CTA_NAT_V4_MINIP]);
+               range->flags |= NF_NAT_RANGE_MAP_IPS;
+       }
+
+       if (tb[CTA_NAT_V4_MAXIP])
+               range->max_addr.ip = nla_get_be32(tb[CTA_NAT_V4_MAXIP]);
+       else
+               range->max_addr.ip = range->min_addr.ip;
+
+       return 0;
+}
+
+static int nf_nat_ipv6_nlattr_to_range(struct nlattr *tb[],
+                                      struct nf_nat_range2 *range)
+{
+       if (tb[CTA_NAT_V6_MINIP]) {
+               nla_memcpy(&range->min_addr.ip6, tb[CTA_NAT_V6_MINIP],
+                          sizeof(struct in6_addr));
+               range->flags |= NF_NAT_RANGE_MAP_IPS;
+       }
+
+       if (tb[CTA_NAT_V6_MAXIP])
+               nla_memcpy(&range->max_addr.ip6, tb[CTA_NAT_V6_MAXIP],
+                          sizeof(struct in6_addr));
+       else
+               range->max_addr = range->min_addr;
+
+       return 0;
+}
+
 static int
 nfnetlink_parse_nat(const struct nlattr *nat,
-                   const struct nf_conn *ct, struct nf_nat_range2 *range,
-                   const struct nf_nat_l3proto *l3proto)
+                   const struct nf_conn *ct, struct nf_nat_range2 *range)
 {
        struct nlattr *tb[CTA_NAT_MAX+1];
        int err;
@@ -901,8 +1002,19 @@ nfnetlink_parse_nat(const struct nlattr *nat,
        if (err < 0)
                return err;
 
-       err = l3proto->nlattr_to_range(tb, range);
-       if (err < 0)
+       switch (nf_ct_l3num(ct)) {
+       case NFPROTO_IPV4:
+               err = nf_nat_ipv4_nlattr_to_range(tb, range);
+               break;
+       case NFPROTO_IPV6:
+               err = nf_nat_ipv6_nlattr_to_range(tb, range);
+               break;
+       default:
+               err = -EPROTONOSUPPORT;
+               break;
+       }
+
+       if (err)
                return err;
 
        if (!tb[CTA_NAT_PROTO])
@@ -918,7 +1030,6 @@ nfnetlink_parse_nat_setup(struct nf_conn *ct,
                          const struct nlattr *attr)
 {
        struct nf_nat_range2 range;
-       const struct nf_nat_l3proto *l3proto;
        int err;
 
        /* Should not happen, restricted to creating new conntracks
@@ -927,18 +1038,11 @@ nfnetlink_parse_nat_setup(struct nf_conn *ct,
        if (WARN_ON_ONCE(nf_nat_initialized(ct, manip)))
                return -EEXIST;
 
-       /* Make sure that L3 NAT is there by when we call nf_nat_setup_info to
-        * attach the null binding, otherwise this may oops.
-        */
-       l3proto = __nf_nat_l3proto_find(nf_ct_l3num(ct));
-       if (l3proto == NULL)
-               return -EAGAIN;
-
        /* No NAT information has been passed, allocate the null-binding */
        if (attr == NULL)
                return __nf_nat_alloc_null_binding(ct, manip) == NF_DROP ? -ENOMEM : 0;
 
-       err = nfnetlink_parse_nat(attr, ct, &range, l3proto);
+       err = nfnetlink_parse_nat(attr, ct, &range);
        if (err < 0)
                return err;