dsr0.0.1程序存档及说明---如何修改ip数据包
2007-10-08 19:41:38
2007-10-08 19:41:38
本程序功能
对发送的数据包的数据包类型进行修改
改为dsr类型,设dsr类型的值为24
同时加入dsr选项,保存原来的数据类型
接收的数据包为逆过程
还原原数据包的数据类型
去掉dsr选项
实现的效果
只用同时运行该程序的机子可以进行通讯
无法其他机子的正常通讯
单机测试效果
ping自己的机子可以ping通
但ping其他的机子则不行
本程序算是我的第一个程序吧
主要目的是实验ip数据包的修改方法,以便进一步的编程,可以说是小实验吧
对于如何修改ip数据包作了详细的说明和代码演示
可以为以后编程作参考
特此存档以便后查
测试内核为2.6.20
==========================================
/*DSR处理程序dsr.c*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/string.h>
#include <linux/ip.h>
#include <net/ip.h>
#include <dsr.h>
#define DSR 24
//定义两个结构体,以便向钩子函数注册
static struct nf_hook_ops nfho1;
static struct nf_hook_ops nfho2;
//发送处理程序,截获发送的数据包,添加dsr头部(4字节),将有的协议类型更换为dsr类型
unsigned int dsr_send(unsigned int hooknum,struct sk_buff **skb,const struct net_device *in,const struct net_device *out,int (*okfn)(struct sk_buff *))
{
struct iphdr *iph_n=(*skb)->nh.iph;
int iph_len=((*skb)->nh.iph->ihl)*4;//ip首部长度,单位字节
//printk("skb_headroom %i/n",skb_headroom(*skb));
//__u8 icmp_type=00000001;
//if(iph_n->protocol == icmp_type){iph_n->protocol=DSR;ip_send_check(iph_n);return NF_ACCEPT;}
if(iph_n->protocol!=0)
{
unsigned char *dsrh_addr=skb_push((*skb),sizeof(struct dsr_header));//返回值为待写入数据的区域
struct dsr_header dsrh;
if(dsrh_addr==NULL){printk("the headroom is not enough/n");return NF_DROP;}
//printk("a is %p/n b is %p/n",dsrh_addr,(*skb)->nh.iph);
(*skb)->nh.iph=memmove(dsrh_addr,iph_n,iph_len);//前移ip头部
iph_n=(*skb)->nh.iph;
dsrh_addr+=iph_len;//确定dsr选项的地址
//dsr选项值设定
dsrh.nextheader=iph_n->protocol;
dsrh.reserved=00000000;
dsrh.length=0000000000000000;
memcpy(dsrh_addr,&dsrh,4);//选项值写入内存相应区域
//更改协议类型为DSR,并校验头部
iph_n->protocol=DSR;
iph_n->tot_len=htons((*skb)->len);
ip_send_check(iph_n);
//printk("a2 is %p/n b2 is %p/n",dsrh_addr,(*skb)->nh.iph);
printk("send %i/n%i/n",iph_n->protocol,dsrh.nextheader);
//printk("the new skb_headroom is %i/n",skb_headroom(*skb));
return NF_ACCEPT;
}
else{return NF_DROP;}
//return NF_ACCEPT;
}
//接收处理函数,还原数据包的原有数据类型,去除dsr选项
unsigned int dsr_rcv(unsigned int hooknum,struct sk_buff **skb,const struct net_device *in,const struct net_device *out,int (*okfn)(struct sk_buff *))
{
struct iphdr *iph_n=(*skb)->nh.iph;
printk("rcving/n");
if(iph_n->protocol==DSR)
{
//iph_n->protocol=1;
int iph_len=((*skb)->nh.iph->ihl)*4;//ip首部长度,单位字节
unsigned char *dsrh_addr=skb_pull((*skb),sizeof(struct dsr_header));//返回的是去掉了sizeof(dsr_header)后的地址,计ip头应移动到的地址;
struct dsr_header *dsrh;//=(struct dsr_header *)iph_n+iph_len;
(*skb)->nh.iph=(struct iphdr *)dsrh_addr;
dsrh_addr=dsrh_addr+iph_len-sizeof(struct dsr_header);//确定dsr选项部分的地址
//printk("%p/n",dsrh_addr);
dsrh=(struct dsr_header *)dsrh_addr;
//printk("iph %p/ndsr %p/n",iph_n,dsrh);
printk("rcv %i/n%i/n",iph_n->protocol,dsrh->nextheader);
iph_n->protocol=dsrh->nextheader;
memmove((*skb)->nh.iph,iph_n,iph_len);//ip头后移
//(*skb)->nh.iph+=iph_len;
iph_n=(*skb)->nh.iph;
iph_n->tot_len=htons((*skb)->len);
//printk("iph2 %p/n",iph_n);
ip_send_check(iph_n);
}
return NF_ACCEPT;
}
//初始化函数,完成向钩子函数的注册
static int __init dsr_init(void)
{
nfho1.hook=dsr_rcv;
nfho1.hooknum=NF_IP_PRE_ROUTING;
nfho1.pf=PF_INET;
nfho1.priority=NF_IP_PRI_FIRST;
nf_register_hook(&nfho1);
nfho2.hook=dsr_send;
nfho2.hooknum=NF_IP_LOCAL_OUT;
nfho2.pf=PF_INET;
nfho2.priority=NF_IP_PRI_FIRST;
nf_register_hook(&nfho2);
return 0;
}
//反注册钩子函数,module的出口
static void __exit dsr_exit(void)
{
nf_unregister_hook(&nfho1);
nf_unregister_hook(&nfho2);
}
module_init(dsr_init);
module_exit(dsr_exit);
==========================================
dsr.h文件如下
#ifndef _DSR_H
#define _DSR_H
#include <linux/types.h>
struct dsr_header
{
__u8 nextheader;
__u8 reserved;
__u16 length;
};
#endif/*_DSR_H*/
==========================================
makefile文件
obj-m +=dsr.o
KERNELBUILD := /lib/modules/`uname -r`/build/
CFLAGS += -I/home/lightmusic/workspace/dsr/include/
default:
make -C $(KERNELBUILD) M=$(shell pwd) modules
clean:
rm -rf *.o .*.cmd *.ko *.mod.c .tmp_versions
==========================================
对发送的数据包的数据包类型进行修改
改为dsr类型,设dsr类型的值为24
同时加入dsr选项,保存原来的数据类型
接收的数据包为逆过程
还原原数据包的数据类型
去掉dsr选项
实现的效果
只用同时运行该程序的机子可以进行通讯
无法其他机子的正常通讯
单机测试效果
ping自己的机子可以ping通
但ping其他的机子则不行
本程序算是我的第一个程序吧
主要目的是实验ip数据包的修改方法,以便进一步的编程,可以说是小实验吧
对于如何修改ip数据包作了详细的说明和代码演示
可以为以后编程作参考
特此存档以便后查
测试内核为2.6.20
==========================================
/*DSR处理程序dsr.c*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/string.h>
#include <linux/ip.h>
#include <net/ip.h>
#include <dsr.h>
#define DSR 24
//定义两个结构体,以便向钩子函数注册
static struct nf_hook_ops nfho1;
static struct nf_hook_ops nfho2;
//发送处理程序,截获发送的数据包,添加dsr头部(4字节),将有的协议类型更换为dsr类型
unsigned int dsr_send(unsigned int hooknum,struct sk_buff **skb,const struct net_device *in,const struct net_device *out,int (*okfn)(struct sk_buff *))
{
struct iphdr *iph_n=(*skb)->nh.iph;
int iph_len=((*skb)->nh.iph->ihl)*4;//ip首部长度,单位字节
//printk("skb_headroom %i/n",skb_headroom(*skb));
//__u8 icmp_type=00000001;
//if(iph_n->protocol == icmp_type){iph_n->protocol=DSR;ip_send_check(iph_n);return NF_ACCEPT;}
if(iph_n->protocol!=0)
{
unsigned char *dsrh_addr=skb_push((*skb),sizeof(struct dsr_header));//返回值为待写入数据的区域
struct dsr_header dsrh;
if(dsrh_addr==NULL){printk("the headroom is not enough/n");return NF_DROP;}
//printk("a is %p/n b is %p/n",dsrh_addr,(*skb)->nh.iph);
(*skb)->nh.iph=memmove(dsrh_addr,iph_n,iph_len);//前移ip头部
iph_n=(*skb)->nh.iph;
dsrh_addr+=iph_len;//确定dsr选项的地址
//dsr选项值设定
dsrh.nextheader=iph_n->protocol;
dsrh.reserved=00000000;
dsrh.length=0000000000000000;
memcpy(dsrh_addr,&dsrh,4);//选项值写入内存相应区域
//更改协议类型为DSR,并校验头部
iph_n->protocol=DSR;
iph_n->tot_len=htons((*skb)->len);
ip_send_check(iph_n);
//printk("a2 is %p/n b2 is %p/n",dsrh_addr,(*skb)->nh.iph);
printk("send %i/n%i/n",iph_n->protocol,dsrh.nextheader);
//printk("the new skb_headroom is %i/n",skb_headroom(*skb));
return NF_ACCEPT;
}
else{return NF_DROP;}
//return NF_ACCEPT;
}
//接收处理函数,还原数据包的原有数据类型,去除dsr选项
unsigned int dsr_rcv(unsigned int hooknum,struct sk_buff **skb,const struct net_device *in,const struct net_device *out,int (*okfn)(struct sk_buff *))
{
struct iphdr *iph_n=(*skb)->nh.iph;
printk("rcving/n");
if(iph_n->protocol==DSR)
{
//iph_n->protocol=1;
int iph_len=((*skb)->nh.iph->ihl)*4;//ip首部长度,单位字节
unsigned char *dsrh_addr=skb_pull((*skb),sizeof(struct dsr_header));//返回的是去掉了sizeof(dsr_header)后的地址,计ip头应移动到的地址;
struct dsr_header *dsrh;//=(struct dsr_header *)iph_n+iph_len;
(*skb)->nh.iph=(struct iphdr *)dsrh_addr;
dsrh_addr=dsrh_addr+iph_len-sizeof(struct dsr_header);//确定dsr选项部分的地址
//printk("%p/n",dsrh_addr);
dsrh=(struct dsr_header *)dsrh_addr;
//printk("iph %p/ndsr %p/n",iph_n,dsrh);
printk("rcv %i/n%i/n",iph_n->protocol,dsrh->nextheader);
iph_n->protocol=dsrh->nextheader;
memmove((*skb)->nh.iph,iph_n,iph_len);//ip头后移
//(*skb)->nh.iph+=iph_len;
iph_n=(*skb)->nh.iph;
iph_n->tot_len=htons((*skb)->len);
//printk("iph2 %p/n",iph_n);
ip_send_check(iph_n);
}
return NF_ACCEPT;
}
//初始化函数,完成向钩子函数的注册
static int __init dsr_init(void)
{
nfho1.hook=dsr_rcv;
nfho1.hooknum=NF_IP_PRE_ROUTING;
nfho1.pf=PF_INET;
nfho1.priority=NF_IP_PRI_FIRST;
nf_register_hook(&nfho1);
nfho2.hook=dsr_send;
nfho2.hooknum=NF_IP_LOCAL_OUT;
nfho2.pf=PF_INET;
nfho2.priority=NF_IP_PRI_FIRST;
nf_register_hook(&nfho2);
return 0;
}
//反注册钩子函数,module的出口
static void __exit dsr_exit(void)
{
nf_unregister_hook(&nfho1);
nf_unregister_hook(&nfho2);
}
module_init(dsr_init);
module_exit(dsr_exit);
==========================================
dsr.h文件如下
#ifndef _DSR_H
#define _DSR_H
#include <linux/types.h>
struct dsr_header
{
__u8 nextheader;
__u8 reserved;
__u16 length;
};
#endif/*_DSR_H*/
==========================================
makefile文件
obj-m +=dsr.o
KERNELBUILD := /lib/modules/`uname -r`/build/
CFLAGS += -I/home/lightmusic/workspace/dsr/include/
default:
make -C $(KERNELBUILD) M=$(shell pwd) modules
clean:
rm -rf *.o .*.cmd *.ko *.mod.c .tmp_versions
==========================================
本文介绍了一个简单的实验程序dsr0.0.1,该程序用于修改IP数据包类型为DSR类型,并加入DSR选项。实现了仅允许运行该程序的机器间通讯,阻止与其他机器的正常通讯。文章提供了详细的代码实现。
1526

被折叠的 条评论
为什么被折叠?



