Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* |
| 2 | * ebt_snat |
| 3 | * |
| 4 | * Authors: |
| 5 | * Bart De Schuymer <bdschuym@pandora.be> |
| 6 | * |
| 7 | * June, 2002 |
| 8 | * |
| 9 | */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 10 | #include <linux/module.h> |
| 11 | #include <net/sock.h> |
Bart De Schuymer | d12cdc3 | 2006-11-29 02:35:40 +0100 | [diff] [blame] | 12 | #include <linux/if_arp.h> |
| 13 | #include <net/arp.h> |
Jan Engelhardt | 18219d3 | 2008-10-08 11:35:13 +0200 | [diff] [blame] | 14 | #include <linux/netfilter.h> |
| 15 | #include <linux/netfilter/x_tables.h> |
| 16 | #include <linux/netfilter_bridge/ebtables.h> |
| 17 | #include <linux/netfilter_bridge/ebt_nat.h> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 18 | |
Jan Engelhardt | 2d06d4a | 2008-10-08 11:35:15 +0200 | [diff] [blame] | 19 | static unsigned int |
Jan Engelhardt | 4b560b4 | 2009-07-05 19:43:26 +0200 | [diff] [blame] | 20 | ebt_snat_tg(struct sk_buff *skb, const struct xt_action_param *par) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 21 | { |
Jan Engelhardt | 7eb3558 | 2008-10-08 11:35:19 +0200 | [diff] [blame] | 22 | const struct ebt_nat_info *info = par->targinfo; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 23 | |
Joonwoo Park | eb1197b | 2008-02-19 17:18:47 -0800 | [diff] [blame] | 24 | if (!skb_make_writable(skb, 0)) |
Joonwoo Park | 1b04ab4 | 2008-02-23 20:22:27 -0800 | [diff] [blame] | 25 | return EBT_DROP; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 26 | |
Joe Perches | 0409114 | 2014-02-23 00:05:26 -0800 | [diff] [blame] | 27 | ether_addr_copy(eth_hdr(skb)->h_source, info->mac); |
Bart De Schuymer | d12cdc3 | 2006-11-29 02:35:40 +0100 | [diff] [blame] | 28 | if (!(info->target & NAT_ARP_BIT) && |
Herbert Xu | 3db05fe | 2007-10-15 00:53:15 -0700 | [diff] [blame] | 29 | eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) { |
Jan Engelhardt | abfdf1c | 2008-01-31 03:59:24 -0800 | [diff] [blame] | 30 | const struct arphdr *ap; |
| 31 | struct arphdr _ah; |
Bart De Schuymer | d12cdc3 | 2006-11-29 02:35:40 +0100 | [diff] [blame] | 32 | |
Herbert Xu | 3db05fe | 2007-10-15 00:53:15 -0700 | [diff] [blame] | 33 | ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah); |
Bart De Schuymer | d12cdc3 | 2006-11-29 02:35:40 +0100 | [diff] [blame] | 34 | if (ap == NULL) |
| 35 | return EBT_DROP; |
| 36 | if (ap->ar_hln != ETH_ALEN) |
| 37 | goto out; |
tanxiaojun | 31a5b83 | 2013-12-19 13:28:12 +0800 | [diff] [blame] | 38 | if (skb_store_bits(skb, sizeof(_ah), info->mac, ETH_ALEN)) |
Bart De Schuymer | d12cdc3 | 2006-11-29 02:35:40 +0100 | [diff] [blame] | 39 | return EBT_DROP; |
| 40 | } |
| 41 | out: |
| 42 | return info->target | ~EBT_VERDICT_BITS; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 43 | } |
| 44 | |
Jan Engelhardt | 135367b | 2010-03-19 17:16:42 +0100 | [diff] [blame] | 45 | static int ebt_snat_tg_check(const struct xt_tgchk_param *par) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 46 | { |
Jan Engelhardt | af5d6dc | 2008-10-08 11:35:19 +0200 | [diff] [blame] | 47 | const struct ebt_nat_info *info = par->targinfo; |
Bart De Schuymer | d12cdc3 | 2006-11-29 02:35:40 +0100 | [diff] [blame] | 48 | int tmp; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 49 | |
Bart De Schuymer | d12cdc3 | 2006-11-29 02:35:40 +0100 | [diff] [blame] | 50 | tmp = info->target | ~EBT_VERDICT_BITS; |
| 51 | if (BASE_CHAIN && tmp == EBT_RETURN) |
Jan Engelhardt | d6b00a5 | 2010-03-25 16:34:45 +0100 | [diff] [blame] | 52 | return -EINVAL; |
Bart De Schuymer | d12cdc3 | 2006-11-29 02:35:40 +0100 | [diff] [blame] | 53 | |
| 54 | if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0) |
Jan Engelhardt | d6b00a5 | 2010-03-25 16:34:45 +0100 | [diff] [blame] | 55 | return -EINVAL; |
Bart De Schuymer | d12cdc3 | 2006-11-29 02:35:40 +0100 | [diff] [blame] | 56 | tmp = info->target | EBT_VERDICT_BITS; |
| 57 | if ((tmp & ~NAT_ARP_BIT) != ~NAT_ARP_BIT) |
Jan Engelhardt | d6b00a5 | 2010-03-25 16:34:45 +0100 | [diff] [blame] | 58 | return -EINVAL; |
| 59 | return 0; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 60 | } |
| 61 | |
Jan Engelhardt | 043ef46 | 2008-10-08 11:35:15 +0200 | [diff] [blame] | 62 | static struct xt_target ebt_snat_tg_reg __read_mostly = { |
| 63 | .name = "snat", |
Jan Engelhardt | 001a18d | 2008-10-08 11:35:14 +0200 | [diff] [blame] | 64 | .revision = 0, |
| 65 | .family = NFPROTO_BRIDGE, |
Jan Engelhardt | f2ff525 | 2008-10-08 11:35:15 +0200 | [diff] [blame] | 66 | .table = "nat", |
| 67 | .hooks = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_POST_ROUTING), |
Jan Engelhardt | 2d06d4a | 2008-10-08 11:35:15 +0200 | [diff] [blame] | 68 | .target = ebt_snat_tg, |
| 69 | .checkentry = ebt_snat_tg_check, |
Florian Westphal | fc0e3df | 2010-02-15 18:16:26 +0100 | [diff] [blame] | 70 | .targetsize = sizeof(struct ebt_nat_info), |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 71 | .me = THIS_MODULE, |
| 72 | }; |
| 73 | |
Andrew Morton | 65b4b4e | 2006-03-28 16:37:06 -0800 | [diff] [blame] | 74 | static int __init ebt_snat_init(void) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 75 | { |
Jan Engelhardt | 043ef46 | 2008-10-08 11:35:15 +0200 | [diff] [blame] | 76 | return xt_register_target(&ebt_snat_tg_reg); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 77 | } |
| 78 | |
Andrew Morton | 65b4b4e | 2006-03-28 16:37:06 -0800 | [diff] [blame] | 79 | static void __exit ebt_snat_fini(void) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 80 | { |
Jan Engelhardt | 043ef46 | 2008-10-08 11:35:15 +0200 | [diff] [blame] | 81 | xt_unregister_target(&ebt_snat_tg_reg); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 82 | } |
| 83 | |
Andrew Morton | 65b4b4e | 2006-03-28 16:37:06 -0800 | [diff] [blame] | 84 | module_init(ebt_snat_init); |
| 85 | module_exit(ebt_snat_fini); |
Jan Engelhardt | f776c4c | 2008-01-31 04:00:30 -0800 | [diff] [blame] | 86 | MODULE_DESCRIPTION("Ebtables: Source MAC address translation"); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 87 | MODULE_LICENSE("GPL"); |