gpt4 book ai didi

c - 从 struct sk_buff 中提取数据

转载 作者:太空宇宙 更新时间:2023-11-04 07:31:11 24 4
gpt4 key购买 nike

我正在尝试从 struct sk_buff 中提取数据,但没有收到我期望的输出。有问题的帧是 34 字节;一个 14 字节的以太网 header 包裹着一个 8 字节(实验协议(protocol)) header :

struct monitoring_hdr {
u8 version;
u8 type;
u8 reserved;
u8 haddr_len;

u32 clock;
} __packed;

在这个 header 之后,有两个可变长度的硬件地址(它们的长度由上面的 haddr_len 字段决定)。在此处的示例中,它们都是 6 个字节长。

以下代码正确提取了 header (结构),但未正确提取后面的两个 MAC 地址。

发送方:

    ...
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);
...

接收方:

   ...
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);
...

预期输出:

我使用 tcpdump 在网络上捕获了有问题的数据包,并看到了这个(它实际上被发送者的 NIC 填充到 60 字节,我已经省略了):

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

前 14 个字节是以太网 header 。接下来的8个字节(01开始,88结束)应该是放入struct monitoring_hdr中的字节,可以正确执行。然后,我希望找到以下 MAC 地址:

src = 00 0e c6 89 04 2f
dst = 00 90 f5 c6 44 5b

实际输出:

但是,我收到的数据向左移动了两个字节:

src = 8c 88 00 0e c6 89
dst = 04 2f 00 90 f5 c6

谁能看出上面代码中的逻辑缺陷?或者有更好的方法吗?我还在接收端尝试用 skb_pull 代替 skb_network_header,但这导致了内核 panic 。

在此先感谢您的帮助。

解决方案:

指向 sk_buff 中数据第一个字节的指针没有被 src 指向,因为它应该是这样。我最终使用了以下内容:

   ...
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);
...

最佳答案

查看 skbuff.h header ,您正在使用的功能如下所示:

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;
}

首先,我会尝试打印出 skb->dataskb->head 以确保它们引用了您期望它们引用的数据包部分。由于您在此处使用的是自定义协议(protocol),因此 header 处理代码中可能存在错误,导致 skb->data 设置不正确。

此外,查看 sky_network_headerskb_pull 的定义让我觉得您可能没有正确使用它们。第一个 6 字节地址不应该在指向 skb_network_header() 返回值的位置吗?看起来该函数将 header block 的长度添加到缓冲区的头部,这应该会导致指向您的第一个数据值的指针。

类似地,它看起来像skb_pull() 添加您传入的字段的长度并返回指向下一个字节的指针。所以你可能想要更像这样的东西:

src = skb_network_header(skb);
dst = skb_pull(skb, nwp->haddr_len);

希望对您有所帮助。很抱歉,这不是一个准确的答案。

关于c - 从 struct sk_buff 中提取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13664783/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com