如何更改ip报头中的tos位而不损坏报头
如何更改ip报头中tos位的值? 我尝试使用iphdr结构直接修改它。 它是在内核级别使用netfilter完成的。 我写的代码如下:如何更改ip报头中的tos位而不损坏报头,ip,kernel-module,Ip,Kernel Module,如何更改ip报头中tos位的值? 我尝试使用iphdr结构直接修改它。 它是在内核级别使用netfilter完成的。 我写的代码如下: // Including the required header files #include <linux/kernel.h> #include <linux/module.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #in
// Including the required header files
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/init.h>
#include <linux/kthread.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/in.h>
#include <linux/inet.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <net/sock.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/proc_fs.h>
// Defining the name of the module
#define MODULE_NAME "TOS_setter"
// Structure definition for processing outgoing packets
static struct nf_hook_ops nf_ops_out;
//===========================================================
// Function that modifies the TOS bits
unsigned int tos_setter(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;
unsigned char tosbits;
if (!skb)return NF_ACCEPT;
iph = ip_hdr(skb);
if (!iph)return NF_ACCEPT;
//if(iph->protocol==IPPROTO_TCP)return NF_ACCEPT;
if (iph->protocol==IPPROTO_TCP)
{
printk(KERN_ALERT " The total length is : %d\n" , (int)iph->tot_len);
iph->tos = tosbits | (unsigned char)2;
tosbits = iph->tos;
printk(KERN_ALERT " The tos bits are : %d\n" , (int)tosbits);
printk(KERN_ALERT " The total length is : %d\n" , (int)iph->tot_len);
}
return NF_ACCEPT;
}
//===========================================================
//Initialisation function
static int __init init(void){
printk(KERN_ALERT " Initialization Started \n");
// Initialize Hook Functions
nf_ops_out.hook = tos_setter;
nf_ops_out.pf = PF_INET;
nf_ops_out.hooknum =4;
nf_ops_out.priority = NF_IP_PRI_FIRST;
// Register the Hook functions
nf_register_hook(&nf_ops_out);
printk(KERN_ALERT "hook functions registered\n");
printk(KERN_ALERT " KSTAT Initialization Completed \n");
return 0;
}
static void __exit cleanup(void){
printk(KERN_ALERT "KSTAT Exit Started\n");
// Unregister the hook functions
nf_unregister_hook(&nf_ops_out);
printk("Unregistered the hooks\n");
printk(KERN_ALERT "KSTAT Exit Completed\n");
}
/* init and cleanup functions */
module_init(init);
module_exit(cleanup);
MODULE_LICENSE("GPL");
//包括所需的头文件
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
//定义模块的名称
#定义模块名称“TOS设置器”
//用于处理传出数据包的结构定义
静态结构nf_hook_ops nf_ops_out;
//===========================================================
//修改TOS位的函数
unsigned int-tos_setter(unsigned int-hooknum,struct sk_buff*skb,const-struct-net_-device*in,
常量结构网络设备*out,int(*okfn)(结构sk\u buff*))
{
结构iphdr*iph;
无符号字符比特;
如果(!skb)返回NF_接受;
iph=ip_hdr(skb);
如果(!iph)返回NF_ACCEPT;
//如果(iph->protocol==IPPROTO\u TCP)返回NF\u ACCEPT;
如果(iph->协议==IPPROTO_TCP)
{
printk(KERN\u ALERT“总长度为:%d\n”,(int)iph->tot\u len);
iph->tos=tosbits |(无符号字符)2;
tosbits=iph->tos;
printk(KERN_ALERT“tos位为:%d\n”,(int)tos位);
printk(KERN\u ALERT“总长度为:%d\n”,(int)iph->tot\u len);
}
返回NF_接受;
}
//===========================================================
//初始化功能
静态int uu init init(void){
printk(内核警报“初始化已启动”\n);
//初始化钩子函数
nf_ops_out.hook=tos_setter;
nf_ops_out.pf=pf_INET;
nf_ops_out.hooknum=4;
nf_ops_out.priority=nf_IP_PRI_FIRST;
//注册钩子函数
nf_寄存器_挂钩(&nf_操作_输出);
printk(KERN_ALERT“hook functions registered\n”);
printk(KERN_警报“KSTAT初始化完成”\n);
返回0;
}
静态void uu退出清理(void){
printk(KERN_警报“KSTAT退出已启动”\n);
//注销钩子函数
nf_取消注册_挂钩(&nf_操作_退出);
printk(“未注册挂钩”);
printk(KERN_警报“KSTAT退出已完成”\n);
}
/*初始化和清除函数*/
模块_init(init);
模块_出口(清理);
模块许可证(“GPL”);
问题是,当我试图改变tos位的值时,我的互联网停止工作。
是否有其他方法,或者如果有人能指出我做错了什么,这将非常有帮助。在更改报头中的任何内容后,您必须重新计算IP报头校验和 见WP:
代码如下:您可以使用增量IP校验和,即:由于IP校验和是一个和,您可以减去旧值并添加新值。Linux通过
net/checksum.h
中的csum\u replace*()
函数支持这一点。只要做:
csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));