使用Linux网络设备别名时,指定TCP套接字的源IP地址(Specify source IP ad

2019-09-20 13:56发布

对于一些特定的网络测试中,我创建了一个VLAN设备,eth1.900,和几个别名,eth1.900:1和eth1.900.2。

    eth1.900  Link encap:Ethernet  HWaddr 00:18:E7:17:2F:13
              inet addr:1.0.1.120  Bcast:1.0.1.255  Mask:255.255.255.0

    eth1.900:1 Link encap:Ethernet  HWaddr 00:18:E7:17:2F:13
              inet addr:1.0.1.200  Bcast:1.0.1.255  Mask:255.255.255.0

    eth1.900:2 Link encap:Ethernet  HWaddr 00:18:E7:17:2F:13
              inet addr:1.0.1.201  Bcast:1.0.1.255  Mask:255.255.255.0

当连接到一台服务器,有没有指定这些别名将被使用的方式? 我可以ping使用-I <IP>地址选项来选择要使用的别名,但我不能看到如何使用TCP套接字做到在代码而不使用原始套接字,因为我也想而无需额外的插槽运行特权,即不以root运行,如果可能的话。

不幸的是,即使有根,SO_BINDTODEVICE不起作用,因为设备的别名无法识别:

printf("Bind to %s\n", devname);
if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, (char*)devname, sizeof(devname)) != 0)
{
    perror("SO_BINDTODEVICE");
    return 1;
}

输出:

    Bind to eth1.900:1
    SO_BINDTODEVICE: No such device

Answer 1:

使用getifaddrs()枚举所有接口并找到您要绑定到该接口的IP地址。 然后使用bind()绑定到该IP地址,则调用connect()之前。



Answer 2:

由于数据包不能被一个别名接口反正送出去,那就没有什么意义使用SO_BINDTODEVICE一个。 该设备的分组从路由是否送出SO_BINDTODEVICE控制不能用于这一目的(例如,如果它是一个原始以太网帧)。



Answer 3:

你不显示的定义devname ,但如果它是一个字符串指针,例如:

char *devname = "eth1.900:1";

然后,也许它的失败,因为您指定使用参数大小sizeof devname ,这将在这种情况下是一样sizeof (char *)即通常在32位系统4。

如果setsockopt()希望看到参数的实际大小,即字符串的长度,这可以解释的问题,因为它是那么也许只是检查前四个字符和失败,因为结果是无效的接口名称。



文章来源: Specify source IP address for TCP socket when using Linux network device aliases