How do you get the local ip address of the adapter which received the packet?
The question is, "What is the ip address from the receiver adapter?" not the address from the sender which we get in the
receive_from( ..., &senderAddr, ... );
call.
Unfortunately the sendto and recvfrom API calls are fundamentally broken when used with sockets bound to "Any IP" because they have no field for local IP information.
So what can you do about it?
None of these options are great. Guessing will obviously produce wrong answers soemtimes. Binding seperate sockets increases the complexity of your software and causes problems if the list of local addresses changes will your program is running. The newer APIs are the correct techical soloution but may reduce portability (in particular it looks like WSArecvmsg is not available on windows XP) and may require modifications to the socket wrapper library you are using.
Edit looks like I was wrong, it seems the MS documentation is misleading and that WSArecvmsg is available on windows XP. See https://stackoverflow.com/a/37334943/5083516
You could enumerate all the network adapters, get their IP addresses and compare the part covered by the subnet mask with the sender's address.
Like:
IPAddress FindLocalIPAddressOfIncomingPacket( senderAddr )
{
foreach( adapter in EnumAllNetworkAdapters() )
{
adapterSubnet = adapter.subnetmask & adapter.ipaddress;
senderSubnet = adapter.subnetmask & senderAddr;
if( adapterSubnet == senderSubnet )
{
return adapter.ipaddress;
}
}
}
The solution provided by timbo assumes that the address ranges are unique and not overlapping. While this is usually the case, it isn't a generic solution.
There is an excellent implementation of a function that does exactly what you're after provided in the Steven's book "Unix network programming" (section 20.2) This is a function based on recvmsg(), rather than recvfrom(). If your socket has the IP_RECVIF option enabled then recvmsg() will return the index of the interface on which the packet was received. This can then be used to look up the destination address.
The source code is available here. The function in question is 'recvfrom_flags()'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With