3

在 IPv4 的情况下,我看到 sendmsg 的以下行为:

假设 10.1.2.3 是客户端 IP。10.1.2.10 配置在客户端的其中一个接口上。

在 UDP 消息中,将以下控制信息添加到数据包中:

它只是服务器在回复客户端时应使用的源地址或接口地址:

cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(sa->sin_addr);
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_SENDSRCADDR_WITH_ERROR;
* (struct in_addr *)CMSG_DATA(cmsg) = sa->sin_addr;
cmsg = (struct cmsghdr *)((caddr_t) cmsg + ALIGN(cmsg->cmsg_len));

消息发送为:

sendmsg(fd, send_msg, 0);

如果我将 10.1.2.10 配置为 source-ip 并且将其添加到 cmsg 中,一切正常。服务器回复 10.1.2.10。

但是,如果我配置了一些无法访问的 IP 地址或未在客户端的任何接口上配置的 IP,sendmsg 将失败并出现以下错误:

sendmsg 到 10.1.2.3(10.1.2.3).1813 失败:无法分配请求的地址

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

但我看不到 IPv6 的相同行为:

假设 2001::1 是客户端 IP。并且 2001::2001 配置在客户端的其中一个接口上。

IPv6 源地址添加到控制消息中,如下所示:

    cmsg->cmsg_level = IPPROTO_IPV6;
    cmsg->cmsg_type = IPV6_PKTINFO;
    cmsg->cmsg_len =  CMSG_LEN(sizeof(struct in6_pktinfo));
    memcpy((struct in6_addr *)CMSG_DATA(cmsg), &(sa6->sin6_addr),
            sizeof(sa6->sin6_addr));
    cmsg = (struct cmsghdr *)((caddr_t) cmsg + ALIGN(cmsg->cmsg_len));

如果我将 2001::2001 配置为源 IP 并且服务器确实回复此地址,它工作正常。

但是,如果我配置了一个无法访问的 IPv6 源地址,比如 1001::1001,那么 sendmsg 不会出现类似于我们在 IPv4 案例中看到的错误消息。消息仍然使用原始 IPv6 发送,即 2001::1。

有人可以建议可能是什么问题吗?

谢谢。

4

2 回答 2

1

IP_SENDSRCADDR 和 IPV6_PKTINFO 必须是两个不同的实现。也许在第一种情况下它只是控制错误。您是否尝试在辅助数据中为 IPV6_PKTINFO 设置接口索引?对于 IPV6_PKTINFO,辅助数据的类型为:in6_pktinfo。

struct in6_pktinfo {
    struct in6_addr ipi6_addr;    /* src/dst IPv6 address */
    unsigned int    ipi6_ifindex; /* send/recv if index */
};

希望这在某种程度上有所帮助

于 2013-10-28T22:33:05.330 回答
0

我遇到了同样的问题,我将源地址设置为408:6666:f:f500::1 (不是本地IP),但是我收到了以4085:6666:f:fc10::1 (本地IP)为源地址的数据包,无论我设置ipi6_ifindex与否。

我会挺身而出进行调查。

于 2019-08-12T07:26:06.387 回答