let info = getHostByName("www.kame.net") for addr in info.addrList: echo addr
But it only outputs the IPV4 address.
I'm a n00b, and I've spent some time trying to research this without finding a good answer. I'm posting my notes in case they are helpful for someone...
In C one would use getaddrinfo. This is much easier in Python, which has a high-level getsocketinfo wrapper:
#!/usr/bin/python3
import socket
host = 'www.kame.net'
port = 80
family = socket.AF_INET6
type = socket.SOCK_STREAM
addrInfo = socket.getaddrinfo(host, port, family, type)
print(addrInfo[0][4][0])
Nim doesn't seem to have an equivalent portable high-level getaddrinfo.
import net, osproc, posix, strutils, nativesockets
proc getIpv6_execCmd(hostname: string): string =
## Would only work on UNIX with https://linux.die.net/man/1/host
const
lookupCmd = "host -t AAAA "
expectStr = " has IPv6 address "
let (output, err) = osproc.execCmdEx(lookupCmd & hostname)
let expectPos = output.find(expectStr)
if expectPos < 0: return ""
let startPos = expectPos + expectStr.len
let finalPos = output.len - 2
if finalPos <= startPos: return ""
return output[startPos..finalPos]
proc getIpv6_dial(hostname: string): string =
## Don't know why this doesn't work... {{{Error: unhandled exception:
## Additional info: "Servname not supported for ai_socktype" [OSError]}}}
let s = net.dial(hostname, 80.Port, Protocol.IPPROTO_IPV6)
return s.getLocalAddr[0]
proc getIpv6_socket(hostname: string): string =
## Also doesn't work... {{{Protocol not supported}}}
let sock = newSocket(Domain.AF_INET6, SockType.SOCK_STREAM,
Protocol.IPPROTO_IPV6)
return sock.getLocalAddr[0]
proc getIpv6_getaddressinfo(hostname: string): string =
## Don't have time to figure this out tonight...
const fam = Domain.AF_INET6
var addrInfo = getAddrInfo(hostname, 80.Port, fam)
echo addrInfo.ai_addr.sa_data.addr
result = ""
while true:
var outBuf = newString(64)
let dataAddr = addr addrInfo.ai_addr.sa_data
let r = inet_ntop(fam.cint, dataAddr, addr outBuf[0], 65'i32)
result &= outBuf
if addrInfo.ai_next.isNil: break
addrInfo = addrInfo.ai_next
freeAddrInfo addrInfo
echo getIpv6_getaddressinfo("www.kame.net")
@satoru
Note that getHostByName is deprecated at least on linux.
@Libman
Nim (nativesockets) does provide getAddrInfo but as you probably saw in your research it's all but worthless because it's a mess. Which btw. is hardly Nim's fault but rather a consequence of IPv6 being a makeshift insanity and mess. So I can perfectly well understand that the Nim developers basically just threw something very close to a blank importc at us. A proper clean Nim version would be quite some work due to both IPv6's insanity and plenty of OS implementation details. And as only a few proponents really use IPv6 while pretty much all servers still use IPv4 it's not exactly an attractive and urgent looking goal to do that work.
My personal approach - and suggestion for those who absolutely want that functionality - would be to create a reasonably sane (well, as sane as anything IPv6 related can be) implementation in C, say, one simply returning a list of objects holding IPs, maybe with an extra field indicating IPv4 or IPv6, and to then create a Nim binding returning a sequence of those simple objects for that.
I am confused by lots of things, including that the same constants like AF_INET6 are present with different values in lib/nativesockets.nim vs lib/posix/posix_linux_amd64_consts.nim.
The edited above code now uses posix's AF_INET6 value (10.cint) cast to nativesockets Domain enum for getAddrInfo. It's no longer looking the gibberish, but something is still off. Current output:
getIpv6_execCmd: 2001:200:dff:fff1:216:3eff:feb1:44d7
getIpv6_getaddressinfo: 50::2001:200:dff:fff1:21650:cbb2:8dc2::102
At least it seems to contain a part of the correct answer...
The getAddrInfo call doesn't return the full struct (only to 0xfff1). Moreover the first couple of bytes are not part of the IPv6 address and the first address byte is the 5th byte after 0x50 (0x20, 0x1, ...).
Frankly, I don't think it worth putting more work into the current solution. If you are interested just have a good c solution with 2 functions, one for IPv6 and one for IPv4 and then a Nim wrapper with an additional convenience function/proc that calls both and returns a seq[IpAddress] (from which btw. the C memory can be freed too once the C helpers are done and Nim has built up its result seq.