5

IPV4アドレスとIPV6アドレスの両方でクライアントにサービスを提供する必要があるUDPサーバーがあります。IPV4クライアントとIPV6クライアントの両方にサービスを提供する単一のIPV6ソケットを作成しました。

サーバーは、最初の通信でクライアントのIPアドレスを保存します。IPV4クライアントの場合はIPV4アドレスとして保存し、IPV6クライアントの場合はサーバーがIPV6アドレスとして保存します。今後のすべての通信では、このクライアントがすでに認識されている(保存されている)かどうかストレージをチェックし、それに応じて動作します。クライアントアドレスを保存されているアドレスと比較するために、ファミリタイプ(AF_INETおよびAF_INET6)に基づいてmemcmpを実行します。

IPV6クライアントと通信している間、システムは正常に動作していますが、IPV4クライアントと通信している間、システムはクライアントを認識していないかのように動作します。デバッグ中に、IPV6が原因で、ソケットタイプIPV4クライアントのIPアドレスが、ファミリがIPV6に設定されたIPV6マップIPV4アドレスとして受信されることがわかりました。これを解決するには、IPV4に保存されているアドレスとIPV6にマップされているアドレスを比較する必要があります。このために、IPV4構造のsin_addr.s_addrとIPV6構造のsin6_addr.in6_u.u6_addr32を使用しています。以下のコードスニペットを見つけてください。

ipv6_clientdata = (const struct sockaddr_in6 *)&sockStor;
ipv4_storeddata = (const struct sockaddr_in *)&(_stData[index].clientaddr);
if( (ipv6_clientdata->sin6_port == ipv4_storeddata->sin_port) && 
    (ipv6_clientdata->sin6_addr.in6_u.u6_addr32[3] == ipv4_storeddata->sin_addr.s_addr) 
  )
{
    addrfound = true;
}

この方法がIPV6マップIPV4アドレスをIPV4アドレスと比較するための適切なソリューションであるかどうか、または他のより良い方法があるかどうかを知りたいです。

4

1 に答える 1

2

Joachim Pileborgが推論したように、IPv4アドレスが同じソケットで受信された以前のパケットからのものである場合、マップされたIPv4アドレスを別のアドレスと比較するため、これを気にする必要はありません。IPv4アドレスが外部ソースから取得された場合にのみ注意する必要があります。

JoãoAugustoが指摘したように、最後の32ビットを比較する前に、IPv6アドレスが実際にIPv4マップアドレスであることを確認することを怠りました。IN6_IS_ADDR_V4MAPPEDこれを行うのに役立つマクロがあります。

if (
    IN6_IS_ADDR_V4MAPPED(&(ipv6_clientdata->sin6_addr)) &&
    (ipv6_clientdata->sin6_port == ipv4_storeddata->sin_port) &&
    (ipv6_clientdata->sin6_addr.in6_u.u6_addr32[3] == ipv4_storeddata->sin_addr.s_addr)
) {
    addrfound = true;
}
于 2012-07-31T00:21:57.313 に答える