views:

909

answers:

3

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  A: 

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().

caf
Thanks caf. Funny enough, it was the first thing I tried, but I must have messed up the args along the way, because I swear it didn't work. Thanks for getting me back on track!
Wade
Note: set sin_port to '0' to let the client socket bind to an ephemeral port chosen by the system.
Wade
+1  A: 

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).

David Schwartz
+1  A: 

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.

unwind
Thanks for the suggestion, but I was most likely using, for example:char devname[] = "eth1.900:1";
Wade