Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Get the local address the OS will be (presumably) using
- * to connect to 'dst_host' and put it into local_addr_buf
- *
- * e.g. imagine the application running on a machine
- * with two interfaces:
- * eth0, configured with 192.168.0.1/24
- * lo, configured with 127.0.0.1/8
- *
- * Depending on the host we need to connect to
- * our local address will be different:
- * if we need to connect to 192.168.0.212, our local address is 192.168.0.1
- * if we need to connect to 127.0.0.1, our local address is 127.0.0.1
- * if we're connecting outside on the Internet
- * and we're behing a router/NAT, we're out of luck.
- *
- * Note: we're returning a numeric host as we don't know if our peer's DNS
- * resolves an hostname to the same IP address as ours.
- * Note 2: dual stack ready!
- */
- int get_local_address(const char *dst_host, char *addr_buf, size_t addr_buf_len, int *is_ipv6)
- {
- struct addrinfo *addrinfo, *result;
- struct addrinfo hints;
- struct sockaddr_storage local_addr;
- socklen_t local_addr_len;
- int sock, s;
- // First, resolve the destination host
- // Tell getaddrinfo we are only interested in datagram (UDP socket):
- // with UDP sockets we can get our local address
- // without sending a single packet
- memset(&hints, 0, sizeof(struct addrinfo));
- hints.ai_family = AF_UNSPEC;
- hints.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED;
- hints.ai_socktype = SOCK_DGRAM;
- s = getaddrinfo(dst_host, NULL, &hints, &addrinfo);
- if (s != 0) {
- g_message("get_local_address: %s", gai_strerror(s));
- return -1;
- }
- // Iterate all the addresses found for dst_host
- sock = -1;
- for (result = addrinfo; result != NULL; result = result->ai_next) {
- if (sock >= 0) {
- close(sock);
- }
- // Create a socket to test the address
- sock = socket(result->ai_family, result->ai_socktype,
- result->ai_protocol);
- if (sock < 0)
- continue;
- // Connect as UDP to our destination address on whatever port
- // it doesn't matter, we're not sending anything
- if (connect(sock, result->ai_addr, result->ai_addrlen) < 0) {
- continue;
- }
- // Get our local address
- local_addr_len = sizeof(struct sockaddr_storage);
- if (getsockname(sock, (struct sockaddr *)&local_addr, &local_addr_len) < 0) {
- continue;
- }
- // Convert the address to a human-readable string
- if (getnameinfo((struct sockaddr *)&local_addr, local_addr_len,
- addr_buf, addr_buf_len,
- NULL, 0, NI_NUMERICHOST) < 0) {
- g_message("get_local_address: %s", gai_strerror(s));
- continue;
- }
- if (is_ipv6 != NULL) {
- if (result->ai_family == AF_INET6) {
- *is_ipv6 = 1;
- } else {
- *is_ipv6 = 0;
- }
- }
- close(sock);
- return 0;
- }
- // Nothing found.
- g_message("get_local_address: couldn\'t determine local IP address");
- return -1;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement