aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorBart De Schuymer <bdschuym@pandora.be>2006-11-28 20:35:40 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:31:32 -0500
commitd12cdc3ccf140bd2febef1c1be92284571da983f (patch)
treeb841cf72562e8179c9c187494a6fe4a3c2ddb184 /net/bridge
parentbaf7b1e11282127e068d149825cccec002091d61 (diff)
[NETFILTER]: ebtables: add --snap-arp option
The attached patch adds --snat-arp support, which makes it possible to change the source mac address in both the mac header and the arp header with one rule. Signed-off-by: Bart De Schuymer <bdschuym@pandora.be> Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/netfilter/ebt_mark.c6
-rw-r--r--net/bridge/netfilter/ebt_snat.c27
2 files changed, 27 insertions, 6 deletions
diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c
index 2458638561cb..62d23c7b25e6 100644
--- a/net/bridge/netfilter/ebt_mark.c
+++ b/net/bridge/netfilter/ebt_mark.c
@@ -33,7 +33,7 @@ static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr,
33 else 33 else
34 (*pskb)->mark ^= info->mark; 34 (*pskb)->mark ^= info->mark;
35 35
36 return info->target | -16; 36 return info->target | ~EBT_VERDICT_BITS;
37} 37}
38 38
39static int ebt_target_mark_check(const char *tablename, unsigned int hookmask, 39static int ebt_target_mark_check(const char *tablename, unsigned int hookmask,
@@ -44,13 +44,13 @@ static int ebt_target_mark_check(const char *tablename, unsigned int hookmask,
44 44
45 if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_t_info))) 45 if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_t_info)))
46 return -EINVAL; 46 return -EINVAL;
47 tmp = info->target | -16; 47 tmp = info->target | ~EBT_VERDICT_BITS;
48 if (BASE_CHAIN && tmp == EBT_RETURN) 48 if (BASE_CHAIN && tmp == EBT_RETURN)
49 return -EINVAL; 49 return -EINVAL;
50 CLEAR_BASE_CHAIN_BIT; 50 CLEAR_BASE_CHAIN_BIT;
51 if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) 51 if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
52 return -EINVAL; 52 return -EINVAL;
53 tmp = info->target & -16; 53 tmp = info->target & ~EBT_VERDICT_BITS;
54 if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE && 54 if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE &&
55 tmp != MARK_AND_VALUE && tmp != MARK_XOR_VALUE) 55 tmp != MARK_AND_VALUE && tmp != MARK_XOR_VALUE)
56 return -EINVAL; 56 return -EINVAL;
diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
index cbb33e24ca8a..a50722182bfe 100644
--- a/net/bridge/netfilter/ebt_snat.c
+++ b/net/bridge/netfilter/ebt_snat.c
@@ -12,6 +12,8 @@
12#include <linux/netfilter_bridge/ebt_nat.h> 12#include <linux/netfilter_bridge/ebt_nat.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <net/sock.h> 14#include <net/sock.h>
15#include <linux/if_arp.h>
16#include <net/arp.h>
15 17
16static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr, 18static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr,
17 const struct net_device *in, const struct net_device *out, 19 const struct net_device *in, const struct net_device *out,
@@ -31,24 +33,43 @@ static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr,
31 *pskb = nskb; 33 *pskb = nskb;
32 } 34 }
33 memcpy(eth_hdr(*pskb)->h_source, info->mac, ETH_ALEN); 35 memcpy(eth_hdr(*pskb)->h_source, info->mac, ETH_ALEN);
34 return info->target; 36 if (!(info->target & NAT_ARP_BIT) &&
37 eth_hdr(*pskb)->h_proto == htons(ETH_P_ARP)) {
38 struct arphdr _ah, *ap;
39
40 ap = skb_header_pointer(*pskb, 0, sizeof(_ah), &_ah);
41 if (ap == NULL)
42 return EBT_DROP;
43 if (ap->ar_hln != ETH_ALEN)
44 goto out;
45 if (skb_store_bits(*pskb, sizeof(_ah), info->mac,ETH_ALEN))
46 return EBT_DROP;
47 }
48out:
49 return info->target | ~EBT_VERDICT_BITS;
35} 50}
36 51
37static int ebt_target_snat_check(const char *tablename, unsigned int hookmask, 52static int ebt_target_snat_check(const char *tablename, unsigned int hookmask,
38 const struct ebt_entry *e, void *data, unsigned int datalen) 53 const struct ebt_entry *e, void *data, unsigned int datalen)
39{ 54{
40 struct ebt_nat_info *info = (struct ebt_nat_info *) data; 55 struct ebt_nat_info *info = (struct ebt_nat_info *) data;
56 int tmp;
41 57
42 if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info))) 58 if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info)))
43 return -EINVAL; 59 return -EINVAL;
44 if (BASE_CHAIN && info->target == EBT_RETURN) 60 tmp = info->target | ~EBT_VERDICT_BITS;
61 if (BASE_CHAIN && tmp == EBT_RETURN)
45 return -EINVAL; 62 return -EINVAL;
46 CLEAR_BASE_CHAIN_BIT; 63 CLEAR_BASE_CHAIN_BIT;
47 if (strcmp(tablename, "nat")) 64 if (strcmp(tablename, "nat"))
48 return -EINVAL; 65 return -EINVAL;
49 if (hookmask & ~(1 << NF_BR_POST_ROUTING)) 66 if (hookmask & ~(1 << NF_BR_POST_ROUTING))
50 return -EINVAL; 67 return -EINVAL;
51 if (INVALID_TARGET) 68
69 if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
70 return -EINVAL;
71 tmp = info->target | EBT_VERDICT_BITS;
72 if ((tmp & ~NAT_ARP_BIT) != ~NAT_ARP_BIT)
52 return -EINVAL; 73 return -EINVAL;
53 return 0; 74 return 0;
54} 75}