3
votes

For some specific networking tests, I've created a VLAN device, eth1.900, and a couple of aliases, eth1.900:1 and 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

When connecting to a server, is there a way to specify which of these aliases will be used? I can ping using the -I <ip> address option to select which alias to use, but I can't see how to do it with a TCP socket in code without using raw sockets, since I would also like to run without extra socket privileges, i.e. not running as root, if possible.

Unfortunately, even with root, SO_BINDTODEVICE doesn't work because the alias device name is not recognized:

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

Output:

    Bind to eth1.900:1
    SO_BINDTODEVICE: No such device
3
Note that using the ip command rather than ifconfig, it is possible to have multiple addresses on a single interface without :1, :2, etc. aliases. That's something of an ifconfig invention...ephemient

3 Answers

6
votes

Use getifaddrs() to enumerate all the interfaces and find the IP address for the interface you want to bind to. Then use bind() to bind to that IP address, before you call connect().

3
votes

Since a packet can't be send out on an aliased interface anyway, it would make no sense to use SO_BINDTODEVICE on one. SO_BINDTODEVICE controls which device a packet is sent out from if routing cannot be used for this purpose (for example, if it's a raw Ethernet frame).

1
votes

You don't show the definition of devname, but if it's a string pointer, e.g.:

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

Then perhaps it's failing since you specify the argument size using sizeof devname, which would in this case be the same as sizeof (char *), i.e. typically 4 on a 32-bit system.

If setsockopt() expects to see the actual size of the argument, i.e. the length of the string, this could explain the issue since it's then perhaps just inspecting the first four characters and failing since the result is an invalid interface name.