0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/module.h>
0012 #include <net/sock.h>
0013 #include <linux/if_arp.h>
0014 #include <net/arp.h>
0015 #include <linux/netfilter.h>
0016 #include <linux/netfilter/x_tables.h>
0017 #include <linux/netfilter_bridge/ebtables.h>
0018 #include <linux/netfilter_bridge/ebt_nat.h>
0019
0020 static unsigned int
0021 ebt_snat_tg(struct sk_buff *skb, const struct xt_action_param *par)
0022 {
0023 const struct ebt_nat_info *info = par->targinfo;
0024
0025 if (skb_ensure_writable(skb, 0))
0026 return EBT_DROP;
0027
0028 ether_addr_copy(eth_hdr(skb)->h_source, info->mac);
0029 if (!(info->target & NAT_ARP_BIT) &&
0030 eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) {
0031 const struct arphdr *ap;
0032 struct arphdr _ah;
0033
0034 ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
0035 if (ap == NULL)
0036 return EBT_DROP;
0037 if (ap->ar_hln != ETH_ALEN)
0038 goto out;
0039 if (skb_store_bits(skb, sizeof(_ah), info->mac, ETH_ALEN))
0040 return EBT_DROP;
0041 }
0042 out:
0043 return info->target | ~EBT_VERDICT_BITS;
0044 }
0045
0046 static int ebt_snat_tg_check(const struct xt_tgchk_param *par)
0047 {
0048 const struct ebt_nat_info *info = par->targinfo;
0049 int tmp;
0050
0051 tmp = info->target | ~EBT_VERDICT_BITS;
0052 if (BASE_CHAIN && tmp == EBT_RETURN)
0053 return -EINVAL;
0054
0055 if (ebt_invalid_target(tmp))
0056 return -EINVAL;
0057 tmp = info->target | EBT_VERDICT_BITS;
0058 if ((tmp & ~NAT_ARP_BIT) != ~NAT_ARP_BIT)
0059 return -EINVAL;
0060 return 0;
0061 }
0062
0063 static struct xt_target ebt_snat_tg_reg __read_mostly = {
0064 .name = "snat",
0065 .revision = 0,
0066 .family = NFPROTO_BRIDGE,
0067 .table = "nat",
0068 .hooks = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_POST_ROUTING),
0069 .target = ebt_snat_tg,
0070 .checkentry = ebt_snat_tg_check,
0071 .targetsize = sizeof(struct ebt_nat_info),
0072 .me = THIS_MODULE,
0073 };
0074
0075 static int __init ebt_snat_init(void)
0076 {
0077 return xt_register_target(&ebt_snat_tg_reg);
0078 }
0079
0080 static void __exit ebt_snat_fini(void)
0081 {
0082 xt_unregister_target(&ebt_snat_tg_reg);
0083 }
0084
0085 module_init(ebt_snat_init);
0086 module_exit(ebt_snat_fini);
0087 MODULE_DESCRIPTION("Ebtables: Source MAC address translation");
0088 MODULE_LICENSE("GPL");