- 论坛徽章:
- 0
|
本帖最后由 zhouunix 于 2012-07-19 20:01 编辑
最近开始接触linux和netfilter,希望能在netfilter框架下实现对本机发送出去的ip包尾添加一个标志。现在自己按照网络上的资料编了一个模块程序,可是一加载模块,系统几乎都崩溃,查了网上好多资料,零零散散,没有头绪,请求大神们帮我看看代码,改改错 ps 本菜的电脑是ubuntu11.04 ,内核2.6.38.8
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/skbuff.h>
#include <linux/udp.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <net/tcp.h>
#include <net/udp.h>
MODULE_LICENSE("GPL" ) ;
#define NIPQUAD(addr) \
((unsigned char *)&addr)[0], \
((unsigned char *)&addr)[1], \
((unsigned char *)&addr)[2], \
((unsigned char *)&addr)[3]
struct iphdr *iph; //ip header struct
struct tcphdr *tcph,_otcph;
struct ethhdr *ethdr;
unsigned int tcph_len;
unsigned int iph_len;
typedef struct addpatch{
unsigned long int packetnumber;
}addpatch;
struct addpatch addpatch1;//想添加的标志
struct sk_buff *nskb;
unsigned char SMAC[ETH_ALEN] = {0x00,0x1d,0x09,0x7e,0x2e,0xec};
unsigned char DMAC[ETH_ALEN] = {0x00,0x50,0x56,0xFA,0x70,0x2A};
unsigned int hook_func(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *))
{
unsigned char *put_skb=NULL;
unsigned int tailroom;
int ret=0;
if(ip_hdr(skb)->frag_off & htons(IP_OFFSET))
return NF_ACCEPT;
tcph=skb_header_pointer(skb,ip_hdrlen(skb),sizeof(_otcph),&_otcph ) ;
iph =ip_hdr(skb) ;
if(tcph == NULL)
return NF_ACCEPT;
if(nf_ip_checksum(skb,hooknum,ip_hdrlen(skb),IPPROTO_TCP))
return NF_ACCEPT;
if(!skb) { return NF_ACCEPT;}
//下面是扩充skb中tail和end的空间,添加数据12345
addpatch1.packetnumber=12345;
if((tailroom=skb_tailroom(skb))>=sizeof(struct addpatch))
{
put_skb=skb_put(skb,sizeof(struct addpatch)) ;
memcpy(put_skb,&addpatch1,sizeof(struct addpatch)) ;
printk("sequence number size is %d\n",sizeof(struct addpatch)) ;
}
else
{
printk("the tailroom of skb is less than the struct addpatch's size %d\n ,it is %d\n",sizeof(struct addpatch), tailroom) ;
nskb = skb_copy_expand(skb, skb_headroom(skb), skb_tailroom(skb)+sizeof(struct addpatch),GFP_ATOMIC) ;
if(!nskb)
{
printk("low memory....\n" ) ;
dev_kfree_skb(skb) ;
return -1;
}
else
{
kfree_skb(skb) ;
skb = nskb;
}
memcpy(skb_put(skb,sizeof(struct addpatch)),&addpatch1,sizeof(struct addpatch)) ;
}
// 下面是重新计算校验和
iph=ip_hdr(skb) ;
iph_len=iph->ihl<<2;
iph->tot_len= htons(skb->len) ;
tcph=skb_header_pointer(skb,ip_hdrlen(skb),sizeof(_otcph),&_otcph) ;
if(tcph == NULL)
return -1;
tcph_len = tcph->doff<<2;
iph->check = 0;
iph->check =ip_fast_csum((unsigned char*)iph,iph->ihl) ;
skb->csum = 0;
skb->csum =csum_partial((unsigned char *)(tcph+tcph_len),ntohs(iph->tot_len)-iph_len-tcph_len,0) ;
tcph->check = 0;
tcph->check = csum_tcpudp_magic(iph->saddr,iph->daddr,ntohs(iph->tot_len)-iph_len,iph->protocol,csum_partial((unsigned char *)tcph,tcph_len,skb->csum)) ;
skb->ip_summed = CHECKSUM_NONE;
skb->pkt_type = PACKET_OTHERHOST;
skb->dev =dev_get_by_name(&init_net,"eth0" ) ;
if(skb->dev==NULL)
{
printk("%s\n", "dev_get_by_name return NULL" ) ;
kfree_skb(skb) ;
return NF_ACCEPT;
}
ethdr = (struct ethhdr*)skb_push(skb,14) ;
memcpy(ethdr->h_dest,DMAC,ETH_ALEN) ;
memcpy(ethdr->h_source,SMAC,ETH_ALEN) ;
ethdr->h_proto=__constant_htons(ETH_P_IP) ;
dev_hold(skb->dev) ;
printk("%s\n", "dev_hold ok" ) ;
ret = dev_queue_xmit(skb) ;
printk("ret:%d\n", ret) ;
return NF_STOLEN;
}
static struct nf_hook_ops nfho={
.list = {NULL,NULL},
.hook = hook_func,
.pf = PF_INET,
.hooknum = NF_INET_LOCAL_OUT,
.priority = NF_IP_PRI_FILTER
};
static int __init addpatch_init(void)
{
nf_register_hook(&nfho) ;
return 0;
}
static void __exit addpatch_exit(void)
{
nf_unregister_hook(&nfho) ;
}
module_init(addpatch_init) ;
module_exit(addpatch_exit) ;
//参考资料 http://bbs.chinaunix.net/thread-1941060-1-1.html |
|