0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/module.h>
0012 #include <net/sock.h>
0013 #include "../br_private.h"
0014 #include <linux/netfilter.h>
0015 #include <linux/netfilter/x_tables.h>
0016 #include <linux/netfilter_bridge/ebtables.h>
0017 #include <linux/netfilter_bridge/ebt_nat.h>
0018
0019 static unsigned int
0020 ebt_dnat_tg(struct sk_buff *skb, const struct xt_action_param *par)
0021 {
0022 const struct ebt_nat_info *info = par->targinfo;
0023
0024 if (skb_ensure_writable(skb, 0))
0025 return EBT_DROP;
0026
0027 ether_addr_copy(eth_hdr(skb)->h_dest, info->mac);
0028
0029 if (is_multicast_ether_addr(info->mac)) {
0030 if (is_broadcast_ether_addr(info->mac))
0031 skb->pkt_type = PACKET_BROADCAST;
0032 else
0033 skb->pkt_type = PACKET_MULTICAST;
0034 } else {
0035 const struct net_device *dev;
0036
0037 switch (xt_hooknum(par)) {
0038 case NF_BR_BROUTING:
0039 dev = xt_in(par);
0040 break;
0041 case NF_BR_PRE_ROUTING:
0042 dev = br_port_get_rcu(xt_in(par))->br->dev;
0043 break;
0044 default:
0045 dev = NULL;
0046 break;
0047 }
0048
0049 if (!dev)
0050 return info->target;
0051
0052 if (ether_addr_equal(info->mac, dev->dev_addr))
0053 skb->pkt_type = PACKET_HOST;
0054 else
0055 skb->pkt_type = PACKET_OTHERHOST;
0056 }
0057
0058 return info->target;
0059 }
0060
0061 static int ebt_dnat_tg_check(const struct xt_tgchk_param *par)
0062 {
0063 const struct ebt_nat_info *info = par->targinfo;
0064 unsigned int hook_mask;
0065
0066 if (BASE_CHAIN && info->target == EBT_RETURN)
0067 return -EINVAL;
0068
0069 hook_mask = par->hook_mask & ~(1 << NF_BR_NUMHOOKS);
0070 if ((strcmp(par->table, "nat") != 0 ||
0071 (hook_mask & ~((1 << NF_BR_PRE_ROUTING) |
0072 (1 << NF_BR_LOCAL_OUT)))) &&
0073 (strcmp(par->table, "broute") != 0 ||
0074 hook_mask & ~(1 << NF_BR_BROUTING)))
0075 return -EINVAL;
0076 if (ebt_invalid_target(info->target))
0077 return -EINVAL;
0078 return 0;
0079 }
0080
0081 static struct xt_target ebt_dnat_tg_reg __read_mostly = {
0082 .name = "dnat",
0083 .revision = 0,
0084 .family = NFPROTO_BRIDGE,
0085 .hooks = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_PRE_ROUTING) |
0086 (1 << NF_BR_LOCAL_OUT) | (1 << NF_BR_BROUTING),
0087 .target = ebt_dnat_tg,
0088 .checkentry = ebt_dnat_tg_check,
0089 .targetsize = sizeof(struct ebt_nat_info),
0090 .me = THIS_MODULE,
0091 };
0092
0093 static int __init ebt_dnat_init(void)
0094 {
0095 return xt_register_target(&ebt_dnat_tg_reg);
0096 }
0097
0098 static void __exit ebt_dnat_fini(void)
0099 {
0100 xt_unregister_target(&ebt_dnat_tg_reg);
0101 }
0102
0103 module_init(ebt_dnat_init);
0104 module_exit(ebt_dnat_fini);
0105 MODULE_DESCRIPTION("Ebtables: Destination MAC address translation");
0106 MODULE_LICENSE("GPL");