diffs[0] = htons((*pskb)->nh.iph->id) ^0xFFFF;
(*pskb)->nh.iph->id

= idinfo->id;
diffs[1] = htons((*pskb)->nh.iph->id);
// 由于IP包数据进行了修改,需要重新计算IP头中的校验和
(*pskb)->nh.iph->check
= csum_fold(csum_partial((char*)diffs,
sizeof(diffs),
(*pskb)->nh.iph->check
^0xFFFF));
(*pskb)->nfcache |= NFC_ALTERED;
}
// 返回IPT_CONTINUE,表示继续按下一条规则处理数据包
return IPT_CONTINUE;
}static int
checkentry(const char *tablename,
const struct ipt_entry *e,
void*targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
{
const u_int8_t id = ((struct ipt_id_target_info*)targinfo)->id;
// 检查用户传入数据的长度是否正确
if (targinfosize != IPT_ALIGN(sizeof(structipt_id_target_info))) {
printk(KERN_WARNING "ID: targinfosize %u != %Zun",
targinfosize,
IPT_ALIGN(sizeof(struct ipt_id_target_info)));
return 0;
}
// 判断是否在mangle表中
if (strcmp(tablename, "mangle") != 0) {
printk(KERN_WARNING "ID: can only be called from"mangle" table, not
"%s"n", tablename);
return 0;
}
return 1;
}
static struct ipt_target ipt_id_reg = {
.name= "ID",
.target= target,
.checkentry= checkentry,
.me= THIS_MODULE,
};
static int __init init(void)
{
return ipt_register_target(&ipt_id_reg);
}
static void __exit fini(void)
{
ipt_unregister_target(&ipt_id_reg);
}
module_init(init);
module_exit(fini);
如果对包中的数据进行了修改,需要修改数据头相应的校验和,如IP头校验和和TCP/UDP头校验和,所以可能会需要调用如csum_partial(),tcp_v4_check(),csum_tcpudp_magic(),ip_send_check(iph)等函数计算校验和,这些函数的使用方法可参考内核中的代码实例。
有些目标对包的操作比较复杂,如REJECT,MIRROR等,需要构造回应包发出,所以一般目标要比匹配要复杂一些。
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-34719-4.html
終於回來了