Re: [PATCH][EBTABLES] add --snat-arp option

Bart De Schuymer <[email protected]> Thu, 02 Nov 2006 21:31:20 +0100
Newsgroups gmane.linux.network.bridge.ebtables.user
Message-ID <[email protected]>
Op di, 24-10-2006 te 00:38 +0200, schreef Patrick McHardy:
> > +#define NAT_ARP_BIT  (0x00000010)
> 
> Since this seems to be a generic (non-SNAT related) header file,
> would it make sense to call it SNAT_ARP_BIT or something like
> that? Just in case you want to add DNAT later on.

I gave it this generic name because it can then be reused for dnat
later, without having to alter the header file.

> This is really confusing to follow, is there no cleaner way
> than mixing negative numbers and bitmasks? At least the
> -16 should become a (bitmask) define, and probably the other
> bitmasks as well. Ideally at some point ebtables would use
> the x_tables infrastructure and revision support.

OK, it's now without magic numbers. I've also removed the -16 from the
mark target. See attachment.

cheers,
Bart

Signed-off-by: Bart De Schuymer <[email protected]>

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

_______________________________________________
Ebtables-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ebtables-user
patch_snat2.diff (text/x-patch, 3.7 KB)
--- linux-2.6.16.1/net/bridge/netfilter/ebt_snat.c.old	2006-10-28 16:23:05.000000000 +0200
+++ linux-2.6.16.1/net/bridge/netfilter/ebt_snat.c	2006-10-28 16:45:03.000000000 +0200
@@ -12,6 +12,8 @@
 #include <linux/netfilter_bridge/ebt_nat.h>
 #include <linux/module.h>
 #include <net/sock.h>
+#include <linux/if_arp.h>
+#include <net/arp.h>
 
 static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr,
    const struct net_device *in, const struct net_device *out,
@@ -31,24 +33,43 @@ static int ebt_target_snat(struct sk_buf
 		*pskb = nskb;
 	}
 	memcpy(eth_hdr(*pskb)->h_source, info->mac, ETH_ALEN);
-	return info->target;
+	if (!(info->target & NAT_ARP_BIT) &&
+	    eth_hdr(*pskb)->h_proto == htons(ETH_P_ARP)) {
+		struct arphdr _ah, *ap;
+
+		ap = skb_header_pointer(*pskb, 0, sizeof(_ah), &_ah);
+		if (ap == NULL)
+			return EBT_DROP;
+		if (ap->ar_hln != ETH_ALEN)
+			goto out;
+		if (skb_store_bits(*pskb, sizeof(_ah), info->mac,ETH_ALEN))
+			return EBT_DROP;
+	}
+out:
+	return info->target | ~EBT_VERDICT_BITS;
 }
 
 static int ebt_target_snat_check(const char *tablename, unsigned int hookmask,
    const struct ebt_entry *e, void *data, unsigned int datalen)
 {
 	struct ebt_nat_info *info = (struct ebt_nat_info *) data;
+	int tmp;
 
 	if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info)))
 		return -EINVAL;
-	if (BASE_CHAIN && info->target == EBT_RETURN)
+	tmp = info->target | ~EBT_VERDICT_BITS;
+	if (BASE_CHAIN && tmp == EBT_RETURN)
 		return -EINVAL;
 	CLEAR_BASE_CHAIN_BIT;
 	if (strcmp(tablename, "nat"))
 		return -EINVAL;
 	if (hookmask & ~(1 << NF_BR_POST_ROUTING))
 		return -EINVAL;
-	if (INVALID_TARGET)
+
+	if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
+		return -EINVAL;
+	tmp = info->target | EBT_VERDICT_BITS;
+	if (tmp & ~NAT_ARP_BIT != ~NAT_ARP_BIT)
 		return -EINVAL;
 	return 0;
 }
--- linux-2.6.16.1/net/bridge/netfilter/ebt_mark.c.old	2006-10-28 16:28:35.000000000 +0200
+++ linux-2.6.16.1/net/bridge/netfilter/ebt_mark.c	2006-10-28 16:41:36.000000000 +0200
@@ -33,7 +33,7 @@ static int ebt_target_mark(struct sk_buf
 	else
 		(*pskb)->nfmark ^= info->mark;
 
-	return info->target | -16;
+	return info->target | ~EBT_VERDICT_BITS;
 }
 
 static int ebt_target_mark_check(const char *tablename, unsigned int hookmask,
@@ -44,13 +44,13 @@ static int ebt_target_mark_check(const c
 
 	if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_t_info)))
 		return -EINVAL;
-	tmp = info->target | -16;
+	tmp = info->target | ~EBT_VERDICT_BITS;
 	if (BASE_CHAIN && tmp == EBT_RETURN)
 		return -EINVAL;
 	CLEAR_BASE_CHAIN_BIT;
 	if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
 		return -EINVAL;
-	tmp = info->target & -16;
+	tmp = info->target & ~EBT_VERDICT_BITS;
 	if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE &&
 	    tmp != MARK_AND_VALUE && tmp != MARK_XOR_VALUE)
 		return -EINVAL;
--- linux-2.6.16.1/include/linux/netfilter_bridge/ebt_nat.h.old	2006-10-28 16:22:56.000000000 +0200
+++ linux-2.6.16.1/include/linux/netfilter_bridge/ebt_nat.h	2006-10-28 16:23:20.000000000 +0200
@@ -1,6 +1,7 @@
 #ifndef __LINUX_BRIDGE_EBT_NAT_H
 #define __LINUX_BRIDGE_EBT_NAT_H
 
+#define NAT_ARP_BIT  (0x00000010)
 struct ebt_nat_info
 {
 	unsigned char mac[ETH_ALEN];
--- linux-2.6.16.1/include/linux/netfilter_bridge/ebtables.h.old	2006-10-28 16:23:35.000000000 +0200
+++ linux-2.6.16.1/include/linux/netfilter_bridge/ebtables.h	2006-10-28 16:39:34.000000000 +0200
@@ -26,6 +26,10 @@
 #define EBT_CONTINUE -3
 #define EBT_RETURN   -4
 #define NUM_STANDARD_TARGETS   4
+/* ebtables target modules store the verdict inside an int. We can
+ * reclaim a part of this int for backwards compatible extensions.
+ * The 4 lsb are more than enough to store the verdict. */
+#define EBT_VERDICT_BITS 0x0000000F
 
 struct ebt_counter
 {