Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get *my* ip from udp endpoint

Boost.Asio's udp::endpoint has a member that is remote address. Because I'm listening on multiple interfaces (like this):

udp_socket(io_service, udp::endpoint(udp::v4(), port))

In my handler, I do not know which network interface received the packet.

Without iterating over network interfaces and looking for a similarity between the endpoint address and my IP on each interface, can I get my IP for the interface that I got message from?

like image 639
NoSenseEtAl Avatar asked Feb 20 '14 15:02

NoSenseEtAl


People also ask

How does UDP find IP?

When IP delivers a UDP datagram, the host checks the port number and delivers the data to the corresponding application. In this way, UDP provides simple multiplexing over IP to allow a host to send and receive data on multiple distinct ports.

What is an endpoint in UDP?

UDP: a UDP endpoint is a combination of the IP address and the UDP port used, so different UDP ports on the same IP address are different UDP endpoints.

How do I find the endpoint of an IP?

The IP address is available in most locations the endpoint name is displayed, including lists and tool tips. In some lists, such as the Endpoint Diary, you can choose to view the Endpoint/Client Name or Endpoint/Client IP Address by clicking the toggle next to the column header.

How is a UDP socket fully identified?

According to "Computer networking: a top-down approach", Kurose et al., a UDP socket is fully identified by destination IP and destination port.


1 Answers

No. Boost.Asio does not expose the ability to identify the datagram's destination address.

The socket::aync_receive_from() and socket::receive_from() operations perform the native socket operations within boost::asio::detail::socket_ops::recvfrom(). On Windows, WSARecvFrom() provides no way to extract lower layer information from the protocol stack. On Linux, the IP_PKTINFO socket option can provided to datagram oriented sockets enabling recvfrom() to populate the msghdr.msg_control buffer with ancillary information, such as the interface index on which the packet was received and the destination address in the packet header. However, the Boost.Asio implementation does not use themsg_control field:

msghdr msg = msghdr();
init_msghdr_msg_name(msg.msg_name, addr);
msg.msg_namelen = static_cast<int>(*addrlen);
msg.msg_iov = bufs;
msg.msg_iovlen = static_cast<int>(count);
signed_size_type result = error_wrapper(::recvmsg(s, &msg, flags), ec);

As suggested in this answer, one can:

  • Use lower-level system calls. (i.e. IP_PKTINFO and recvfrom())
  • Explicitly bind a socket to each interface rather than INADDR_ANY, causing the socket::local_endpoint() to return a specific interface. The completion handlers will need some way to obtain the local endpoint on the socket for which the operation was invoked, such as passing a reference to the socket or its local endpoint via boost::bind().
like image 86
Tanner Sansbury Avatar answered Sep 22 '22 12:09

Tanner Sansbury