From 9eaeac69829469108bce954ccce0710bbdb27fb3 Mon Sep 17 00:00:00 2001
From: beware <beware@bircd.org>
Date: Tue, 22 Feb 2011 05:40:41 +0000
Subject: [PATCH] added ipv6 detection on windows for built-in resolver

git-svn-id: file:///svnroot/lcore/trunk@95 b1de8a11-f9be-4011-bde0-cc7ace90066a
---
 dnscore.pas | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/dnscore.pas b/dnscore.pas
index d0dbbf0..7cbb828 100644
--- a/dnscore.pas
+++ b/dnscore.pas
@@ -221,7 +221,7 @@ implementation
 
 uses
   {$ifdef win32}
-    windows,
+    windows,winsock,
   {$endif}
 
   sysutils;
@@ -781,9 +781,34 @@ begin
 end;
 
 {$else}
+
+{the following code's purpose is to determine what IP windows would come from, to reach an IP
+it can be abused to find if there's any global v6 IPs, getaddrinfo seems unreliable (not working on XP atleast)
+}
+const
+  SIO_ROUTING_INTERFACE_QUERY = $c8000014;
+  function WSAIoctl(s: TSocket; code:integer; const Buf; len: Integer; var output; outlen:integer; var outreturned: Integer; overlapped:pointer; completion: pointer): Integer; stdcall; external 'ws2_32.dll' name 'WSAIoctl';
+
+function getlocalipforip(const ip:tbinip):tbinip;
+var
+  handle:integer;
+  a,b:integer;
+  inaddrv,inaddrv2:tinetsockaddrv;
+  srcx:winsock.tsockaddr absolute inaddrv2;
+begin
+  makeinaddrv(ip,'0',inaddrv);
+  handle := Socket(inaddrv.inaddr.family,SOCK_DGRAM,IPPROTO_UDP);
+  if WSAIoctl(handle, SIO_ROUTING_INTERFACE_QUERY, inaddrv, sizeof(inaddrv), inaddrv2, sizeof(inaddrv2), a, nil, nil) <> 0
+  then raise exception.create('getlocalipforip failed with error: '+inttostr(wsagetlasterror));
+  result := inaddrvtobinip(inaddrv2);
+  closesocket(handle);
+end;
+
 function getv6localips:tbiniplist;
 begin
   result := biniplist_new;
+  {this IP is chosen because it's the first normal global v6 IP that has no special purpose}
+  biniplist_add(result,getlocalipforip(ipstrtobinf('2001:200::')));
 end;
 {$endif}
 
-- 
2.30.2