在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。
有人可以建议可能出现什么问题吗?
感谢。
答案 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
。
我将继续进行调查。