about summary refs log tree commit diff
path: root/resolv
diff options
context:
space:
mode:
Diffstat (limited to 'resolv')
-rw-r--r--resolv/Depend1
-rw-r--r--resolv/Makefile4
-rw-r--r--resolv/Versions2
-rw-r--r--resolv/gai_cancel.c4
-rw-r--r--resolv/gai_error.c4
-rw-r--r--resolv/gai_misc.c32
-rw-r--r--resolv/gai_misc.h4
-rw-r--r--resolv/gai_notify.c53
-rw-r--r--resolv/gai_sigqueue.c36
-rw-r--r--resolv/gai_suspend.c19
-rw-r--r--resolv/getaddrinfo_a.c21
-rw-r--r--resolv/gethnamaddr.c10
-rw-r--r--resolv/herror.c5
-rw-r--r--resolv/inet_ntop.c2
-rw-r--r--resolv/nss_dns/dns-canon.c16
-rw-r--r--resolv/nss_dns/dns-host.c15
-rw-r--r--resolv/nss_dns/dns-network.c47
-rw-r--r--resolv/res-state.c45
-rw-r--r--resolv/res_data.c4
-rw-r--r--resolv/res_debug.c24
-rw-r--r--resolv/res_hconf.c221
-rw-r--r--resolv/res_hconf.h13
-rw-r--r--resolv/res_init.c36
-rw-r--r--resolv/res_libc.c16
-rw-r--r--resolv/res_mkquery.c48
-rw-r--r--resolv/res_query.c6
-rw-r--r--resolv/res_send.c123
-rw-r--r--resolv/tst-inet_ntop.c111
28 files changed, 531 insertions, 391 deletions
diff --git a/resolv/Depend b/resolv/Depend
index fe673ba5ec..8d2587bbc1 100644
--- a/resolv/Depend
+++ b/resolv/Depend
@@ -1 +1,2 @@
 linuxthreads
+nptl
diff --git a/resolv/Makefile b/resolv/Makefile
index f6230da8fb..6ac226735a 100644
--- a/resolv/Makefile
+++ b/resolv/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1994,1995,1996,1997,1998,1999,2000,2001,2003,2004
+# Copyright (C) 1994,1995,1996,1997,1998,1999,2000,2001,2003,2004,2007
 #	Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 
@@ -32,7 +32,7 @@ distribute := ../conf/portability.h mapv4v6addr.h mapv4v6hostent.h \
 routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \
 	    res_hconf res_libc res-state
 
-tests = tst-aton tst-leaks
+tests = tst-aton tst-leaks tst-inet_ntop
 xtests = tst-leaks2
 
 generate := mtrace-tst-leaks tst-leaks.mtrace tst-leaks2.mtrace
diff --git a/resolv/Versions b/resolv/Versions
index 2a67677d8e..7016365be5 100644
--- a/resolv/Versions
+++ b/resolv/Versions
@@ -39,7 +39,7 @@ libc {
     h_errno; __resp;
 %endif
 
-    __res_maybe_init;
+    __res_maybe_init; __res_iclose;
   }
 }
 
diff --git a/resolv/gai_cancel.c b/resolv/gai_cancel.c
index 45432065c4..19a0a9bb87 100644
--- a/resolv/gai_cancel.c
+++ b/resolv/gai_cancel.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
 
@@ -20,7 +20,7 @@
 #include <netdb.h>
 #include <pthread.h>
 
-#include "gai_misc.h"
+#include <gai_misc.h>
 
 
 int
diff --git a/resolv/gai_error.c b/resolv/gai_error.c
index 0620b04b9d..4c91628a62 100644
--- a/resolv/gai_error.c
+++ b/resolv/gai_error.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
 
@@ -19,7 +19,7 @@
 
 #include <netdb.h>
 
-#include "gai_misc.h"
+#include <gai_misc.h>
 
 int
 gai_error (struct gaicb *req)
diff --git a/resolv/gai_misc.c b/resolv/gai_misc.c
index b3334f38ef..2eec0f529d 100644
--- a/resolv/gai_misc.c
+++ b/resolv/gai_misc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
 
@@ -23,10 +23,31 @@
 #include <stdlib.h>
 #include <sys/time.h>
 
-#include "gai_misc.h"
+#include <gai_misc.h>
 
 
 
+#ifndef gai_create_helper_thread
+# define gai_create_helper_thread __gai_create_helper_thread
+
+extern inline int
+__gai_create_helper_thread (pthread_t *threadp, void *(*tf) (void *),
+			    void *arg)
+{
+  pthread_attr_t attr;
+
+  /* Make sure the thread is created detached.  */
+  pthread_attr_init (&attr);
+  pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+
+  int ret = pthread_create (threadp, &attr, tf, arg);
+
+  (void) pthread_attr_destroy (&attr);
+  return ret;
+}
+#endif
+
+
 /* Pool of request list entries.  */
 static struct requestlist **pool;
 
@@ -229,16 +250,11 @@ __gai_enqueue_request (struct gaicb *gaicbp)
   if (nthreads < optim.gai_threads && idle_thread_count == 0)
     {
       pthread_t thid;
-      pthread_attr_t attr;
 
       newp->running = 1;
 
-      /* Make sure the thread is created detached.  */
-      pthread_attr_init (&attr);
-      pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
-
       /* Now try to start a thread.  */
-      if (pthread_create (&thid, &attr, handle_requests, newp) == 0)
+      if (gai_create_helper_thread (&thid, handle_requests, newp) == 0)
 	/* We managed to enqueue the request.  All errors which can
 	   happen now can be recognized by calls to `gai_error'.  */
 	++nthreads;
diff --git a/resolv/gai_misc.h b/resolv/gai_misc.h
index 48a93977ae..94005de02c 100644
--- a/resolv/gai_misc.h
+++ b/resolv/gai_misc.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
 
@@ -29,7 +29,9 @@ struct waitlist
   {
     struct waitlist *next;
 
+#ifndef DONT_NEED_GAI_MISC_COND
     pthread_cond_t *cond;
+#endif
     volatile int *counterp;
     /* The next field is used in asynchronous `lio_listio' operations.  */
     struct sigevent *sigevp;
diff --git a/resolv/gai_notify.c b/resolv/gai_notify.c
index 987a64c0e2..c3ce0afb45 100644
--- a/resolv/gai_notify.c
+++ b/resolv/gai_notify.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
 
@@ -20,15 +20,24 @@
 #include <netdb.h>
 #include <pthread.h>
 #include <stdlib.h>
+#include <gai_misc.h>
 
-#include "gai_misc.h"
 
+struct notify_func
+  {
+    void (*func) (sigval_t);
+    sigval_t value;
+  };
 
 static void *
 notify_func_wrapper (void *arg)
 {
-  struct sigevent *sigev = arg;
-  sigev->sigev_notify_function (sigev->sigev_value);
+  gai_start_notify_thread ();
+  struct notify_func *const n = arg;
+  void (*func) (sigval_t) = n->func;
+  sigval_t value = n->value;
+  free (n);
+  (*func) (value);
   return NULL;
 }
 
@@ -54,8 +63,26 @@ __gai_notify_only (struct sigevent *sigev, pid_t caller_pid)
 	  pattr = &attr;
 	}
 
-      if (pthread_create (&tid, pattr, notify_func_wrapper, sigev) < 0)
+      /* SIGEV may be freed as soon as we return, so we cannot let the
+	 notification thread use that pointer.  Even though a sigval_t is
+	 only one word and the same size as a void *, we cannot just pass
+	 the value through pthread_create as the argument and have the new
+	 thread run the user's function directly, because on some machines
+	 the calling convention for a union like sigval_t is different from
+	 that for a pointer type like void *.  */
+      struct notify_func *nf = malloc (sizeof *nf);
+      if (nf == NULL)
 	result = -1;
+      else
+	{
+	  nf->func = sigev->sigev_notify_function;
+	  nf->value = sigev->sigev_value;
+	  if (pthread_create (&tid, pattr, notify_func_wrapper, nf) < 0)
+	    {
+	      free (nf);
+	      result = -1;
+	    }
+	}
     }
   else if (sigev->sigev_notify == SIGEV_SIGNAL)
     /* We have to send a signal.  */
@@ -79,15 +106,21 @@ __gai_notify (struct requestlist *req)
     {
       struct waitlist *next = waitlist->next;
 
-      /* Decrement the counter.  This is used in both cases.  */
-      --*waitlist->counterp;
-
       if (waitlist->sigevp == NULL)
-	pthread_cond_signal (waitlist->cond);
+	{
+#ifdef DONT_NEED_GAI_MISC_COND
+	  GAI_MISC_NOTIFY (waitlist);
+#else
+	  /* Decrement the counter.  */
+	  --*waitlist->counterp;
+
+	  pthread_cond_signal (waitlist->cond);
+#endif
+	}
       else
 	/* This is part of a asynchronous `getaddrinfo_a' operation.  If
 	   this request is the last one, send the signal.  */
-	if (*waitlist->counterp == 0)
+	if (--*waitlist->counterp == 0)
 	  {
 	    __gai_notify_only (waitlist->sigevp, waitlist->caller_pid);
 	    /* This is tricky.  See getaddrinfo_a.c for the reason why
diff --git a/resolv/gai_sigqueue.c b/resolv/gai_sigqueue.c
new file mode 100644
index 0000000000..278a1d8026
--- /dev/null
+++ b/resolv/gai_sigqueue.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 2001, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <aio.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <gai_misc.h>
+
+int
+__gai_sigqueue (sig, val, caller_pid)
+     int sig;
+     const union sigval val;
+     pid_t caller_pid;
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+stub_warning (__gai_sigqueue)
+#include <stub-tag.h>
diff --git a/resolv/gai_suspend.c b/resolv/gai_suspend.c
index bb3c9c3402..4d85ac2c10 100644
--- a/resolv/gai_suspend.c
+++ b/resolv/gai_suspend.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
 
@@ -23,7 +23,7 @@
 #include <stdlib.h>
 #include <sys/time.h>
 
-#include "gai_misc.h"
+#include <gai_misc.h>
 
 
 int
@@ -32,9 +32,11 @@ gai_suspend (const struct gaicb *const list[], int ent,
 {
   struct waitlist waitlist[ent];
   struct requestlist *requestlist[ent];
+#ifndef DONT_NEED_GAI_MISC_COND
   pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+#endif
   int cnt;
-  int dummy;
+  int cntr = 1;
   int none = 1;
   int result;
 
@@ -50,9 +52,11 @@ gai_suspend (const struct gaicb *const list[], int ent,
 
 	if (requestlist[cnt] != NULL)
 	  {
+#ifndef DONT_NEED_GAI_MISC_COND
 	    waitlist[cnt].cond = &cond;
+#endif
 	    waitlist[cnt].next = requestlist[cnt]->waiting;
-	    waitlist[cnt].counterp = &dummy;
+	    waitlist[cnt].counterp = &cntr;
 	    waitlist[cnt].sigevp = NULL;
 	    waitlist[cnt].caller_pid = 0;	/* Not needed.  */
 	    requestlist[cnt]->waiting = &waitlist[cnt];
@@ -78,6 +82,10 @@ gai_suspend (const struct gaicb *const list[], int ent,
 	 which we must remove.  So defer cancelation for now.  */
       pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate);
 
+#ifdef DONT_NEED_GAI_MISC_COND
+      result = 0;
+      GAI_MISC_WAIT (result, cntr, timeout, 1);
+#else
       if (timeout == NULL)
 	result = pthread_cond_wait (&cond, &__gai_requests_mutex);
       else
@@ -99,6 +107,7 @@ gai_suspend (const struct gaicb *const list[], int ent,
 	  result = pthread_cond_timedwait (&cond, &__gai_requests_mutex,
 					   &abstime);
 	}
+#endif
 
       /* Now remove the entry in the waiting list for all requests
 	 which didn't terminate.  */
@@ -121,10 +130,12 @@ gai_suspend (const struct gaicb *const list[], int ent,
       /* Now it's time to restore the cancelation state.  */
       pthread_setcancelstate (oldstate, NULL);
 
+#ifndef DONT_NEED_GAI_MISC_COND
       /* Release the conditional variable.  */
       if (pthread_cond_destroy (&cond) != 0)
 	/* This must never happen.  */
 	abort ();
+#endif
 
       if (result != 0)
 	{
diff --git a/resolv/getaddrinfo_a.c b/resolv/getaddrinfo_a.c
index abac27d361..f6af3aa45a 100644
--- a/resolv/getaddrinfo_a.c
+++ b/resolv/getaddrinfo_a.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
 
@@ -23,7 +23,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 
-#include "gai_misc.h"
+#include <gai_misc.h>
 
 
 /* We need this special structure to handle asynchronous I/O.  */
@@ -96,7 +96,9 @@ getaddrinfo_a (int mode, struct gaicb *list[], int ent, struct sigevent *sig)
     }
   else if (mode == GAI_WAIT)
     {
+#ifndef DONT_NEED_GAI_MISC_COND
       pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+#endif
       struct waitlist waitlist[ent];
       int oldstate;
 
@@ -104,7 +106,9 @@ getaddrinfo_a (int mode, struct gaicb *list[], int ent, struct sigevent *sig)
       for (cnt = 0; cnt < ent; ++cnt)
 	if (requests[cnt] != NULL)
 	  {
+#ifndef DONT_NEED_GAI_MISC_COND
 	    waitlist[cnt].cond = &cond;
+#endif
 	    waitlist[cnt].next = requests[cnt]->waiting;
 	    waitlist[cnt].counterp = &total;
 	    waitlist[cnt].sigevp = NULL;
@@ -119,15 +123,24 @@ getaddrinfo_a (int mode, struct gaicb *list[], int ent, struct sigevent *sig)
       pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate);
 
       while (total > 0)
-	pthread_cond_wait (&cond, &__gai_requests_mutex);
+	{
+#ifdef DONT_NEED_GAI_MISC_COND
+	  int result;
+	  GAI_MISC_WAIT (result, total, NULL, 1);
+#else
+	  pthread_cond_wait (&cond, &__gai_requests_mutex);
+#endif
+	}
 
       /* Now it's time to restore the cancelation state.  */
       pthread_setcancelstate (oldstate, NULL);
 
+#ifndef DONT_NEED_GAI_MISC_COND
       /* Release the conditional variable.  */
       if (pthread_cond_destroy (&cond) != 0)
 	/* This must never happen.  */
 	abort ();
+#endif
     }
   else
     {
@@ -147,7 +160,9 @@ getaddrinfo_a (int mode, struct gaicb *list[], int ent, struct sigevent *sig)
 	  for (cnt = 0; cnt < ent; ++cnt)
 	    if (requests[cnt] != NULL)
 	      {
+#ifndef DONT_NEED_GAI_MISC_COND
 		waitlist->list[cnt].cond = NULL;
+#endif
 		waitlist->list[cnt].next = requests[cnt]->waiting;
 		waitlist->list[cnt].counterp = &waitlist->counter;
 		waitlist->list[cnt].sigevp = &waitlist->sigev;
diff --git a/resolv/gethnamaddr.c b/resolv/gethnamaddr.c
index 3698e4b841..7be23158d0 100644
--- a/resolv/gethnamaddr.c
+++ b/resolv/gethnamaddr.c
@@ -51,7 +51,6 @@
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)gethostnamadr.c	8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id$";
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/types.h>
@@ -177,11 +176,7 @@ Dprintf(msg, num)
 
 
 static struct hostent *
-getanswer(answer, anslen, qname, qtype)
-	const querybuf *answer;
-	int anslen;
-	const char *qname;
-	int qtype;
+getanswer (const querybuf *answer, int anslen, const char *qname, int qtype)
 {
 	register const HEADER *hp;
 	register const u_char *cp;
@@ -523,7 +518,6 @@ gethostbyname2(name, af)
 	char *bp;
 	int n, size, type, len;
 	struct hostent *ret;
-	extern struct hostent *_gethtbyname2();
 
 	if (__res_maybe_init (&_res, 0) == -1) {
 		__set_h_errno (NETDB_INTERNAL);
@@ -667,7 +661,6 @@ gethostbyaddr(addr, len, af)
 	u_long old_options;
 	char hname2[MAXDNAME+1];
 #endif /*SUNSECURITY*/
-	extern struct hostent *_gethtbyaddr();
 
 	if (__res_maybe_init (&_res, 0) == -1) {
 		__set_h_errno (NETDB_INTERNAL);
@@ -880,7 +873,6 @@ struct hostent *
 _gethtbyname(name)
 	const char *name;
 {
-	extern struct hostent *_gethtbyname2();
 	struct hostent *hp;
 
 	if (_res.options & RES_USE_INET6) {
diff --git a/resolv/herror.c b/resolv/herror.c
index a61a3a9a4d..0aaf29f9db 100644
--- a/resolv/herror.c
+++ b/resolv/herror.c
@@ -64,14 +64,14 @@ static const char rcsid[] = "$BINDId: herror.c,v 8.11 1999/10/13 16:39:39 vixie
 #include <libintl.h>
 #include <not-cancel.h>
 
-const char *h_errlist[] = {
+const char *const h_errlist[] = {
 	N_("Resolver Error 0 (no error)"),
 	N_("Unknown host"),			/* 1 HOST_NOT_FOUND */
 	N_("Host name lookup failure"),		/* 2 TRY_AGAIN */
 	N_("Unknown server error"),		/* 3 NO_RECOVERY */
 	N_("No address associated with name"),	/* 4 NO_ADDRESS */
 };
-int	h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
+const int	h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
 
 /*
  * herror --
@@ -80,7 +80,6 @@ int	h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
 void
 herror(const char *s) {
 	struct iovec iov[4], *v = iov;
-	extern int * __h_errno();
 
 	if (s != NULL && *s != '\0') {
 		v->iov_base = (/*noconst*/ char *)s;
diff --git a/resolv/inet_ntop.c b/resolv/inet_ntop.c
index e5553a1d3b..1222d08bda 100644
--- a/resolv/inet_ntop.c
+++ b/resolv/inet_ntop.c
@@ -96,7 +96,7 @@ inet_ntop4(src, dst, size)
 	static const char fmt[] = "%u.%u.%u.%u";
 	char tmp[sizeof "255.255.255.255"];
 
-	if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) > size) {
+	if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) >= size) {
 		__set_errno (ENOSPC);
 		return (NULL);
 	}
diff --git a/resolv/nss_dns/dns-canon.c b/resolv/nss_dns/dns-canon.c
index 91708df51f..fca6cd8997 100644
--- a/resolv/nss_dns/dns-canon.c
+++ b/resolv/nss_dns/dns-canon.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
 
@@ -40,6 +40,10 @@ typedef union querybuf
 } querybuf;
 
 
+static const short int qtypes[] = { ns_t_a, ns_t_aaaa };
+#define nqtypes (sizeof (qtypes) / sizeof (qtypes[0]))
+
+
 enum nss_status
 _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen,
 			 char **result,int *errnop, int *h_errnop)
@@ -53,8 +57,6 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen,
     unsigned char *ptr;
   } ansp = { .ptr = buf };
   enum nss_status status = NSS_STATUS_UNAVAIL;
-  int qtypes[] = { ns_t_a, ns_t_aaaa };
-#define nqtypes (sizeof (qtypes) / sizeof (qtypes[0]))
 
   for (int i = 0; i < nqtypes; ++i)
     {
@@ -101,7 +103,8 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen,
 	      ptr += s;
 
 	      /* Check whether type and class match.  */
-	      unsigned int type = ntohs (*(uint16_t *) ptr);
+	      uint_fast16_t type;
+	      NS_GET16 (type, ptr);
 	      if (type == qtypes[i])
 		{
 		  /* We found the record.  */
@@ -130,15 +133,14 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen,
 	      if (type != ns_t_cname)
 		goto unavail;
 
-	      ptr += sizeof (uint16_t);
-	      if (*(uint16_t *) ptr != htons (ns_c_in))
+	      if (ns_get16 (ptr) != ns_c_in)
 		goto unavail;
 
 	      /* Also skip over the TTL.  */
 	      ptr += sizeof (uint16_t) + sizeof (uint32_t);
 
 	      /* Skip over the data length and data.  */
-	      ptr += sizeof (uint16_t) + ntohs (*(uint16_t *) ptr);
+	      ptr += sizeof (uint16_t) + ns_get16 (ptr);
 	    }
 	}
     }
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index 7045c5915b..cf060be8ef 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2003, 2004, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
@@ -465,8 +465,8 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
     char *aliases[MAX_NR_ALIASES];
     unsigned char host_addr[16];	/* IPv4 or IPv6 */
     char *h_addr_ptrs[0];
-  } *host_data = (struct host_data *) buffer;
-  int linebuflen = buflen - sizeof (struct host_data);
+  } *host_data;
+  int linebuflen;
   register const HEADER *hp;
   const u_char *end_of_message, *cp;
   int n, ancount, qdcount;
@@ -478,8 +478,9 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
   u_char packtmp[NS_MAXCDNAME];
   int have_to_map = 0;
   int32_t ttl = 0;
-
-  if (__builtin_expect (linebuflen, 0) < 0)
+  uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
+  buffer += pad;
+  if (__builtin_expect (buflen < sizeof (struct host_data) + pad, 0))
     {
       /* The buffer is too small.  */
     too_small:
@@ -487,6 +488,10 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
       *h_errnop = NETDB_INTERNAL;
       return NSS_STATUS_TRYAGAIN;
     }
+  host_data = (struct host_data *) buffer;
+  linebuflen = buflen - sizeof (struct host_data);
+  if (buflen - sizeof (struct host_data) != linebuflen)
+    linebuflen = INT_MAX;
 
   tname = qname;
   result->h_name = NULL;
diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
index 6ff60f3119..4552b5b678 100644
--- a/resolv/nss_dns/dns-network.c
+++ b/resolv/nss_dns/dns-network.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997, 1998, 1999, 2002, 2004
+/* Copyright (C) 1996, 1997, 1998, 1999, 2002, 2004, 2007
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996.
@@ -102,7 +102,8 @@ extern int __ns_name_unpack (const u_char *, const u_char *,
 /* Prototypes for local functions.  */
 static enum nss_status getanswer_r (const querybuf *answer, int anslen,
 				    struct netent *result, char *buffer,
-				    size_t buflen, lookup_method net_i);
+				    size_t buflen, int *errnop, int *h_errnop,
+				    lookup_method net_i);
 
 
 enum nss_status
@@ -142,7 +143,8 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result,
 	? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
     }
 
-  status = getanswer_r (net_buffer.buf, anslen, result, buffer, buflen, BYNAME);
+  status = getanswer_r (net_buffer.buf, anslen, result, buffer, buflen,
+			errnop, herrnop, BYNAME);
   if (net_buffer.buf != orig_net_buffer)
     free (net_buffer.buf);
   return status;
@@ -218,7 +220,8 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result,
 	? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
     }
 
-  status = getanswer_r (net_buffer.buf, anslen, result, buffer, buflen, BYADDR);
+  status = getanswer_r (net_buffer.buf, anslen, result, buffer, buflen,
+			errnop, herrnop, BYADDR);
   if (net_buffer.buf != orig_net_buffer)
     free (net_buffer.buf);
   if (status == NSS_STATUS_SUCCESS)
@@ -240,7 +243,8 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result,
 
 static enum nss_status
 getanswer_r (const querybuf *answer, int anslen, struct netent *result,
-	     char *buffer, size_t buflen, lookup_method net_i)
+	     char *buffer, size_t buflen, int *errnop, int *h_errnop,
+	     lookup_method net_i)
 {
   /*
    * Find first satisfactory answer
@@ -260,16 +264,33 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
   {
     char *aliases[MAX_NR_ALIASES];
     char linebuffer[0];
-  } *net_data = (struct net_data *) buffer;
+  } *net_data;
+
+  uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct net_data);
+  buffer += pad;
+
+  if (__builtin_expect (buflen < sizeof (*net_data) + pad, 0))
+    {
+      /* The buffer is too small.  */
+    too_small:
+      *errnop = ERANGE;
+      *h_errnop = NETDB_INTERNAL;
+      return NSS_STATUS_TRYAGAIN;
+    }
+  buflen -= pad;
+
+  net_data = (struct net_data *) buffer;
   int linebuflen = buflen - offsetof (struct net_data, linebuffer);
-  const char *end_of_message = &answer->buf[anslen];
+  if (buflen - offsetof (struct net_data, linebuffer) != linebuflen)
+    linebuflen = INT_MAX;
+  const unsigned char *end_of_message = &answer->buf[anslen];
   const HEADER *header_pointer = &answer->hdr;
   /* #/records in the answer section.  */
   int answer_count =  ntohs (header_pointer->ancount);
   /* #/entries in the question section.  */
   int question_count = ntohs (header_pointer->qdcount);
   char *bp = net_data->linebuffer;
-  const char *cp = &answer->buf[HFIXEDSZ];
+  const unsigned char *cp = &answer->buf[HFIXEDSZ];
   char **alias_pointer;
   int have_answer;
   char *ans;
@@ -319,10 +340,7 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
       if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
 	{
 	  if (errno == EMSGSIZE)
-	    {
-	      errno = ERANGE;
-	      return NSS_STATUS_TRYAGAIN;
-	    }
+	    goto too_small;
 
 	  n = -1;
 	}
@@ -346,10 +364,7 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
 	  if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
 	    {
 	      if (errno == EMSGSIZE)
-		{
-		  errno = ERANGE;
-		  return NSS_STATUS_TRYAGAIN;
-		}
+		goto too_small;
 
 	      n = -1;
 	    }
diff --git a/resolv/res-state.c b/resolv/res-state.c
new file mode 100644
index 0000000000..e327e34f59
--- /dev/null
+++ b/resolv/res-state.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 1996, 97, 98, 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <resolv.h>
+#include <tls.h>
+
+#if ! USE___THREAD
+
+# undef _res
+extern struct __res_state _res;
+
+/* When threaded, _res may be a per-thread variable.  */
+struct __res_state *
+weak_const_function
+__res_state (void)
+{
+  return &_res;
+}
+
+#else
+
+struct __res_state *
+__res_state (void)
+{
+  return __resp;
+}
+
+#endif
+
+libc_hidden_def (__res_state)
diff --git a/resolv/res_data.c b/resolv/res_data.c
index adadcdcd7a..1beea1dc4f 100644
--- a/resolv/res_data.c
+++ b/resolv/res_data.c
@@ -246,7 +246,9 @@ res_close(void) {
 	if ((_res.options & RES_INIT) == 0)
 	  return;
 #endif
-	res_nclose(&_res);
+	/* We don't free the name server addresses because we never
+	   did it and it would be done implicitly on shutdown.  */
+	__res_iclose(&_res, false);
 }
 
 #ifdef BIND_UPDATE
diff --git a/resolv/res_debug.c b/resolv/res_debug.c
index 839069de3d..d9f1607df6 100644
--- a/resolv/res_debug.c
+++ b/resolv/res_debug.c
@@ -626,8 +626,7 @@ static const unsigned int poweroften[10]=
 
 /* takes an XeY precision/size value, returns a string representation. */
 static const char *
-precsize_ntoa(prec)
-	u_int8_t prec;
+precsize_ntoa (u_int8_t prec)
 {
 	static char retbuf[sizeof "90000000.00"];	/* XXX nonreentrant */
 	unsigned long val;
@@ -644,8 +643,7 @@ precsize_ntoa(prec)
 
 /* converts ascii size/precision X * 10**Y(cm) to 0xXY.  moves pointer. */
 static u_int8_t
-precsize_aton(strptr)
-	const char **strptr;
+precsize_aton (const char **strptr)
 {
 	unsigned int mval = 0, cmval = 0;
 	u_int8_t retval = 0;
@@ -686,9 +684,7 @@ precsize_aton(strptr)
 
 /* converts ascii lat/lon to unsigned encoded 32-bit number.  moves pointer. */
 static u_int32_t
-latlon2ul(latlonstrptr,which)
-	const char **latlonstrptr;
-	int *which;
+latlon2ul (const char **latlonstrptr, int *which)
 {
 	const char *cp;
 	u_int32_t retval;
@@ -900,7 +896,7 @@ loc_ntoa(binary, ascii)
 	const u_char *binary;
 	char *ascii;
 {
-	static char *error = "?";
+	static const char error[] = "?";
 	static char tmpbuf[sizeof
 "1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"];
 	const u_char *cp = binary;
@@ -980,11 +976,11 @@ loc_ntoa(binary, ascii)
 	altmeters = (altval / 100) * altsign;
 
 	if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
-		sizestr = error;
+		sizestr = (char *) error;
 	if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
-		hpstr = error;
+		hpstr = (char *) error;
 	if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
-		vpstr = error;
+		vpstr = (char *) error;
 
 	sprintf(ascii,
 	      "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
@@ -992,11 +988,11 @@ loc_ntoa(binary, ascii)
 		longdeg, longmin, longsec, longsecfrac, eastwest,
 		altmeters, altfrac, sizestr, hpstr, vpstr);
 
-	if (sizestr != error)
+	if (sizestr != (char *) error)
 		free(sizestr);
-	if (hpstr != error)
+	if (hpstr != (char *) error)
 		free(hpstr);
-	if (vpstr != error)
+	if (vpstr != (char *) error)
 		free(vpstr);
 
 	return (ascii);
diff --git a/resolv/res_hconf.c b/resolv/res_hconf.c
index 91cd300482..f45888933f 100644
--- a/resolv/res_hconf.c
+++ b/resolv/res_hconf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995-2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1995-2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by David Mosberger (davidm@azstarnet.com).
 
@@ -53,35 +53,34 @@
 
 /* Environment vars that all user to override default behavior:  */
 #define ENV_HOSTCONF	"RESOLV_HOST_CONF"
-#define ENV_SERVORDER	"RESOLV_SERV_ORDER"
 #define ENV_SPOOF	"RESOLV_SPOOF_CHECK"
 #define ENV_TRIM_OVERR	"RESOLV_OVERRIDE_TRIM_DOMAINS"
 #define ENV_TRIM_ADD	"RESOLV_ADD_TRIM_DOMAINS"
 #define ENV_MULTI	"RESOLV_MULTI"
 #define ENV_REORDER	"RESOLV_REORDER"
 
-static const char *arg_service_list (const char *, int, const char *,
-				     unsigned int);
-static const char *arg_trimdomain_list (const char *, int, const char *,
-					unsigned int);
-static const char *arg_spoof (const char *, int, const char *, unsigned int);
-static const char *arg_bool (const char *, int, const char *, unsigned int);
+enum parse_cbs
+  {
+    CB_none,
+    CB_arg_trimdomain_list,
+    CB_arg_spoof,
+    CB_arg_bool
+  };
 
-static struct cmd
+static const struct cmd
 {
-  const char *name;
-  const char *(*parse_args) (const char * filename, int line_num,
-			     const char * args, unsigned int arg);
+  const char name[11];
+  uint8_t cb;
   unsigned int arg;
 } cmd[] =
 {
-  {"order",		arg_service_list,	0},
-  {"trim",		arg_trimdomain_list,	0},
-  {"spoof",		arg_spoof,		0},
-  {"multi",		arg_bool,		HCONF_FLAG_MULTI},
-  {"nospoof",		arg_bool,		HCONF_FLAG_SPOOF},
-  {"spoofalert",	arg_bool,		HCONF_FLAG_SPOOFALERT},
-  {"reorder",		arg_bool,		HCONF_FLAG_REORDER}
+  {"order",		CB_none,		0},
+  {"trim",		CB_arg_trimdomain_list,	0},
+  {"spoof",		CB_arg_spoof,		0},
+  {"multi",		CB_arg_bool,		HCONF_FLAG_MULTI},
+  {"nospoof",		CB_arg_bool,		HCONF_FLAG_SPOOF},
+  {"spoofalert",	CB_arg_bool,		HCONF_FLAG_SPOOFALERT},
+  {"reorder",		CB_arg_bool,		HCONF_FLAG_REORDER}
 };
 
 /* Structure containing the state.  */
@@ -107,118 +106,7 @@ skip_string (const char *str)
 
 
 static const char *
-arg_service_list (const char *fname, int line_num, const char *args,
-		  unsigned int arg)
-{
-  enum Name_Service service;
-  const char *start;
-  size_t len;
-  size_t i;
-  static struct
-  {
-    const char * name;
-    enum Name_Service service;
-  } svcs[] =
-    {
-      {"bind",	SERVICE_BIND},
-      {"hosts",	SERVICE_HOSTS},
-      {"nis",	SERVICE_NIS},
-    };
-
-  do
-    {
-      start = args;
-      args = skip_string (args);
-      len = args - start;
-
-      service = SERVICE_NONE;
-      for (i = 0; i < sizeof (svcs) / sizeof (svcs[0]); ++i)
-	{
-	  if (__strncasecmp (start, svcs[i].name, len) == 0
-	      && len == strlen (svcs[i].name))
-	  {
-	    service = svcs[i].service;
-	    break;
-	  }
-      }
-      if (service == SERVICE_NONE)
-	{
-	  char *buf;
-
-	  if (__asprintf (&buf,
-			  _("%s: line %d: expected service, found `%s'\n"),
-			  fname, line_num, start) < 0)
-	    return 0;
-
-#ifdef USE_IN_LIBIO
-	  if (_IO_fwide (stderr, 0) > 0)
-	    __fwprintf (stderr, L"%s", buf);
-	  else
-#endif
-	    fputs (buf, stderr);
-
-	  free (buf);
-	  return 0;
-	}
-      if (_res_hconf.num_services >= SERVICE_MAX)
-	{
-	  char *buf;
-
-	  if (__asprintf (&buf, _("\
-%s: line %d: cannot specify more than %d services"),
-			  fname, line_num, SERVICE_MAX) < 0)
-	    return 0;
-
-#ifdef USE_IN_LIBIO
-	  if (_IO_fwide (stderr, 0) > 0)
-	    __fwprintf (stderr, L"%s", buf);
-	  else
-#endif
-	    fputs (buf, stderr);
-
-	  free (buf);
-	  return 0;
-	}
-      _res_hconf.service[_res_hconf.num_services++] = service;
-
-      args = skip_ws (args);
-      switch (*args)
-	{
-	case ',':
-	case ';':
-	case ':':
-	  args = skip_ws (++args);
-	  if (!*args || *args == '#')
-	    {
-	      char *buf;
-
-	      if (__asprintf (&buf, _("\
-%s: line %d: list delimiter not followed by keyword"),
-			      fname, line_num) < 0)
-		return 0;
-
-#ifdef USE_IN_LIBIO
-	      if (_IO_fwide (stderr, 0) > 0)
-		__fwprintf (stderr, L"%s", buf);
-	      else
-#endif
-		fputs (buf, stderr);
-
-	      free (buf);
-	      return 0;
-	    }
-	default:
-	  break;
-	}
-    }
-  while (*args && *args != '#');
-  return args;
-}
-
-
-static const char *
-arg_trimdomain_list (const char *fname, int line_num, const char *args,
-		     unsigned int flag)
+arg_trimdomain_list (const char *fname, int line_num, const char *args)
 {
   const char * start;
   size_t len;
@@ -238,14 +126,9 @@ arg_trimdomain_list (const char *fname, int line_num, const char *args,
 			  fname, line_num, TRIMDOMAINS_MAX) < 0)
 	    return 0;
 
-#ifdef USE_IN_LIBIO
-	      if (_IO_fwide (stderr, 0) > 0)
-		__fwprintf (stderr, L"%s", buf);
-	      else
-#endif
-		fputs (buf, stderr);
+	  __fxprintf (NULL, "%s", buf);
 
-	      free (buf);
+	  free (buf);
 	  return 0;
 	}
       _res_hconf.trimdomain[_res_hconf.num_trimdomains++] =
@@ -264,12 +147,7 @@ arg_trimdomain_list (const char *fname, int line_num, const char *args,
 			      fname, line_num) < 0)
 		return 0;
 
-#ifdef USE_IN_LIBIO
-	      if (_IO_fwide (stderr, 0) > 0)
-		__fwprintf (stderr, L"%s", buf);
-	      else
-#endif
-		fputs (buf, stderr);
+	      __fxprintf (NULL, "%s", buf);
 
 	      free (buf);
 	      return 0;
@@ -284,7 +162,7 @@ arg_trimdomain_list (const char *fname, int line_num, const char *args,
 
 
 static const char *
-arg_spoof (const char *fname, int line_num, const char *args, unsigned flag)
+arg_spoof (const char *fname, int line_num, const char *args)
 {
   const char *start = args;
   size_t len;
@@ -327,12 +205,7 @@ arg_bool (const char *fname, int line_num, const char *args, unsigned flag)
 		      fname, line_num, args) < 0)
 	return 0;
 
-#ifdef USE_IN_LIBIO
-      if (_IO_fwide (stderr, 0) > 0)
-	__fwprintf (stderr, L"%s", buf);
-      else
-#endif
-	fputs (buf, stderr);
+      __fxprintf (NULL, "%s", buf);
 
       free (buf);
       return 0;
@@ -345,7 +218,7 @@ static void
 parse_line (const char *fname, int line_num, const char *str)
 {
   const char *start;
-  struct cmd *c = 0;
+  const struct cmd *c = 0;
   size_t len;
   size_t i;
 
@@ -375,12 +248,7 @@ parse_line (const char *fname, int line_num, const char *str)
 		      fname, line_num, start) < 0)
 	return;
 
-#ifdef USE_IN_LIBIO
-      if (_IO_fwide (stderr, 0) > 0)
-	__fwprintf (stderr, L"%s", buf);
-      else
-#endif
-	fputs (buf, stderr);
+      __fxprintf (NULL, "%s", buf);
 
       free (buf);
       return;
@@ -388,7 +256,17 @@ parse_line (const char *fname, int line_num, const char *str)
 
   /* process args: */
   str = skip_ws (str);
-  str = (*c->parse_args) (fname, line_num, str, c->arg);
+
+  if (c->cb == CB_arg_trimdomain_list)
+    str = arg_trimdomain_list (fname, line_num, str);
+  else if (c->cb == CB_arg_spoof)
+    str = arg_spoof (fname, line_num, str);
+  else if (c->cb == CB_arg_bool)
+    str = arg_bool (fname, line_num, str, c->arg);
+  else
+    /* Ignore the line.  */
+    return;
+
   if (!str)
     return;
 
@@ -405,12 +283,7 @@ parse_line (const char *fname, int line_num, const char *str)
 			    fname, line_num, str) < 0)
 	      break;
 
-#ifdef USE_IN_LIBIO
-	    if (_IO_fwide (stderr, 0) > 0)
-	      __fwprintf (stderr, L"%s", buf);
-	    else
-#endif
-	      fputs (buf, stderr);
+	    __fxprintf (NULL, "%s", buf);
 
 	    free (buf);
 	  }
@@ -436,10 +309,7 @@ do_init (void)
     hconf_name = _PATH_HOSTCONF;
 
   fp = fopen (hconf_name, "rc");
-  if (!fp)
-    /* make up something reasonable: */
-    _res_hconf.service[_res_hconf.num_services++] = SERVICE_BIND;
-  else
+  if (fp)
     {
       /* No threads using this stream.  */
       __fsetlocking (fp, FSETLOCKING_BYCALLER);
@@ -453,16 +323,9 @@ do_init (void)
       fclose (fp);
     }
 
-  envval = getenv (ENV_SERVORDER);
-  if (envval)
-    {
-      _res_hconf.num_services = 0;
-      arg_service_list (ENV_SERVORDER, 1, envval, 0);
-    }
-
   envval = getenv (ENV_SPOOF);
   if (envval)
-    arg_spoof (ENV_SPOOF, 1, envval, 0);
+    arg_spoof (ENV_SPOOF, 1, envval);
 
   envval = getenv (ENV_MULTI);
   if (envval)
@@ -474,13 +337,13 @@ do_init (void)
 
   envval = getenv (ENV_TRIM_ADD);
   if (envval)
-    arg_trimdomain_list (ENV_TRIM_ADD, 1, envval, 0);
+    arg_trimdomain_list (ENV_TRIM_ADD, 1, envval);
 
   envval = getenv (ENV_TRIM_OVERR);
   if (envval)
     {
       _res_hconf.num_trimdomains = 0;
-      arg_trimdomain_list (ENV_TRIM_OVERR, 1, envval, 0);
+      arg_trimdomain_list (ENV_TRIM_OVERR, 1, envval);
     }
 
   _res_hconf.initialized = 1;
diff --git a/resolv/res_hconf.h b/resolv/res_hconf.h
index 77eeca4dea..b40da0df74 100644
--- a/resolv/res_hconf.h
+++ b/resolv/res_hconf.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1995-1998, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by David Mosberger (davidm@azstarnet.com).
 
@@ -24,18 +24,11 @@
 
 #define TRIMDOMAINS_MAX	4
 
-enum Name_Service
-{
-  SERVICE_NONE = 0,
-  SERVICE_BIND, SERVICE_HOSTS, SERVICE_NIS,
-  SERVICE_MAX
-};
-
 struct hconf
 {
   int initialized;
-  int num_services;
-  enum Name_Service service[SERVICE_MAX];
+  int unused1;
+  int unused2[4];
   int num_trimdomains;
   const char *trimdomain[TRIMDOMAINS_MAX];
   unsigned int flags;
diff --git a/resolv/res_init.c b/resolv/res_init.c
index 731c784e17..b5a03d1883 100644
--- a/resolv/res_init.c
+++ b/resolv/res_init.c
@@ -537,10 +537,7 @@ net_mask(in)		/* XXX - should really use system's version of this */
 
 u_int
 res_randomid(void) {
-	struct timeval now;
-
-	__gettimeofday(&now, NULL);
-	return (0xffff & (now.tv_sec ^ now.tv_usec ^ __getpid()));
+	return 0xffff & __getpid();
 }
 #ifdef _LIBC
 libc_hidden_def (__res_randomid)
@@ -555,7 +552,7 @@ libc_hidden_def (__res_randomid)
  * This routine is not expected to be user visible.
  */
 void
-res_nclose(res_state statp) {
+__res_iclose(res_state statp, bool free_addr) {
 	int ns;
 
 	if (statp->_vcsock >= 0) {
@@ -568,13 +565,25 @@ res_nclose(res_state statp) {
 #else
 	for (ns = 0; ns < statp->_u._ext.nscount; ns++)
 #endif
-		if (statp->_u._ext.nsaddrs[ns]
-		    && statp->_u._ext.nssocks[ns] != -1) {
-			close_not_cancel_no_status(statp->_u._ext.nssocks[ns]);
-			statp->_u._ext.nssocks[ns] = -1;
+		if (statp->_u._ext.nsaddrs[ns]) {
+			if (statp->_u._ext.nssocks[ns] != -1) {
+				close_not_cancel_no_status(statp->_u._ext.nssocks[ns]);
+				statp->_u._ext.nssocks[ns] = -1;
+			}
+			if (free_addr) {
+				free (statp->_u._ext.nsaddrs[ns]);
+				statp->_u._ext.nsaddrs[ns] = NULL;
+			}
 		}
 	statp->_u._ext.nsinit = 0;
 }
+libc_hidden_def (__res_iclose)
+
+void
+res_nclose(res_state statp)
+{
+  __res_iclose (statp, true);
+}
 #ifdef _LIBC
 libc_hidden_def (__res_nclose)
 #endif
@@ -589,14 +598,7 @@ res_thread_freeres (void)
     /* Never called res_ninit.  */
     return;
 
-  __res_nclose (&_res);		/* Close any VC sockets.  */
-
-  for (int ns = 0; ns < MAXNS; ns++)
-    if (_res._u._ext.nsaddrs[ns] != NULL)
-      {
-	free (_res._u._ext.nsaddrs[ns]);
-	_res._u._ext.nsaddrs[ns] = NULL;
-      }
+  __res_iclose (&_res, true);		/* Close any VC sockets.  */
 
   /* Make sure we do a full re-initialization the next time.  */
   _res.options = 0;
diff --git a/resolv/res_libc.c b/resolv/res_libc.c
index 76abca8442..834773c32f 100644
--- a/resolv/res_libc.c
+++ b/resolv/res_libc.c
@@ -70,14 +70,8 @@ res_init(void) {
 		_res.retry = 4;
 	if (!(_res.options & RES_INIT))
 		_res.options = RES_DEFAULT;
-	else if (_res.nscount > 0) {
-		__res_nclose (&_res);	/* Close any VC sockets.  */
-
-		for (int ns = 0; ns < MAXNS; ns++) {
-			free (_res._u._ext.nsaddrs[ns]);
-			_res._u._ext.nsaddrs[ns] = NULL;
-		}
-	}
+	else if (_res.nscount > 0)
+		__res_iclose (&_res, true);	/* Close any VC sockets.  */
 
 	/*
 	 * This one used to initialize implicitly to zero, so unless the app
@@ -103,11 +97,7 @@ __res_maybe_init (res_state resp, int preinit)
 	if (resp->options & RES_INIT) {
 		if (__res_initstamp != resp->_u._ext.initstamp) {
 			if (resp->nscount > 0) {
-				__res_nclose (resp);
-				for (int ns = 0; ns < MAXNS; ns++) {
-					free (resp->_u._ext.nsaddrs[ns]);
-					resp->_u._ext.nsaddrs[ns] = NULL;
-				}
+				__res_iclose (resp, true);
 				return __res_vinit (resp, 1);
 			}
 		}
diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c
index 815fcf8ab3..fd80569fe2 100644
--- a/resolv/res_mkquery.c
+++ b/resolv/res_mkquery.c
@@ -124,10 +124,6 @@ res_nmkquery(res_state statp,
 	   incremented by one after the initial randomization which
 	   still predictable if the application does multiple
 	   requests.  */
-#if 0
-	hp->id = htons(++statp->id);
-#else
-	hp->id = htons(statp->id);
 	int randombits;
 	do
 	  {
@@ -141,7 +137,7 @@ res_nmkquery(res_state statp,
 	  }
 	while ((randombits & 0xffff) == 0);
 	statp->id = (statp->id + randombits) & 0xffff;
-#endif
+	hp->id = statp->id;
 	hp->opcode = op;
 	hp->rd = (statp->options & RES_RECURSE) != 0;
 	hp->rcode = NOERROR;
@@ -155,38 +151,36 @@ res_nmkquery(res_state statp,
 	 * perform opcode specific processing
 	 */
 	switch (op) {
-	case QUERY:	/*FALLTHROUGH*/
 	case NS_NOTIFY_OP:
+		if ((buflen -= QFIXEDSZ + (data == NULL ? 0 : RRFIXEDSZ)) < 0)
+			return (-1);
+		goto compose;
+
+	case QUERY:
 		if ((buflen -= QFIXEDSZ) < 0)
 			return (-1);
+	compose:
 		if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
 			return (-1);
 		cp += n;
 		buflen -= n;
-		__putshort(type, cp);
-		cp += INT16SZ;
-		__putshort(class, cp);
-		cp += INT16SZ;
+		NS_PUT16 (type, cp);
+		NS_PUT16 (class, cp);
 		hp->qdcount = htons(1);
 		if (op == QUERY || data == NULL)
 			break;
 		/*
 		 * Make an additional record for completion domain.
 		 */
-		buflen -= RRFIXEDSZ;
 		n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr);
-		if (n < 0)
+		if (__builtin_expect (n < 0, 0))
 			return (-1);
 		cp += n;
 		buflen -= n;
-		__putshort(T_NULL, cp);
-		cp += INT16SZ;
-		__putshort(class, cp);
-		cp += INT16SZ;
-		__putlong(0, cp);
-		cp += INT32SZ;
-		__putshort(0, cp);
-		cp += INT16SZ;
+		NS_PUT16 (T_NULL, cp);
+		NS_PUT16 (class, cp);
+		NS_PUT32 (0, cp);
+		NS_PUT16 (0, cp);
 		hp->arcount = htons(1);
 		break;
 
@@ -194,17 +188,13 @@ res_nmkquery(res_state statp,
 		/*
 		 * Initialize answer section
 		 */
-		if (buflen < 1 + RRFIXEDSZ + datalen)
+		if (__builtin_expect (buflen < 1 + RRFIXEDSZ + datalen, 0))
 			return (-1);
 		*cp++ = '\0';	/* no domain name */
-		__putshort(type, cp);
-		cp += INT16SZ;
-		__putshort(class, cp);
-		cp += INT16SZ;
-		__putlong(0, cp);
-		cp += INT32SZ;
-		__putshort(datalen, cp);
-		cp += INT16SZ;
+		NS_PUT16 (type, cp);
+		NS_PUT16 (class, cp);
+		NS_PUT32 (0, cp);
+		NS_PUT16 (datalen, cp);
 		if (datalen) {
 			memcpy(cp, data, datalen);
 			cp += datalen;
diff --git a/resolv/res_query.c b/resolv/res_query.c
index 0feba6687a..85bad97d2d 100644
--- a/resolv/res_query.c
+++ b/resolv/res_query.c
@@ -69,6 +69,7 @@ static const char sccsid[] = "@(#)res_query.c	8.1 (Berkeley) 6/4/93";
 static const char rcsid[] = "$BINDId: res_query.c,v 8.20 2000/02/29 05:39:12 vixie Exp $";
 #endif /* LIBC_SCCS and not lint */
 
+#include <assert.h>
 #include <sys/types.h>
 #include <sys/param.h>
 #include <netinet/in.h>
@@ -151,6 +152,7 @@ __libc_res_nquery(res_state statp,
 			free (buf);
 		return (n);
 	}
+	assert (answerp == NULL || (void *) *answerp == (void *) answer);
 	n = __libc_res_nsend(statp, buf, n, answer, anslen, answerp);
 	if (use_malloc)
 		free (buf);
@@ -163,6 +165,10 @@ __libc_res_nquery(res_state statp,
 		return (n);
 	}
 
+	if (answerp != NULL)
+	  /* __libc_res_nsend might have reallocated the buffer.  */
+	  hp = (HEADER *) *answerp;
+
 	if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
 #ifdef DEBUG
 		if (statp->options & RES_DEBUG)
diff --git a/resolv/res_send.c b/resolv/res_send.c
index 8fb21a9446..887d048e19 100644
--- a/resolv/res_send.c
+++ b/resolv/res_send.c
@@ -267,8 +267,8 @@ res_nameinquery(const char *name, int type, int class,
 		cp += n;
 		if (cp + 2 * INT16SZ > eom)
 			return (-1);
-		ttype = ns_get16(cp); cp += INT16SZ;
-		tclass = ns_get16(cp); cp += INT16SZ;
+		NS_GET16(ttype, cp);
+		NS_GET16(tclass, cp);
 		if (ttype == type && tclass == class &&
 		    ns_samename(tname, name) == 1)
 			return (1);
@@ -292,9 +292,6 @@ int
 res_queriesmatch(const u_char *buf1, const u_char *eom1,
 		 const u_char *buf2, const u_char *eom2)
 {
-	const u_char *cp = buf1 + HFIXEDSZ;
-	int qdcount = ntohs(((HEADER*)buf1)->qdcount);
-
 	if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
 		return (-1);
 
@@ -306,8 +303,16 @@ res_queriesmatch(const u_char *buf1, const u_char *eom1,
 	    (((HEADER *)buf2)->opcode == ns_o_update))
 		return (1);
 
-	if (qdcount != ntohs(((HEADER*)buf2)->qdcount))
+	/* Note that we initially do not convert QDCOUNT to the host byte
+	   order.  We can compare it with the second buffer's QDCOUNT
+	   value without doing this.  */
+	int qdcount = ((HEADER*)buf1)->qdcount;
+	if (qdcount != ((HEADER*)buf2)->qdcount)
 		return (0);
+
+	qdcount = htons (qdcount);
+	const u_char *cp = buf1 + HFIXEDSZ;
+
 	while (qdcount-- > 0) {
 		char tname[MAXDNAME+1];
 		int n, ttype, tclass;
@@ -318,8 +323,8 @@ res_queriesmatch(const u_char *buf1, const u_char *eom1,
 		cp += n;
 		if (cp + 2 * INT16SZ > eom1)
 			return (-1);
-		ttype = ns_get16(cp);	cp += INT16SZ;
-		tclass = ns_get16(cp); cp += INT16SZ;
+		NS_GET16(ttype, cp);
+		NS_GET16(tclass, cp);
 		if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
 			return (0);
 	}
@@ -381,7 +386,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
 				}
 			}
 		if (needclose)
-			res_nclose(statp);
+			__res_iclose(statp, false);
 	}
 
 	/*
@@ -488,7 +493,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
 					done = 1;
 					break;
 				case res_nextns:
-					res_nclose(statp);
+					__res_iclose(statp, false);
 					goto next_ns;
 				case res_done:
 					return (resplen);
@@ -553,7 +558,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
 		 */
 		if ((v_circuit && (statp->options & RES_USEVC) == 0) ||
 		    (statp->options & RES_STAYOPEN) == 0) {
-			res_nclose(statp);
+			__res_iclose(statp, false);
 		}
 		if (statp->rhook) {
 			int done = 0, loops = 0;
@@ -570,7 +575,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
 					done = 1;
 					break;
 				case res_nextns:
-					res_nclose(statp);
+					__res_iclose(statp, false);
 					goto next_ns;
 				case res_modified:
 					/* give the hook another try */
@@ -589,7 +594,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
  next_ns: ;
 	   } /*foreach ns*/
 	} /*foreach retry*/
-	res_nclose(statp);
+	__res_iclose(statp, false);
 	if (!v_circuit) {
 		if (!gotsomewhere)
 			__set_errno (ECONNREFUSED);	/* no nameservers found */
@@ -632,19 +637,19 @@ send_vc(res_state statp,
 	/* Are we still talking to whom we want to talk to? */
 	if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
 		struct sockaddr_in6 peer;
-		int size = sizeof peer;
+		socklen_t size = sizeof peer;
 
 		if (getpeername(statp->_vcsock,
 				(struct sockaddr *)&peer, &size) < 0 ||
 		    !sock_eq(&peer, nsap)) {
-			res_nclose(statp);
+		  __res_iclose(statp, false);
 			statp->_flags &= ~RES_F_VC;
 		}
 	}
 
 	if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
 		if (statp->_vcsock >= 0)
-			res_nclose(statp);
+		  __res_iclose(statp, false);
 
 		statp->_vcsock = socket(nsap->sin6_family, SOCK_STREAM, 0);
 		if (statp->_vcsock < 0) {
@@ -654,11 +659,13 @@ send_vc(res_state statp,
 		}
 		__set_errno (0);
 		if (connect(statp->_vcsock, (struct sockaddr *)nsap,
-			    sizeof *nsap) < 0) {
+			    nsap->sin6_family == AF_INET
+			    ? sizeof (struct sockaddr_in)
+			    : sizeof (struct sockaddr_in6)) < 0) {
 			*terrno = errno;
 			Aerror(statp, stderr, "connect/vc", errno,
 			       (struct sockaddr *) nsap);
-			res_nclose(statp);
+			__res_iclose(statp, false);
 			return (0);
 		}
 		statp->_flags |= RES_F_VC;
@@ -667,14 +674,14 @@ send_vc(res_state statp,
 	/*
 	 * Send length & message
 	 */
-	putshort((u_short)buflen, (u_char*)&len);
+	ns_put16((u_short)buflen, (u_char*)&len);
 	evConsIovec(&len, INT16SZ, &iov[0]);
 	evConsIovec((void*)buf, buflen, &iov[1]);
 	if (TEMP_FAILURE_RETRY (writev(statp->_vcsock, iov, 2))
 	    != (INT16SZ + buflen)) {
 		*terrno = errno;
 		Perror(statp, stderr, "write failed", errno);
-		res_nclose(statp);
+		__res_iclose(statp, false);
 		return (0);
 	}
 	/*
@@ -692,7 +699,7 @@ send_vc(res_state statp,
 	if (n <= 0) {
 		*terrno = errno;
 		Perror(statp, stderr, "read failed", errno);
-		res_nclose(statp);
+		__res_iclose(statp, false);
 		/*
 		 * A long running process might get its TCP
 		 * connection reset if the remote server was
@@ -704,10 +711,8 @@ send_vc(res_state statp,
 		 */
 		if (*terrno == ECONNRESET && !connreset) {
 			connreset = 1;
-			res_nclose(statp);
 			goto same_ns;
 		}
-		res_nclose(statp);
 		return (0);
 	}
 	resplen = ns_get16(ans);
@@ -716,7 +721,7 @@ send_vc(res_state statp,
 			ans = malloc (MAXPACKET);
 			if (ans == NULL) {
 				*terrno = ENOMEM;
-				res_nclose(statp);
+				__res_iclose(statp, false);
 				return (0);
 			}
 			anssiz = MAXPACKET;
@@ -741,7 +746,7 @@ send_vc(res_state statp,
 		Dprint(statp->options & RES_DEBUG,
 		       (stdout, ";; undersized: %d\n", len));
 		*terrno = EMSGSIZE;
-		res_nclose(statp);
+		__res_iclose(statp, false);
 		return (0);
 	}
 	cp = ans;
@@ -752,7 +757,7 @@ send_vc(res_state statp,
 	if (n <= 0) {
 		*terrno = errno;
 		Perror(statp, stderr, "read(vc)", errno);
-		res_nclose(statp);
+		__res_iclose(statp, false);
 		return (0);
 	}
 	if (truncating) {
@@ -809,7 +814,8 @@ send_dg(res_state statp,
         int ptimeout;
 	struct sockaddr_in6 from;
 	static int socket_pf = 0;
-	int fromlen, resplen, seconds, n;
+	socklen_t fromlen;
+	int resplen, seconds, n;
 
 	if (EXT(statp).nssocks[ns] == -1) {
 		/* only try IPv6 if IPv6 NS and if not failed before */
@@ -844,7 +850,7 @@ send_dg(res_state statp,
 			    sizeof *nsap) < 0) {
 			Aerror(statp, stderr, "connect(dg)", errno,
 			       (struct sockaddr *) nsap);
-			res_nclose(statp);
+			__res_iclose(statp, false);
 			return (0);
 		}
 		/* Make socket non-blocking.  */
@@ -873,10 +879,13 @@ send_dg(res_state statp,
 	pfd[0].events = POLLOUT;
  wait:
 	if (need_recompute) {
+	recompute_resend:
 		evNowTime(&now);
 		if (evCmpTime(finish, now) <= 0) {
-			Perror(statp, stderr, "select", errno);
-			res_nclose(statp);
+		poll_err_out:
+			Perror(statp, stderr, "poll", errno);
+		err_out:
+			__res_iclose(statp, false);
 			return (0);
 		}
 		evSubTime(&timeout, &finish, &now);
@@ -898,26 +907,18 @@ send_dg(res_state statp,
 		return (0);
 	}
 	if (n < 0) {
-		if (errno == EINTR) {
-		recompute_resend:
-			evNowTime(&now);
-			if (evCmpTime(finish, now) > 0) {
-				evSubTime(&timeout, &finish, &now);
-				goto wait;
-			}
-		}
-		Perror(statp, stderr, "poll", errno);
-		res_nclose(statp);
-		return (0);
+		if (errno == EINTR)
+			goto recompute_resend;
+
+		goto poll_err_out;
 	}
 	__set_errno (0);
 	if (pfd[0].revents & POLLOUT) {
-		if (send(pfd[0].fd, (char*)buf, buflen, 0) != buflen) {
+		if (send (pfd[0].fd, buf, buflen, MSG_NOSIGNAL) != buflen) {
 			if (errno == EINTR || errno == EAGAIN)
 				goto recompute_resend;
 			Perror(statp, stderr, "send", errno);
-			res_nclose(statp);
-			return (0);
+			goto err_out;
 		}
 		pfd[0].events = POLLIN;
 		++nwritten;
@@ -947,8 +948,7 @@ send_dg(res_state statp,
 				goto wait;
 			}
 			Perror(statp, stderr, "recvfrom", errno);
-			res_nclose(statp);
-			return (0);
+			goto err_out;
 		}
 		*gotsomewhere = 1;
 		if (resplen < HFIXEDSZ) {
@@ -959,8 +959,7 @@ send_dg(res_state statp,
 			       (stdout, ";; undersized: %d\n",
 				resplen));
 			*terrno = EMSGSIZE;
-			res_nclose(statp);
-			return (0);
+			goto err_out;
 		}
 		if (hp->id != anhp->id) {
 			/*
@@ -1007,11 +1006,19 @@ send_dg(res_state statp,
 			DprintQ(statp->options & RES_DEBUG,
 				(stdout, "server rejected query:\n"),
 				ans, (resplen > anssiz) ? anssiz : resplen);
-			res_nclose(statp);
+		next_ns:
+			__res_iclose(statp, false);
 			/* don't retry if called from dig */
 			if (!statp->pfcode)
 				return (0);
 		}
+		if (anhp->rcode == NOERROR && anhp->ancount == 0
+		    && anhp->aa == 0 && anhp->ra == 0 && anhp->arcount == 0) {
+			DprintQ(statp->options & RES_DEBUG,
+				(stdout, "referred query:\n"),
+				ans, (resplen > anssiz) ? anssiz : resplen);
+			goto next_ns;
+		}
 		if (!(statp->options & RES_IGNTC) && anhp->tc) {
 			/*
 			 * To get the rest of answer,
@@ -1020,7 +1027,7 @@ send_dg(res_state statp,
 			Dprint(statp->options & RES_DEBUG,
 			       (stdout, ";; truncated answer\n"));
 			*v_circuit = 1;
-			res_nclose(statp);
+			__res_iclose(statp, false);
 			return (1);
 		}
 		/*
@@ -1030,8 +1037,11 @@ send_dg(res_state statp,
 		return (resplen);
 	} else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
 		/* Something went wrong.  We can stop trying.  */
-		res_nclose(statp);
-		return (0);
+		goto err_out;
+	}
+	else {
+	  	/* poll should not have returned > 0 in this case.  */
+		abort ();
 	}
 }
 
@@ -1047,8 +1057,13 @@ Aerror(const res_state statp, FILE *file, const char *string, int error,
 
 		fprintf(file, "res_send: %s ([%s].%u): %s\n",
 			string,
-			inet_ntop(address->sa_family, address->sa_data,
-				  tmp, sizeof tmp),
+			(address->sa_family == AF_INET
+			 ? inet_ntop(address->sa_family,
+				     &((const struct sockaddr_in *) address)->sin_addr,
+				     tmp, sizeof tmp)
+			 : inet_ntop(address->sa_family,
+				     &((const struct sockaddr_in6 *) address)->sin6_addr,
+				     tmp, sizeof tmp)),
 			(address->sa_family == AF_INET
 			 ? ntohs(((struct sockaddr_in *) address)->sin_port)
 			 : address->sa_family == AF_INET6
diff --git a/resolv/tst-inet_ntop.c b/resolv/tst-inet_ntop.c
new file mode 100644
index 0000000000..a042c74c91
--- /dev/null
+++ b/resolv/tst-inet_ntop.c
@@ -0,0 +1,111 @@
+#include <arpa/inet.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+
+int
+main (void)
+{
+  struct in_addr addr4;
+  struct in6_addr addr6;
+  char buf[64];
+  int result = 0;
+
+  addr4.s_addr = 0xe0e0e0e0;
+  addr6.s6_addr16[0] = 0;
+  addr6.s6_addr16[1] = 0;
+  addr6.s6_addr16[2] = 0;
+  addr6.s6_addr16[3] = 0;
+  addr6.s6_addr16[4] = 0;
+  addr6.s6_addr16[5] = 0xffff;
+  addr6.s6_addr32[3] = 0xe0e0e0e0;
+  memset (buf, 'x', sizeof buf);
+
+  if (inet_ntop (AF_INET, &addr4, buf, 15) != NULL)
+    {
+      puts ("1st inet_ntop returned non-NULL");
+      result++;
+    }
+  else if (errno != ENOSPC)
+    {
+      puts ("1st inet_ntop didn't fail with ENOSPC");
+      result++;
+    }
+  if (buf[15] != 'x')
+    {
+      puts ("1st inet_ntop wrote past the end of buffer");
+      result++;
+    }
+
+  if (inet_ntop (AF_INET, &addr4, buf, 16) != buf)
+    {
+      puts ("2nd inet_ntop did not return buf");
+      result++;
+    }
+  if (memcmp (buf, "224.224.224.224\0" "xxxxxxxx", 24) != 0)
+    {
+      puts ("2nd inet_ntop wrote past the end of buffer");
+      result++;
+    }
+
+  if (inet_ntop (AF_INET6, &addr6, buf, 22) != NULL)
+    {
+      puts ("3rd inet_ntop returned non-NULL");
+      result++;
+    }
+  else if (errno != ENOSPC)
+    {
+      puts ("3rd inet_ntop didn't fail with ENOSPC");
+      result++;
+    }
+  if (buf[22] != 'x')
+    {
+      puts ("3rd inet_ntop wrote past the end of buffer");
+      result++;
+    }
+
+  if (inet_ntop (AF_INET6, &addr6, buf, 23) != buf)
+    {
+      puts ("4th inet_ntop did not return buf");
+      result++;
+    }
+  if (memcmp (buf, "::ffff:224.224.224.224\0" "xxxxxxxx", 31) != 0)
+    {
+      puts ("4th inet_ntop wrote past the end of buffer");
+      result++;
+    }
+
+  memset (&addr6.s6_addr, 0xe0, sizeof (addr6.s6_addr));
+
+  if (inet_ntop (AF_INET6, &addr6, buf, 39) != NULL)
+    {
+      puts ("5th inet_ntop returned non-NULL");
+      result++;
+    }
+  else if (errno != ENOSPC)
+    {
+      puts ("5th inet_ntop didn't fail with ENOSPC");
+      result++;
+    }
+  if (buf[39] != 'x')
+    {
+      puts ("5th inet_ntop wrote past the end of buffer");
+      result++;
+    }
+
+  if (inet_ntop (AF_INET6, &addr6, buf, 40) != buf)
+    {
+      puts ("6th inet_ntop did not return buf");
+      result++;
+    }
+  if (memcmp (buf, "e0e0:e0e0:e0e0:e0e0:e0e0:e0e0:e0e0:e0e0\0"
+		   "xxxxxxxx", 48) != 0)
+    {
+      puts ("6th inet_ntop wrote past the end of buffer");
+      result++;
+    }
+
+  
+  return result;
+}