icmp_hdr 在 CentOS 6 内核上是错误的
icmp_hdr is wrong on CentOS 6 kernels
我有一个简单的 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吗?
提到的 Linux 内核之间存在一些差异。
在 3.10 内核中我们可以看到 ip_rcv()
中的传输 header 设置是这样的:
skb->transport_header = skb->network_header + iph->ihl*4;
因此传输 header 已经在 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
钩子之后。因此,您似乎无法在 2.6.32 内核上提到的挂钩中以这种方式访问 ICMP-header。但是您可以轻松地做出一些解决方法:)
我有一个简单的 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吗?
提到的 Linux 内核之间存在一些差异。
在 3.10 内核中我们可以看到 ip_rcv()
中的传输 header 设置是这样的:
skb->transport_header = skb->network_header + iph->ihl*4;
因此传输 header 已经在 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
钩子之后。因此,您似乎无法在 2.6.32 内核上提到的挂钩中以这种方式访问 ICMP-header。但是您可以轻松地做出一些解决方法:)