sendmsg系统调用是否验证添加到辅助数据中的IPv6源地址?

时间:2013-10-24 06:29:49

标签: linux network-programming

在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配置为source-ip并且服务器确实回复此地址。

但如果我配置一个无法访问的IPv6源地址为1001 :: 1001,则sendmsg没有类似于我们在IPv4情况下看到的错误消息。消息仍然使用原始IPv6发送,即2001 :: 1。

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

感谢。

2 个答案:

答案 0 :(得分: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 */
};

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

答案 1 :(得分:0)

我遇到相同的问题,我将源地址设置为408:6666:f:f500::1 (不是本地IP),但是收到的数据包中却带有4085:6666:f:fc10::1 (本地IP )作为源地址,无论我是否设置了ipi6_ifindex

我将继续进行调查。