]> jfr.im git - solanum.git/commitdiff
authd: initial pass at win32 porting
authorWilliam Pitcock <redacted>
Sun, 20 Mar 2016 06:16:41 +0000 (01:16 -0500)
committerWilliam Pitcock <redacted>
Sun, 20 Mar 2016 06:16:41 +0000 (01:16 -0500)
authd/Makefile.am
authd/getaddrinfo.c [new file with mode: 0644]
authd/getaddrinfo.h [new file with mode: 0644]
authd/getnameinfo.c [new file with mode: 0644]
authd/getnameinfo.h [new file with mode: 0644]
authd/reslib.c
authd/reslist.c [new file with mode: 0644]
include/stdinc.h

index e1b705e14e0ba21427e01ea05ee68af225e2a1a5..1b8ebf71034be38a2df187178c887ee6542e82f6 100644 (file)
@@ -3,5 +3,5 @@ AM_CFLAGS=$(WARNFLAGS)
 AM_CPPFLAGS = -I../include -I../librb/include 
 
 
-authd_SOURCES = authd.c res.c reslib.c dns.c
+authd_SOURCES = authd.c res.c reslib.c reslist.c getnameinfo.c getaddrinfo.c dns.c
 authd_LDADD = ../librb/src/librb.la
diff --git a/authd/getaddrinfo.c b/authd/getaddrinfo.c
new file mode 100644 (file)
index 0000000..482e648
--- /dev/null
@@ -0,0 +1,617 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef _WIN32
+#include <ratbox_lib.h>
+#include "getaddrinfo.h"
+
+/*  $Id$ */
+
+static const char in_addrany[] = { 0, 0, 0, 0 };
+static const char in_loopback[] = { 127, 0, 0, 1 };
+static const char in6_addrany[] = {
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+static const char in6_loopback[] = {
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+};
+
+static const struct afd {
+       int a_af;
+       int a_addrlen;
+       int a_socklen;
+       int a_off;
+       const char *a_addrany;
+       const char *a_loopback;
+       int a_scoped;
+} afdl [] = {
+#define        N_INET6 0
+#ifdef IPV6
+       {PF_INET6, sizeof(struct in6_addr),
+        sizeof(struct sockaddr_in6),
+        offsetof(struct sockaddr_in6, sin6_addr),
+        in6_addrany, in6_loopback, 1},
+#endif
+#define        N_INET 1
+       {PF_INET, sizeof(struct in_addr),
+        sizeof(struct sockaddr_in),
+        offsetof(struct sockaddr_in, sin_addr),
+        in_addrany, in_loopback, 0},
+       {0, 0, 0, 0, NULL, NULL, 0},
+};
+
+struct explore {
+       int e_af;
+       int e_socktype;
+       int e_protocol;
+       const char *e_protostr;
+       int e_wild;
+#define WILD_AF(ex)            ((ex)->e_wild & 0x01)
+#define WILD_SOCKTYPE(ex)      ((ex)->e_wild & 0x02)
+#define WILD_PROTOCOL(ex)      ((ex)->e_wild & 0x04)
+};
+
+static const struct explore explore[] = {
+#ifdef IPV6
+       { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
+       { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
+       { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
+#endif
+       { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
+       { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
+       { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
+       { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
+       { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
+       { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 },
+       { -1, 0, 0, NULL, 0 },
+};
+
+#define PTON_MAX       16
+
+static int str_isnumber(const char *);
+static int explore_null(const struct rb_addrinfo *,
+       const char *, struct rb_addrinfo **);
+static int explore_numeric(const struct rb_addrinfo *, const char *,
+       const char *, struct rb_addrinfo **);
+static struct rb_addrinfo *get_ai(const struct rb_addrinfo *,
+       const struct afd *, const char *);
+static int get_portmatch(const struct rb_addrinfo *, const char *);
+static int get_port(struct rb_addrinfo *, const char *, int);
+static const struct afd *find_afd(int);
+#if 0
+/* We will need this should we ever want gai_strerror() */
+static char *ai_errlist[] = {
+       "Success",
+       "Address family for hostname not supported",    /* EAI_ADDRFAMILY */
+       "Temporary failure in name resolution",         /* EAI_AGAIN      */
+       "Invalid value for ai_flags",                   /* EAI_BADFLAGS   */
+       "Non-recoverable failure in name resolution",   /* EAI_FAIL       */
+       "ai_family not supported",                      /* EAI_FAMILY     */
+       "Memory allocation failure",                    /* EAI_MEMORY     */
+       "No address associated with hostname",          /* EAI_NODATA     */
+       "hostname nor servname provided, or not known", /* EAI_NONAME     */
+       "servname not supported for ai_socktype",       /* EAI_SERVICE    */
+       "ai_socktype not supported",                    /* EAI_SOCKTYPE   */
+       "System error returned in errno",               /* EAI_SYSTEM     */
+       "Invalid value for hints",                      /* EAI_BADHINTS   */
+       "Resolved protocol is unknown",                 /* EAI_PROTOCOL   */
+       "Unknown error",                                /* EAI_MAX        */
+};
+#endif
+/* XXX macros that make external reference is BAD. */
+
+#define GET_AI(ai, afd, addr) \
+do { \
+       /* external reference: pai, error, and label free */ \
+       (ai) = get_ai(pai, (afd), (addr)); \
+       if ((ai) == NULL) { \
+               error = EAI_MEMORY; \
+               goto free; \
+       } \
+} while (/*CONSTCOND*/0)
+
+#define GET_PORT(ai, serv) \
+do { \
+       /* external reference: error and label free */ \
+       error = get_port((ai), (serv), 0); \
+       if (error != 0) \
+               goto free; \
+} while (/*CONSTCOND*/0)
+
+#define ERR(err) \
+do { \
+       /* external reference: error, and label bad */ \
+       error = (err); \
+       goto bad; \
+       /*NOTREACHED*/ \
+} while (/*CONSTCOND*/0)
+
+#define MATCH_FAMILY(x, y, w) \
+       ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
+#define MATCH(x, y, w) \
+       ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
+
+#if 0
+/* We will need this should we ever want gai_strerror() */
+char *
+gai_strerror(int ecode)
+{
+       if (ecode < 0 || ecode > EAI_MAX)
+               ecode = EAI_MAX;
+       return ai_errlist[ecode];
+}
+#endif
+
+void
+rb_freeaddrinfo(struct rb_addrinfo *ai)
+{
+       struct rb_addrinfo *next;
+
+       do {
+               next = ai->ai_next;
+               if (ai->ai_canonname)
+                       rb_free(ai->ai_canonname);
+               /* no need to free(ai->ai_addr) */
+               rb_free(ai);
+               ai = next;
+       } while (ai);
+}
+
+static int
+str_isnumber(const char *p)
+{
+       char *ep;
+
+       if (*p == '\0')
+               return NO;
+       ep = NULL;
+       errno = 0;
+       (void)strtoul(p, &ep, 10);
+       if (errno == 0 && ep && *ep == '\0')
+               return YES;
+       else
+               return NO;
+}
+
+int
+rb_getaddrinfo(const char *hostname, const char *servname,
+               const struct rb_addrinfo *hints, struct rb_addrinfo **res)
+{
+  struct rb_addrinfo sentinel;
+  struct rb_addrinfo *cur;
+  int error = 0;
+  struct rb_addrinfo ai;
+  struct rb_addrinfo ai0;
+  struct rb_addrinfo *pai;
+  const struct explore *ex;
+
+  memset(&sentinel, 0, sizeof(sentinel));
+  cur = &sentinel;
+  pai = &ai;
+  pai->ai_flags = 0;
+  pai->ai_family = PF_UNSPEC;
+  pai->ai_socktype = ANY;
+  pai->ai_protocol = ANY;
+  pai->ai_addrlen = 0;
+  pai->ai_canonname = NULL;
+  pai->ai_addr = NULL;
+  pai->ai_next = NULL;
+
+  if (hostname == NULL && servname == NULL)
+    return EAI_NONAME;
+       if (hints) {
+               /* error check for hints */
+               if (hints->ai_addrlen || hints->ai_canonname ||
+                   hints->ai_addr || hints->ai_next)
+                       ERR(EAI_BADHINTS); /* xxx */
+               if (hints->ai_flags & ~AI_MASK)
+                       ERR(EAI_BADFLAGS);
+               switch (hints->ai_family) {
+               case PF_UNSPEC:
+               case PF_INET:
+#ifdef IPV6
+               case PF_INET6:
+#endif
+                       break;
+               default:
+                       ERR(EAI_FAMILY);
+               }
+               memcpy(pai, hints, sizeof(*pai));
+
+               /*
+                * if both socktype/protocol are specified, check if they
+                * are meaningful combination.
+                */
+               if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
+                       for (ex = explore; ex->e_af >= 0; ex++) {
+                               if (pai->ai_family != ex->e_af)
+                                       continue;
+                               if (ex->e_socktype == ANY)
+                                       continue;
+                               if (ex->e_protocol == ANY)
+                                       continue;
+                               if (pai->ai_socktype == ex->e_socktype &&
+                                   pai->ai_protocol != ex->e_protocol) {
+                                       ERR(EAI_BADHINTS);
+                               }
+                       }
+               }
+       }
+
+       /*
+        * check for special cases.  (1) numeric servname is disallowed if
+        * socktype/protocol are left unspecified. (2) servname is disallowed
+        * for raw and other inet{,6} sockets.
+        */
+       if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
+#ifdef IPV6
+           || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
+#endif
+           ) {
+               ai0 = *pai;     /* backup *pai */
+
+               if (pai->ai_family == PF_UNSPEC) {
+#ifdef IPV6
+                       pai->ai_family = PF_INET6;
+#else
+                       pai->ai_family = PF_INET;
+#endif
+               }
+               error = get_portmatch(pai, servname);
+               if (error)
+                       ERR(error);
+
+               *pai = ai0;
+       }
+
+       ai0 = *pai;
+
+       /* NULL hostname, or numeric hostname */
+       for (ex = explore; ex->e_af >= 0; ex++) {
+               *pai = ai0;
+
+               /* PF_UNSPEC entries are prepared for DNS queries only */
+               if (ex->e_af == PF_UNSPEC)
+                       continue;
+
+               if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
+                       continue;
+               if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
+                       continue;
+               if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
+                       continue;
+
+               if (pai->ai_family == PF_UNSPEC)
+                       pai->ai_family = ex->e_af;
+               if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
+                       pai->ai_socktype = ex->e_socktype;
+               if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
+                       pai->ai_protocol = ex->e_protocol;
+
+               if (hostname == NULL)
+                       error = explore_null(pai, servname, &cur->ai_next);
+               else
+                       error = explore_numeric(pai, hostname, servname, &cur->ai_next);
+
+               if (error)
+                       goto free;
+
+               while (cur && cur->ai_next)
+                       cur = cur->ai_next;
+       }
+
+       /*
+        * XXX
+        * If numreic representation of AF1 can be interpreted as FQDN
+        * representation of AF2, we need to think again about the code below.
+        */
+       if (sentinel.ai_next)
+               goto good;
+
+       if (pai->ai_flags & AI_NUMERICHOST)
+               ERR(EAI_NONAME);
+       if (hostname == NULL)
+               ERR(EAI_NODATA);
+
+       /* XXX */
+       if (sentinel.ai_next)
+               error = 0;
+
+       if (error)
+               goto free;
+       if (error == 0) {
+               if (sentinel.ai_next) {
+ good:
+                       *res = sentinel.ai_next;
+                       return SUCCESS;
+               } else
+                       error = EAI_FAIL;
+       }
+ free:
+ bad:
+       if (sentinel.ai_next)
+               rb_freeaddrinfo(sentinel.ai_next);
+       *res = NULL;
+       return error;
+}
+
+/*
+ * hostname == NULL.
+ * passive socket -> anyaddr (0.0.0.0 or ::)
+ * non-passive socket -> localhost (127.0.0.1 or ::1)
+ */
+static int
+explore_null(const struct rb_addrinfo *pai, const char *servname, struct rb_addrinfo **res)
+{
+  int s;
+  const struct afd *afd;
+  struct rb_addrinfo *cur;
+  struct rb_addrinfo sentinel;
+  int error;
+
+       *res = NULL;
+       sentinel.ai_next = NULL;
+       cur = &sentinel;
+
+       /*
+        * filter out AFs that are not supported by the kernel
+        * XXX errno?
+        */
+       s = socket(pai->ai_family, SOCK_DGRAM, 0);
+       if (s < 0) {
+#ifdef _WIN32
+               errno = WSAGetLastError();
+#endif
+               if (errno != EMFILE)
+                       return 0;
+       } else
+#ifdef _WIN32
+               closesocket(s);
+#else
+               close(s);
+#endif
+
+       /*
+        * if the servname does not match socktype/protocol, ignore it.
+        */
+       if (get_portmatch(pai, servname) != 0)
+               return 0;
+
+       afd = find_afd(pai->ai_family);
+       if (afd == NULL)
+               return 0;
+
+       if (pai->ai_flags & AI_PASSIVE) {
+               GET_AI(cur->ai_next, afd, afd->a_addrany);
+               GET_PORT(cur->ai_next, servname);
+       } else {
+               GET_AI(cur->ai_next, afd, afd->a_loopback);
+               GET_PORT(cur->ai_next, servname);
+       }
+       cur = cur->ai_next;
+
+       *res = sentinel.ai_next;
+       return 0;
+
+free:
+       if (sentinel.ai_next)
+               rb_freeaddrinfo(sentinel.ai_next);
+       return error;
+}
+
+/*
+ * numeric hostname
+ */
+static int
+explore_numeric(const struct rb_addrinfo *pai, const char *hostname,
+               const char *servname, struct rb_addrinfo **res)
+{
+  const struct afd *afd;
+  struct rb_addrinfo *cur;
+  struct rb_addrinfo sentinel;
+  int error;
+  char pton[PTON_MAX];
+
+  *res = NULL;
+  sentinel.ai_next = NULL;
+  cur = &sentinel;
+
+       /*
+        * if the servname does not match socktype/protocol, ignore it.
+        */
+       if (get_portmatch(pai, servname) != 0)
+               return 0;
+
+       afd = find_afd(pai->ai_family);
+       if (afd == NULL)
+               return 0;
+
+       switch (afd->a_af) {
+#if 0 /*X/Open spec*/
+       case AF_INET:
+               if (rb_inet_pton
+               if (inet_aton(hostname, (struct in_addr *)pton) == 1) {
+                       if (pai->ai_family == afd->a_af ||
+                           pai->ai_family == PF_UNSPEC /*?*/) {
+                               GET_AI(cur->ai_next, afd, pton);
+                               GET_PORT(cur->ai_next, servname);
+                               while (cur && cur->ai_next)
+                                       cur = cur->ai_next;
+                       } else
+                               ERR(EAI_FAMILY);        /*xxx*/
+               }
+               break;
+#endif
+       default:
+               if (rb_inet_pton(afd->a_af, hostname, pton) == 1) {
+                       if (pai->ai_family == afd->a_af ||
+                           pai->ai_family == PF_UNSPEC /*?*/) {
+                               GET_AI(cur->ai_next, afd, pton);
+                               GET_PORT(cur->ai_next, servname);
+                               while (cur && cur->ai_next)
+                                       cur = cur->ai_next;
+                       } else
+                               ERR(EAI_FAMILY);        /* XXX */
+               }
+               break;
+       }
+
+       *res = sentinel.ai_next;
+       return 0;
+
+free:
+bad:
+       if (sentinel.ai_next)
+               rb_freeaddrinfo(sentinel.ai_next);
+       return error;
+}
+
+static struct rb_addrinfo *
+get_ai(const struct rb_addrinfo *pai, const struct afd *afd, const char *addr)
+{
+  char *p;
+  struct rb_addrinfo *ai;
+       
+    ai = (struct rb_addrinfo *)rb_malloc(sizeof(struct rb_addrinfo)
+               + (afd->a_socklen));
+       if (ai == NULL)
+               return NULL;
+
+       memcpy(ai, pai, sizeof(struct rb_addrinfo));
+       ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
+       memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
+       ai->ai_addrlen = afd->a_socklen;
+       ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
+       p = (char *)(void *)(ai->ai_addr);
+       memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
+       return ai;
+}
+
+static int
+get_portmatch(const struct rb_addrinfo *ai, const char *servname)
+{
+  struct rb_addrinfo xai;
+  memcpy(&xai, ai, sizeof(struct rb_addrinfo)); 
+  return(get_port(&xai, servname, 1));
+}
+
+static int
+get_port(struct rb_addrinfo *ai, const char *servname, int matchonly)
+{
+  const char *proto;
+  struct servent *sp;
+  int port;
+  int allownumeric;
+
+  if (servname == NULL)
+    return 0;
+       switch (ai->ai_family) {
+       case AF_INET:
+#ifdef AF_INET6
+       case AF_INET6:
+#endif
+               break;
+       default:
+               return 0;
+       }
+
+       switch (ai->ai_socktype) {
+       case SOCK_RAW:
+               return EAI_SERVICE;
+       case SOCK_DGRAM:
+       case SOCK_STREAM:
+               allownumeric = 1;
+               break;
+       case ANY:
+               allownumeric = 0;
+               break;
+       default:
+               return EAI_SOCKTYPE;
+       }
+
+       if (str_isnumber(servname)) {
+               if (!allownumeric)
+                       return EAI_SERVICE;
+               port = atoi(servname);
+               if (port < 0 || port > 65535)
+                       return EAI_SERVICE;
+               port = htons(port);
+       } else {
+               switch (ai->ai_socktype) {
+               case SOCK_DGRAM:
+                       proto = "udp";
+                       break;
+               case SOCK_STREAM:
+                       proto = "tcp";
+                       break;
+               default:
+                       proto = NULL;
+                       break;
+               }
+
+               if ((sp = getservbyname(servname, proto)) == NULL)
+                       return EAI_SERVICE;
+               port = sp->s_port;
+       }
+
+       if (!matchonly) {
+               switch (ai->ai_family) {
+               case AF_INET:
+                       ((struct sockaddr_in *)(void *)
+                           ai->ai_addr)->sin_port = port;
+                       break;
+#ifdef IPV6
+               case AF_INET6:
+                       ((struct sockaddr_in6 *)(void *)
+                           ai->ai_addr)->sin6_port = port;
+                       break;
+#endif
+               }
+       }
+
+       return 0;
+}
+
+static const struct afd *
+find_afd(int af)
+{
+  const struct afd *afd;
+
+  if (af == PF_UNSPEC)
+    return(NULL);
+
+  for (afd = afdl; afd->a_af; afd++)
+  {
+    if (afd->a_af == af)
+      return(afd);
+  }
+
+  return(NULL);
+}
+#endif
diff --git a/authd/getaddrinfo.h b/authd/getaddrinfo.h
new file mode 100644 (file)
index 0000000..746db14
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *  $Id$
+ */
+
+struct rb_addrinfo {
+       int ai_flags;
+       int ai_family;
+       int ai_socktype;
+       int ai_protocol;
+       size_t ai_addrlen;
+       char *ai_canonname;
+       struct sockaddr *ai_addr;
+       struct rb_addrinfo *ai_next;
+};
+
+#ifndef AI_PASSIVE
+#define AI_PASSIVE      0x00000001 /* get address to use bind() */
+#endif /* AI_PASSIVE */
+
+#ifndef AI_NUMERICHOST
+#define AI_NUMERICHOST  0x00000004 /* prevent name resolution */
+#endif /* AI_NUMERICHOST */
+
+#ifndef EAI_FAIL
+#define EAI_FAIL         4      /* non-recoverable failure in name resolution */
+#endif /* EAI_FAIL */
+
+#ifndef EAI_FAMILY
+#define EAI_FAMILY       5      /* ai_family not supported */
+#endif /* EAI_FAMILY */
+
+#ifndef EAI_MEMORY
+#define EAI_MEMORY       6      /* memory allocation failure */
+#endif /* EAI_MEMORY */
+
+#ifndef EAI_NONAME
+#define EAI_NONAME       8      /* hostname nor servname provided, or not known */
+#endif /* EAI_NONAME */
+
+#ifndef EAI_SYSTEM
+#define EAI_SYSTEM      11      /* system error returned in errno */
+#endif /* EAI_SYSTEM */
+
+#ifndef NI_NUMERICHOST
+#define NI_NUMERICHOST 0x00000002
+#endif /* NI_NUMERICHOST */
+
+#ifndef NI_NAMEREQD
+#define NI_NAMEREQD     0x00000004
+#endif /* NI_NAMEREQD */
+
+#ifndef NI_NUMERICSERV
+#define NI_NUMERICSERV  0x00000008
+#endif /* NI_NUMERICSERV */
+
+#ifndef NI_DGRAM
+#define NI_DGRAM        0x00000010
+#endif /* NI_DGRAM */
+
+#ifndef INADDR_NONE
+#define INADDR_NONE ((unsigned int) 0xffffffff)
+#endif /* INADDR_NONE */
+
+int rb_getaddrinfo(const char *hostname, const char *servname,
+                           const struct rb_addrinfo *hints, struct rb_addrinfo **res);
+void rb_freeaddrinfo(struct rb_addrinfo *ai);
+
+#define SUCCESS 0
+#define ANY 0
+#define YES 1
+#define NO  0
+
+#undef EAI_ADDRFAMILY
+#undef EAI_AGAIN
+#undef EAI_BADFLAGS
+#undef EAI_FAIL
+#undef EAI_FAMILY
+#undef EAI_MEMORY
+#undef EAI_NODATA
+#undef EAI_NONAME
+#undef EAI_SERVICE
+#undef EAI_SOCKTYPE
+#undef EAI_SYSTEM
+#undef EAI_BADHINTS
+#undef EAI_PROTOCOL
+#undef EAI_MAX
+#undef AI_MASK
+
+#define EAI_ADDRFAMILY   1  /* address family for hostname not supported */
+#define EAI_AGAIN    2  /* temporary failure in name resolution */
+#define EAI_BADFLAGS     3  /* invalid value for ai_flags */
+#define EAI_FAIL     4  /* non-recoverable failure in name resolution */
+#define EAI_FAMILY   5  /* ai_family not supported */
+#define EAI_MEMORY   6  /* memory allocation failure */
+#define EAI_NODATA   7  /* no address associated with hostname */
+#define EAI_NONAME   8  /* hostname nor servname provided, or not known */
+#define EAI_SERVICE  9  /* servname not supported for ai_socktype */
+#define EAI_SOCKTYPE    10  /* ai_socktype not supported */
+#define EAI_SYSTEM  11  /* system error returned in errno */
+#define EAI_BADHINTS    12
+#define EAI_PROTOCOL    13
+#define EAI_MAX     14
+#define AI_MASK (AI_PASSIVE | AI_NUMERICHOST)
diff --git a/authd/getnameinfo.c b/authd/getnameinfo.c
new file mode 100644 (file)
index 0000000..eba0181
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Issues to be discussed:
+ * - Thread safe-ness must be checked
+ * - RFC2553 says that we should raise error on short buffer.  X/Open says
+ *   we need to truncate the result.  We obey RFC2553 (and X/Open should be
+ *   modified).         ipngwg rough consensus seems to follow RFC2553.
+ * - What is "local" in NI_FQDN?
+ * - NI_NAMEREQD and NI_NUMERICHOST conflict with each other.
+ * - (KAME extension) always attach textual scopeid (fe80::1%lo0), if
+ *   sin6_scope_id is filled - standardization status?
+ *   XXX breaks backward compat for code that expects no scopeid.
+ *   beware on merge.
+ */
+
+#ifdef _WIN32
+#include <ratbox_lib.h>
+#include "getaddrinfo.h"
+#include "getnameinfo.h"
+
+/*  $Id$ */
+
+static const struct afd {
+  int a_af;
+  int a_addrlen;
+  rb_socklen_t a_socklen;
+  int a_off;
+} afdl [] = {
+#ifdef IPV6
+    {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
+            offsetof(struct sockaddr_in6, sin6_addr)},
+#endif
+    {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
+           offsetof(struct sockaddr_in, sin_addr)},
+    {0, 0, 0, 0},
+};
+
+struct sockinet
+{
+  unsigned char si_len;
+  unsigned char si_family;
+  unsigned short si_port;
+};
+
+#ifdef IPV6
+static int ip6_parsenumeric(const struct sockaddr *, const char *, char *,
+    size_t, int);
+#endif
+
+int
+rb_getnameinfo(const struct sockaddr *sa, rb_socklen_t salen, char *host,
+               size_t hostlen, char *serv, size_t servlen, int flags)
+{
+  const struct afd *afd;
+  struct servent *sp;
+  unsigned short port;
+  int family, i;
+  const char *addr;
+  uint32_t v4a;
+  char numserv[512];
+  char numaddr[512];
+
+  if (sa == NULL)
+    return EAI_FAIL;
+
+/*     if (sa->sa_len != salen)
+               return EAI_FAIL;
+*/
+       family = sa->sa_family;
+       for (i = 0; afdl[i].a_af; i++)
+               if (afdl[i].a_af == family) {
+                       afd = &afdl[i];
+                       goto found;
+               }
+       return EAI_FAMILY;
+
+ found:
+       if (salen != afd->a_socklen)
+               return EAI_FAIL;
+
+       /* network byte order */
+       port = ((const struct sockinet *)sa)->si_port;
+       addr = (const char *)sa + afd->a_off;
+
+       if (serv == NULL || servlen == 0) {
+               /*
+                * do nothing in this case.
+                * in case you are wondering if "&&" is more correct than
+                * "||" here: rfc2553bis-03 says that serv == NULL OR
+                * servlen == 0 means that the caller does not want the result.
+                */
+       } else {
+               if (flags & NI_NUMERICSERV)
+                       sp = NULL;
+               else {
+                       sp = getservbyport(port,
+                               (flags & NI_DGRAM) ? "udp" : "tcp");
+               }
+               if (sp) {
+                       if (strlen(sp->s_name) + 1 > servlen)
+                               return EAI_MEMORY;
+                       rb_strlcpy(serv, sp->s_name, servlen);
+               } else {
+                       snprintf(numserv, sizeof(numserv), "%u", ntohs(port));
+                       if (strlen(numserv) + 1 > servlen)
+                               return EAI_MEMORY;
+                       rb_strlcpy(serv, numserv, servlen);
+               }
+       }
+
+       switch (sa->sa_family) {
+       case AF_INET:
+               v4a = (uint32_t)
+                   ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr);
+               if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
+                       flags |= NI_NUMERICHOST;
+               v4a >>= IN_CLASSA_NSHIFT;
+               if (v4a == 0)
+                       flags |= NI_NUMERICHOST;                        
+               break;
+#ifdef IPV6
+       case AF_INET6:
+           {
+               const struct sockaddr_in6 *sin6;
+               sin6 = (const struct sockaddr_in6 *)sa;
+               switch (sin6->sin6_addr.s6_addr[0]) {
+               case 0x00:
+                       if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
+                               ;
+                       else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
+                               ;
+                       else
+                               flags |= NI_NUMERICHOST;
+                       break;
+               default:
+                       if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+                               flags |= NI_NUMERICHOST;
+                       }
+                       else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
+                               flags |= NI_NUMERICHOST;
+                       break;
+               }
+           }
+               break;
+#endif
+       }
+       if (host == NULL || hostlen == 0) {
+               /*
+                * do nothing in this case.
+                * in case you are wondering if "&&" is more correct than
+                * "||" here: rfc2553bis-03 says that host == NULL or
+                * hostlen == 0 means that the caller does not want the result.
+                */
+       } else if (flags & NI_NUMERICHOST) {
+               size_t numaddrlen;
+
+               /* NUMERICHOST and NAMEREQD conflicts with each other */
+               if (flags & NI_NAMEREQD)
+                       return EAI_NONAME;
+
+               switch(afd->a_af) {
+#ifdef IPV6
+               case AF_INET6:
+               {
+                       int error;
+
+                       if ((error = ip6_parsenumeric(sa, addr, host,
+                                                     hostlen, flags)) != 0)
+                               return(error);
+                       break;
+               }
+#endif
+               default:
+                       if (rb_inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
+                           == NULL)
+                               return EAI_SYSTEM;
+                       numaddrlen = strlen(numaddr);
+                       if (numaddrlen + 1 > hostlen) /* don't forget terminator */
+                               return EAI_MEMORY;
+                       rb_strlcpy(host, numaddr, hostlen);
+                       break;
+               }
+       }
+       return(0);
+}
+
+#ifdef IPV6
+static int
+ip6_parsenumeric(const struct sockaddr *sa, const char *addr,
+                char *host, size_t hostlen, int flags)
+{
+  size_t numaddrlen;
+  char numaddr[512];
+
+  if (rb_inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL)
+    return(EAI_SYSTEM);
+
+  numaddrlen = strlen(numaddr);
+
+  if (numaddrlen + 1 > hostlen) /* don't forget terminator */
+    return(EAI_MEMORY);
+
+  if (*numaddr == ':')
+  {
+    *host = '0';
+    rb_strlcpy(host+1, numaddr, hostlen-1);
+  }
+  else
+    rb_strlcpy(host, numaddr, hostlen);
+
+  return(0);
+}
+#endif
+#endif
diff --git a/authd/getnameinfo.h b/authd/getnameinfo.h
new file mode 100644 (file)
index 0000000..26b965a
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *  $Id$
+ */
+
+int rb_getnameinfo(const struct sockaddr *sa, rb_socklen_t salen, char *host,
+                           size_t hostlen, char *serv, size_t servlen, int flags);
+
+#ifndef IN_MULTICAST
+#define IN_MULTICAST(a)         ((((long int) (a)) & 0xf0000000) == 0xe0000000)
+#endif
+
+#ifndef IN_EXPERIMENTAL
+#define IN_EXPERIMENTAL(a)      ((((long int) (a)) & 0xe0000000) == 0xe0000000)
+#endif
index 6f0180db456e8eb05374b6888a4330ff4e2ab5ab..963679dbe8762480b958b80b666ebd447baf5fc3 100644 (file)
  * - Dianora
  */
 
+#ifndef _WIN32
+#include <netdb.h>
+#else
+#include "getaddrinfo.h"
+#include "getnameinfo.h"
+#define getaddrinfo rb_getaddrinfo
+#define getnameinfo rb_getnameinfo
+#define freeaddrinfo rb_freeaddrinfo
+
+extern const char * get_windows_nameservers(void);
+#endif
+
 #include "stdinc.h"
 #include "ircd_defs.h"
 #include "common.h"
diff --git a/authd/reslist.c b/authd/reslist.c
new file mode 100644 (file)
index 0000000..d18a069
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ * reslist.c - get nameservers from windows *
+ * 
+ * ircd-ratbox related changes are as follows
+ * 
+ * Copyright (C) 2008 Aaron Sethman <androsyn@ratbox.org>
+ * Copyright (C) 2008-2012 ircd-ratbox development team
+ * 
+ * pretty much all of this was yanked from c-ares ares_init.c here is the original 
+ * header from there --
+ *
+ * Id: ares_init.c,v 1.72 2008-05-15 00:00:19 yangtse Exp $ 
+ * Copyright 1998 by the Massachusetts Institute of Technology.
+ * Copyright (C) 2007-2008 by Daniel Stenberg
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting
+ * documentation, and that the name of M.I.T. not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ *
+ */
+
+#ifdef _WIN32
+#include <ratbox_lib.h>
+
+#include <windows.h>
+#include <iphlpapi.h>
+
+const char *get_windows_nameservers(void);
+
+
+#define IS_NT()               ((int)GetVersion() > 0)
+#define WIN_NS_9X      "System\\CurrentControlSet\\Services\\VxD\\MSTCP"
+#define WIN_NS_NT_KEY  "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"
+#define NAMESERVER     "NameServer"
+#define DHCPNAMESERVER "DhcpNameServer"
+#define DATABASEPATH   "DatabasePath"
+#define WIN_PATH_HOSTS "\\hosts"
+
+static int
+get_iphlpapi_dns_info(char *ret_buf, size_t ret_size)
+{
+       FIXED_INFO *fi = alloca(sizeof(*fi));
+       DWORD size = sizeof(*fi);
+       typedef DWORD(WINAPI * get_net_param_func) (FIXED_INFO *, DWORD *);
+       get_net_param_func xxGetNetworkParams;  /* available only on Win-98/2000+ */
+       HMODULE handle;
+       IP_ADDR_STRING *ipAddr;
+       int i, count = 0;
+       int debug = 0;
+       size_t ip_size = sizeof("255.255.255.255,") - 1;
+       size_t left = ret_size;
+       char *ret = ret_buf;
+       HRESULT res;
+
+       if(!fi)
+               return (0);
+
+       handle = LoadLibrary("iphlpapi.dll");
+       if(!handle)
+               return (0);
+
+       xxGetNetworkParams = (get_net_param_func) GetProcAddress(handle, "GetNetworkParams");
+       if(!xxGetNetworkParams)
+               goto quit;
+
+       res = (*xxGetNetworkParams) (fi, &size);
+       if((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS))
+               goto quit;
+
+       fi = alloca(size);
+       if(!fi || (*xxGetNetworkParams) (fi, &size) != ERROR_SUCCESS)
+               goto quit;
+
+       if(debug)
+       {
+               printf("Host Name: %s\n", fi->HostName);
+               printf("Domain Name: %s\n", fi->DomainName);
+               printf("DNS Servers:\n" "    %s (primary)\n", fi->DnsServerList.IpAddress.String);
+       }
+       if(strlen(fi->DnsServerList.IpAddress.String) > 0 &&
+          inet_addr(fi->DnsServerList.IpAddress.String) != INADDR_NONE && left > ip_size)
+       {
+               ret += sprintf(ret, "%s,", fi->DnsServerList.IpAddress.String);
+               left -= ret - ret_buf;
+               count++;
+       }
+
+       for(i = 0, ipAddr = fi->DnsServerList.Next; ipAddr && left > ip_size;
+           ipAddr = ipAddr->Next, i++)
+       {
+               if(inet_addr(ipAddr->IpAddress.String) != INADDR_NONE)
+               {
+                       ret += sprintf(ret, "%s,", ipAddr->IpAddress.String);
+                       left -= ret - ret_buf;
+                       count++;
+               }
+               if(debug)
+                       printf("    %s (secondary %d)\n", ipAddr->IpAddress.String, i + 1);
+       }
+
+      quit:
+       if(handle)
+               FreeLibrary(handle);
+
+       if(debug && left <= ip_size)
+               printf("Too many nameservers. Truncating to %d addressess", count);
+       if(ret > ret_buf)
+               ret[-1] = '\0';
+       return (count);
+}
+
+/*
+ * Warning: returns a dynamically allocated buffer, the user MUST
+ * use free() / rb_free() if the function returns 1
+ */
+static int
+get_res_nt(HKEY hKey, const char *subkey, char **obuf)
+{
+       /* Test for the size we need */
+       DWORD size = 0;
+       int result;
+
+       result = RegQueryValueEx(hKey, subkey, 0, NULL, NULL, &size);
+       if((result != ERROR_SUCCESS && result != ERROR_MORE_DATA) || !size)
+               return 0;
+       *obuf = rb_malloc(size + 1);
+       if(!*obuf)
+               return 0;
+
+       if(RegQueryValueEx(hKey, subkey, 0, NULL, (LPBYTE) * obuf, &size) != ERROR_SUCCESS)
+       {
+               rb_free(*obuf);
+               return 0;
+       }
+       if(size == 1)
+       {
+               rb_free(*obuf);
+               return 0;
+       }
+       return 1;
+}
+
+static int
+get_res_interfaces_nt(HKEY hKey, const char *subkey, char **obuf)
+{
+       char enumbuf[39];       /* GUIDs are 38 chars + 1 for NULL */
+       DWORD enum_size = 39;
+       int idx = 0;
+       HKEY hVal;
+
+       while(RegEnumKeyEx(hKey, idx++, enumbuf, &enum_size, 0,
+                          NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS)
+       {
+               int rc;
+
+               enum_size = 39;
+               if(RegOpenKeyEx(hKey, enumbuf, 0, KEY_QUERY_VALUE, &hVal) != ERROR_SUCCESS)
+                       continue;
+               rc = get_res_nt(hVal, subkey, obuf);
+               RegCloseKey(hVal);
+               if(rc)
+                       return 1;
+       }
+       return 0;
+}
+
+const char *
+get_windows_nameservers(void)
+{
+       /*
+          NameServer info via IPHLPAPI (IP helper API):
+          GetNetworkParams() should be the trusted source for this.
+          Available in Win-98/2000 and later. If that fail, fall-back to
+          registry information.
+
+          NameServer Registry:
+
+          On Windows 9X, the DNS server can be found in:
+          HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD\MSTCP\NameServer
+
+          On Windows NT/2000/XP/2003:
+          HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\NameServer
+          or
+          HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\DhcpNameServer
+          or
+          HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\{AdapterID}\
+          NameServer
+          or
+          HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\{AdapterID}\
+          DhcpNameServer
+        */
+       static char namelist[512];
+       HKEY mykey;
+       HKEY subkey;
+       DWORD data_type;
+       DWORD bytes;
+       DWORD result;
+       char *line = NULL;
+       memset(&namelist, 0, sizeof(namelist));
+       if(get_iphlpapi_dns_info(namelist, sizeof(namelist)) > 0)
+       {
+               return namelist;
+       }
+
+       if(IS_NT())
+       {
+               if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0,
+                               KEY_READ, &mykey) == ERROR_SUCCESS)
+               {
+                       RegOpenKeyEx(mykey, "Interfaces", 0,
+                                    KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &subkey);
+                       if(get_res_nt(mykey, NAMESERVER, &line))
+                       {
+                               rb_strlcpy(namelist, line, sizeof(namelist));
+                               return namelist;
+                       }
+                       else if(get_res_nt(mykey, DHCPNAMESERVER, &line))
+                       {
+                               rb_strlcpy(namelist, line, sizeof(namelist));
+                               rb_free(line);
+                       }
+                       /* Try the interfaces */
+                       else if(get_res_interfaces_nt(subkey, NAMESERVER, &line))
+                       {
+                               rb_strlcpy(namelist, line, sizeof(namelist));
+                               rb_free(line);
+                       }
+                       else if(get_res_interfaces_nt(subkey, DHCPNAMESERVER, &line))
+                       {
+                               rb_strlcpy(namelist, line, sizeof(namelist));
+                               rb_free(line);
+                       }
+                       RegCloseKey(subkey);
+                       RegCloseKey(mykey);
+               }
+       }
+       else
+       {
+               if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_9X, 0,
+                               KEY_READ, &mykey) == ERROR_SUCCESS)
+               {
+                       if((result = RegQueryValueEx(mykey, NAMESERVER, NULL, &data_type,
+                                                    NULL, &bytes)) == ERROR_SUCCESS ||
+                          result == ERROR_MORE_DATA)
+                       {
+                               if(bytes)
+                               {
+                                       line = (char *)rb_malloc(bytes + 1);
+                                       if(RegQueryValueEx(mykey, NAMESERVER, NULL, &data_type,
+                                                          (unsigned char *)line, &bytes) ==
+                                          ERROR_SUCCESS)
+                                       {
+                                               rb_strlcpy(namelist, line, sizeof(namelist));
+                                       }
+                                       free(line);
+                               }
+                       }
+               }
+               RegCloseKey(mykey);
+       }
+       if(strlen(namelist) > 0)
+               return namelist;
+       return NULL;
+}
+
+
+#endif
index 0712e6219e782c7e7a19a7616f72657b7286fb42..eb321edb6b3006a50e088a826e7ca5d4200088e4 100644 (file)
@@ -92,7 +92,6 @@ typedef bool _Bool;
 #include <stdio.h>
 #include <time.h>
 #include <fcntl.h>
-#include <netdb.h>
 #include <stdarg.h>
 #include <signal.h>
 #include <dirent.h>
@@ -112,7 +111,6 @@ typedef bool _Bool;
 #endif
 
 
-#include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/wait.h>