IP_ADD_MEMBERSHIP 在接口及其子接口上都设置时失败;这是预期的吗?

IP_ADD_MEMBERSHIP fails when set both on interface and its subinterface; is that expected?

我正在调试 3rd-party network application 并试图弄清楚为什么它在使用 IP_ADD_MEMBERSHIP 调用 setsockopt 来设置多播组时报告错误。该应用程序是用 C++ 编写的,但我在 python 中编写了一个 MWE,它复制了相同的系统调用:

import socket
import struct

ETH0_IP = "192.168.88.85"
ETH0_1_IP = "192.168.88.254"

MULTICAST_IP = "224.0.0.7"

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
ip = socket.inet_aton(ETH0_IP)
s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, ip)
group = struct.pack("4s4s", socket.inet_aton(MULTICAST_IP), ip)
s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, group)
# s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)

s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
ip2 = socket.inet_aton(ETH0_1_IP)
s2.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, ip2)
group2 = struct.pack("4s4s", socket.inet_aton(MULTICAST_IP), ip2)

# the second group is added to the first socket so that we can only bind to one socket and read data from it
s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, group2)

在第二次 IP_ADD_MEMBERSHIP 调用时我收到错误 OSError: [Errno 98] Address already in use

我发现只有当 ETH0_1_IPETH_0_IP 的子接口时才会发生这种情况。我不确定这是否符合预期。如果是,是否有办法实际检测到这种情况并丢弃已绑定接口的子接口?此外,如果注册失败并出现上述错误,我的多播套接字是否会接收发送到子接口的数据?

为了完整起见:

$ cat /etc/network/interfaces
auto lo
iface lo inet loopback
iface lo inet6 loopback

auto eth0:1
iface eth0:1 inet static
    address 192.168.88.254
    netmask 255.255.240.0

Linux 正在将您的别名接口作为同一接口进行跟踪,因此拒绝重新使用该接口的尝试。

更详细一点,我 运行 您的代码在 CentOS 7 上使用两个单独的物理接口成功运行,没有任何更改。如果我随后更改代码以在同一物理地址上使用别名,它将失败并出现与您看到的相同的错误。

再深入一点,我发现如果我为物理适配器和别名转储接口索引(使用 SIOCGIFINDEX),它们确实具有相同的索引。

如果您想使用 Python 自己检查一下,请快速查看 https://gist.github.com/firaxis/0e538c8e5f81eaa55748acc5e679a36e 中的一些代码(缺少 ctypes 和套接字的导入),然后尝试如下操作:

print(Interface(name="eth0").index)
print(Interface(name="eth0:1").index)