1 // SPDX-License-Identifier: GPL-2.0-only
6 * Bart De Schuymer <bdschuym@pandora.be>
11 #include <linux/module.h>
13 #include <linux/if_arp.h>
15 #include <linux/netfilter.h>
16 #include <linux/netfilter/x_tables.h>
17 #include <linux/netfilter_bridge/ebtables.h>
18 #include <linux/netfilter_bridge/ebt_nat.h>
21 ebt_snat_tg(struct sk_buff
*skb
, const struct xt_action_param
*par
)
23 const struct ebt_nat_info
*info
= par
->targinfo
;
25 if (skb_ensure_writable(skb
, 0))
28 ether_addr_copy(eth_hdr(skb
)->h_source
, info
->mac
);
29 if (!(info
->target
& NAT_ARP_BIT
) &&
30 eth_hdr(skb
)->h_proto
== htons(ETH_P_ARP
)) {
31 const struct arphdr
*ap
;
34 ap
= skb_header_pointer(skb
, 0, sizeof(_ah
), &_ah
);
37 if (ap
->ar_hln
!= ETH_ALEN
)
39 if (skb_store_bits(skb
, sizeof(_ah
), info
->mac
, ETH_ALEN
))
43 return info
->target
| ~EBT_VERDICT_BITS
;
46 static int ebt_snat_tg_check(const struct xt_tgchk_param
*par
)
48 const struct ebt_nat_info
*info
= par
->targinfo
;
51 tmp
= info
->target
| ~EBT_VERDICT_BITS
;
52 if (BASE_CHAIN
&& tmp
== EBT_RETURN
)
55 if (ebt_invalid_target(tmp
))
57 tmp
= info
->target
| EBT_VERDICT_BITS
;
58 if ((tmp
& ~NAT_ARP_BIT
) != ~NAT_ARP_BIT
)
63 static struct xt_target ebt_snat_tg_reg __read_mostly
= {
66 .family
= NFPROTO_BRIDGE
,
68 .hooks
= (1 << NF_BR_NUMHOOKS
) | (1 << NF_BR_POST_ROUTING
),
69 .target
= ebt_snat_tg
,
70 .checkentry
= ebt_snat_tg_check
,
71 .targetsize
= sizeof(struct ebt_nat_info
),
75 static int __init
ebt_snat_init(void)
77 return xt_register_target(&ebt_snat_tg_reg
);
80 static void __exit
ebt_snat_fini(void)
82 xt_unregister_target(&ebt_snat_tg_reg
);
85 module_init(ebt_snat_init
);
86 module_exit(ebt_snat_fini
);
87 MODULE_DESCRIPTION("Ebtables: Source MAC address translation");
88 MODULE_LICENSE("GPL");