diff options
author | Bart De Schuymer <bdschuym@pandora.be> | 2006-11-28 20:35:40 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-03 00:31:32 -0500 |
commit | d12cdc3ccf140bd2febef1c1be92284571da983f (patch) | |
tree | b841cf72562e8179c9c187494a6fe4a3c2ddb184 /net/bridge | |
parent | baf7b1e11282127e068d149825cccec002091d61 (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.c | 6 | ||||
-rw-r--r-- | net/bridge/netfilter/ebt_snat.c | 27 |
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 | ||
39 | static int ebt_target_mark_check(const char *tablename, unsigned int hookmask, | 39 | static 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 | ||
16 | static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr, | 18 | static 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 | } | ||
48 | out: | ||
49 | return info->target | ~EBT_VERDICT_BITS; | ||
35 | } | 50 | } |
36 | 51 | ||
37 | static int ebt_target_snat_check(const char *tablename, unsigned int hookmask, | 52 | static 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 | } |