Advertisement
Guest User

Untitled

a guest
Sep 26th, 2012
387
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.54 KB | None | 0 0
  1. /*
  2.  * Get the local address the OS will be (presumably) using
  3.  * to connect to 'dst_host' and put it into local_addr_buf
  4.  *
  5.  * e.g. imagine the application running on a machine
  6.  * with two interfaces:
  7.  *   eth0, configured with 192.168.0.1/24
  8.  *   lo, configured with 127.0.0.1/8
  9.  *
  10.  * Depending on the host we need to connect to
  11.  * our local address will be different:
  12.  *   if we need to connect to 192.168.0.212, our local address is 192.168.0.1
  13.  *   if we need to connect to 127.0.0.1, our local address is 127.0.0.1
  14.  *   if we're connecting outside on the Internet
  15.  *   and we're behing a router/NAT, we're out of luck.
  16.  *
  17.  * Note: we're returning a numeric host as we don't know if our peer's DNS
  18.  *       resolves an hostname to the same IP address as ours.
  19.  * Note 2: dual stack ready!
  20.  */
  21. int get_local_address(const char *dst_host, char *addr_buf, size_t addr_buf_len, int *is_ipv6)
  22. {
  23.         struct addrinfo *addrinfo, *result;
  24.         struct addrinfo hints;
  25.         struct sockaddr_storage local_addr;
  26.         socklen_t local_addr_len;
  27.         int sock, s;
  28.  
  29.         // First, resolve the destination host
  30.         // Tell getaddrinfo we are only interested in datagram (UDP socket):
  31.         // with UDP sockets we can get our local address
  32.         // without sending a single packet
  33.         memset(&hints, 0, sizeof(struct addrinfo));
  34.         hints.ai_family = AF_UNSPEC;
  35.         hints.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED;
  36.         hints.ai_socktype = SOCK_DGRAM;
  37.  
  38.         s = getaddrinfo(dst_host, NULL, &hints, &addrinfo);
  39.  
  40.         if (s != 0) {
  41.                 g_message("get_local_address: %s", gai_strerror(s));
  42.                 return -1;
  43.         }
  44.  
  45.         // Iterate all the addresses found for dst_host
  46.         sock = -1;
  47.         for (result = addrinfo; result != NULL; result = result->ai_next) {
  48.                 if (sock >= 0) {
  49.                         close(sock);
  50.                 }
  51.  
  52.                 // Create a socket to test the address
  53.                 sock = socket(result->ai_family, result->ai_socktype,
  54.                         result->ai_protocol);
  55.                 if (sock < 0)
  56.                         continue;
  57.  
  58.                 // Connect as UDP to our destination address on whatever port
  59.                 // it doesn't matter, we're not sending anything
  60.                 if (connect(sock, result->ai_addr, result->ai_addrlen) < 0) {
  61.                         continue;
  62.                 }
  63.  
  64.                 // Get our local address
  65.                 local_addr_len = sizeof(struct sockaddr_storage);
  66.                 if (getsockname(sock, (struct sockaddr *)&local_addr, &local_addr_len) < 0) {
  67.                         continue;
  68.                 }
  69.  
  70.                 // Convert the address to a human-readable string
  71.                 if (getnameinfo((struct sockaddr *)&local_addr, local_addr_len,
  72.                                 addr_buf, addr_buf_len,
  73.                                 NULL, 0, NI_NUMERICHOST) < 0) {
  74.                         g_message("get_local_address: %s", gai_strerror(s));
  75.                         continue;
  76.                 }
  77.  
  78.                 if (is_ipv6 != NULL) {
  79.                         if (result->ai_family == AF_INET6) {
  80.                                 *is_ipv6 = 1;
  81.                         } else {
  82.                                 *is_ipv6 = 0;
  83.                         }
  84.                 }
  85.  
  86.                 close(sock);
  87.                 return 0;
  88.         }
  89.  
  90.         // Nothing found.
  91.         g_message("get_local_address: couldn\'t determine local IP address");
  92.         return -1;
  93. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement