Re: How to lookup the IPV6 addr of a domain name?

2018-12-03 Thread moerm
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.


Re: How to lookup the IPV6 addr of a domain name?

2018-12-03 Thread Libman
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


Run

At least it seems to contain a part of the correct answer...


Re: How to lookup the IPV6 addr of a domain name?

2018-12-02 Thread moerm
@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. 


Re: How to lookup the IPV6 addr of a domain name?

2018-12-01 Thread Libman
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](https://archive.fo/eFztO#selection-589.810-589.883). This is much 
easier in Python, which has a high-level [getsocketinfo 
wrapper](https://hg.python.org/cpython/file/3.5/Modules/socketmodule.c):


#!/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])


Run

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  "
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")



Run