从结构sk_buff中提取数据 [英] Extracting data from struct sk_buff
问题描述
我试图从结构的sk_buff
中提取数据,但没有收到我期待的输出。所讨论的帧是34字节;一个14字节的以太网首部周围的8个字节(实验协议)报头包
结构monitoring_hdr {
U8版本;
U8型;
U8保留;
U8 haddr_len; U32时钟;
} __packed;
这个头之后,有两种,可变长度的硬件地址(其长度由 haddr_len
字段上方决定)。在这里的例子中,它们都是6个字节长。
以下code提取头(结构体)正确,但不是说跟着两个MAC地址。
发送方:
...
SKB = alloc_skb(MTU,GFP_ATOMIC);
如果(不太可能(!SKB))
返回;
skb_reserve(SKB,ll_hlen);
skb_reset_network_header(SKB);
NWP =(结构monitoring_hdr *)skb_put(SKB,hdr_len);
在结构monitoring_hdr / * ...设置领域... * /
的memcpy(skb_put(SKB,dev亡> addr_len),SRC,dev亡> addr_len);
的memcpy(skb_put(SKB,dev亡> addr_len),DST,dev亡> addr_len);
...
接收侧:
...
skb_reset_network_header(SKB);
NWP =(结构monitoring_hdr *)skb_network_header(SKB); SRC = skb_pull(SKB,nwp-> haddr_len);
DST = skb_pull(SKB,nwp-> haddr_len);
...
期望的输出:
我使用tcpdump的捕捉上线问题的数据包,并看到这个(它实际上是由发件人的NIC,我已经省略填充到60字节):
0000 | 00 90 F5 C6 44 5B 00 0E 89 C6 04 2F C0 DF 01 03
0010 | 00 06 D0 BA 8C 88 0E 00 89 6 04 00 2F 90 F5 C6
0020 | 44 5B
第14个字节是以太网报头。下面的8个字节(从 01
和结束 88
)应放入<$ C $字节C>结构monitoring_hdr ,它正确执行。然后,我期待下面的MAC地址为:
SRC = 00 0E 89 C6 04 2F
DST = 00 90 F5 C6 44 5B
实际输出:
但是,我接收移位两个字节左侧的数据:
SRC = 8C 88 00 0E 89 C6
DST = 04 2F 00 90 F5 C6
有人能看到上面code逻辑缺陷?还是有更好的方式来做到这一点?我也试过 skb_pull
在 skb_network_header
的接收方,但导致内核崩溃。
感谢您事先的任何帮助。
SOLUTION
的指针数据在的sk_buff
没有被指向的src
作为第一个字节它本来应该。我最终使用以下内容:
...
skb_reset_network_header(SKB);
NWP =(结构monitoring_hdr *)skb_network_header(SKB);
skb_pull(SKB,offsetof(结构monitoring_hdr,haddrs_begin)); SRC =&是skb- GT;数据;
DST = skb_pull(SKB,nwp-&GT; haddr_len);
...
综观的 skbuff.h中头,您使用的是看起来像这样的功能:
静态内嵌无效skb_reset_network_header(结构的sk_buff * SKB)
{
&是skb- GT; network_header =&是skb- GT;数据 - - 是skb- GT;头;
}静态内嵌无符号字符* skb_network_header(常量结构的sk_buff * SKB)
{
返回&是skb- GT;头+&是skb- GT; network_header;
}的extern unsigned char型* skb_pull(结构的sk_buff * SKB,无符号整型LEN);
静态内嵌无符号字符* __ skb_pull(结构的sk_buff * SKB,无符号整型LEN)
{
&是skb- GT; LEN - = len个;
BUG_ON(&是skb- GT; LEN&LT;&是skb- GT; DATA_LEN);
返回&是skb- GT;数据+ = LEN;
}
因此,首先,我会试着打印出是skb-&GT;数据
和是skb-&GT;头
制作确保它们在引用您希望他们包的部分。既然你在这里使用的是自定义协议,也许是在头处理code的一个错误,这是造成是skb-方式&gt;数据
来设置不正确
另外,在看的定义sky_network_header
和 skb_pull
让我觉得也许你没有正确使用它们。如果不是第6个字节的地址是在所指向的位置是的skb_network_header返回值()
?这看起来函数添加报头块的长度的缓冲区的头部,这将导致的指针的第一数据值
同样,它看起来像 skb_pull()
添加字段的长度你传递和返回指向下一个字节。所以,你可能要像这样的东西更多:
SRC = skb_network_header(SKB);
DST = skb_pull(SKB,nwp-&GT; haddr_len);
我希望帮助。对不起,这不是一个确切的答案。
I'm attempting to extract data from a struct sk_buff
, but have not received the output I am expecting. The frame in question is 34 bytes; a 14-byte Ethernet header wrapped around an 8-byte (experimental protocol) header:
struct monitoring_hdr {
u8 version;
u8 type;
u8 reserved;
u8 haddr_len;
u32 clock;
} __packed;
After this header, there are two, variable-length hardware addresses (their lengths are dictated by the haddr_len
field above). In the example here, they are both 6 bytes long.
The following code extracts the header (the struct) correctly, but not the two MAC addresses that follow.
Sender side:
...
skb = alloc_skb(mtu, GFP_ATOMIC);
if (unlikely(!skb))
return;
skb_reserve(skb, ll_hlen);
skb_reset_network_header(skb);
nwp = (struct monitoring_hdr *)skb_put(skb, hdr_len);
/* ... Set up fields in struct monitoring_hdr ... */
memcpy(skb_put(skb, dev->addr_len), src, dev->addr_len);
memcpy(skb_put(skb, dev->addr_len), dst, dev->addr_len);
...
Receiver side:
...
skb_reset_network_header(skb);
nwp = (struct monitoring_hdr *)skb_network_header(skb);
src = skb_pull(skb, nwp->haddr_len);
dst = skb_pull(skb, nwp->haddr_len);
...
Expected output:
I used tcpdump to capture the packet in question on the wire, and saw this (it was actually padded to 60 bytes by the sender's NIC, which I've omitted):
0000 | 00 90 f5 c6 44 5b 00 0e c6 89 04 2f c0 df 01 03
0010 | 00 06 d0 ba 8c 88 00 0e c6 89 04 2f 00 90 f5 c6
0020 | 44 5b
The first 14 bytes is the Ethernet header. The following 8 bytes (starting with 01
and ending with 88
) should be the bytes put into the struct monitoring_hdr
, which executes correctly. Then, I am expecting the following MAC addresses to be found:
src = 00 0e c6 89 04 2f
dst = 00 90 f5 c6 44 5b
Actual output:
However, the data that I receive is shifted two bytes to the left:
src = 8c 88 00 0e c6 89
dst = 04 2f 00 90 f5 c6
Can anyone see a logical flaw in above code? Or is there a better way to do this? I've also tried skb_pull
in place of skb_network_header
on the receiving side, but that resulted in a kernel panic.
Thanks in advance for any help.
SOLUTION:
The pointer to the first byte of the data in the sk_buff
was not being pointed to by src
as it should have been. I ended up using the following:
...
skb_reset_network_header(skb);
nwp = (struct monitoring_hdr *)skb_network_header(skb);
skb_pull(skb, offsetof(struct monitoring_hdr, haddrs_begin));
src = skb->data;
dst = skb_pull(skb, nwp->haddr_len);
...
Looking at the skbuff.h header, the functions you are using look like this:
static inline void skb_reset_network_header(struct sk_buff *skb)
{
skb->network_header = skb->data - skb->head;
}
static inline unsigned char *skb_network_header(const struct sk_buff *skb)
{
return skb->head + skb->network_header;
}
extern unsigned char *skb_pull(struct sk_buff *skb, unsigned int len);
static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len)
{
skb->len -= len;
BUG_ON(skb->len < skb->data_len);
return skb->data += len;
}
So first, I would try printing out skb->data
and skb->head
to make sure they are referencing the parts of the packet you expect them to. Since you are using a custom protocol here, perhaps there is a bug in the header processing code which is causing skb->data
to be set incorrectly.
Also, looking at the definitions of sky_network_header
and skb_pull
makes me think perhaps you are using them incorrectly. Shouldn't the first 6-byte addr be at the location pointed to be the return value of skb_network_header()
? It looks like that function adds the length of the header block to the head of the buffer, which should result in a pointer to your first data value.
Similarly, it looks like skb_pull()
adds the length of the field you pass in and returns the pointer to the next byte. So you probably want something more like this:
src = skb_network_header(skb);
dst = skb_pull(skb, nwp->haddr_len);
I hope that helps. I'm sorry that this is not an exact answer.
这篇关于从结构sk_buff中提取数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!