内核数据包处理文档格式.docx
《内核数据包处理文档格式.docx》由会员分享,可在线阅读,更多相关《内核数据包处理文档格式.docx(14页珍藏版)》请在冰豆网上搜索。
1)__netif_receive_skb()在进入三层处理前就对network_header进行了设置。
2)ip_rcv()中详细的检查保证了IP头部到netfilter后是完整的。
ﻩ3)netfilter可以尽情使用ip头部。
ﻩ获取tcp头部
错误1:
tcph=tcp_hdr(skb);
陷阱:
netfilter的钩子点是属于TCP/IP协议栈的三层流程中,而四层的TCP头部此时还没有正确获取,只是初始化为IP头部的值,无法直接使用。
ﻩ错误2:
tcph=(char*)iph+(iph->
ihl<
<
2);
陷阱:
数据包可能是非线性的
ﻩ改进:
tcpoff=skb_network_offset(skb)+(iph->
tcph=skb_header_pointer(skb,tcpoff,sizeof(_tcph),&
_tcph);
if(tcph==NULL)
return;
接口介绍:
skb_network_offset(structskb_buff*skb)
计算三层头部相对于skb->
data的偏移
void*skb_header_pointer(structsk_buff*skb,intoffset,intlen,void*buffer)
ﻩ从skb的指定偏移取制定长度的数据,如果要取的数据位于线性区,直接返回其开始指针,否则,则拷贝到buffer中,并将buffer指针返回。
printk("
%pI4%d----->
%pI4%dlen:
%dID:
%d\n"
&
iph->
saddr,
ntohs(tcph->
source),
daddr,
dest),
ntohs(iph->
tot_len),
id));
打印信息
注意要点:
ﻩ1)IP地址输出
ﻩﻩIpv4:
%pI4 %pi4
ﻩﻩIPv6:
%pI6 %pi6
2) MAC地址
ﻩ%pM %pm
ﻩ3)字节序的转换
ﻩﻩntohs() ntohl()htons() htonl()
ﻩﻩ__const_ntohl()__const_ntohs() __const_htonl() __const_htons()
ﻩ区别:
__const_*()是编译时处理的。
获取TCP负载
风险:
payload=(char*)tcph+tcph->
doff*4;
陷阱1:
数据包可能是非线性的,同TCP头部。
陷阱2:
TCP头部数据有可能是被篡改过的,tcph->doff如果很大怎么办?
改进1:
tcplen=skb->
len-tcpoff;
if(tcph->
doff*4<
sizeof(structtcphdr)||tcplen<
tcph->
doff*4)
{
printk("
Badtcp.\n"
);
returnNF_ACCEPT;
if(skb_is_nonlinear(skb))
Nonlinearskb.\n"
payload_len=tcplen-tcph->
if(payload_len==0)
接口介绍:
intskb_is_nonlinear(structsk_buff*skb)
判断skb的数据是否是非线性的
ﻩ改进2:
charpayload_buf[1500];
if(payload_len>
sizeof(payload_buf))
payload=skb_header_pointer(skb,tcpoff+tcph->
doff*4,payload_len,payload_buf);
if(payload==NULL)
改进3:
if(skb_linearize(skb))
Cannotlinearizeskb.\n"
intskb_linearize(structsk_buff*skb)
ﻩ将skb线性化
解析数据
ﻩ1)判断数据包内容
风险1:
if(payload[0]!
='
G'
||payload[1]!
E'
||payload[2]!
T'
)
风险2:
if((payload[0]=='
&
&
payload[1]=='
payload[2]=='
)&
payload_len==3)
ﻩ如果payload的长度只有1个字节怎么办?
改进:
if(payload_len<
3||payload[0]!
ﻩ2)查找数据包中的某个字符串
ﻩ风险:
host=strstr(payload,"
Host:
"
可能会越界,数据包不一定是以'
\0'结束。
host=strnstr(payload,"
payload_len);
if(host==NULL)
return;
ﻩ一定要使用这一系列的函数:
strnchr
ﻩstrncpy
ﻩstrncat
strncmp
strnicmp
ﻩstrnlen
memcpy
3)移动指向数据包的指针
ﻩ风险:
host=host+sizeof("
)-1;
/*
*dealwithhost
*/
ﻩ查找的字符串有可能是数据包的最后一部分。
if(host>
=(payload+payload_len))
ﻩ4)数据包操作
错误:
u32len;
len=payload_len-512;
if(len<
=0)
memcpy(buf,payload,len);
ﻩ陷阱:
无符号数的强制类型转换,u32类型永远都是大于等于0的,当payload_len小于512时,判断就会不生效。
改进:
=512)
或者
intlen;
ﻩ5)
风险:
intlen=payload[1];
memcpy(buf,&
payload[2],len);
ﻩ可能是异常数据包,offset不是你想要的
ﻩ正确做法:
if(len>
=payload_len-2)
ﻩ综述:
数据包处理要时刻保持警醒,它可能不是你想象的样子!
ﻩ内存分配
void*xxx_alloc(unsignedlongsize,gfp_tflags)
intmalloc_size=size+sizeof(unsignedlong);
void*p;
if(memory_use+malloc_size>
memory_max)
return;
p=kmalloc(malloc_size,flags);
if(p==NULL)
returnNULL;
memory_u