Changing MAC address for forwarding a pacjet with ebtables
"Mark Ryden" <[email protected]>
| Newsgroups | gmane.linux.network.bridge.ebtables.devel |
|---|---|
| Message-ID | <[email protected]> |
Hello,
I am writing a kernel module which changes the MAC address of a received UDP
packet so that it will be of a different machine on the same LAN and
so that the
packet will be forwarded to that machine.
Namely, I am trying to do fowarding in layer 2 using ebtables hook.
I am catching the packet with NF_BR_PRE_ROUTING ebtable hook.
In this hook, I am changing its MAC address to 00:11:2F:93:E0:52 ;
this is the MAC
address of another machine which is on the same LAN (my ARP table
knows this MAC).
The code is below; it is short; (only 100 lines). If someone can
take a look at it and give some advice it will be more than welcomed.
I saw a posting in this mailing list a few days ago in which
somebody tried also to adjust a MAC address and it was suggested that
he should follow ebt_snat.c; so this is what I did.
see:
http://sourceforge.net/mailarchive/forum.php?thread_name=6.1.2.0.2.20050218133252.04555610%40luna.tlmat.unican.es&forum_name=ebtables-devel
More details:
When running the module and sending UDP packets on port 5555, I
see that I get the packets in the module;
Moreover, I see that the following if statement is valid:
if (skb_shared(*pskb) || skb_cloned(*pskb)) ..
However, when I put a sniffer on that machine or the second machine I
**don't** see that a packet is sent to the second machine,
namely to 00:11:2F:93:E0:52.
What is missing here ? should I add some ebtable forwarding hook?
BTW, on my machine, there is a bridge defined thus (as far as I know,this
should be ok):
ifconfig eth0 0.0.0.0
brctl addbr mybr
brctl addif mybr eth0
ifconfig mybr up
ifconfig mybr 192.168.0.45 netmask 255.255.255.0
Below is the code:
// ebtable.c
#include <linux/version.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kmod.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/inet.h>
#include <linux/udp.h>
#include <linux/netdevice.h>
#include <linux/time.h>
#include <linux/netfilter_ipv4/ip_nat.h>
#include <net/ip.h>
#include <net/checksum.h>
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/netfilter_bridge/ebt_nat.h>
#include <linux/netfilter_bridge.h>
static unsigned short ethpip;
static struct nf_hook_ops netfilter_ops_in;
unsigned int main_hook(unsigned int hooknum,
struct sk_buff** pskb,
const struct net_device* in,
const struct net_device* out,
int (*okfn)(struct sk_buff*))
{
static int counter;
struct sk_buff *nskb;
unsigned char *data;
int i;
counter++;
if( (*pskb)->protocol == ethpip && (*pskb)->nh.iph->protocol == IPPROTO_UDP)
{
struct udphdr *udp_header = (struct udphdr *)((*pskb)->data +
((*pskb)->nh.iph->ihl *4));
int port = ntohs(udp_header->dest);
if (port == 5555)
{
char a[] = { 0x00, 0x11, 0x2F, 0x93, 0xE0, 0x52 };
printk("changing IP dst address in %s\n", __FUNCTION__);
if (skb_shared(*pskb) || skb_cloned(*pskb)) {
struct sk_buff *nskb;
// printk("in if if (skb_shared(*pskb) || skb_cloned(*pskb)) \n");
nskb = skb_copy(*pskb, GFP_ATOMIC);
if (!nskb)
return NF_DROP;
if ((*pskb)->sk)
skb_set_owner_w(nskb, (*pskb)->sk);
kfree_skb(*pskb);
*pskb = nskb;
}
memcpy(eth_hdr(*pskb)->h_dest, a, ETH_ALEN);
}// of if port = 5555
}
return NF_ACCEPT;
}
static int __init ebtable_init(void)
{
int ret;
ethpip = htons(ETH_P_IP);
netfilter_ops_in.hook = main_hook;
netfilter_ops_in.owner = THIS_MODULE,
netfilter_ops_in.pf = PF_BRIDGE;
netfilter_ops_in.hooknum = NF_BR_PRE_ROUTING;
netfilter_ops_in.priority = NF_BR_PRI_FILTER_BRIDGED;
ret = nf_register_hook(&netfilter_ops_in);
if (ret < 0)
{
nf_unregister_hook(&netfilter_ops_in);
return -1;
}
return 0;
}
static void __exit ebtable_exit(void)
{
nf_unregister_hook(&netfilter_ops_in);
}
module_init(ebtable_init)
module_exit(ebtable_exit)
MODULE_AUTHOR("MarkRyde");
MODULE_DESCRIPTION("ebtables changing mac address");
MODULE_LICENSE("GPL");
Regards,
Mark
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/