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

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

问题描述:

对于某些特定的网络测试,我创建了一个VLAN设备eth1.900和两个别名eth1.900:1和eth1.900.2。使用Linux网络设备别名时指定TCP套接字的源IP地址

 
    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 

当连接到服务器时,有没有办法指定这些别名将被使用?我可以使用-I <ip>地址选项来选择要使用哪个别名,但我看不到如何使用代码中的TCP套接字而不使用原始套接字,因为我也想在没有额外套接字的情况下运行如果可能的话,即不作为根运行。

不幸的是,即使有根,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 
+1

请注意,使用`ip`命令而不是`ifconfig`,可能在单个接口*上没有*`:1`,`:2`等别名。这是'ifconfig'发明... – ephemient 2009-07-24 04:51:08

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

+0

谢谢caf。有趣的是,这是我尝试的第一件事,但我一路上一直搞歪了,因为我发誓它没有奏效。感谢让我回到正轨! – Wade 2009-07-24 17:12:55

+0

注意:将sin_port设置为'0',让客户端套接字绑定到系统选择的临时端口。 – Wade 2009-07-24 17:14:53

由于无论如何都无法在别名接口上发送数据包,因此在其中一个上使用SO_BINDTODEVICE是没有意义的。如果路由不能用于此目的(例如,如果它是原始以太网帧),则SO_BINDTODEVICE控制从哪个设备发送数据包。

你没有表现的devname的定义,但如果它是一个字符串指针,如:

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

那么也许它的失败,因为你使用sizeof devname指定参数的大小,这将在这种情况下是与sizeof (char *)相同,即在32位系统上通常为4。

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