From 887a897c02144f2d01896d3112bdae5ce7d6df5c Mon Sep 17 00:00:00 2001
From: Ariel Manzur <ariel@godotengine.org>
Date: Tue, 18 Oct 2016 18:53:18 -0300
Subject: adding ipv6

---
 drivers/unix/ip_unix.cpp | 89 +++++++++++++++++++++++++++++++++---------------
 1 file changed, 61 insertions(+), 28 deletions(-)

(limited to 'drivers/unix/ip_unix.cpp')

diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp
index 08a8c19583..6294f57b03 100644
--- a/drivers/unix/ip_unix.cpp
+++ b/drivers/unix/ip_unix.cpp
@@ -30,6 +30,7 @@
 
 #if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED)
 
+#include <string.h>
 
 #ifdef WINDOWS_ENABLED
  #ifdef WINRT_ENABLED
@@ -62,16 +63,51 @@
  #endif
 #endif
 
-IP_Address IP_Unix::_resolve_hostname(const String& p_hostname) {
+static IP_Address _sockaddr2ip(struct sockaddr* p_addr) {
 
-	struct hostent *he;
-	if ((he=gethostbyname(p_hostname.utf8().get_data())) == NULL) {  // get the host info
-		ERR_PRINT("gethostbyname failed!");
-		return IP_Address();
-	}
 	IP_Address ip;
+	if (p_addr->sa_family == AF_INET) {
+		struct sockaddr_in* addr = (struct sockaddr_in*)p_addr;
+		ip.field32[0] = ntohl(addr->sin_addr.s_addr);
+		ip.type = IP_Address::TYPE_IPV4;
+	} else {
+		struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr;
+		for (int i=0; i<16; i++)
+			ip.field8[i] = addr6->sin6_addr.s6_addr[i];
+		ip.type = IP_Address::TYPE_IPV6;
+	};
+
+	return ip;
+};
+
+IP_Address IP_Unix::_resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type) {
 
-	ip.host= *((unsigned long*)he->h_addr);
+	struct addrinfo hints;
+	struct addrinfo* result;
+
+	memset(&hints, 0, sizeof(struct addrinfo));
+	if (p_type == IP_Address::TYPE_IPV4) {
+		hints.ai_family = AF_INET;
+	} else if (p_type == IP_Address::TYPE_IPV6) {
+		hints.ai_family = AF_INET6;
+	} else {
+		hints.ai_family = AF_UNSPEC;
+	};
+
+	int s = getaddrinfo(p_hostname.utf8().get_data(), NULL, &hints, &result);
+	if (s != 0) {
+		ERR_PRINT("getaddrinfo failed!");
+		return IP_Address();
+	};
+
+	if (result == NULL || result->ai_addr == NULL) {
+		ERR_PRINT("Invalid response from getaddrinfo");
+		return IP_Address();
+	};
+
+	IP_Address ip = _sockaddr2ip(result->ai_addr);
+
+	freeaddrinfo(result);
 
 	return ip;
 
@@ -90,10 +126,9 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const {
 
 	for (int i = 0; i < hostnames->Size; i++) {
 
-		if (hostnames->GetAt(i)->Type == HostNameType::Ipv4 && hostnames->GetAt(i)->IPInformation != nullptr) {
+		if (hostnames->GetAt(i)->Type == HostNameType::Ipv4 || hostnames->GetAt(i)->Type == HostNameType::Ipv6 && hostnames->GetAt(i)->IPInformation != nullptr) {
 
 			r_addresses->push_back(IP_Address(String(hostnames->GetAt(i)->CanonicalName->Data())));
-
 		}
 	}
 
@@ -108,7 +143,7 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const {
 	while (true) {
 
 		addrs = (IP_ADAPTER_ADDRESSES*)memalloc(buf_size);
-		int err = GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_ANYCAST |
+		int err = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST |
 									   GAA_FLAG_SKIP_MULTICAST |
 									   GAA_FLAG_SKIP_DNS_SERVER |
 									   GAA_FLAG_SKIP_FRIENDLY_NAME,
@@ -134,14 +169,23 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const {
 		IP_ADAPTER_UNICAST_ADDRESS* address = adapter->FirstUnicastAddress;
 		while (address != NULL) {
 
-			char addr_chr[INET_ADDRSTRLEN];
-			SOCKADDR_IN* ipv4 = reinterpret_cast<SOCKADDR_IN*>(address->Address.lpSockaddr);
-
 			IP_Address ip;
-			ip.host= *((unsigned long*)&ipv4->sin_addr);
 
+			if (address->Address.lpSockaddr->sa_family == AF_INET) {
+
+				SOCKADDR_IN* ipv4 = reinterpret_cast<SOCKADDR_IN*>(address->Address.lpSockaddr);
+
+				ip.field32[0] = *((unsigned long*)&ipv4->sin_addr);
+				ip.type = IP_Address::TYPE_IPV4;
+			} else { // ipv6
+
+				SOCKADDR_IN6* ipv6 = reinterpret_cast<SOCKADDR_IN6*>(address->Address.lpSockaddr);
+				for (int i=0; i<16; i++) {
+					ip.field8[i] = ipv6->sin6_addr.s6_addr[i];
+				};
+				ip.type = IP_Address::TYPE_IPV6;
+			};
 
-			//inet_ntop(AF_INET, &ipv4->sin_addr, addr_chr, INET_ADDRSTRLEN);
 
 			r_addresses->push_back(ip);
 
@@ -167,20 +211,9 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const {
 	for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
 		if (!ifa->ifa_addr)
 			continue;
-		if (ifa ->ifa_addr->sa_family==AF_INET) { // check it is IP4
-			// is a valid IP4 Address
 
-			IP_Address ip;
-			ip.host= *((unsigned long*)&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr);
-
-			r_addresses->push_back(ip);
-		}/* else if (ifa->ifa_addr->sa_family==AF_INET6) { // check it is IP6
-			// is a valid IP6 Address
-			tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
-			char addressBuffer[INET6_ADDRSTRLEN];
-			inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
-			printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer);
-		} */
+		IP_Address ip = _sockaddr2ip(ifa->ifa_addr);
+		r_addresses->push_back(ip);
 	}
 
 	if (ifAddrStruct!=NULL) freeifaddrs(ifAddrStruct);
-- 
cgit v1.2.3


From 1d45f35a4a190360fea74e51b66457efe44d3177 Mon Sep 17 00:00:00 2001
From: Ariel Manzur <ariel@godotengine.org>
Date: Wed, 19 Oct 2016 18:32:36 -0300
Subject: fixed some byte order and parsing problems

---
 drivers/unix/ip_unix.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'drivers/unix/ip_unix.cpp')

diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp
index 6294f57b03..d6d1be3395 100644
--- a/drivers/unix/ip_unix.cpp
+++ b/drivers/unix/ip_unix.cpp
@@ -68,7 +68,7 @@ static IP_Address _sockaddr2ip(struct sockaddr* p_addr) {
 	IP_Address ip;
 	if (p_addr->sa_family == AF_INET) {
 		struct sockaddr_in* addr = (struct sockaddr_in*)p_addr;
-		ip.field32[0] = ntohl(addr->sin_addr.s_addr);
+		ip.field32[0] = *((unsigned long*)&addr->sin_addr);
 		ip.type = IP_Address::TYPE_IPV4;
 	} else {
 		struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr;
-- 
cgit v1.2.3