我在功能的/net/core/dev.c文件中捕获了网络数据包__netif_receive_skb_core()
。我解析数据包并提取src_port
,dest_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 = %d\n", __LINE__);
}
}
我看不到您在何处以及如何打印或比较端口(也许您在某处打印src_port
和dest_port
或fast_node->org_srcport
并fast_node->org_destport
带有的%u
指定符printk
)。
但是,你必须考虑到端口的TCP和UDP报头是没有1个字节的字段(它有2个字节长度),所以它具有字节顺序。具体来说是网络字节顺序。
这就是为什么在打印时按主机字节顺序查看端口的原因,应该使用特殊功能来交换字节ntohs()
-网络到主机短。粗略地说,“短”表示该函数适用于2字节变量。
因此,最后,如果您需要打印端口,应该是这样的:
printk(KERN_INFO "sport:%u dport:%u\n", ntohs(src_port), ntohs(dest_port));
以及是否需要比较:
if (ntohs(dest_port) == 53)
顺便说一句,network_header
并且transport_header
必须在您通过ip_hdr()
/ tcp_hdr()
/ 访问标头时设置udp_hdr()
,否则返回的指针可能无效。
另外,您还必须注意如何在内核内部的不同位置分配内存。
__netif_receive_skb_core()
在原子上下文中执行,因此您无法在这里睡觉。GFP_KERNEL
标志允许进行一些睡眠kmalloc()
,因此您有一个错误。更改GFP_KERNEL
为GFP_ATOMIC
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句