c语言 - skb 中的端口信息与 tcpdump 的端口信息不匹配



我在函数__netif_receive_skb_core()/net/core/dev.c文件中捕获网络数据包。我解析数据包并获取src_portdest_port等。我在任何接口上都使用了tcpdump。但是tcpdump的端口信息与我获取的端口信息不匹配。我不明白为什么。

orig_dev = skb->dev;
eth = eth_hdr(skb);
__be16 src_port = 0, dest_port = 0; 
if (skb->protocol == htons(ETH_P_IP))
{
ih = ip_hdr(skb);
proto_num = ih->protocol;
switch (ih->protocol)
{
case IPPROTO_TCP:
{
struct tcphdr *th = tcp_hdr(skb);
src_port = th->source;
dest_port = th->dest;
break;
}
case IPPROTO_UDP:
{
struct udphdr *uh = udp_hdr(skb);
src_port = uh->source;
dest_port = uh->dest;
break;
}
default:
src_port = 0;
dest_port = 0;
}
fast_node = NULL;
fast_node = (struct fast_pktlist *)kzalloc(sizeof(*fast_node), GFP_KERNEL);
if (fast_node)
{
fast_node->protocol_num = proto_num;
strcpy(fast_node->in_interface, orig_dev->name);
fast_node->orgsrc_ip = ih->saddr;
fast_node->orgdest_ip = ih->daddr;
memcpy(fast_node->orgsrc_mac, eth->h_source, 6);
fast_node->org_srcport = src_port;
fast_node->org_destport = dest_port;
INIT_LIST_HEAD(&fast_node->_list);
list_add_tail(&fast_node->_list, &FAST_HEAD);
}
else
{
printk("can not allocate memory at line number = %dn", __LINE__);
}
}

我看不出在哪里以及如何打印或比较端口(也许您在某个地方打印了src_portdest_port,或者fast_node->org_srcportfast_node->org_destport,其中%u说明符为printk(
但您必须考虑到TCP和UDP标头中的端口不是1字节字段(长度为2字节(,因此它具有endianness。特别是网络字节顺序
这就是为什么要在打印时按主机字节顺序查看端口,您应该使用特殊功能来交换字节-ntohs()-网络到主机短。粗略地说;短";意味着is函数适用于2字节的变量。

所以最后,如果你需要打印端口,它应该是这样的:

printk(KERN_INFO "sport:%u dport:%un", ntohs(src_port), ntohs(dest_port));

如果你需要比较:

if (ntohs(dest_port) == 53)

BTWnetwork_headertransport_header必须在您通过ip_hdr()/tcp_hdr()/udp_hdr()访问标头时设置,否则返回的指针可能无效。


此外,您必须注意如何在内核内的不同位置分配内存
__netif_receive_skb_core()原子上下文中执行,因此您无法在此睡眠。GFP_KERNEL标志允许kmalloc()有一些睡眠,因此您有一个错误。将GFP_KERNEL更改为GFP_ATOMIC

最新更新