aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2016-03-18 09:33:45 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2016-03-28 11:58:59 -0400
commit99b7248e2ad57ca93ada10c6598affb267ffc99a (patch)
treef10a1fb299924a9cf89f5be57781c734cbe42b52 /net/openvswitch
parent5745b0be05a0f8ccbc92a36b69f3a6bc58e91954 (diff)
openvswitch: call only into reachable nf-nat code
The openvswitch code has gained support for calling into the nf-nat-ipv4/ipv6 modules, however those can be loadable modules in a configuration in which openvswitch is built-in, leading to link errors: net/built-in.o: In function `__ovs_ct_lookup': :(.text+0x2cc2c8): undefined reference to `nf_nat_icmp_reply_translation' :(.text+0x2cc66c): undefined reference to `nf_nat_icmpv6_reply_translation' The dependency on (!NF_NAT || NF_NAT) prevents similar issues, but NF_NAT is set to 'y' if any of the symbols selecting it are built-in, but the link error happens when any of them are modular. A second issue is that even if CONFIG_NF_NAT_IPV6 is built-in, CONFIG_NF_NAT_IPV4 might be completely disabled. This is unlikely to be useful in practice, but the driver currently only handles IPv6 being optional. This patch improves the Kconfig dependency so that openvswitch cannot be built-in if either of the two other symbols are set to 'm', and it replaces the incorrect #ifdef in ovs_ct_nat_execute() with two "if (IS_ENABLED())" checks that should catch all corner cases also make the code more readable. The same #ifdef exists ovs_ct_nat_to_attr(), where it does not cause a link error, but for consistency I'm changing it the same way. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Fixes: 05752523e565 ("openvswitch: Interface with NAT.") Acked-by: Joe Stringer <joe@ovn.org> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/openvswitch')
-rw-r--r--net/openvswitch/Kconfig4
-rw-r--r--net/openvswitch/conntrack.c16
2 files changed, 11 insertions, 9 deletions
diff --git a/net/openvswitch/Kconfig b/net/openvswitch/Kconfig
index 234a73344c6e..ce947292ae77 100644
--- a/net/openvswitch/Kconfig
+++ b/net/openvswitch/Kconfig
@@ -7,7 +7,9 @@ config OPENVSWITCH
7 depends on INET 7 depends on INET
8 depends on !NF_CONNTRACK || \ 8 depends on !NF_CONNTRACK || \
9 (NF_CONNTRACK && ((!NF_DEFRAG_IPV6 || NF_DEFRAG_IPV6) && \ 9 (NF_CONNTRACK && ((!NF_DEFRAG_IPV6 || NF_DEFRAG_IPV6) && \
10 (!NF_NAT || NF_NAT))) 10 (!NF_NAT || NF_NAT) && \
11 (!NF_NAT_IPV4 || NF_NAT_IPV4) && \
12 (!NF_NAT_IPV6 || NF_NAT_IPV6)))
11 select LIBCRC32C 13 select LIBCRC32C
12 select MPLS 14 select MPLS
13 select NET_MPLS_GSO 15 select NET_MPLS_GSO
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
index 47f7c62761d2..3797879b0bf8 100644
--- a/net/openvswitch/conntrack.c
+++ b/net/openvswitch/conntrack.c
@@ -535,14 +535,15 @@ static int ovs_ct_nat_execute(struct sk_buff *skb, struct nf_conn *ct,
535 switch (ctinfo) { 535 switch (ctinfo) {
536 case IP_CT_RELATED: 536 case IP_CT_RELATED:
537 case IP_CT_RELATED_REPLY: 537 case IP_CT_RELATED_REPLY:
538 if (skb->protocol == htons(ETH_P_IP) && 538 if (IS_ENABLED(CONFIG_NF_NAT_IPV4) &&
539 skb->protocol == htons(ETH_P_IP) &&
539 ip_hdr(skb)->protocol == IPPROTO_ICMP) { 540 ip_hdr(skb)->protocol == IPPROTO_ICMP) {
540 if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo, 541 if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo,
541 hooknum)) 542 hooknum))
542 err = NF_DROP; 543 err = NF_DROP;
543 goto push; 544 goto push;
544#if IS_ENABLED(CONFIG_NF_NAT_IPV6) 545 } else if (IS_ENABLED(CONFIG_NF_NAT_IPV6) &&
545 } else if (skb->protocol == htons(ETH_P_IPV6)) { 546 skb->protocol == htons(ETH_P_IPV6)) {
546 __be16 frag_off; 547 __be16 frag_off;
547 u8 nexthdr = ipv6_hdr(skb)->nexthdr; 548 u8 nexthdr = ipv6_hdr(skb)->nexthdr;
548 int hdrlen = ipv6_skip_exthdr(skb, 549 int hdrlen = ipv6_skip_exthdr(skb,
@@ -557,7 +558,6 @@ static int ovs_ct_nat_execute(struct sk_buff *skb, struct nf_conn *ct,
557 err = NF_DROP; 558 err = NF_DROP;
558 goto push; 559 goto push;
559 } 560 }
560#endif
561 } 561 }
562 /* Non-ICMP, fall thru to initialize if needed. */ 562 /* Non-ICMP, fall thru to initialize if needed. */
563 case IP_CT_NEW: 563 case IP_CT_NEW:
@@ -1239,7 +1239,8 @@ static bool ovs_ct_nat_to_attr(const struct ovs_conntrack_info *info,
1239 } 1239 }
1240 1240
1241 if (info->range.flags & NF_NAT_RANGE_MAP_IPS) { 1241 if (info->range.flags & NF_NAT_RANGE_MAP_IPS) {
1242 if (info->family == NFPROTO_IPV4) { 1242 if (IS_ENABLED(CONFIG_NF_NAT_IPV4) &&
1243 info->family == NFPROTO_IPV4) {
1243 if (nla_put_in_addr(skb, OVS_NAT_ATTR_IP_MIN, 1244 if (nla_put_in_addr(skb, OVS_NAT_ATTR_IP_MIN,
1244 info->range.min_addr.ip) || 1245 info->range.min_addr.ip) ||
1245 (info->range.max_addr.ip 1246 (info->range.max_addr.ip
@@ -1247,8 +1248,8 @@ static bool ovs_ct_nat_to_attr(const struct ovs_conntrack_info *info,
1247 (nla_put_in_addr(skb, OVS_NAT_ATTR_IP_MAX, 1248 (nla_put_in_addr(skb, OVS_NAT_ATTR_IP_MAX,
1248 info->range.max_addr.ip)))) 1249 info->range.max_addr.ip))))
1249 return false; 1250 return false;
1250#if IS_ENABLED(CONFIG_NF_NAT_IPV6) 1251 } else if (IS_ENABLED(CONFIG_NF_NAT_IPV6) &&
1251 } else if (info->family == NFPROTO_IPV6) { 1252 info->family == NFPROTO_IPV6) {
1252 if (nla_put_in6_addr(skb, OVS_NAT_ATTR_IP_MIN, 1253 if (nla_put_in6_addr(skb, OVS_NAT_ATTR_IP_MIN,
1253 &info->range.min_addr.in6) || 1254 &info->range.min_addr.in6) ||
1254 (memcmp(&info->range.max_addr.in6, 1255 (memcmp(&info->range.max_addr.in6,
@@ -1257,7 +1258,6 @@ static bool ovs_ct_nat_to_attr(const struct ovs_conntrack_info *info,
1257 (nla_put_in6_addr(skb, OVS_NAT_ATTR_IP_MAX, 1258 (nla_put_in6_addr(skb, OVS_NAT_ATTR_IP_MAX,
1258 &info->range.max_addr.in6)))) 1259 &info->range.max_addr.in6))))
1259 return false; 1260 return false;
1260#endif
1261 } else { 1261 } else {
1262 return false; 1262 return false;
1263 } 1263 }