我正在编写网络设备驱动程序
内核2.6.35.12
当设备连接到桥接端口时,设备应该正常工作。
我试图拦截从桥接器转发到接口的ICMPv6 RA和NS消息(路由器/邻居请求)。
eth< - > br0< - > mydevice
在设备start_xmit函数中,我正在做以下操作:
检查以太网报头后的协议字段是否为IPV6(0x86dd)
检查ipv6 next标头是否为ICMPv6并检查其类型:
__u8 nexthdr = ipv6_hdr(skb)->nexthdr;
if (nexthdr == htons (IPPROTO_ICMPV6))
{
struct icmp6hdr *hdr = icmp6_hdr(skb);
u8 type = hdr->icmp6_type;
if(type == htons (NDISC_NEIGHBOUR_SOLICITATION) || type == htons (NDISC_ROUTER_SOLICITATION))
{
….Do something here…
}
}
当从设备内发送RS / NS时(例如br0),我看到代码正常工作。
问题是当流量从另一个端口通过网桥转发时。
我看到icmp6_hdr(skb)返回错误的标题 调试一些,似乎是 skb-> network_header和skb-> transport_header指向同一个地方。
icmp6_hdr正在使用transport_header来解释它为什么不正确。
转储skb数据时,它看起来所有的标头和有效负载都处于正确的偏移量(也与tcpdump进行比较)
我怀疑它可能与桥接代码有关,然后再潜入它,
我认为也许有人遇到任何类似或有任何其他想法?
答案 0 :(得分:0)
部分问题在于你假设Netfilter做了什么,而不仅仅是弄清楚下一个标题是什么。根据我的经验(虽然不是很长)你想做这样的事情:
struct icmp6hdr *icmp6;
// Obviously don't do this unless you check to make sure that it's the right protocol
struct ipv6_hdr *ip6hdr = (struct ipv6_hdr*)skb->network_header;
// You need to move the headers around
// Notice the memory address of skb->data and skb->network_header are the same
// that means that the IP header hasn't been "pulled"
skb->transport_header = skb_pull(skb, sizeof(struct ipv6_hdr));
if(ntohs(ip6hdr->nexthdr) == IPPROTO_ICMPV6) {
icmp6 = (struct icmp6hdr*)skb->transport_header;
// Doing this is more efficient, since you only are calling the
// Network to Host function once
__u8 type = ntohs(hdr->icmp6_type);
switch(type) {
case NDISC_NEIGHBOUR_SOLICITATION:
case NDISC_ROUTER_SOLICITATION:
// Do your stuff
break;
}
}
希望这很有帮助。我刚刚开始编写Netfilter代码,所以我不完全确定100%,但是当我尝试在NF_IP_LOCAL_IN
钩子上尝试使用类似IPv4的东西时,我发现了这一点。