linux 2.6.26 下获取tcp信息:
tcph=skb_header_pointer(skb, protoff, sizeof(tcph), &tcph); //skb_header_pointer是个库函数
skb_header_pointer函数
该函数本身很简单,定义如下:
/* #include <linux/skbuff.h>*/
static inline void *skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer)
{
int hlen = skb_headlen(skb);
if (hlen - offset >= len)
return skb->data + offset;
if (skb_copy_bits(skb, offset, buffer, len) < 0)
return NULL;
return buffer;
}
其中参数为:
skb:数据包struct sk_buff的指针
offset:相对数据起始头(如IP头)的偏移量
len:数据长度
buffer:缓冲区,大小不小于len
其中skb_headlen()定义为:
/* #include <linux/skbuff.h> */
static inline unsigned int skb_headlen(const struct sk_buff *skb)
{
return skb->len - skb->data_len;
}
其中skb->len是数据包长度,在IPv4中就是单个完整IP包的总长,但这些数据并不一定都在当前内存页;skb->data_len表示在其他页的数据长度,因此skb->len - skb->data_len表示在当前页的数据大小。
/* net/core/skbuff.c */
/* Copy some data bits from skb to kernel buffer. */
int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len)
{
int i, copy;
int start = skb_headlen(skb);
if (offset > (int)skb->len - len)
goto fault;
/* Copy header. */
if ((copy = start - offset) > 0) {
// 拷贝在当前页面中的部分
if (copy > len)
copy = len;
memcpy(to, skb->data + offset, copy);
if ((len -= copy) == 0)
return 0;
offset += copy;
to += copy;
}
// 拷贝本skb中其他碎片中的部分
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
int end;
BUG_TRAP(start <= offset + len);
end = start + skb_shinfo(skb)->frags[i].size;
if ((copy = end - offset) > 0) {
u8 *vaddr;
if (copy > len)
copy = len;
vaddr = kmap_skb_frag(&skb_shinfo(
iphdr与tcphdr详解(skb_header_pointer函数分析)
最新推荐文章于 2021-10-08 10:05:51 发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)