我有一个简单的netfilter模块来测试icmp_hdr功能:
unsigned int hook_func(
unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
const struct iphdr *ip_header = ip_hdr(skb);
if (ip_header && ip_header->protocol == IPPROTO_ICMP)
{
const struct icmphdr *icmp_header = icmp_hdr(skb);
printk(KERN_INFO "ICMP type %d", icmp_header->type);
}
return NF_ACCEPT;
}
static int __init startup(void)
{
hook_ops.hook = hook_func;
hook_ops.hooknum = NF_INET_PRE_ROUTING;
hook_ops.pf = PF_INET;
hook_ops.priority = NF_IP_PRI_FIRST;
nf_register_hook(&hook_ops);
return 0;
}然后我开始PING主机。
在CentOS 6 (2.6.32-754.12.1.el6.x86_64)上,他打印的ICMP类型始终为69 (INVALID)。
在CentOS 7 (3.10)上,结果是ICMP_ECHO (8),这是正确的。
有什么想法吗?2.6.32内核中有没有bug?
发布于 2019-09-18 18:46:25
上面提到的Linux内核之间有一些不同。在3.10内核中,我们可以看到ip_rcv()中的传输头设置是这样的:
skb->transport_header = skb->network_header + iph->ihl*4;因此,在NF_INET_PRE_ROUTING钩子之前就已经设置了传输头。
在2.6内核中,我没有看到任何类似于ip_local_deliver_finish()的东西
__skb_pull(skb, ip_hdrlen(skb));
/* Points to the IP datagram, just past the header. */
skb_reset_transport_header(skb);就在NF_INET_LOCAL_IN hooks之后。因此,在2.6.32内核中,你似乎不能以这种方式访问ICMP-header。但您可以轻松地进行一些解决方法:)
https://stackoverflow.com/questions/57983349
复制相似问题