@@ -18,12 +18,21 @@ enum nf_nat_manip_type {
#include <linux/netfilter/nf_conntrack_pptp.h>
#include <net/netfilter/nf_conntrack_extend.h>
+/* Check if packet is a bridged packet when do SNAT */
+#if defined(CONFIG_BRIDGE_NETFILTER)
+#define nf_nat_is_bridged_pkt(SKB) ((SKB)->nf_bridge && \
+ ((SKB)->nf_bridge->physoutdev != NULL))
+#else
+#define nf_nat_is_bridged_pkt(SKB) 0
+#endif
+
/* per conntrack: nat application helper private data */
union nf_conntrack_nat_help {
/* insert nat helper private data here */
#if defined(CONFIG_NF_NAT_PPTP) || defined(CONFIG_NF_NAT_PPTP_MODULE)
struct nf_nat_pptp nat_pptp_info;
#endif
+ bool snat_in_bridge;
};
struct nf_conn;
@@ -14,6 +14,7 @@
#include <linux/ip.h>
#include <linux/icmp.h>
#include <linux/netfilter.h>
+#include <linux/netfilter_bridge.h>
#include <linux/netfilter_ipv4.h>
#include <net/secure_seq.h>
#include <net/checksum.h>
@@ -277,6 +278,12 @@ nf_nat_ipv4_fn(void *priv, struct sk_buff *skb,
if (nat == NULL)
return NF_ACCEPT;
+ if ((maniptype == NF_NAT_MANIP_SRC) &&
+ nf_nat_initialized(ct, maniptype) &&
+ (nat->help.snat_in_bridge != nf_nat_is_bridged_pkt(skb))) {
+ return NF_ACCEPT;
+ }
+
switch (ctinfo) {
case IP_CT_RELATED:
case IP_CT_RELATED_REPLY:
@@ -299,8 +306,14 @@ nf_nat_ipv4_fn(void *priv, struct sk_buff *skb,
if (ret != NF_ACCEPT)
return ret;
- if (nf_nat_initialized(ct, HOOK2MANIP(state->hook)))
+ if (nf_nat_initialized(ct, HOOK2MANIP(state->hook))) {
+ if (maniptype == NF_NAT_MANIP_SRC) {
+ nfct_nat(ct)->help.snat_in_bridge =
+ nf_nat_is_bridged_pkt(skb);
+ }
+
break;
+ }
ret = nf_nat_alloc_null_binding(ct, state->hook);
if (ret != NF_ACCEPT)
@@ -12,6 +12,7 @@
#include <linux/skbuff.h>
#include <linux/ipv6.h>
#include <linux/netfilter.h>
+#include <linux/netfilter_bridge.h>
#include <linux/netfilter_ipv6.h>
#include <net/secure_seq.h>
#include <net/checksum.h>
@@ -281,6 +282,12 @@ nf_nat_ipv6_fn(void *priv, struct sk_buff *skb,
if (nat == NULL)
return NF_ACCEPT;
+ if ((maniptype == NF_NAT_MANIP_SRC) &&
+ nf_nat_initialized(ct, maniptype) &&
+ (nat->help.snat_in_bridge != nf_nat_is_bridged_pkt(skb))) {
+ return NF_ACCEPT;
+ }
+
switch (ctinfo) {
case IP_CT_RELATED:
case IP_CT_RELATED_REPLY:
@@ -308,8 +315,14 @@ nf_nat_ipv6_fn(void *priv, struct sk_buff *skb,
if (ret != NF_ACCEPT)
return ret;
- if (nf_nat_initialized(ct, HOOK2MANIP(state->hook)))
+ if (nf_nat_initialized(ct, HOOK2MANIP(state->hook))) {
+ if (maniptype == NF_NAT_MANIP_SRC) {
+ nfct_nat(ct)->help.snat_in_bridge =
+ nf_nat_is_bridged_pkt(skb);
+ }
+
break;
+ }
ret = nf_nat_alloc_null_binding(ct, state->hook);
if (ret != NF_ACCEPT)