skb中的端口信息不';t与tcpdump';是一个
我在函数skb中的端口信息不';t与tcpdump';是一个,c,linux,networking,linux-kernel,network-programming,C,Linux,Networking,Linux Kernel,Network Programming,我在函数\uu netif\u receive\u skb\u core()的/net/core/dev.c文件中捕获网络数据包。我解析数据包并获取src_端口,dest_端口,等等。我在任何接口上获取了tcpdump。但是tcpdump的端口信息与我获取的端口信息不匹配。我不明白为什么 orig_dev = skb->dev; eth = eth_hdr(skb); __be16 src_port = 0, dest_port = 0; if (skb->protocol ==
\uu netif\u receive\u skb\u core()
的/net/core/dev.c文件中捕获网络数据包。我解析数据包并获取src_端口
,dest_端口
,等等。我在任何接口上获取了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 = %d\n", __LINE__);
}
}
我看不到您打印或比较端口的位置和方式(可能您在某处打印
src\u端口
和dest\u端口
或fast\u节点->org\u srcport
和fast\u节点->org\u destport
与%u
printk的说明符)。但您必须考虑到端口in和头是非1字节字段(它有2个字节的长度),所以它有。特别是网络字节顺序。
这就是为什么要在打印时按主机字节顺序查看端口,应使用特殊功能交换字节——网络到主机短。粗略地说,“short”意味着is函数用于2字节变量 最后,如果您需要打印端口,它应该是:
printk(KERN_INFO "sport:%u dport:%u\n", ntohs(src_port), ntohs(dest_port));
如果您需要比较:
if (ntohs(dest_port) == 53)
顺便说一句,必须在通过ip\u hdr()
/tcp\u hdr()
//udp\u hdr()
访问标头时设置网络标头
和传输标头
,否则返回的指针可能无效
您还必须注意如何在内核中的不同位置分配内存。
\uu netif\u receive\u skb\u core()
在原子上下文中执行,所以您不能在这里睡觉。标志允许对kmalloc()
进行一些睡眠,因此您有一个bug。将GFP\u内核更改为。我看不到打印或比较端口的位置和方式(可能您在某处打印src\u端口和dest\u端口或fast\u节点->org\u srcport
和fast\u节点->org\u destport
与%u
printk
的说明符)。
但您必须考虑到端口in和头是非1字节字段(它有2个字节的长度),所以它有。特别是网络字节顺序。
这就是为什么要在打印时按主机字节顺序查看端口,应使用特殊功能交换字节——网络到主机短。粗略地说,“short”意味着is函数用于2字节变量
最后,如果您需要打印端口,它应该是:
printk(KERN_INFO "sport:%u dport:%u\n", ntohs(src_port), ntohs(dest_port));
如果您需要比较:
if (ntohs(dest_port) == 53)
顺便说一句,必须在通过ip\u hdr()
/tcp\u hdr()
//udp\u hdr()
访问标头时设置网络标头
和传输标头
,否则返回的指针可能无效
您还必须注意如何在内核中的不同位置分配内存。
\uu netif\u receive\u skb\u core()
在原子上下文中执行,所以您不能在这里睡觉。标志允许对kmalloc()
进行一些睡眠,因此您有一个bug。将GFP_内核更改为。您所说的“函数中的捕获包”是什么意思?您修补了内核,即将代码添加到此函数?是的,我将代码添加到内核中,并希望在链接列表中加载收到的skb信息(srcport、destport等)。但srcport和目标端口当时与tcp转储不匹配。例如,我提出了许多dns请求。在tcp转储中,所有请求都有目标端口53,但在我的链接列表中,我没有得到目标端口53的数据包。您所说的“函数中捕获数据包”是什么意思?您修补了内核,即将代码添加到此函数?是的,我将代码添加到内核中,并希望在链接列表中加载收到的skb信息(srcport、destport等)。但srcport和目标端口当时与tcp转储不匹配。例如,我提出了许多dns请求。在tcp转储中,所有请求都有目标端口53,但在我的链接列表中,我没有得到目标端口53的数据包。顺便说一句,必须在访问这些数据头时设置network_头和transport_头。我不明白。请解释。@Nayanskb->network\u header
和skb->transport\u header
偏移量必须由网络堆栈正确设置。如果未设置-ip_hdr()
&co将返回无效指针。因此,您应该将代码嵌入到已设置偏移的正确位置。我不知道你的代码在哪里,因为你没有在问题中描述它。所以这只是一个预先警告..案例IPPROTO_UDP:{struct udphdr*uh=UDP_hdr(skb);src_port=uh->source;dest_port=uh->dest;printk(KERN_INFO“sport:%u dport:%u\n”,ntohs(src_port),ntohs(dest_port));break;}src_port为所有数据包打印一个固定值(17664)。dest_端口随数据包的变化而变化,但为什么源端口从不变化,尽管在tcpdump中我得到了不同的srcport。@Nayan您如何准确地将tcpdump
中的数据包映射到从内核打印的数据包?我认为linux路由器会接收netif_receive_skb_核心函数中的所有数据包,并使用相同的目标端口发送这些数据包(接收时与目标端口相同)通过uuu dev_queue_xmit。我对不对?顺便说一句,网络头和传输头必须在您访问头时设置。我无法理解。请解释。@Nayanskb->network_头
和skb->transport_头
偏移量必须由网络堆栈正确设置。如果未设置-ip_hdr()
&co将返回无效的指针。因此,您应该将代码嵌入到已设置偏移量的正确位置。我不知道您的代码位于何处,因为您在问题中没有对其进行描述。因此,这只是一个预先警告。..case IPPROTO_UDP:{struct udphdr*uh=UDP_hdr(skb);src_port=uh->source;dest_port=uh->dest;printk(KERN_INFO“sport:%u dport:%u\n”、ntohs(src_port)、ntohs(dest_port));break;}src_port为