ネットワークデバイスドライバーを書いています。
カーネル 2.6.35.12
デバイスは、ブリッジ ポートに接続されているときに動作するはずです。
ブリッジからインターフェイスに転送された ICMPv6 RA および NS メッセージ (ルーター/近隣要請) を傍受しようとしています。
eth <–> br0 <–> mydevice
デバイスの start_xmit 関数では、次のことを行っています。
イーサネット ヘッダーの後のプロトコル フィールドが IPV6 (0x86dd) であることを確認します。
ipv6 の次のヘッダーが 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 と比較してください)。
橋のコードに関係している可能性があるのではないかと思います。
誰かが似たようなことに出くわしたり、他のアイデアを持っているのではないかと思いましたか?