4

ASIO ドキュメントで提供されている ICMP のを使用して、簡単な ping ユーティリティを作成しました。ただし、この例は IPv4 のみを対象としており、IPv6 で動作させるのに苦労しています。

IPv6 をサポートするために ICMP ヘッダー クラスをアップグレードするには、小さな変更が必要です。ICMP と ICMPv6 ヘッダーの唯一の違いは、ICMP タイプの列挙の違いです。ただし、ICMPv6 ヘッダーに組み込む必要があるチェックサムの計算に問題があります。

IPv4 の場合、チェックサムは ICMP ヘッダーとペイロードに基づいています。ただし、IPv6 の場合、チェックサムには ICMPv6 ヘッダーとペイロードの前に IPv6 疑似ヘッダーを含める必要があります。ICMPv6 チェックサム機能は、IPv6 ヘッダーに含まれる送信元アドレスと宛先アドレスを知る必要があります。ただし、IPv6 ヘッダーに何が入るかは制御できません。これは Asio-Boost でどのように行うことができますか?

参考までに、IPv4 チェックサム計算の関数を以下に示します。

void compute_checksum(icmp_header& header, Iterator body_begin, Iterator body_end)
{
  unsigned int sum = (header.type() << 8) + header.code()
    + header.identifier() + header.sequence_number();

  Iterator body_iter = body_begin;
  while (body_iter != body_end)
  {
    sum += (static_cast<unsigned char>(*body_iter++) << 8);
    if (body_iter != body_end)
    sum += static_cast<unsigned char>(*body_iter++);
  }

  sum = (sum >> 16) + (sum & 0xFFFF);
  sum += (sum >> 16);
  header.checksum(static_cast<unsigned short>(~sum));
}

[編集]

チェックサムが正しく計算されない場合、どのような結果になりますか? エコー要求のチェックサムが無効な場合、ターゲット ホストはエコー応答を送信しますか?

4

1 に答える 1

1

チェックサムが正しくない場合、通常の IPv6 実装ではパケットがドロップされます。だから、それは深刻な問題です。

自分でパケットを作成することに固執する場合は、完全に作成する必要があります. これには、チェックサムを計算する前にソース IP アドレスを見つけて疑似ヘッダーに入れることが含まれます。意図した宛先アドレスに対して connect() を呼び出して、C でそれを行う方法を次に示します (UDP を使用している場合でも、ICMP で機能するはずです)。

     /* Get the source IP addresse chosen by the system (for verbose display, and 
     * for checksumming) */
    if (connect(sd, destination->ai_addr, destination->ai_addrlen) < 0) {
        fprintf(stderr, "Cannot connect the socket: %s\n", strerror(errno));
        abort();
    }
    source = malloc(sizeof(struct addrinfo));
    source->ai_addr = malloc(sizeof(struct sockaddr_storage));
    source_len = sizeof(struct sockaddr_storage);
    if (getsockname(sd, source->ai_addr, &source_len) < 0) {
        fprintf(stderr, "Cannot getsockname: %s\n", strerror(errno));
        abort();
    }

じゃあ後で:

        sockaddr6 = (struct sockaddr_in6 *) source->ai_addr;
        op6.ip.ip6_src = sockaddr6->sin6_addr;

と:

        op6.udp.check =
            checksum6(op6.ip, op6.udp, (u_int8_t *) & message, messagesize);
于 2013-06-15T21:29:34.370 に答える