summary refs log tree commit diff stats
path: root/lib/pure/nativesockets.nim
diff options
context:
space:
mode:
authorrockcavera <rockcavera@gmail.com>2023-10-20 04:43:53 -0300
committerGitHub <noreply@github.com>2023-10-20 09:43:53 +0200
commit27deacecaadd711cbb5a615abba3237925250616 (patch)
tree399b874d6adb6131e8bfb4d278dff1e818623f1e /lib/pure/nativesockets.nim
parent05a7c0fdd098b1971041f742ebf9e1871e4ad2b4 (diff)
downloadNim-27deacecaadd711cbb5a615abba3237925250616.tar.gz
fix #22834 (#22843)
fix #22834

Edit: also fixes `result.addrList` when IPv6, which previously only
performed a `result.addrList = cstringArrayToSeq(s.h_addr_list)` which
does not provide the textual representation of an IPv6
Diffstat (limited to 'lib/pure/nativesockets.nim')
-rw-r--r--lib/pure/nativesockets.nim47
1 files changed, 38 insertions, 9 deletions
diff --git a/lib/pure/nativesockets.nim b/lib/pure/nativesockets.nim
index b3465ef14..e1784491b 100644
--- a/lib/pure/nativesockets.nim
+++ b/lib/pure/nativesockets.nim
@@ -387,21 +387,37 @@ when not useNimNetLite:
 
   proc getHostByAddr*(ip: string): Hostent {.tags: [ReadIOEffect].} =
     ## This function will lookup the hostname of an IP Address.
-    var myaddr: InAddr
-    myaddr.s_addr = inet_addr(ip)
+    var
+      addrInfo = getAddrInfo(ip, Port(0), AF_UNSPEC)
+      myAddr: pointer
+      addrLen = 0
+      family = 0
+
+    if addrInfo.ai_addr.sa_family.cint == nativeAfInet:
+      family = nativeAfInet
+      myAddr = addr cast[ptr Sockaddr_in](addrInfo.ai_addr).sin_addr
+      addrLen = 4
+    elif addrInfo.ai_addr.sa_family.cint == nativeAfInet6:
+      family = nativeAfInet6
+      myAddr = addr cast[ptr Sockaddr_in6](addrInfo.ai_addr).sin6_addr
+      addrLen = 16
+    else:
+      raise newException(IOError, "Unknown socket family in `getHostByAddr()`")
+
+    freeAddrInfo(addrInfo)
 
     when useWinVersion:
-      var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cuint,
-                                    cint(AF_INET))
+      var s = winlean.gethostbyaddr(cast[ptr InAddr](myAddr), addrLen.cuint,
+                                    cint(family))
       if s == nil: raiseOSError(osLastError())
     else:
       var s =
         when defined(android4):
-          posix.gethostbyaddr(cast[cstring](addr(myaddr)), sizeof(myaddr).cint,
-                              cint(posix.AF_INET))
+          posix.gethostbyaddr(cast[cstring](myAddr), addrLen.cint,
+                              cint(family))
         else:
-          posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).SockLen,
-                              cint(posix.AF_INET))
+          posix.gethostbyaddr(myAddr, addrLen.SockLen,
+                              cint(family))
       if s == nil:
         raiseOSError(osLastError(), $hstrerror(h_errno))
 
@@ -424,7 +440,20 @@ when not useNimNetLite:
         result.addrList.add($inet_ntoa(inaddrPtr[]))
         inc(i)
     else:
-      result.addrList = cstringArrayToSeq(s.h_addr_list)
+      let strAddrLen = when not useWinVersion: posix.INET6_ADDRSTRLEN.int
+                       else: 46
+      var i = 0
+      while not isNil(s.h_addr_list[i]):
+        var ipStr = newString(strAddrLen)
+        if inet_ntop(nativeAfInet6, cast[pointer](s.h_addr_list[i]),
+                     cstring(ipStr), len(ipStr).int32) == nil:
+          raiseOSError(osLastError())
+        when not useWinVersion:
+          if posix.IN6_IS_ADDR_V4MAPPED(cast[ptr In6Addr](s.h_addr_list[i])) != 0:
+            ipStr.setSlice("::ffff:".len..<strAddrLen)
+        setLen(ipStr, len(cstring(ipStr)))
+        result.addrList.add(ipStr)
+        inc(i)
     result.length = int(s.h_length)
 
   proc getHostByName*(name: string): Hostent {.tags: [ReadIOEffect].} =