【问题标题】:Checksum calculation issue for ICMPv6 using Asio Boost使用 Asio Boost 的 ICMPv6 校验和计算问题
【发布时间】:2013-06-04 22:11:49
【问题描述】:

我使用了 ASIO 文档中提供的 ICMP example 来创建一个简单的 ping 实用程序。但是,该示例仅涵盖 IPv4,我很难使其与 IPv6 一起使用。

升级 ICMP 标头类以支持 IPv6 需要进行细微更改 - 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));
}

[编辑]

如果校验和计算不正确会有什么后果?如果 echo 请求的校验和无效,目标主机是否会发送 echo 回复?

【问题讨论】:

    标签: boost-asio ipv6 ping icmp


    【解决方案1】:

    如果校验和不正确,典型的 IPv6 实现将丢弃数据包。所以,这是一个严重的问题。

    如果您坚持自己制作数据包,则必须自己动手 完全地。这包括查找源 IP 地址,将其放入 计算校验和之前的伪标头。这是我的做法 在 C 中,通过为我的预期目标地址调用 connect() (即使我使用 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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-02
      • 2014-06-22
      • 1970-01-01
      • 1970-01-01
      • 2017-08-26
      • 2012-10-24
      相关资源
      最近更新 更多