#ifndef __KERNEL__
# define __KERNEL__
#endif
#ifndef MODULE
# define MODULE
#endif
#define DEVNAME "firsteth"
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
#include <linux/rtnetlink.h>
#include <linux/if_arp.h>
/* netfilters related */
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/in.h>
#include <linux/udp.h>
#include <net/ip.h>
int test_open(struct inode *,struct file *);
int test_release(struct inode *,struct file*);
struct test_struct{
struct net_device *dev;
char name[IFNAMSIZ];
};
struct file_operations test_fop={
llseek: NULL,
read: NULL,
write: NULL,
ioctl: NULL,
open: test_open,
release: test_release,
};
struct test_struct pTestStruct;
static int testdev_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct iphdr *oldiph;
unsigned char tos=0;
unsigned short df =0;
unsigned char ttl;
printk(KERN_INFO " In xmit function\n");
oldiph = (skb->protocol==htons(ETH_P_IP))
? (struct iphdr*)(skb->data+ETH_HLEN)
: NULL;
tos = oldiph->tos;
df = oldiph->frag_off;
ttl = oldiph->ttl;
printk(KERN_INFO"src IP: %x dst IP: %x , protocol %d \n",ntohl(oldiph->saddr), ntohl(oldiph->daddr),oldiph->protocol);
return 0;
}
int test_open(struct inode *inode, struct file *filep)
{
MOD_INC_USE_COUNT;
return 0;
}
int test_release(struct inode *inode, struct file *filep)
{
MOD_DEC_USE_COUNT;
return 0;
}
int testdev_open(struct net_device *dev)
{
MOD_INC_USE_COUNT;
return 0;
}
int testdev_close(struct net_device *dev)
{
unregister_netdev(dev);
MOD_DEC_USE_COUNT;
return 0;
}
//t test_ioctl(struct inode *inode,
static int test_init_dev(struct net_device *dev)
{
struct test_struct *c;
printk(KERN_INFO "in test_init_dev\n");
c = (struct test_struct *)dev->priv;
if(!c)
return -ENODEV;
memset(c,0,sizeof(struct test_struct));
c->dev = dev;
// ether_setup(dev);
dev->open = testdev_open;
dev->stop = testdev_close;
dev->hard_start_xmit = testdev_xmit;
dev->mtu = ETH_DATA_LEN - sizeof(struct udphdr) - sizeof(struct iphdr) ;
dev_init_buffers(dev);
printk(KERN_INFO "completed test_init_dev\n");
return 0;
}
int init_module(void)
{
int result,i;
struct net_device *tempDev;
struct test_struct *temp_struct;
char devname[25]; // Remove the hardcode
for(i=0;i<99;i++)
{
sprintf(devname,"firseth%d",i);
if(__dev_get_by_name(devname) == NULL)
break;
}
if(i==100)
return -ENFILE;
printk(KERN_INFO "********MACOUDP TUNNEL******\n");
temp_struct = (struct test_struct *)kmalloc(sizeof(struct test_struct),GFP_KERNEL);
if(!temp_struct)
{
printk(KERN_ERR "error in allocating memory\n");
return -ENOMEM;
}
result = register_chrdev(244,"testdrv",&test_fop);
if( result != 0 ){
printk(KERN_WARNING "test: cant get major\n");
return result;
}
i=0;
memset(temp_struct,0,sizeof(struct test_struct));
//sprintf(temp_struct->name, DEVNAME "%d",i);
tempDev = (struct net_device *)kmalloc(sizeof(struct net_device),GFP_KERNEL);
if( !tempDev)
{
printk(KERN_ERR "kmalloc faied\n");
return -ENOMEM;
}
memset(tempDev,0,sizeof(struct net_device));
temp_struct->dev = tempDev;
temp_struct->dev->priv = &pTestStruct;
temp_struct->dev->next = NULL;
temp_struct->dev->base_addr=0;
temp_struct->dev->init = test_init_dev;
temp_struct->dev->dev_addr[0]=0xFC;
temp_struct->dev->dev_addr[1]=0xFC;
temp_struct->dev->dev_addr[2]=0xA;
temp_struct->dev->dev_addr[3]=0xB;
temp_struct->dev->dev_addr[4]=0xC;
temp_struct->dev->addr_len = ETH_ALEN;
i = dev_alloc_name(temp_struct->dev,"firsteth%d");
if(i < 0 )
{
printk(KERN_ERR "cant allocate device\n");
return -ENODEV;
}
ether_setup(temp_struct->dev);
rtnl_lock();
printk(KERN_INFO "Before calling register_netdevice\n");
i = register_netdevice((temp_struct->dev));
rtnl_unlock();
memcpy(&pTestStruct,temp_struct,sizeof(struct test_struct));
if( i < 0 ){
printk(KERN_ERR "register netdevice failed\n");
return -1;
}
return 0;
}
void cleanup_module(void)
{
rtnl_lock();
unregister_netdevice(pTestStruct.dev);
rtnl_unlock();
unregister_chrdev(244,"testdrv");
}