11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  ebt_dnat
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Authors:
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Bart De Schuymer <bdschuym@pandora.be>
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  June, 2002
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1018219d3f7d6a5bc43825a41e0763158efbdb80d3Jan Engelhardt#include <linux/module.h>
1118219d3f7d6a5bc43825a41e0763158efbdb80d3Jan Engelhardt#include <net/sock.h>
122ca7b0ac022aa0158599178fe1056b1ba9ec8b97Herbert Xu#include <linux/netfilter.h>
1318219d3f7d6a5bc43825a41e0763158efbdb80d3Jan Engelhardt#include <linux/netfilter/x_tables.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netfilter_bridge/ebtables.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netfilter_bridge/ebt_nat.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
172d06d4a5cc107046508d860a0b47dbc43b829b79Jan Engelhardtstatic unsigned int
184b560b447df83368df44bd3712c0c39b1d79ba04Jan Engelhardtebt_dnat_tg(struct sk_buff *skb, const struct xt_action_param *par)
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
207eb3558655aaa87a3e71a0c065dfaddda521fa6dJan Engelhardt	const struct ebt_nat_info *info = par->targinfo;
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22eb1197bc0e20d3ceb450883dbd181460252f0306Joonwoo Park	if (!skb_make_writable(skb, 0))
231b04ab4597725f75f94942da9aa40daa7b9a4bd9Joonwoo Park		return EBT_DROP;
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2504091142826e5823e31cc6418942ac447b3edb0aJoe Perches	ether_addr_copy(eth_hdr(skb)->h_dest, info->mac);
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return info->target;
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29135367b8f6a18507af6b9a6910a14b5699415309Jan Engelhardtstatic int ebt_dnat_tg_check(const struct xt_tgchk_param *par)
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
31af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt	const struct ebt_nat_info *info = par->targinfo;
32af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt	unsigned int hook_mask;
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (BASE_CHAIN && info->target == EBT_RETURN)
35d6b00a5345ce4e86e8b00a88bb84a2c0c1f69ddcJan Engelhardt		return -EINVAL;
36af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt
37af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt	hook_mask = par->hook_mask & ~(1 << NF_BR_NUMHOOKS);
38af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt	if ((strcmp(par->table, "nat") != 0 ||
39af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt	    (hook_mask & ~((1 << NF_BR_PRE_ROUTING) |
40af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt	    (1 << NF_BR_LOCAL_OUT)))) &&
41af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt	    (strcmp(par->table, "broute") != 0 ||
42af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt	    hook_mask & ~(1 << NF_BR_BROUTING)))
43d6b00a5345ce4e86e8b00a88bb84a2c0c1f69ddcJan Engelhardt		return -EINVAL;
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (INVALID_TARGET)
45d6b00a5345ce4e86e8b00a88bb84a2c0c1f69ddcJan Engelhardt		return -EINVAL;
46d6b00a5345ce4e86e8b00a88bb84a2c0c1f69ddcJan Engelhardt	return 0;
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49043ef46c7690bfdbd5b012e15812a14a19ca5604Jan Engelhardtstatic struct xt_target ebt_dnat_tg_reg __read_mostly = {
50043ef46c7690bfdbd5b012e15812a14a19ca5604Jan Engelhardt	.name		= "dnat",
51001a18d369f4813ed792629ff4a9a6ade2a4a031Jan Engelhardt	.revision	= 0,
52001a18d369f4813ed792629ff4a9a6ade2a4a031Jan Engelhardt	.family		= NFPROTO_BRIDGE,
53f2ff525c8dae57b3cda51d76443f60f764f34202Jan Engelhardt	.hooks		= (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_PRE_ROUTING) |
54f2ff525c8dae57b3cda51d76443f60f764f34202Jan Engelhardt			  (1 << NF_BR_LOCAL_OUT) | (1 << NF_BR_BROUTING),
552d06d4a5cc107046508d860a0b47dbc43b829b79Jan Engelhardt	.target		= ebt_dnat_tg,
562d06d4a5cc107046508d860a0b47dbc43b829b79Jan Engelhardt	.checkentry	= ebt_dnat_tg_check,
57fc0e3df4f00a5f62c2f2fce84bf496136b58c474Florian Westphal	.targetsize	= sizeof(struct ebt_nat_info),
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.me		= THIS_MODULE,
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6165b4b4e81a5094d52cbe372b887b1779abe53f9bAndrew Mortonstatic int __init ebt_dnat_init(void)
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
63043ef46c7690bfdbd5b012e15812a14a19ca5604Jan Engelhardt	return xt_register_target(&ebt_dnat_tg_reg);
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6665b4b4e81a5094d52cbe372b887b1779abe53f9bAndrew Mortonstatic void __exit ebt_dnat_fini(void)
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
68043ef46c7690bfdbd5b012e15812a14a19ca5604Jan Engelhardt	xt_unregister_target(&ebt_dnat_tg_reg);
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7165b4b4e81a5094d52cbe372b887b1779abe53f9bAndrew Mortonmodule_init(ebt_dnat_init);
7265b4b4e81a5094d52cbe372b887b1779abe53f9bAndrew Mortonmodule_exit(ebt_dnat_fini);
73f776c4cda449bab463f5388eb07bd63dc52e2b13Jan EngelhardtMODULE_DESCRIPTION("Ebtables: Destination MAC address translation");
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
75