tags:

views:

4160

answers:

5
  1. You have multiple network adapters.
  2. Bind a UDP socket to an local port, without specifying an address.
  3. Receive packets on one of the adapters.

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.

+1  A: 
diciu
+4  A: 

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;
        }
    }
}
Timbo
Only if the packet originated on the subnet of the adapter. Not if it was routed to get there...
Len Holgate
Yep, Len's right. If the packet arrived through NAT on your local router, you'll just see your local IP (something like 10.0.0.2)
Eli Bendersky
Isn't it the case that broadcasts are not routed (only sent locally)? IIRC the method should thus work.
Luis Soeiro
+3  A: 

G'day,

I assume that you've done your bind using INADDR_ANY to specify the address.

If this is the case, then the semantics of INADDR_ANY is such that a UDP socket is created on the port specified on all of your interfaces. The socket is going to get all packets sent to all interfaces on the port specified.

When sending using this socket, the lowest numbered interface is used. The outgoing sender's address field is set to the IP address of that first outgoing interface used.

First outgoing interface is defined as the sequence when you do an ifconfig -a. It will probably be eth0.

HTH.

cheers, Rob

Rob Wells
+2  A: 

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

Andrew Edgecombe
I am going to look into that. Maybe that is a better solution.
Christopher
A: 

gethostbyname("localhost");

Chris Evans