5
votes

I have several Ethernet interfaces with IPv4 Link-Local addresses, which means I have multiple routes to 169.254.0.0/16 on different interfaces. (Those interfaces are not necessarily on the same layer 2 network, so the same IP in this range can be used by different systems on different interfaces.)

When sending a UDP packet to an address in 169.254.0.0/16 I can't pick which interface will be used to send the packet using Rust's standard library UdpSocket, but without specifying the interface it is very likely to use the wrong one.

How can I send a UDP packet from a specific interface?

(IPv6 Link-Local fe80::/64 has a similar problem, but SocketAddrV6 has a scope_id which can be used to set the index of the interface to use).

1
so I can't choose which — why does this logically follow from the fact that they have the same mask/route/broadcast address? How would you do it if that were not the case? - Shepmaster
I don't think Rust should handle that, you must configure your OS to route specific IP to specific interface. - Stargateur
In the C socket API you can specify the interface for a socket, so I presume that is what the OP wants to do. - starblue
@starblue You mean SO_BINDTODEVICE? socket(7) describes it as "only packets received from that particular interface are processed", but it's not clear to me whether it works for sending too. Or IP_UNICAST_IF (from windows, but I read some claims it got ported to linux for wine)? - Stefan
@Stefan SO_BINDTODEVICE, and it also works for sending, if I remember correctly (it was in a commercial project and I don't have access to the code any more). A quick look into the Linux kernel seems to confirm that, though it is hard to be sure because everything in the network stack is so indirect. - starblue

1 Answers

2
votes

Assuming you know which local IP address belongs to which network, you can use bind to bind the socket to that IP address.