全部博文(24)
分类: LINUX
2010-11-03 17:11:59
skb_buff(内核2.6.18)
(1) skb_buff中数据长度的讨论
skb_buff中有两个数据长度:len,data_len;
len=skb->tail-skb->data+data_len,它包括主缓冲区中的数据长度(data指针指向它)和分片中的数据长度;
data_len只计算分片中数据的长度,即struct ip_shared_info中有效数据总长度(包括frag_list,frags[]中的扩展数据);显然随着数据到达不同的层,len的值会随着改变。
(2)skb_buff中数据部分的获取
在ip层,sk_buff中skb_head,skb->data,skb->tail,skb->end的位置如下图所示
数据包在不同的层,skb_data指向的是当前层的头;在IP层要获得tcp payload,则计算指针偏移量如下:
char *data;
struct iphdr *iph;
struct tcphdr *th;
iph=skb->nh.iph;
th=(struct tcphdr*)((__u32*)iph+iph->ihl);//TCP头
data=(char*)((__u32*)th+th->doff);//数据的起始地址
注:iph->ihl为32位字个数,ip头长度为20字节则此值为5;
th->doff为32位字个数,ip头总长度为th->doff,单位是字。
skb_buff(内核2.6.24以上)
skb_buff中将2.6.18中的n,nh和mac改变为
sk_buff_data_t transport_header;
sk_buff_data_t network_header;
sk_buff_data_t mac_header;
它提供了分别是传输层头,网络层头以及mac头相对于sk_buff的head的偏移量。
故针对不同的内核版本程序可能不同,可以用下段程序避免内核版本的不同。
钩子位于IP层
char *data;
struct iphdr *iph;
struct tcphdr *th;
iph=ip_hdr(skb);
th=(struct tcphdr*)((__u32*)iph+iph->ihl);//TCP头
data=(char*)((__u32*)th+th->doff);//数据的起始地址
那么data到skb->tail这段buffer就是我们要的数据。