netcat 在发送到 UDP IPv6 多播时生成 EINVAL

netcat 在发送到 UDP IPv6 多播时生成 EINVAL

我在 Fedora 上使用 netcat 来测试 IPv6 UDP 多播地址。命令是

echo hi | nc -6 -u ff02::777:777:777 7777

netcat 回应:“参数无效。”

运行 strace 产量

connect(3, {sa_family=AF_INET6, sin6_port=htons(7777), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "ff02::777:777:777", &sin6_addr), sin6_scope_id=0}, 28) = -1 EINVAL

运行类似的命令但没有 IPv6,

echo hi | nc -u 192.168.255.255 7777

工作得很好。

答案1

初步说明:您的 IPv4 网络未设置为 192.168.0.0/16,但很可能设置为 192.168.0.0/24 或任何其他 /24 范围:因此 192.168.255.255 不是广播,否则echo hi | nc -u 192.168.255.255 7777会失败。对于广播,IPv6 不支持而仅支持 IPv4,应用程序必须使用SO_BROADCAST套接字选项。这是通过-bnetcat 选项实现的。假设您实际上位于网络 192.168.0.0/24(而不是 /16)中,则为:

nc -b -u 192.168.0.255 7777

请注意,广播不是多播。


关于这个问题。整个ff02::/16范围在链接本地多播范围。对于此范围,只有当接口与其关联时,地址才是完整的(这就是为什么它是一个关联- 本地范围)。此范围内的有效地址不能只是ff02::777:777:777.假设 LAN 接口被称为eth0ff02::777:777:777%eth0是一个有效地址,如定义在RFC 4007:

nc -6 -u ff02::777:777:777%eth0 7777

这可能是由库自动处理的,而不是由nc命令本身处理的。使用不需要接口的作用域通常会失败,因为接口不应该是地址的一部分。

如果您不想必须需要该接口,请不要使用链接本地(或节点本地)范围。切换到 site-local: ff05 ,不需要指定接口即可工作:

nc -6 -u ff05::777:777:777 7777

在 Linux 上,可以通过以下命令看出这两个命令的区别ss

$ ss -aun dport == 7777
State  Recv-Q  Send-Q                     Local Address:Port          Peer Address:Port
ESTAB  0       0           [2001:db8:900d:cafe:0:1:2:3]:58092  [ff05::777:777:777]:7777        
ESTAB  0       0       [fe80::8c5f:87ff:fe50:d08a]%eth0:60937  [ff02::777:777:777]:7777        

这里有一个全球地址以太网0并且它不是链接本地范围,该地址被选为源。对于链路本地范围地址,套接字绑定到接口。对于 Linux 情况,请参阅此 Q/A,了解与发送时(以及未使用IPV6_MULTICAST_IF)接口选择相关的其他注意事项:如何设置首选 IPv6 接口


最后注意:您应该考虑切换到索卡特具有比网猫, 包括加入多播组对于 IPv4。虽然它支持 IPv6,但它并不直接支持 IPv6 多播,但可以使用任意setsockopt(2)调用来实现不支持的功能,包括处理 IPv6 多播。这还是比网猫它只是不支持接收前一个发出的多播流量网猫命令。

所以与索卡特,这里是一个至少在具有 amd64 (x86_64) 架构的 Linux 上有效的示例,并且可能在其他 *nix 上工作,可能在更改下面的值 20 及其适当的替换(对于IPV6_ADD_MEMBERSHIP/ IPV6_JOIN_GROUP)之后,使用原始setsockopt(2)选项来启用在索引为 2 的接口(之后的第一个接口),由第一个发送网猫命令:

socat udp6-recv:7777,setsockopt-listen=41:20:xff020000000000000000077707770777i2 -

该选项将使用以下命令进行解码strace

setsockopt(5, SOL_IPV6, IPV6_ADD_MEMBERSHIP, {inet_pton(AF_INET6, "ff02::777:777:777", &ipv6mr_multiaddr), ipv6mr_interface=if_nametoindex("eth0")}, 20) = 0

这里使用所谓的“dalan”格式来传递任意套接字选项ipv6_mreq结构:一个 IPv6 地址(x对于任意十六进制值,这里是 16 字节的 IPv6 地址),后跟一个接口索引(i对于整数)。

相关内容