about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog108
-rw-r--r--aout/Makefile30
-rwxr-xr-xconfig.guess12
-rw-r--r--csu/gmon-start.c4
-rw-r--r--elf/Makefile3
-rw-r--r--elf/dl-load.c7
-rw-r--r--elf/dl-profile.c267
-rw-r--r--elf/dl-reloc.c3
-rw-r--r--elf/dl-runtime.c71
-rw-r--r--elf/dl-support.c4
-rw-r--r--elf/do-rel.h6
-rw-r--r--elf/dynamic-link.h13
-rw-r--r--elf/link.h13
-rw-r--r--elf/rtld.c32
-rw-r--r--gmon/bb_exit_func.c6
-rw-r--r--gmon/gmon.c26
-rw-r--r--gmon/sys/gmon.h5
-rw-r--r--gmon/sys/gmon_out.h2
-rw-r--r--include/sys/gmon_out.h1
-rw-r--r--inet/netinet/icmp6.h270
-rw-r--r--inet/netinet/in.h96
-rw-r--r--inet/netinet/ip6.h101
-rw-r--r--libc.map2
-rw-r--r--manual/libc.texinfo2
-rw-r--r--manual/socket.texi134
-rw-r--r--manual/texinfo.tex17
-rw-r--r--nis/Makefile3
-rw-r--r--nis/TODO1
-rw-r--r--nis/lckcache.c8
-rw-r--r--nis/nis_call.c251
-rw-r--r--nis/nis_findserv.c251
-rw-r--r--nis/nis_intern.h24
-rw-r--r--nis/nis_lookup.c4
-rw-r--r--nis/nis_ping.c8
-rw-r--r--nis/nis_table.c6
-rw-r--r--nis/nis_util.c16
-rw-r--r--nis/nss_compat/compat-grp.c29
-rw-r--r--nis/nss_compat/compat-pwd.c43
-rw-r--r--nis/nss_compat/compat-spwd.c29
-rw-r--r--nis/ypclnt.c16
-rw-r--r--nss/nss_db/db-XXX.c24
-rw-r--r--nss/nss_db/db-alias.c22
-rw-r--r--nss/nss_db/db-netgrp.c20
-rw-r--r--nss/nss_files/files-XXX.c21
-rw-r--r--nss/nss_files/files-alias.c23
-rw-r--r--nss/nss_files/files-hosts.c20
-rw-r--r--posix/sys/types.h1
-rw-r--r--string/string.h13
-rw-r--r--sysdeps/alpha/dl-machine.h6
-rw-r--r--sysdeps/generic/htons.c2
-rw-r--r--sysdeps/i386/dl-machine.h51
-rw-r--r--sysdeps/i386/fpu/bits/mathinline.h868
-rw-r--r--sysdeps/m68k/bits/byteswap.h63
-rw-r--r--sysdeps/m68k/dl-machine.h7
-rw-r--r--sysdeps/mips/dl-machine.h6
-rw-r--r--sysdeps/mips/mips64/dl-machine.h6
-rw-r--r--sysdeps/powerpc/dl-machine.h6
-rw-r--r--sysdeps/sparc/dl-machine.h2
-rw-r--r--sysdeps/sparc64/dl-machine.h6
-rw-r--r--sysdeps/unix/sysv/linux/bits/socket.h8
60 files changed, 2180 insertions, 919 deletions
diff --git a/ChangeLog b/ChangeLog
index 842ed6f0dc..b57649c6d2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,111 @@
+1997-07-28 23:35  Ulrich Drepper  <drepper@cygnus.com>
+
+	* csu/gmon-start.c (__gmon_start__): Call __monstartup not
+	monstartup.
+	* gmon/gmon.c: Rename moncontrol to __moncontrol and monstartup
+	to __monstartup.
+	* gmon/sys/gmon.h: Fix prototypes.
+	* gmon/sys/gmon_out.h: Pretty print.
+
+	* gmon/bb_exit_func.c (__bb_exit_func): Use memcpy instead of bcopy.
+	* gmon/gmon.c (__monstartup): Likewise.
+	(write_hist): Remove dependency on 32 int.
+	(_mcleanup): Don't call perror, use fprintf.
+
+	* elf/dl-load.c: Fix handling of current directory in search path.
+
+	* elf/Makefile (dl-routines): Add dl-profile.
+	* elf/dl-profile.c: New file.
+	* elf/dl-runtime.c (fixup): Add new parameter with address to store
+	relocation result in to elf_machine_relplt.
+	(profile_fixup): New function.
+	* elf/do-rel.h (elf_dynamic_do_rel): Add new parameter with address
+	to store relocation result in to elf_machine_relplt.
+	* elf/dl-support.c: Define _dl_profile and _dl_profile_map.
+	* elf/dynamic-link.h (ELF_DYNAMIC_RELOCATE): Add new parameter and
+	call elf_machine_runtime_setup with extra argument.
+	* elf/dl-reloc.c (_dl_relocate_object): Add new argument to
+	ELF_DYNAMIC_RELOCATE.
+	* elf/link.h: Add prototypes for new functions and variables.
+	* elf/rtld.c: Parse LD_PROFILE and LD_PROFILE_OUTPUT environment
+	variables and call _dl_start_profile if necessary.
+	* include/sys/gmon_out.h: New file.
+	* sysdeps/alpha/dl-machine.h (elf_machine_runtime_setup): Add
+	new parameter to enable profiling.
+	(elf_machine_rela): Add new parameter to specify place to store
+	result in.
+	* sysdeps/m68k/dl-machine.h: Likewise.
+	* sysdeps/mips/dl-machine.h: Likewise.
+	* sysdeps/mips/mips64/dl-machine.h: Likewise.
+	* sysdeps/powerpc/dl-machine.h: Likewise.
+	* sysdeps/sparc/dl-machine.h: Likewise.
+	* sysdeps/sparc64/dl-machine.h: Likewise.
+	* sysdeps/i386/dl-machine.h: Likewise.
+	(elf_machine_runtime_setup): Setup got[2] to _dl_runtime_resolve if
+	we do profiling.
+	(ELF_MACHINE_RUNTIME_TRAMPOLINE): Add code for _dl_runtime_profile.
+
+	* nis/nss_compat/compat-grp.c (internal_setgrent): Set FD_CLOEXEC
+	for stream on input file.
+	* nis/nss_compat/compat-pwd.c (internal_setpwent): Likewise.
+	* nis/nss_compat/compat-spwd.c (internal_setspent): Likewise.
+	* nss/nss_db/db-XXX.c (internal_setent): Likewise.
+	* nss/nss_db/db-alias.c (internal_setent): Likewise.
+	* nss/nss_db/db-netgrp.c (internal_setent): Likewise.
+	* nss/nss_files/files-XXX.c (internal_setent): Likewise.
+	* nss/nss_files/files-alias.c (internal_setent): Likewise.
+	* nss/nss_files/files-netgrp.c (internal_setent): Likewise.
+
+	* string/string.h: Pretty print.
+
+	* sysdeps/i386/fpu/bits/mathinline.h: Major update by John Bowman.
+	Add float and long double versions.
+
+1997-07-27  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* elf/rtld.c (print_unresolved): Replace empty object name by main
+	program name.
+
+1997-07-27  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* sysdeps/generic/htons.c (htons): Renamed from __htons.
+
+1997-07-27  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+	* sysdeps/m68k/bits/byteswap.h: New file.
+
+1997-07-27 23:50  Philip Blundell  <Philip.Blundell@pobox.com>
+
+	* inet/netinet/icmp6.h: Update for new drafts of POSIX.1g and IPv6
+	advanced API.
+	* inet/netinet/in.h: Likewise.
+	* inet/netinet/ip6.h: Likewise.
+	* sysdeps/unix/sysv/linux/bits/socket.h: Likewise.
+	* posix/sys/types.h: Add socklen_t.
+
+	* manual/socket.texi: Document some more IPv6 things.
+	* manual/libc.texinfo: Likewise.
+
+1997-07-26  Andreas Jaeger  <aj@arthur.rhein-neckar.de>
+
+	* libc.map: Define missing symbol.
+
+1997-07-27 14:31  Thorsten Kukuk  <kukuk@vt.uni-paderborn.de>
+
+	* nis/Makefile: Add nis_findserv.
+	* nis/lckcache.c: Fix typo.
+	* nis/nis_call.c: Fix problems with multihomed servers.
+	* nis/nis_findserv.c: New file.
+	* nis/nis_intern.h: Add more prototypes.
+	* nis/nis_lookup.c (nis_lookup): Don't try the next server if network
+	is unreachable.
+	* nis/nis_table.c (nis_list): Likewise.
+	* nis/nis_ping.c (nis_ping): Use MASTER_ONLY, don't call abort()
+	in error case.
+	* nis/nis_util.c (__nis_finddirectory): Give the right error code
+	back.
+	* nis/ypclnt.c: Make sure, that all sockets are closed.
+
 1997-07-26 04:14  Ulrich Drepper  <drepper@cygnus.com>
 
 	* elf/Makefile (distribute): Add genrtldtbl.awk.
diff --git a/aout/Makefile b/aout/Makefile
new file mode 100644
index 0000000000..b1e2d643be
--- /dev/null
+++ b/aout/Makefile
@@ -0,0 +1,30 @@
+# Makefile for aout subdirectory of GNU C Library.
+
+# Copyright (C) 1995, 1996, 1997 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 Library General Public License as
+# published by the Free Software Foundation; either version 2 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
+# Library General Public License for more details.
+
+# You should have received a copy of the GNU Library General Public
+# License along with the GNU C Library; see the file COPYING.LIB.  If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+subdir		:= aout
+
+headers		= 
+routines	= enbl-secure
+
+all: # Make this the default target; it will be defined in Rules.
+
+include ../Makeconfig
+include ../Rules
+
diff --git a/config.guess b/config.guess
index a73a8d93c0..ee2742b9e0 100755
--- a/config.guess
+++ b/config.guess
@@ -157,6 +157,18 @@ EOF
     sun3*:SunOS:*:*)
 	echo m68k-sun-sunos${UNAME_RELEASE}
 	exit 0 ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit 0 ;;
     aushp:SunOS:*:*)
 	echo sparc-auspex-sunos${UNAME_RELEASE}
 	exit 0 ;;
diff --git a/csu/gmon-start.c b/csu/gmon-start.c
index 02c44e2fcf..8c66905a3b 100644
--- a/csu/gmon-start.c
+++ b/csu/gmon-start.c
@@ -1,5 +1,5 @@
 /* Code to enable profiling at program startup.
-   Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997 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
@@ -50,7 +50,7 @@ __gmon_start__ (void)
 #endif
 
   /* Start keeping profiling records.  */
-  monstartup ((u_long) &_start, (u_long) &etext);
+  __monstartup ((u_long) &_start, (u_long) &etext);
 
   /* Call _mcleanup before exiting; it will write out gmon.out from the
      collected data.  */
diff --git a/elf/Makefile b/elf/Makefile
index e44711471b..904099cbeb 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -27,7 +27,8 @@ routines	= $(dl-routines) dl-open dl-close dl-symbol dl-support \
 # The core dynamic linking functions are in libc for the static and
 # profiled libraries.
 dl-routines	= $(addprefix dl-,load cache lookup object reloc deps \
-			          runtime error init fini debug misc)
+			          runtime error init fini debug misc \
+				  profile)
 # But they are absent from the shared libc, because that code is in ld.so.
 elide-routines.so = $(dl-routines) dl-support enbl-secure
 
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 1301e73996..f7c2c53f7e 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -193,7 +193,10 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
 			      "cannot create cache for search path");
 
 	  dirp->dirnamelen = len;
-	  dirp->dirstatus = unknown;
+	  /* We have to make sure all the relative directories are never
+	     ignored.  The current directory might change and all our
+	     saved information would be void.  */
+	  dirp->dirstatus = cp[0] != '/' ? existing : unknown;
 
 	  /* Add the name of the machine dependent directory if a machine
 	     is defined.  */
@@ -212,7 +215,7 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
 	      tmp[len + _dl_platformlen + 1] = '\0';
 
 	      dirp->dirname = tmp;
-	      dirp->machdirstatus = unknown;
+	      dirp->machdirstatus = dirp->dirstatus;
 
 	      if (max_dirnamelen < dirp->machdirnamelen)
 		max_dirnamelen = dirp->machdirnamelen;
diff --git a/elf/dl-profile.c b/elf/dl-profile.c
new file mode 100644
index 0000000000..cc25b6105f
--- /dev/null
+++ b/elf/dl-profile.c
@@ -0,0 +1,267 @@
+/* Profiling of shared libraries.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <link.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/gmon.h>
+#include <sys/gmon_out.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+/* The LD_PROFILE feature has to be implemented different to the
+   normal profiling using the gmon/ functions.  The problem is that an
+   arbitrary amount of processes simulataneously can be run using
+   profiling and all write the results in the same file.  To provide
+   this mechanism one could implement a complicated mechanism to merge
+   the content of two profiling runs or one could extend the file
+   format to allow more than one data set.  For the second solution we
+   would have the problem that the file can grow in size beyond any
+   limit and both solutions have the problem that the concurrency of
+   writing the results is a big problem.
+
+   Another much simpler method is to use mmap to map the same file in
+   all using programs and modify the data in the mmap'ed area and so
+   also automatically on the disk.  Using the MAP_SHARED option of
+   mmap(2) this can be done without big problems in more than one
+   file.
+
+   This approach is very different from the normal profiling.  We have
+   to use the profiling data in exactly the way they are expected to
+   be written to disk.  */
+
+extern char *_strerror_internal __P ((int, char *buf, size_t));
+
+extern int __profile_frequency __P ((void));
+
+
+static struct gmonparam param;
+
+/* We define a special type to address the elements of the arc table.
+   This is basically the `gmon_cg_arc_record' format but it includes
+   the room for the tag and it uses real types.  */
+struct here_cg_arc_record
+  {
+    char tag;
+    uintptr_t from_pc __attribute__ ((packed));
+    uintptr_t self_pc __attribute__ ((packed));
+    uint32_t count __attribute__ ((packed));
+  };
+
+static struct here_cg_arc_record *data;
+
+
+void
+_dl_start_profile (struct link_map *map, const char *output_dir)
+{
+  char *filename;
+  int fd;
+  struct stat st;
+  const ElfW(Phdr) *ph;
+  ElfW(Addr) mapstart = ~((ElfW(Addr)) 0);
+  ElfW(Addr) mapend = 0;
+  off_t expected_size;
+  struct gmon_hdr gmon_hdr;
+  struct gmon_hist_hdr hist_hdr;
+  struct gmon_hdr *addr;
+  char *hist;
+
+  /* Compute the size of the sections which contain program code.  */
+  for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
+    if (ph->p_type == PT_LOAD && (ph->p_flags & PF_X))
+      {
+	ElfW(Addr) start = (ph->p_vaddr & ~(_dl_pagesize - 1));
+	ElfW(Addr) end = ((ph->p_vaddr + ph->p_memsz + _dl_pagesize - 1)
+			  & ~(_dl_pagesize - 1));
+
+	if (start < mapstart)
+	  mapstart = start;
+	if (end > mapend)
+	  mapend = end;
+      }
+
+  /* Now we can compute the size of the profiling data.  This is done
+     with the same formulars as in `monstartup' (see gmon.c).  */
+  param.state = GMON_PROF_OFF;
+  param.lowpc = mapstart + map->l_addr;
+  param.highpc = mapend + map->l_addr;
+  param.textsize = mapend - mapstart;
+  param.kcountsize = param.textsize / HISTFRACTION;
+  param.hashfraction = HASHFRACTION;
+  param.log_hashfraction = -1;
+  if ((HASHFRACTION & (HASHFRACTION - 1)) == 0)
+    /* If HASHFRACTION is a power of two, mcount can use shifting
+       instead of integer division.  Precompute shift amount.  */
+    param.log_hashfraction = ffs (param.hashfraction
+				  * sizeof (*param.froms)) - 1;
+  param.fromssize = param.textsize / HASHFRACTION;
+  param.tolimit = param.textsize * ARCDENSITY / 100;
+  if (param.tolimit < MINARCS)
+    param.tolimit = MINARCS;
+  if (param.tolimit > MAXARCS)
+    param.tolimit = MAXARCS;
+  param.tossize = param.tolimit * sizeof (struct tostruct);
+
+  expected_size = (sizeof (struct gmon_hdr)
+		   + 1 + sizeof (struct gmon_hist_hdr)
+		   + ((1 + sizeof (struct gmon_cg_arc_record))
+		      * (param.fromssize / sizeof (*param.froms))));
+
+  /* Create the gmon_hdr we expect or write.  */
+  memset (&gmon_hdr, '\0', sizeof (struct gmon_hdr));
+  memcpy (&gmon_hdr.cookie[0], GMON_MAGIC, sizeof (gmon_hdr.cookie));
+  *(int32_t *) gmon_hdr.version = GMON_VERSION;
+
+  /* Create the hist_hdr we expect or write.  */
+  *(char **) hist_hdr.low_pc = (char *) mapstart;
+  *(char **) hist_hdr.high_pc = (char *) mapend;
+  *(int32_t *) hist_hdr.hist_size = param.kcountsize / sizeof (HISTCOUNTER);
+  *(int32_t *) hist_hdr.prof_rate = __profile_frequency ();
+  strncpy (hist_hdr.dimen, "seconds", sizeof (hist_hdr.dimen));
+  hist_hdr.dimen_abbrev = 's';
+
+  /* First determine the output name.  We write in the directory
+     OUTPUT_DIR and the name is composed from the shared objects
+     soname (or the file name) and the ending ".profile".  */
+  filename = (char *) alloca (strlen (output_dir) + 1 + strlen (_dl_profile)
+			      + sizeof ".profile");
+  __stpcpy (__stpcpy (__stpcpy (__stpcpy (filename, output_dir), "/"),
+		      _dl_profile),
+	    ".profile");
+
+  fd = __open (filename, O_RDWR | O_CREAT, 0666);
+  if (fd == -1)
+    /* We cannot write the profiling data so don't do anthing.  */
+    return;
+
+  if (fstat (fd, &st) < 0 || !S_ISREG (st.st_mode))
+    {
+      /* Not stat'able or not a regular file => don't use it.  */
+      close (fd);
+      return;
+    }
+
+  /* Test the size.  If it does not match what we expect from the size
+     values in the map MAP we don't use it and warn the user.  */
+  if (st.st_size == 0)
+    {
+      /* We have to create the file.  */
+      char buf[_dl_pagesize];
+
+      memset (buf, '\0', _dl_pagesize);
+
+      if (__lseek (fd, expected_size & ~(_dl_pagesize - 1), SEEK_SET) == -1)
+	{
+	  char buf[400];
+	  int errnum;
+	cannot_create:
+	  errnum = errno;
+	  __close (fd);
+	  fprintf (stderr, "%s: cannot create file: %s\n", filename,
+		   _strerror_internal (errnum, buf, sizeof buf));
+	  return;
+	}
+
+      if (TEMP_FAILURE_RETRY (__write (fd, buf, (expected_size
+						 & (_dl_pagesize - 1)))) < 0)
+	goto cannot_create;
+    }
+  else if (st.st_size != expected_size)
+    {
+      __close (fd);
+    wrong_format:
+      fprintf (stderr, "%s: file is no correct profile data file for `%s'\n",
+	       filename, _dl_profile);
+      return;
+    }
+
+  addr = (void *) __mmap (NULL, expected_size, PROT_READ|PROT_WRITE,
+			  MAP_SHARED|MAP_FILE, fd, 0);
+  if (addr == (void *) -1)
+    {
+      char buf[400];
+      int errnum = errno;
+      __close (fd);
+      fprintf (stderr, "%s: cannot map file: %s\n", filename,
+	       _strerror_internal (errnum, buf, sizeof buf));
+      return;
+    }
+
+  /* We don't need the file desriptor anymore.  */
+  __close (fd);
+
+  /* Pointer to data after the header.  */
+  hist = (char *) (addr + 1);
+
+  /* Compute pointer to array of the arc information.  */
+  data = (struct here_cg_arc_record *) (hist + 1
+					+ sizeof (struct gmon_hist_hdr));
+
+  if (st.st_size == 0)
+    {
+      /* Create the signature.  */
+      size_t cnt;
+
+      memcpy (addr, &gmon_hdr, sizeof (struct gmon_hdr));
+
+      *hist = GMON_TAG_TIME_HIST;
+      memcpy (hist + 1, &hist_hdr, sizeof (struct gmon_hist_hdr));
+
+      for (cnt = 0; cnt < param.fromssize / sizeof (*param.froms); ++cnt)
+	data[cnt].tag = GMON_TAG_CG_ARC;
+    }
+  else
+    {
+      /* Test the signature in the file.  */
+      if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0
+	  || *hist != GMON_TAG_TIME_HIST
+	  || memcmp (hist + 1, &hist_hdr, sizeof (struct gmon_hist_hdr)) != 0)
+	goto wrong_format;
+    }
+
+  /* Turn on profiling.  */
+  param.state = GMON_PROF_ON;
+}
+
+
+void
+_dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc)
+{
+  if (param.state != GMON_PROF_ON)
+    return;
+  param.state = GMON_PROF_BUSY;
+
+  /* Compute relative addresses.  The shared object can be loaded at
+     any address.  The value of frompc could be anything.  We cannot
+     restrict it in any way, just set to a fixed value (0) in case it
+     is outside the allowed range.  These calls show up as calls from
+     <external> in the gprof output.  */
+  frompc -= param.lowpc;
+  if (frompc >= param.textsize)
+    frompc = 0;
+  selfpc -= param.lowpc;
+
+  param.state = GMON_PROF_ON;
+}
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index 5b22a506da..4f6eff8835 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -24,6 +24,7 @@
 #include <errno.h>
 #include "dynamic-link.h"
 
+
 void
 _dl_relocate_object (struct link_map *l, struct link_map *scope[], int lazy)
 {
@@ -65,7 +66,7 @@ _dl_relocate_object (struct link_map *l, struct link_map *scope[], int lazy)
 			  l->l_name, (flags)))
 
 #include "dynamic-link.h"
-    ELF_DYNAMIC_RELOCATE (l, lazy);
+    ELF_DYNAMIC_RELOCATE (l, lazy, 1);
   }
 
   /* Mark the object so we know this work has been done.  */
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index 7a44ea4ce3..1b34026d38 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -137,17 +137,18 @@ fixup (
     /* Perform the specified relocation.  */
     if (l->l_info[VERSYMIDX (DT_VERSYM)])
       {
-	const ElfW(Half) * version =
+	const ElfW(Half) *version =
 	  (const ElfW(Half) *) (l->l_addr +
 				l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr);
 	ElfW(Half) ndx = version[ELFW(R_SYM) (reloc->r_info)];
 
 	elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)],
-			    &l->l_versions[ndx]);
+			    &l->l_versions[ndx],
+			    (void *) (l->l_addr + reloc->r_offset));
       }
     else
       elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)],
-			  NULL);
+			  NULL, (void *) (l->l_addr + reloc->r_offset));
   }
 
   *_dl_global_scope_end = NULL;
@@ -161,6 +162,70 @@ fixup (
 }
 
 
+#ifndef PROF
+static ElfW(Addr)
+profile_fixup (
+#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
+       ELF_MACHINE_RUNTIME_FIXUP_ARGS,
+#endif
+       struct link_map *l, ElfW(Word) reloc_offset, ElfW(Addr) retaddr)
+{
+  void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = _dl_mcount;
+  const ElfW(Sym) *const symtab
+    = (const ElfW(Sym) *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);
+  const char *strtab =
+    (const char *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
+
+  const PLTREL *const reloc
+    = (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
+		      reloc_offset);
+  ElfW(Addr) result;
+
+  /* Set up the scope to find symbols referenced by this object.  */
+  struct link_map **scope = _dl_object_relocation_scope (l);
+
+  {
+    /* This macro is used as a callback from the elf_machine_relplt code.  */
+#define RESOLVE(ref, version, flags) \
+  ((version) != NULL && (version)->hash != 0				      \
+   ? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, (ref), scope,     \
+				  l->l_name, (version), (flags))	      \
+   : _dl_lookup_symbol (strtab + (*ref)->st_name, (ref), scope,		      \
+			l->l_name, (flags)))
+#include "dynamic-link.h"
+
+    /* Perform the specified relocation.  */
+    if (l->l_info[VERSYMIDX (DT_VERSYM)])
+      {
+	const ElfW(Half) *version =
+	  (const ElfW(Half) *) (l->l_addr +
+				l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr);
+	ElfW(Half) ndx = version[ELFW(R_SYM) (reloc->r_info)];
+
+	elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)],
+			    &l->l_versions[ndx], (void *) &result);
+      }
+    else
+      elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)],
+			  NULL, (void *) &result);
+  }
+
+  *_dl_global_scope_end = NULL;
+
+  /* Return the address that was written by the relocation.  */
+#ifdef ELF_FIXUP_RETURNS_ADDRESS
+  (*mcount_fct) (retaddr, result);
+
+  return &result;	/* XXX This cannot work.  What to do??? --drepper */
+#else
+  (*mcount_fct) (retaddr, result);
+
+  return result;
+#endif
+}
+#endif
+
+
 /* This macro is defined in dl-machine.h to define the entry point called
    by the PLT.  The `fixup' function above does the real work, but a little
    more twiddling is needed to get the stack right and jump to the address
diff --git a/elf/dl-support.c b/elf/dl-support.c
index 3333bf10fb..41997ccafb 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -42,6 +42,10 @@ int _dl_verbose;
 /* Structure to store information about search paths.  */
 struct r_search_path *_dl_search_paths;
 
+/* We never do profiling.  */
+const char *_dl_profile;
+struct link_map *_dl_profile_map;
+
 
 static void non_dynamic_init (void) __attribute__ ((unused));
 
diff --git a/elf/do-rel.h b/elf/do-rel.h
index 766e62c219..7f4b1259a2 100644
--- a/elf/do-rel.h
+++ b/elf/do-rel.h
@@ -63,12 +63,14 @@ elf_dynamic_do_rel (struct link_map *map,
 	    {
 	      ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)];
 	      elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
-			       &map->l_versions[ndx]);
+			       &map->l_versions[ndx],
+			       (void *) (map->l_addr + r->r_offset));
 	    }
 	}
       else
 	for (; r < end; ++r)
-	  elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL);
+	  elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
+			   (void *) (map->l_addr + r->r_offset));
     }
 }
 
diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h
index 3377ee7ff6..4a946f8ad8 100644
--- a/elf/dynamic-link.h
+++ b/elf/dynamic-link.h
@@ -102,11 +102,14 @@ elf_get_dynamic_info (ElfW(Dyn) *dyn,
 
 /* This can't just be an inline function because GCC is too dumb
    to inline functions containing inlines themselves.  */
-#define ELF_DYNAMIC_RELOCATE(map, lazy)				\
-  do {								\
-    int edr_lazy = elf_machine_runtime_setup((map), (lazy));	\
-    ELF_DYNAMIC_DO_REL ((map), edr_lazy);			\
-    ELF_DYNAMIC_DO_RELA ((map), edr_lazy);			\
+#define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile) \
+  do {									      \
+    int profile = (consider_profile && _dl_profile != NULL		      \
+		   && _dl_name_match_p (_dl_profile, (map)));		      \
+    int edr_lazy = elf_machine_runtime_setup ((map), (lazy) || profile,	      \
+					      profile);			      \
+    ELF_DYNAMIC_DO_REL ((map), edr_lazy);				      \
+    ELF_DYNAMIC_DO_RELA ((map), edr_lazy);				      \
   } while (0)
 
 #endif
diff --git a/elf/link.h b/elf/link.h
index e0fccd0fca..38a7c88d9a 100644
--- a/elf/link.h
+++ b/elf/link.h
@@ -225,6 +225,11 @@ extern size_t _dl_pagesize;
 /* File descriptor referring to the zero-fill device.  */
 extern int _dl_zerofd;
 
+/* Name of the shared object to be profiled (if any).  */
+extern const char *_dl_profile;
+/* Map of shared object to be profiled.  */
+extern struct link_map *_dl_profile_map;
+
 /* OS-dependent function to open the zero-fill device.  */
 extern int _dl_sysdep_open_zero_fill (void); /* dl-sysdep.c */
 
@@ -430,8 +435,14 @@ extern void _dl_debug_state (void);
 extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase);
 
 /* Initialize the basic data structure for the search paths.  */
-void _dl_init_paths (void);
+extern void _dl_init_paths (void);
+
+/* Gather the information needed to install the profiling tables and start
+   the timers.  */
+extern void _dl_start_profile (struct link_map *map, const char *output_dir);
 
+/* The actual functions used to keep book on the calls.  */
+extern void _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc);
 
 __END_DECLS
 
diff --git a/elf/rtld.c b/elf/rtld.c
index 7189ca6b2b..726463c882 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -61,6 +61,9 @@ int _dl_verbose;
 const char *_dl_platform;
 size_t _dl_platformlen;
 struct r_search_path *_dl_search_paths;
+const char *_dl_profile;
+const char *_dl_profile_output;
+struct link_map *_dl_profile_map;
 
 /* Set nonzero during loading and initialization of executable and
    libraries, cleared before the executable's entry point runs.  This
@@ -109,7 +112,7 @@ _dl_start (void *arg)
   /* Relocate ourselves so we can do normal function calls and
      data access using the global offset table.  */
 
-  ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0);
+  ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0);
 
   /* Now life is sane; we can call functions and access global data.
      Set up to use the operating system facilities, and find out from
@@ -269,6 +272,26 @@ dl_main (const ElfW(Phdr) *phdr,
   else
     lazy = !__libc_enable_secure && *(getenv ("LD_BIND_NOW") ?: "") == '\0';
 
+  /* See whether we want to use profiling.  */
+  _dl_profile = getenv ("LD_PROFILE");
+  if (_dl_profile != NULL)
+    if (_dl_profile[0] == '\0')
+      /* An empty string is of not much help.  Disable profiling.  */
+      _dl_profile = NULL;
+    else
+      {
+	/* OK, we have the name of a shared object we want to
+	   profile.  It's up to the user to provide a good name, it
+	   must match the file name or soname of one of the loaded
+	   objects.  Now let's see where we are supposed to place the
+	   result.  */
+	_dl_profile_output = getenv ("LD_PROFILE_OUTPUT");
+
+	if (_dl_profile_output == NULL || _dl_profile_output[0] == '\0')
+	  /* This is the default place.  */
+	  _dl_profile_output = "/var/tmp";
+      }
+
   /* Set up a flag which tells we are just starting.  */
   _dl_starting_up = 1;
 
@@ -814,6 +837,11 @@ of this helper program; chances are you did not intend to run this program.\n",
     _dl_debug_state ();
   }
 
+  /* Now enable profiling if needed.  */
+  if (_dl_profile_map != NULL)
+    /* We must prepare the profiling.  */
+    _dl_start_profile (_dl_profile_map, _dl_profile_output);
+
   /* Once we return, _dl_sysdep_start will invoke
      the DT_INIT functions and then *USER_ENTRY.  */
 }
@@ -824,6 +852,8 @@ static void
 print_unresolved (int errcode __attribute__ ((unused)), const char *objname,
 		  const char *errstring)
 {
+  if (objname[0] == '\0')
+    objname = _dl_argv[0] ?: "<main program>";
   _dl_sysdep_error (errstring, "	(", objname, ")\n", NULL);
 }
 
diff --git a/gmon/bb_exit_func.c b/gmon/bb_exit_func.c
index dc9def2bb5..53ddbfdbe9 100644
--- a/gmon/bb_exit_func.c
+++ b/gmon/bb_exit_func.c
@@ -18,7 +18,7 @@
    Boston, MA 02111-1307, USA.  */
 
 /* __bb_exit_func() dumps all the basic-block statistics linked into
-   the bb_head chain to .d files.  */
+   the __bb_head chain to .d files.  */
 
 #include <sys/gmon_out.h>
 #include <sys/types.h>
@@ -55,8 +55,8 @@ __bb_exit_func (void)
       perror (OUT_NAME);
       return;
     }
-  bcopy (GMON_MAGIC, &ghdr.cookie[0], 4);
-  bcopy (&version, &ghdr.version, sizeof (version));
+  memcpy (&ghdr.cookie[0], GMON_MAGIC, 4);
+  memcpy (&ghdr.version, &version, sizeof (version));
   fwrite (&ghdr, sizeof (ghdr), 1, fp);
 
   for (ptr = __bb_head; ptr != 0; ptr = ptr->next)
diff --git a/gmon/gmon.c b/gmon/gmon.c
index d484ec2c9e..6b7ef81d93 100644
--- a/gmon/gmon.c
+++ b/gmon/gmon.c
@@ -36,6 +36,7 @@
 #include <sys/gmon_out.h>
 #include <sys/uio.h>
 
+#include <errno.h>
 #include <stdio.h>
 #include <fcntl.h>
 #include <unistd.h>
@@ -60,6 +61,7 @@ static int	s_scale;
 #define ERR(s) write(2, s, sizeof(s) - 1)
 
 void moncontrol __P ((int mode));
+void __moncontrol __P ((int mode));
 static void write_hist __P ((int fd));
 static void write_call_graph __P ((int fd));
 static void write_bb_counts __P ((int fd));
@@ -70,7 +72,7 @@ static void write_bb_counts __P ((int fd));
  *	all the data structures are ready.
  */
 void
-moncontrol (mode)
+__moncontrol (mode)
      int mode;
 {
   struct gmonparam *p = &_gmonparam;
@@ -91,7 +93,7 @@ moncontrol (mode)
 
 
 void
-monstartup (lowpc, highpc)
+__monstartup (lowpc, highpc)
      u_long lowpc;
      u_long highpc;
 {
@@ -128,7 +130,7 @@ monstartup (lowpc, highpc)
       ERR(_("monstartup: out of memory\n"));
       return;
     }
-  bzero(cp, p->kcountsize + p->fromssize + p->tossize);
+  memset (cp, '\0', p->kcountsize + p->fromssize + p->tossize);
   p->tos = (struct tostruct *)cp;
   cp += p->tossize;
   p->kcount = (u_short *)cp;
@@ -158,7 +160,7 @@ monstartup (lowpc, highpc)
     } else
       s_scale = SCALE_1_TO_1;
 
-  moncontrol(1);
+  __moncontrol(1);
 }
 
 
@@ -180,8 +182,9 @@ write_hist (fd)
 
       *(char **) thdr.low_pc = (char *) _gmonparam.lowpc;
       *(char **) thdr.high_pc = (char *) _gmonparam.highpc;
-      *(int *) thdr.hist_size = _gmonparam.kcountsize / sizeof (HISTCOUNTER);
-      *(int *) thdr.prof_rate = __profile_frequency ();
+      *(int32_t *) thdr.hist_size = (_gmonparam.kcountsize
+				     / sizeof (HISTCOUNTER));
+      *(int32_t *) thdr.prof_rate = __profile_frequency ();
       strncpy (thdr.dimen, "seconds", sizeof (thdr.dimen));
       thdr.dimen_abbrev = 's';
 
@@ -296,18 +299,21 @@ _mcleanup ()
     struct gmon_hdr ghdr __attribute__ ((aligned (__alignof__ (int))));
     int fd;
 
-    moncontrol (0);
+    __moncontrol (0);
     fd = __open ("gmon.out", O_CREAT|O_TRUNC|O_WRONLY, 0666);
     if (fd < 0)
       {
-	perror ("_mcleanup: gmon.out");
+	char buf[300];
+	int errnum = errno;
+	fprintf (stderr, "_mcleanup: gmon.out: %s\n",
+		 _strerror_internal (errnum, buf, sizeof buf));
 	return;
       }
 
     /* write gmon.out header: */
-    memset (&ghdr, 0, sizeof (struct gmon_hdr));
+    memset (&ghdr, '\0', sizeof (struct gmon_hdr));
     memcpy (&ghdr.cookie[0], GMON_MAGIC, sizeof (ghdr.cookie));
-    *(int *) ghdr.version = GMON_VERSION;
+    *(int32_t *) ghdr.version = GMON_VERSION;
     __write (fd, &ghdr, sizeof (struct gmon_hdr));
 
     /* write PC histogram: */
diff --git a/gmon/sys/gmon.h b/gmon/sys/gmon.h
index 2eff69b01c..8368ca1ce3 100644
--- a/gmon/sys/gmon.h
+++ b/gmon/sys/gmon.h
@@ -169,10 +169,11 @@ extern struct gmonparam _gmonparam;
 __BEGIN_DECLS
 
 /* Set up data structures and start profiling.  */
-void monstartup __P ((u_long lowpc, u_long highpc));
+extern void __monstartup __P ((u_long __lowpc, u_long __highpc));
+extern void monstartup __P ((u_long __lowpc, u_long __highpc));
 
 /* Clean up profiling and write out gmon.out.  */
-void _mcleanup __P ((void));
+extern void _mcleanup __P ((void));
 
 __END_DECLS
 
diff --git a/gmon/sys/gmon_out.h b/gmon/sys/gmon_out.h
index bb80a1a16f..c84f945ce8 100644
--- a/gmon/sys/gmon_out.h
+++ b/gmon/sys/gmon_out.h
@@ -70,7 +70,7 @@ struct gmon_cg_arc_record
     char from_pc[sizeof (char *)];	/* address within caller's body */
     char self_pc[sizeof (char *)];	/* address within callee's body */
     char count[4];			/* number of arc traversals */
-};
+  };
 
 __END_DECLS
 
diff --git a/include/sys/gmon_out.h b/include/sys/gmon_out.h
new file mode 100644
index 0000000000..249f834ba3
--- /dev/null
+++ b/include/sys/gmon_out.h
@@ -0,0 +1 @@
+#include <gmon/sys/gmon_out.h>
diff --git a/inet/netinet/icmp6.h b/inet/netinet/icmp6.h
index 224fb64f08..38c1bc19dd 100644
--- a/inet/netinet/icmp6.h
+++ b/inet/netinet/icmp6.h
@@ -19,6 +19,8 @@
 #ifndef _NETINET_ICMP6_H
 #define _NETINET_ICMP6_H 1
 
+#include <inttypes.h>
+#include <string.h>
 #include <sys/types.h>
 #include <netinet/in.h>
 
@@ -29,160 +31,202 @@
 #define ICMPV6_FILTER_BLOCKOTHERS	3
 #define ICMPV6_FILTER_PASSONLY		4
 
-struct icmpv6_filter
+struct icmp6_filter
   {
-    u_int32_t data[8];
+    uint32_t data[8];
   };
 
-struct icmpv6hdr
+struct icmp6_hdr 
   {
-    u_int8_t icmpv6_type;   /* type field */
-    u_int8_t icmpv6_code;   /* code field */
-    u_int16_t icmpv6_cksum;  /* checksum field */
-    union
+    uint8_t     icmp6_type;   /* type field */
+    uint8_t     icmp6_code;   /* code field */
+    uint16_t    icmp6_cksum;  /* checksum field */
+    union 
       {
-	u_int32_t un_data32[1]; /* type-specific field */
-	u_int16_t un_data16[2]; /* type-specific field */
-	u_int8_t un_data8[4];  /* type-specific field */
-      } icmpv6_dataun;
-  };
-
-#define icmpv6_data32    icmpv6_dataun.un_data32
-#define icmpv6_data16    icmpv6_dataun.un_data16
-#define icmpv6_data8     icmpv6_dataun.un_data8
-#define icmpv6_pptr      icmpv6_data32[0]  /* parameter prob */
-#define icmpv6_mtu       icmpv6_data32[0]  /* packet too big */
-#define icmpv6_id        icmpv6_data16[0]  /* echo request/reply */
-#define icmpv6_seq       icmpv6_data16[1]  /* echo request/reply */
-#define icmpv6_maxdelay  icmpv6_data16[0]  /* mcast group membership */
-
-#define ICMPV6_DEST_UNREACH             1
-#define ICMPV6_PACKET_TOOBIG            2
-#define ICMPV6_TIME_EXCEEDED            3
-#define ICMPV6_PARAMETER_PROBLEM        4
-#define ICMPV6_INFOMSG_MASK             128 /* message is info if bit set */
-#define ICMPV6_ECHOREQUEST              128
-#define ICMPV6_ECHOREPLY                129
-#define ICMPV6_MGM_QUERY                130
-#define ICMPV6_MGM_REPORT               131
-#define ICMPV6_MGM_REDUCTION            132
-
-#define ICMPV6_DEST_UNREACH_NOROUTE	  0
-#define ICMPV6_DEST_UNREACH_ADMIN	  1 /* administratively prohibited */
-#define ICMPV6_DEST_UNREACH_NOTNEIGHBOR   2 /* not a neighbor (and must be) */
-#define ICMPV6_DEST_UNREACH_ADDR          3
-#define ICMPV6_DEST_UNREACH_NOPORT        4
-#define ICMPV6_TIME_EXCEED_HOPS           0 /* Hop Limit == 0 in transit */
-#define ICMPV6_TIME_EXCEED_REASSEMBLY     1 /* Reassembly time out */
-#define ICMPV6_PARAMPROB_HEADER           0 /* erroneous header field */
-#define ICMPV6_PARAMPROB_NEXTHEADER       1 /* unrecognized Next Header */
-#define ICMPV6_PARAMPROB_OPTION           2 /* unrecognized option */
-
-#define ICMPV6_FILTER_WILLPASS(type, filterp) \
+	uint32_t  icmp6_un_data32[1]; /* type-specific field */
+	uint16_t  icmp6_un_data16[2]; /* type-specific field */
+	uint8_t   icmp6_un_data8[4];  /* type-specific field */
+      } icmp6_dataun;
+  }; 
+
+#define icmp6_data32    icmp6_dataun.icmp6_un_data32
+#define icmp6_data16    icmp6_dataun.icmp6_un_data16
+#define icmp6_data8     icmp6_dataun.icmp6_un_data8
+#define icmp6_pptr      icmp6_data32[0]  /* parameter prob */
+#define icmp6_mtu       icmp6_data32[0]  /* packet too big */
+#define icmp6_id        icmp6_data16[0]  /* echo request/reply */
+#define icmp6_seq       icmp6_data16[1]  /* echo request/reply */
+#define icmp6_maxdelay  icmp6_data16[0]  /* mcast group membership */
+
+#define ICMP6_DST_UNREACH             1
+#define ICMP6_PACKET_TOO_BIG          2
+#define ICMP6_TIME_EXCEEDED           3
+#define ICMP6_PARAM_PROB              4
+
+#define ICMP6_INFOMSG_MASK  0x80    /* all informational messages */
+
+#define ICMP6_ECHO_REQUEST          128
+#define ICMP6_ECHO_REPLY            129
+#define ICMP6_MEMBERSHIP_QUERY      130
+#define ICMP6_MEMBERSHIP_REPORT     131
+#define ICMP6_MEMBERSHIP_REDUCTION  132
+
+#define ICMP6_DST_UNREACH_NOROUTE     0 /* no route to destination */
+#define ICMP6_DST_UNREACH_ADMIN       1 /* communication with destination */
+                                        /* administratively prohibited */
+#define ICMP6_DST_UNREACH_NOTNEIGHBOR 2 /* not a neighbor */
+#define ICMP6_DST_UNREACH_ADDR        3 /* address unreachable */
+#define ICMP6_DST_UNREACH_NOPORT      4 /* bad port */
+
+#define ICMP6_TIME_EXCEED_TRANSIT     0 /* Hop Limit == 0 in transit */
+#define ICMP6_TIME_EXCEED_REASSEMBLY  1 /* Reassembly time out */
+
+#define ICMP6_PARAMPROB_HEADER        0 /* erroneous header field */
+#define ICMP6_PARAMPROB_NEXTHEADER    1 /* unrecognized Next Header */
+#define ICMP6_PARAMPROB_OPTION        2 /* unrecognized IPv6 option */
+
+#define ICMP6_FILTER_WILLPASS(type, filterp) \
 	((((filterp)->data[(type) >> 5]) & (1 << ((type) & 31))) == 0)
 
-#define ICMPV6_FILTER_WILLBLOCK(type, filterp) \
+#define ICMP6_FILTER_WILLBLOCK(type, filterp) \
 	((((filterp)->data[(type) >> 5]) & (1 << ((type) & 31))) != 0)
 
-#define ICMPV6_FILTER_SETPASS(type, filterp) \
+#define ICMP6_FILTER_SETPASS(type, filterp) \
 	((((filterp)->data[(type) >> 5]) &= ~(1 << ((type) & 31))))
 
-#define ICMPV6_FILTER_SETBLOCK(type, filterp) \
+#define ICMP6_FILTER_SETBLOCK(type, filterp) \
 	((((filterp)->data[(type) >> 5]) |=  (1 << ((type) & 31))))
 
-#define ICMPV6_FILTER_SETPASSALL(filterp) \
-	memset (filterp, 0, sizeof (struct icmpv6_filter));
+#define ICMP6_FILTER_SETPASSALL(filterp) \
+	memset (filterp, 0, sizeof (struct icmp6_filter));
 
-#define ICMPV6_FILTER_SETBLOCKALL(filterp) \
-	memset (filterp, 0xFF, sizeof (struct icmpv6_filter));
+#define ICMP6_FILTER_SETBLOCKALL(filterp) \
+	memset (filterp, 0xFF, sizeof (struct icmp6_filter));
 
-#define ND6_ROUTER_SOLICITATION		133
-#define ND6_ROUTER_ADVERTISEMENT	134
-#define ND6_NEIGHBOR_SOLICITATION	135
-#define ND6_NEIGHBOR_ADVERTISEMENT	136
-#define ND6_REDIRECT			137
+#define ND_ROUTER_SOLICIT           133
+#define ND_ROUTER_ADVERT            134
+#define ND_NEIGHBOR_SOLICIT         135
+#define ND_NEIGHBOR_ADVERT          136
+#define ND_REDIRECT                 137
 
-enum nd6_option
+struct nd_router_solicit      /* router solicitation */
   {
-    ND6_OPT_SOURCE_LINKADDR=1,
-    ND6_OPT_TARGET_LINKADDR=2,
-    ND6_OPT_PREFIX_INFORMATION=3,
-    ND6_OPT_REDIRECTED_HEADER=4,
-    ND6_OPT_MTU=5,
-    ND6_OPT_ENDOFLIST=256
+    struct icmp6_hdr  nd_rs_hdr;
+    /* could be followed by options */
   };
 
-struct nd6_router_solicit      /* router solicitation */
+#define nd_rs_type               nd_rs_hdr.icmp6_type
+#define nd_rs_code               nd_rs_hdr.icmp6_code
+#define nd_rs_cksum              nd_rs_hdr.icmp6_cksum
+#define nd_rs_reserved           nd_rs_hdr.icmp6_data32[0]
+
+struct nd_router_advert       /* router advertisement */
   {
-    struct icmpv6hdr		rsol_hdr;
+    struct icmp6_hdr  nd_ra_hdr;
+    uint32_t   nd_ra_reachable;   /* reachable time */
+    uint32_t   nd_ra_retransmit;  /* retransmit timer */
+    /* could be followed by options */
   };
 
-#define rsol_type		rsol_hdr.icmpv6_type
-#define rsol_code		rsol_hdr.icmpv6_code
-#define rsol_cksum		rsol_hdr.icmpv6_cksum
-#define rsol_reserved		rsol_hdr.icmpv6_data32[0]
+#define nd_ra_type               nd_ra_hdr.icmp6_type
+#define nd_ra_code               nd_ra_hdr.icmp6_code
+#define nd_ra_cksum              nd_ra_hdr.icmp6_cksum
+#define nd_ra_curhoplimit        nd_ra_hdr.icmp6_data8[0]
+#define nd_ra_flags_reserved     nd_ra_hdr.icmp6_data8[1]
+#define ND_RA_FLAG_MANAGED       0x80
+#define ND_RA_FLAG_OTHER         0x40
+#define nd_ra_router_lifetime    nd_ra_hdr.icmp6_data16[1]
 
-struct nd6_router_advert
+struct nd_neighbor_solicit    /* neighbor solicitation */
   {
-    struct icmpv6hdr	radv_hdr;
-    u_int32_t		radv_reachable;	 /* reachable time	*/
-    u_int32_t		radv_retransmit; /* reachable retransmit time */
+    struct icmp6_hdr  nd_ns_hdr;
+    struct in6_addr   nd_ns_target; /* target address */
+    /* could be followed by options */
   };
 
-#define radv_type		radv_hdr.icmpv6_type
-#define radv_code		radv_hdr.icmpv6_code
-#define radv_cksum		radv_hdr.icmpv6_cksum
-#define radv_maxhoplimit	radv_hdr.icmpv6_data8[0]
-#define radv_m_o_res		radv_hdr.icmpv6_data8[1]
-#define ND6_RADV_M_BIT		0x80
-#define ND6_RADV_O_BIT		0x40
-#define radv_router_lifetime	radv_hdr.icmpv6_data16[1]
+#define nd_ns_type               nd_ns_hdr.icmp6_type
+#define nd_ns_code               nd_ns_hdr.icmp6_code
+#define nd_ns_cksum              nd_ns_hdr.icmp6_cksum
+#define nd_ns_reserved           nd_ns_hdr.icmp6_data32[0]
 
-struct nd6_nsolicitation 	/* neighbor solicitation */
+struct nd_neighbor_advert     /* neighbor advertisement */
   {
-    struct icmpv6hdr	nsol6_hdr;
-    struct in6_addr	nsol6_target;
+    struct icmp6_hdr  nd_na_hdr;
+    struct in6_addr   nd_na_target; /* target address */
+    /* could be followed by options */
   };
 
-struct nd6_nadvertisement 	/* neighbor advertisement */
+#define nd_na_type               nd_na_hdr.icmp6_type
+#define nd_na_code               nd_na_hdr.icmp6_code
+#define nd_na_cksum              nd_na_hdr.icmp6_cksum
+#define nd_na_flags_reserved     nd_na_hdr.icmp6_data32[0]
+#if     BYTE_ORDER == BIG_ENDIAN
+#define ND_NA_FLAG_ROUTER        0x80000000
+#define ND_NA_FLAG_SOLICITED     0x40000000
+#define ND_NA_FLAG_OVERRIDE      0x20000000
+#else   /* BYTE_ORDER == LITTLE_ENDIAN */
+#define ND_NA_FLAG_ROUTER        0x00000080
+#define ND_NA_FLAG_SOLICITED     0x00000040
+#define ND_NA_FLAG_OVERRIDE      0x00000020
+#endif
+
+struct nd_redirect            /* redirect */
   {
-    struct icmpv6hdr	nadv6_hdr;
-    struct in6_addr	nadv6_target;
+    struct icmp6_hdr  nd_rd_hdr;
+    struct in6_addr   nd_rd_target; /* target address */
+    struct in6_addr   nd_rd_dst;    /* destination address */
+    /* could be followed by options */
   };
+ 
+#define nd_rd_type               nd_rd_hdr.icmp6_type
+#define nd_rd_code               nd_rd_hdr.icmp6_code
+#define nd_rd_cksum              nd_rd_hdr.icmp6_cksum
+#define nd_rd_reserved           nd_rd_hdr.icmp6_data32[0]
 
-#define nadv6_flags			nadv6_hdr.icmpv6_data32[0]
-#define ND6_NADVERFLAG_ISROUTER		0x80
-#define ND6_NADVERFLAG_SOLICITED	0x40
-#define ND6_NADVERFLAG_OVERRIDE		0x20
-
-struct nd6_redirect            /* redirect */
+struct nd_opt_hdr             /* Neighbor discovery option header */
   {
-    struct icmpv6hdr	redirect_hdr;
-    struct in6_addr	redirect_target;
-    struct in6_addr	redirect_destination;
+    uint8_t  nd_opt_type;
+    uint8_t  nd_opt_len;        /* in units of 8 octets */
+    /* followed by option specific data */
   };
 
-struct nd6_opt_prefix_info     /* prefix information */
+#define  ND_OPT_SOURCE_LINKADDR       1
+#define  ND_OPT_TARGET_LINKADDR       2
+#define  ND_OPT_PREFIX_INFORMATION    3
+#define  ND_OPT_REDIRECTED_HEADER     4
+#define  ND_OPT_MTU                   5
+
+struct nd_opt_prefix_info     /* prefix information */
   {
-    u_int8_t		opt_type;
-    u_int8_t		opt_length;
-    u_int8_t		opt_prefix_length;
-    u_int8_t		opt_l_a_res;
-    u_int32_t		opt_valid_life;
-    u_int32_t		opt_preferred_life;
-    u_int32_t		opt_reserved2;
-    struct in6_addr	opt_prefix;
+    uint8_t   nd_opt_pi_type;
+    uint8_t   nd_opt_pi_len;
+    uint8_t   nd_opt_pi_prefix_len;
+    uint8_t   nd_opt_pi_flags_reserved;
+    uint32_t  nd_opt_pi_valid_time;
+    uint32_t  nd_opt_pi_preferred_time;
+    uint32_t  nd_opt_pi_reserved2;
+    struct in6_addr  nd_opt_pi_prefix;
   };
 
-#define ND6_OPT_PI_L_BIT	0x80
-#define ND6_OPT_PI_A_BIT	0x40
+#define ND_OPT_PI_FLAG_ONLINK        0x80
+#define ND_OPT_PI_FLAG_AUTO          0x40
 
-struct nd6_opt_mtu 		/* MTU option */
+struct nd_opt_rd_hdr          /* redirected header */
   {
-    u_int8_t		opt_type;
-    u_int8_t		opt_length;
-    u_int16_t		opt_reserved;
-    u_int32_t		opt_mtu;
+    uint8_t   nd_opt_rh_type;
+    uint8_t   nd_opt_rh_len;
+    uint16_t  nd_opt_rh_reserved1;
+    uint32_t  nd_opt_rh_reserved2;
+    /* followed by IP header and data */
   };
 
+struct nd_opt_mtu             /* MTU option */
+  {
+    uint8_t   nd_opt_mtu_type;
+    uint8_t   nd_opt_mtu_len;
+    uint16_t  nd_opt_mtu_reserved;
+    uint32_t  nd_opt_mtu_mtu;
+  };
+
+
 #endif /* netinet/icmpv6.h */
diff --git a/inet/netinet/in.h b/inet/netinet/in.h
index d2a366b51c..9eda281360 100644
--- a/inet/netinet/in.h
+++ b/inet/netinet/in.h
@@ -20,6 +20,7 @@
 #define	_NETINET_IN_H	1
 
 #include <features.h>
+#include <inttypes.h>
 
 #include <sys/socket.h>
 #include <sys/types.h>
@@ -30,19 +31,25 @@ __BEGIN_DECLS
 /* Standard well-defined IP protocols.  */
 enum
   {
-    IPPROTO_IP = 0,	 /* Dummy protocol for TCP.  */
-    IPPROTO_ICMP = 1,	 /* Internet Control Message Protocol.  */
-    IPPROTO_IGMP = 2,	 /* Internet Group Management Protocol. */
-    IPPROTO_IPIP = 4,	 /* IPIP tunnels (older KA9Q tunnels use 94).  */
-    IPPROTO_TCP = 6,	 /* Transmission Control Protocol.  */
-    IPPROTO_EGP = 8,	 /* Exterior Gateway Protocol.  */
-    IPPROTO_PUP = 12,	 /* PUP protocol.  */
-    IPPROTO_UDP = 17,	 /* User Datagram Protocol.  */
-    IPPROTO_IDP = 22,	 /* XNS IDP protocol.  */
-    IPPROTO_IPV6 = 41,   /* IPv6-in-IPv4 tunnelling.  */
-    IPPROTO_ICMPV6 = 58, /* ICMPv6.  */
-
-    IPPROTO_RAW = 255,	 /* Raw IP packets.  */
+    IPPROTO_IP = 0,	   /* Dummy protocol for TCP.  */
+    IPPROTO_HOPOPTS = 0,   /* IPv6 Hop-by-Hop options.  */
+    IPPROTO_ICMP = 1,	   /* Internet Control Message Protocol.  */
+    IPPROTO_IGMP = 2,	   /* Internet Group Management Protocol. */
+    IPPROTO_IPIP = 4,	   /* IPIP tunnels (older KA9Q tunnels use 94).  */
+    IPPROTO_TCP = 6,	   /* Transmission Control Protocol.  */
+    IPPROTO_EGP = 8,	   /* Exterior Gateway Protocol.  */
+    IPPROTO_PUP = 12,	   /* PUP protocol.  */
+    IPPROTO_UDP = 17,	   /* User Datagram Protocol.  */
+    IPPROTO_IDP = 22,	   /* XNS IDP protocol.  */
+    IPPROTO_IPV6 = 41,     /* IPv6 header.  */
+    IPPROTO_ROUTING = 43,  /* IPv6 routing header.  */
+    IPPROTO_FRAGMENT = 44, /* IPv6 fragmentation header.  */
+    IPPROTO_ESP = 50,      /* encapsulating security payload.  */
+    IPPROTO_AH = 51,       /* authentication header.  */
+    IPPROTO_ICMPV6 = 58,   /* ICMPv6.  */
+    IPPROTO_NONE = 59,     /* IPv6 no next header.  */
+    IPPROTO_DSTOPTS = 60,  /* IPv6 destination options.  */
+    IPPROTO_RAW = 255,	   /* Raw IP packets.  */
     IPPROTO_MAX
   };
 
@@ -90,7 +97,7 @@ enum
 /* Internet address.  */
 struct in_addr
   {
-    u_int32_t s_addr;
+    uint32_t s_addr;
   };
 
 
@@ -142,11 +149,11 @@ struct in6_addr
   {
     union
       {
-	u_int8_t	u6_addr8[16];
-	u_int16_t	u6_addr16[8];
-	u_int32_t	u6_addr32[4];
+	uint8_t		u6_addr8[16];
+	uint16_t	u6_addr16[8];
+	uint32_t	u6_addr32[4];
 #if (~0UL) > 0xffffffff
-	u_int64_t	u6_addr64[2];
+	uint64_t	u6_addr64[2];
 #endif
       } in6_u;
 #define s6_addr			in6_u.u6_addr8
@@ -171,13 +178,13 @@ extern const struct in6_addr in6addr_loopback;   /* ::1 */
 struct sockaddr_in
   {
     __SOCKADDR_COMMON (sin_);
-    unsigned short int sin_port;	/* Port number.  */
+    uint16_t sin_port;			/* Port number.  */
     struct in_addr sin_addr;		/* Internet address.  */
 
     /* Pad to size of `struct sockaddr'.  */
     unsigned char sin_zero[sizeof (struct sockaddr) -
 			   __SOCKADDR_COMMON_SIZE -
-			   sizeof (unsigned short int) -
+			   sizeof (uint16_t) -
 			   sizeof (struct in_addr)];
   };
 
@@ -185,8 +192,8 @@ struct sockaddr_in
 struct sockaddr_in6
   {
     __SOCKADDR_COMMON (sin6_);
-    u_int16_t sin6_port;	/* Transport layer port # */
-    u_int32_t sin6_flowinfo;	/* IPv6 flow information */
+    uint16_t sin6_port;		/* Transport layer port # */
+    uint32_t sin6_flowinfo;	/* IPv6 flow information */
     struct in6_addr sin6_addr;	/* IPv6 address */
   };
 
@@ -196,8 +203,8 @@ struct ipv6_mreq
     /* IPv6 multicast address of group */
     struct in6_addr ipv6mr_multiaddr;
 
-    /* local IPv6 address of interface */
-    int ipv6mr_ifindex;
+    /* local interface */
+    unsigned int ipv6mr_ifindex;
   };
 
 /* Get system-specific definitions.  */
@@ -210,10 +217,10 @@ struct ipv6_mreq
    this was a short-sighted decision since on different systems the types
    may have different representations but the values are always the same.  */
 
-extern u_int32_t ntohl __P ((u_int32_t __netlong));
-extern u_int16_t ntohs __P ((u_int16_t __netshort));
-extern u_int32_t htonl __P ((u_int32_t __hostlong));
-extern u_int16_t htons __P ((u_int16_t __hostshort));
+extern uint32_t ntohl __P ((uint32_t __netlong));
+extern uint16_t ntohs __P ((uint16_t __netshort));
+extern uint32_t htonl __P ((uint32_t __hostlong));
+extern uint16_t htons __P ((uint16_t __hostshort));
 
 #include <endian.h>
 
@@ -237,30 +244,35 @@ extern u_int16_t htons __P ((u_int16_t __hostshort));
 #endif
 
 #define IN6_IS_ADDR_UNSPECIFIED(a) \
-	((((u_int32_t *) (a))[0] == 0) && ((u_int32_t *) (a))[1] == 0) && \
-	 (((u_int32_t *) (a))[2] == 0) && ((u_int32_t *) (a))[3] == 0))
+	((((uint32_t *) (a))[0] == 0) && ((uint32_t *) (a))[1] == 0) && \
+	 (((uint32_t *) (a))[2] == 0) && ((uint32_t *) (a))[3] == 0))
 
 #define IN6_IS_ADDR_LOOPBACK(a) \
-	((((u_int32_t *) (a))[0] == 0) && ((u_int32_t *) (a))[1] == 0) && \
-	 (((u_int32_t *) (a))[2] == 0) && ((u_int32_t *) (a))[3] == htonl (1)))
+	((((uint32_t *) (a))[0] == 0) && ((uint32_t *) (a))[1] == 0) && \
+	 (((uint32_t *) (a))[2] == 0) && ((uint32_t *) (a))[3] == htonl (1)))
 
 #define IN6_IS_ADDR_MULTICAST(a) (((u_int8_t *) (a))[0] == 0xff)
 
 #define IN6_IS_ADDR_LINKLOCAL(a) \
-	((((u_int32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfe800000))
+	((((uint32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfe800000))
 
 #define IN6_IS_ADDR_SITELOCAL(a) \
-	((((u_int32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfec00000))
+	((((uint32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfec00000))
 
 #define IN6_IS_ADDR_V4MAPPED(a) \
-	((((u_int32_t *) (a))[0] == 0) && (((u_int32_t *) (a))[1] == 0) && \
-	 (((u_int32_t *) (a))[2] == htonl (0xffff)))
+	((((uint32_t *) (a))[0] == 0) && (((uint32_t *) (a))[1] == 0) && \
+	 (((uint32_t *) (a))[2] == htonl (0xffff)))
 
 #define IN6_IS_ADDR_V4COMPAT(a) \
-	((((u_int32_t *) (a))[0] == 0) && (((u_int32_t *) (a))[1] == 0) && \
-	 (((u_int32_t *) (a))[2] == 0) && (ntohl (((u_int32_t *) (a))[3]) > 1))
-
-
+	((((uint32_t *) (a))[0] == 0) && (((uint32_t *) (a))[1] == 0) && \
+	 (((uint32_t *) (a))[2] == 0) && (ntohl (((uint32_t *) (a))[3]) > 1))
+
+#define IN6_ARE_ADDR_EQUAL(a,b) \
+	((((uint32_t *) (a))[0] == ((uint32_t *) (b))[0]) && \
+	 (((uint32_t *) (a))[1] == ((uint32_t *) (b))[2]) && \
+	 (((uint32_t *) (a))[2] == ((uint32_t *) (b))[1]) && \
+	 (((uint32_t *) (a))[3] == ((uint32_t *) (b))[3]))
+	
 /* Bind socket to a privileged IP port.  */
 extern int bindresvport __P ((int __sockfd, struct sockaddr_in *__sin));
 
@@ -268,8 +280,8 @@ extern int bindresvport __P ((int __sockfd, struct sockaddr_in *__sin));
 /* IPv6 packet information.  */
 struct in6_pktinfo
   {
-    struct in6_addr ipi6_addr;    /* src/dst IPv6 address */
-    int             ipi6_ifindex; /* send/recv interface index */
+    struct in6_addr	ipi6_addr;    /* src/dst IPv6 address */
+    unsigned int	ipi6_ifindex; /* send/recv interface index */
   };
 
 __END_DECLS
diff --git a/inet/netinet/ip6.h b/inet/netinet/ip6.h
index 2930578e4f..cd42ef64b9 100644
--- a/inet/netinet/ip6.h
+++ b/inet/netinet/ip6.h
@@ -19,27 +19,88 @@
 #ifndef _NETINET_IP6_H
 #define _NETINET_IP6_H 1
 
+#include <inttypes.h>
 #include <netinet/in.h>
-#include <endian.h>
-
-struct ipv6hdr
-{
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-  u_int8_t ipv6_version:4;
-  u_int8_t ipv6_priority:4; /* going away? */
-  u_int32_t ipv6_flowid:24;
-#elif __BYTE_ORDER == __BIG_ENDIAN
-  u_int32_t ipv6_flowid:24;
-  u_int8_t ipv6_priority:4; /* going away? */
-  u_int8_t ipv6_version:4;
-#else
-# error  Unknown endianness
+
+struct ip6_hdr 
+  {
+    union 
+      {
+	struct ip6_hdrctl 
+	  {
+	    uint32_t ip6_un1_flow;   /* 24 bits of flow-ID */
+	    uint16_t ip6_un1_plen;   /* payload length */
+	    uint8_t  ip6_un1_nxt;    /* next header */
+	    uint8_t  ip6_un1_hlim;   /* hop limit */
+	  } ip6_un1;
+	uint8_t ip6_un2_vfc;       /* 4 bits version, 4 bits priority */
+      } ip6_ctlun;
+    struct in6_addr ip6_src;      /* source address */
+    struct in6_addr ip6_dst;      /* destination address */
+  };
+
+#define ip6_vfc   ip6_ctlun.ip6_un2_vfc
+#define ip6_flow  ip6_ctlun.ip6_un1.ip6_un1_flow
+#define ip6_plen  ip6_ctlun.ip6_un1.ip6_un1_plen
+#define ip6_nxt   ip6_ctlun.ip6_un1.ip6_un1_nxt
+#define ip6_hlim  ip6_ctlun.ip6_un1.ip6_un1_hlim
+#define ip6_hops  ip6_ctlun.ip6_un1.ip6_un1_hlim
+
+/* Hop-by-Hop options header.  */
+struct ip6_hbh 
+  {
+    uint8_t  ip6h_nxt;        /* next hesder.  */
+    uint8_t  ip6h_len;        /* length in units of 8 octets.  */
+    /* followed by options */
+  };
+
+/* Destination options header */
+struct ip6_dest 
+  {
+    uint8_t  ip6d_nxt;        /* next header */
+    uint8_t  ip6d_len;        /* length in units of 8 octets */
+    /* followed by options */
+  };
+
+/* Routing header */
+struct ip6_rthdr 
+  {
+    uint8_t  ip6r_nxt;        /* next header */
+    uint8_t  ip6r_len;        /* length in units of 8 octets */
+    uint8_t  ip6r_type;       /* routing type */
+    uint8_t  ip6r_segleft;    /* segments left */
+    /* followed by routing type specific data */
+  };
+
+/* Type 0 Routing header */
+struct ip6_rthdr0 
+  {
+    uint8_t  ip6r0_nxt;       /* next header */
+    uint8_t  ip6r0_len;       /* length in units of 8 octets */
+    uint8_t  ip6r0_type;      /* always zero */
+    uint8_t  ip6r0_segleft;   /* segments left */
+    uint8_t  ip6r0_reserved;  /* reserved field */
+    uint8_t  ip6r0_slmap[3];  /* strict/loose bit map */
+    struct in6_addr  ip6r0_addr[1];  /* up to 23 addresses */
+  };
+
+/* Fragment header */
+struct ip6_frag 
+  {
+    uint8_t   ip6f_nxt;       /* next header */
+    uint8_t   ip6f_reserved;  /* reserved field */
+    uint16_t  ip6f_offlg;     /* offset, reserved, and flag */
+    uint32_t  ip6f_ident;     /* identification */
+  };
+
+#if     BYTE_ORDER == BIG_ENDIAN
+#define IP6F_OFF_MASK       0xfff8  /* mask out offset from _offlg */
+#define IP6F_RESERVED_MASK  0x0006  /* reserved bits in ip6f_offlg */
+#define IP6F_MORE_FRAG      0x0001  /* more-fragments flag */
+#else   /* BYTE_ORDER == LITTLE_ENDIAN */
+#define IP6F_OFF_MASK       0xf8ff  /* mask out offset from _offlg */
+#define IP6F_RESERVED_MASK  0x0600  /* reserved bits in ip6f_offlg */
+#define IP6F_MORE_FRAG      0x0100  /* more-fragments flag */
 #endif
-  u_int16_t ipv6_len;
-  u_int8_t ipv6_nextheader;
-  u_int8_t ipv6_hoplimit;
-  struct in6_addr ipv6_src;
-  struct in6_addr ipv6_dst;
-};
 
 #endif /* netinet/ip6.h */
diff --git a/libc.map b/libc.map
index b23a8ff5d3..c9949448b8 100644
--- a/libc.map
+++ b/libc.map
@@ -7,7 +7,7 @@ GLIBC_2.0 {
     _nl_msg_cat_cntr; __environ; _environ; _res;
     ___brk_addr; __curbrk; _nl_current_LC_CTYPE; _libc_intl_domainname;
     _sys_errlist; _sys_siglist; __progname; _nl_default_dirname;
-    __timezone; __daylight;
+    __timezone; __daylight; __tzname;
     _nl_current_LC_COLLATE; __collate_element_hash;
     __collate_element_strings; __collate_symbol_classes;
     __collate_symbol_hash; __collate_symbol_strings;
diff --git a/manual/libc.texinfo b/manual/libc.texinfo
index 7d81247cdb..2d79d960af 100644
--- a/manual/libc.texinfo
+++ b/manual/libc.texinfo
@@ -514,7 +514,7 @@ Socket Addresses
 
 Internet Domain
 
-* Internet Address Format::     How socket addresses are specified in the
+* Internet Address Formats::    How socket addresses are specified in the
                                  Internet namespace.
 * Host Addresses::              All about host addresses of Internet hosts.
 * Protocols Database::          Referring to protocols by name.
diff --git a/manual/socket.texi b/manual/socket.texi
index c122106e2b..6efc54d1a5 100644
--- a/manual/socket.texi
+++ b/manual/socket.texi
@@ -323,7 +323,13 @@ This is a synonym for @code{AF_FILE}, for compatibility.
 @vindex AF_INET
 This designates the address format that goes with the Internet
 namespace.  (@code{PF_INET} is the name of that namespace.)
-@xref{Internet Address Format}.
+@xref{Internet Address Formats}.
+
+@comment sys/socket.h
+@comment IPv6 Basic API
+@item AF_INET6
+This is similar to @code{AF_INET}, but refers to the IPv6 protocol.
+(@code{PF_INET6} is the name of the corresponding namespace.)
 
 @comment sys/socket.h
 @comment BSD
@@ -566,7 +572,7 @@ A socket address for the Internet namespace includes the following components:
 @item
 The address of the machine you want to connect to.  Internet addresses
 can be specified in several ways; these are discussed in @ref{Internet
-Address Format}, @ref{Host Addresses}, and @ref{Host Names}.
+Address Formats}, @ref{Host Addresses}, and @ref{Host Names}.
 
 @item
 A port number for that machine.  @xref{Ports}.
@@ -577,7 +583,7 @@ canonical format called @dfn{network byte order}.  @xref{Byte Order},
 for information about this.
 
 @menu
-* Internet Address Format::     How socket addresses are specified in the
+* Internet Address Formats::    How socket addresses are specified in the
                                  Internet namespace.
 * Host Addresses::	        All about host addresses of internet host.
 * Protocols Database::		Referring to protocols by name.
@@ -589,16 +595,17 @@ for information about this.
 * Inet Example::	        Putting it all together.
 @end menu
 
-@node Internet Address Format
-@subsection Internet Socket Address Format
+@node Internet Address Formats
+@subsection Internet Socket Address Formats
 
-In the Internet namespace, a socket address consists of a host address
+In the Internet namespace, for both IPv4 (@code{AF_INET}) and IPv6
+(@code{AF_INET6}), a socket address consists of a host address
 and a port on that host.  In addition, the protocol you choose serves
 effectively as a part of the address because local port numbers are
 meaningful only within a particular protocol.
 
-The data type for representing socket addresses in the Internet namespace
-is defined in the header file @file{netinet/in.h}.
+The data types for representing socket addresses in the Internet namespace
+are defined in the header file @file{netinet/in.h}.
 @pindex netinet/in.h
 
 @comment netinet/in.h
@@ -627,13 +634,39 @@ When you call @code{bind} or @code{getsockname}, you should specify
 @code{sizeof (struct sockaddr_in)} as the @var{length} parameter if
 you are using an Internet namespace socket address.
 
+@deftp {Data Type} {struct sockaddr_in6}
+This is the data type used to represent socket addresses in the IPv6
+namespace.  It has the following members:
+
+@table @code
+@item short int sin6_family
+This identifies the address family or format of the socket address.
+You should store the value of @code{AF_INET6} in this member.
+@xref{Socket Addresses}.
+
+@item struct in6_addr sin6_addr
+This is the IPv6 address of the host machine.  @xref{Host
+Addresses}, and @ref{Host Names}, for how to get a value to store
+here.
+
+@item uint32_t sin6_flowinfo
+This is a currently unimplemented field.
+
+@item uint16_t sin6_port
+This is the port number.  @xref{Ports}.
+
+@end table
+@end deftp
+
 @node Host Addresses
 @subsection Host Addresses
 
 Each computer on the Internet has one or more @dfn{Internet addresses},
 numbers which identify that computer among all those on the Internet.
-Users typically write numeric host addresses as sequences of four
-numbers, separated by periods, as in @samp{128.52.46.32}.
+Users typically write IPv4 numeric host addresses as sequences of four
+numbers, separated by periods, as in @samp{128.52.46.32}, and IPv6
+numeric host addresses as sequences of up to eight numbers seperated by
+colons, as in @samp{5f03:1200:836f:c100::1}.
 
 Each computer also has one or more @dfn{host names}, which are strings
 of words separated by periods, as in @samp{churchy.gnu.ai.mit.edu}.
@@ -660,6 +693,9 @@ Each computer on the Internet has one or more Internet addresses,
 numbers which identify that computer among all those on the Internet.
 @end ifinfo
 
+@c I think this whole section could possibly be removed.  It is slightly
+@c misleading these days.
+
 @cindex network number
 @cindex local network address number
 An Internet host address is a number containing four bytes of data.
@@ -779,6 +815,31 @@ This constant is the address you use to send a broadcast message.
 This constant is returned by some functions to indicate an error.
 @end deftypevr
 
+@comment netinet/in.h
+@comment IPv6 basic API
+@deftp {Data Type} {struct in6_addr}
+This data type is used to store an IPv6 address.  It stores 128 bits of
+data, which can be accessed (via a union) in a variety of ways.
+@end deftp
+
+@comment netinet/in.h
+@comment IPv6 basic API
+@deftypevr Constant {struct in6_addr} in6addr_loopback.
+This constant is the IPv6 address @samp{::1}, the loopback address.  See
+above for a description of what this means.  The macro
+@code{IN6ADDR_LOOPBACK_INIT} is provided to allow you to initialise your
+own variables to this value.
+@end deftypevr
+
+@comment netinet/in.h
+@comment IPv6 basic API
+@deftypevr Constant {struct in6_addr} in6addr_any
+This constant is the IPv6 address @samp{::}, the unspecified address.  See
+above for a description of what this means.  The macro
+@code{IN6ADDR_ANY_INIT} is provided to allow you to initialise your
+own variables to this value.
+@end deftypevr
+
 @node Host Address Functions
 @subsubsection Host Address Functions
 
@@ -854,6 +915,30 @@ This function returns the network number part of the Internet host
 address @var{addr}.
 @end deftypefun
 
+@comment arpa/inet.h
+@comment IPv6 basic API
+@deftypefun int inet_pton (int @var{af}, const char *@var{cp}, void
+*@var{buf})
+This function converts an Internet address (either IPv4 or IPv6) from
+presentation (textual) to network (binary) format.  @var{af} should be
+either @code{AF_INET} or @code{AF_INET6}, as appropriate for the type of
+address being converted.  @var{cp} is a pointer to the input string, and
+@var{buf} is a pointer to a buffer for the result.  It is the caller's
+responsibility to make sure the buffer is large enough.
+@end deftypefun
+
+@comment arpa/inet.h
+@comment IPv6 basic API
+@deftypefun char *inet_ntop(int @var{af}, const void *@var{cp}, char
+*@var{buf}, size_t @var{len})
+This function converts an Internet address (either IPv4 or IPv6) from
+network (binary) to presentation (textual) form.  @var{af} should be
+either @code{AF_INET} or @code{AF_INET6}, as appropriate.  @var{cp} is a
+pointer to the address to be converted.  @var{buf} should be a pointer
+to a buffer to hold the result, and @var{len} is the length of this
+buffer.  The return value from the function will be this buffer address.
+@end deftypefun
+
 @node Host Names
 @subsubsection Host Names
 @cindex hosts database
@@ -891,11 +976,12 @@ These are alternative names for the host, represented as a null-terminated
 vector of strings.
 
 @item int h_addrtype
-This is the host address type; in practice, its value is always
-@code{AF_INET}.  In principle other kinds of addresses could be
-represented in the data base as well as Internet addresses; if this were
-done, you might find a value in this field other than @code{AF_INET}.
-@xref{Socket Addresses}.
+This is the host address type; in practice, its value is always either
+@code{AF_INET} or @code{AF_INET6}, with the latter being used for IPv6
+hosts.  In principle other kinds of addresses could be represented in
+the data base as well as Internet addresses; if this were done, you
+might find a value in this field other than @code{AF_INET} or
+@code{AF_INET6}.  @xref{Socket Addresses}.
 
 @item int h_length
 This is the length, in bytes, of each address.
@@ -917,10 +1003,12 @@ implicit assumption that you can convert this to a @code{struct in_addr} or
 an @code{unsigned long int}.  Host addresses in a @code{struct hostent}
 structure are always given in network byte order; see @ref{Byte Order}.
 
-You can use @code{gethostbyname} or @code{gethostbyaddr} to search the
-hosts database for information about a particular host.  The information
-is returned in a statically-allocated structure; you must copy the
-information if you need to save it across calls.
+You can use @code{gethostbyname}, @code{gethostbyname2} or
+@code{gethostbyaddr} to search the hosts database for information about
+a particular host.  The information is returned in a
+statically-allocated structure; you must copy the information if you
+need to save it across calls.  You can also use @code{getaddrinfo} and
+@code{getnameinfo} to obtain this information.
 
 @comment netdb.h
 @comment BSD
@@ -930,6 +1018,14 @@ named @var{name}.  If the lookup fails, it returns a null pointer.
 @end deftypefun
 
 @comment netdb.h
+@comment IPv6 Basic API
+@deftypefun {struct hostent *} gethostbyname2 (const char *@var{name}, int @var{af})
+The @code{gethostbyname2} function is like @code{gethostbyname}, but
+allows the caller to specify the desired address family (e.g.@:
+@code{AF_INET} or @code{AF_INET6}) for the result.
+@end deftypefun
+
+@comment netdb.h
 @comment BSD
 @deftypefun {struct hostent *} gethostbyaddr (const char *@var{addr}, int @var{length}, int @var{format})
 The @code{gethostbyaddr} function returns information about the host
diff --git a/manual/texinfo.tex b/manual/texinfo.tex
index fd306fa290..813d3c2bb7 100644
--- a/manual/texinfo.tex
+++ b/manual/texinfo.tex
@@ -1,5 +1,5 @@
 %% TeX macros to handle Texinfo files.
-%% $Id: texinfo.tex,v 2.210 1997/07/15 19:22:46 drepper Exp $
+%% $Id: texinfo.tex,v 2.211 1997/07/28 21:55:24 drepper Exp $
 
 %  Copyright (C) 1985, 86, 88, 90, 91, 92, 93,
 %                94, 95, 96, 97 Free Software Foundation, Inc.
@@ -36,7 +36,7 @@
 
 % This automatically updates the version number based on RCS.
 \def\deftexinfoversion$#1: #2 ${\def\texinfoversion{#2}}
-\deftexinfoversion$Revision: 2.210 $
+\deftexinfoversion$Revision: 2.211 $
 \message{Loading texinfo package [Version \texinfoversion]:}
 
 % If in a .fmt file, print the version number
@@ -1406,14 +1406,12 @@ where each line of input produces a line of output.}
 \else{\tclose{\kbdfont\look}}\fi
 \else{\tclose{\kbdfont\look}}\fi}
 
-% @url, @email.  Quotes do not seem necessary.
-\let\url=\code % perhaps include a hypertex \special eventually
-% rms does not like the angle brackets --karl, 17may97.
-%\def\email#1{$\langle${\tt #1}$\rangle$}
-\let\email=\code
+% @url.  Quotes do not seem necessary, so use \code.
+\let\url=\code
 
 % @uref (abbreviation for `urlref') takes an optional second argument
 % specifying the text to display.  First (mandatory) arg is the url.
+% Perhaps eventually put in a hypertex \special here.
 %
 \def\uref#1{\urefxxx #1,,\finish}
 \def\urefxxx#1,#2,#3\finish{%
@@ -1425,6 +1423,11 @@ where each line of input produces a line of output.}
   \fi
 }
 
+% rms does not like the angle brackets --karl, 17may97.
+% So now @email is just like @uref.
+%\def\email#1{$\langle${\tt #1}$\rangle$}
+\let\email=\uref
+
 % Check if we are currently using a typewriter font.  Since all the
 % Computer Modern typewriter fonts have zero interword stretch (and
 % shrink), and it is reasonable to expect all typewriter fonts to have
diff --git a/nis/Makefile b/nis/Makefile
index c10c175e7d..e7dd50c1d9 100644
--- a/nis/Makefile
+++ b/nis/Makefile
@@ -50,7 +50,8 @@ libnsl-routines = yp_xdr ypclnt ypupdate_xdr \
 		  nis_verifygroup nis_ismember nis_addmember nis_util\
 		  nis_removemember nis_creategroup nis_destroygroup\
 		  nis_print_group_entry nis_domain_of nis_domain_of_r\
-		  nis_modify nis_remove nis_add nis_defaults lckcache
+		  nis_modify nis_remove nis_add nis_defaults lckcache\
+		  nis_findserv
 libnsl-map	= libnsl.map
 
 libnss_compat-routines	:= $(addprefix compat-,grp pwd spwd) nisplus-parser
diff --git a/nis/TODO b/nis/TODO
index 0fe695d78b..f34bc09a06 100644
--- a/nis/TODO
+++ b/nis/TODO
@@ -9,4 +9,3 @@
  * Missing flags:
 	- FOLLOW_PATH	(nis_list, not supported)
 	- ALL_RESULTS	(nis_list, not supported, needs server callback)
-	- NO_CACHE	(__do_niscall, cache not supported yet)
diff --git a/nis/lckcache.c b/nis/lckcache.c
index ead577372e..f8c0a97296 100644
--- a/nis/lckcache.c
+++ b/nis/lckcache.c
@@ -1,6 +1,6 @@
 /* Handle locking of NIS+ cache file.
-   Copyright (C) 1996 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
+   Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library and based on shadow/lckfile.c.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public License as
@@ -30,7 +30,7 @@
 
 /* How long to wait for getting the lock before returning with an
    error.  */
-#define TIMEOUT 15 /* sec */
+#define TIMEOUT 5 /* sec */
 
 
 /* File descriptor for lock file.  */
@@ -141,7 +141,7 @@ __nis_lock_cache (void)
   memset (&fl, '\0', sizeof (struct flock));
   fl.l_type = F_RDLCK;
   fl.l_whence = SEEK_SET;
-  result = fcntl (lock_fd, F_SETLK, &fl);
+  result = fcntl (lock_fd, F_SETLKW, &fl);
 
   RETURN_CLEAR_ALARM (result);
 }
diff --git a/nis/nis_call.c b/nis/nis_call.c
index f25b8017a5..1dfb12944a 100644
--- a/nis/nis_call.c
+++ b/nis/nis_call.c
@@ -29,30 +29,7 @@
 
 static struct timeval TIMEOUT = {10, 0};
 
-struct dir_binding
-{
-  CLIENT *clnt;                  /* RPC CLIENT handle */
-  nis_server *server_val;        /* List of servers */
-  u_int server_len;              /* # of servers */
-  u_int server_used;             /* Which server we are bind in the moment ? */
-  u_int trys;                    /* How many server have we tried ? */
-  bool_t master_only;            /* Is only binded to the master */
-  bool_t use_auth;               /* Do we use AUTH ? */
-  bool_t use_udp;                /* Do we use UDP ? */
-  time_t create;                 /* Binding creation time */
-  struct sockaddr_in addr;       /* Server's IP address */
-  int socket;                    /* Server's local socket */
-  unsigned short port;           /* Local port */
-};
-typedef struct dir_binding dir_binding;
-
-static inline u_int
-__nis_ping (const nis_server *serv, u_int serv_len)
-{
-  return 0;
-}
-
-static unsigned long
+unsigned long
 inetstr2int (const char *str)
 {
   char buffer[strlen (str) + 3];
@@ -92,12 +69,7 @@ __bind_destroy (dir_binding *bind)
 static nis_error
 __bind_next (dir_binding *bind)
 {
-  if (bind->trys >= bind->server_len)
-    return NIS_FAIL;
-  
-  bind->server_used++;
-  if (bind->server_used >= bind->server_len)
-    bind->server_used = 0;
+  u_int j;
 
   if (bind->clnt != NULL)
     {
@@ -106,8 +78,38 @@ __bind_next (dir_binding *bind)
       clnt_destroy (bind->clnt);
       bind->clnt = NULL;
     }
-  
-  return NIS_SUCCESS;
+
+  if (bind->trys >= bind->server_len)
+    return NIS_FAIL;
+
+  for (j = bind->current_ep + 1;
+       j < bind->server_val[bind->server_used].ep.ep_len; ++j)
+    if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].family,
+		"inet") == 0)
+      if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].proto,
+		  "-") == 0)
+	{
+	  bind->current_ep = j;
+	  return NIS_SUCCESS;
+	}
+
+  ++bind->trys;
+  ++bind->server_used;
+  if (bind->server_used >= bind->server_len)
+    bind->server_used = 0;
+
+  for (j = bind->current_ep + 1;
+       j < bind->server_val[bind->server_used].ep.ep_len; ++j)
+    if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].family,
+		"inet") == 0)
+      if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].proto,
+		  "-") == 0)
+	{
+	  bind->current_ep = j;
+	  return NIS_SUCCESS;
+	}
+
+  return NIS_FAIL;
 }
 
 static nis_error
@@ -116,7 +118,6 @@ __bind_connect (dir_binding *dbp)
   struct sockaddr_in check;
   nis_server *serv;
   int checklen;
-  u_int i;
 
   if (dbp == NULL)
     return NIS_FAIL;
@@ -125,26 +126,10 @@ __bind_connect (dir_binding *dbp)
 
   memset (&dbp->addr, '\0', sizeof (dbp->addr));
   dbp->addr.sin_family = AF_INET;
-  for (i = 0; i < serv->ep.ep_len; ++i)
-    {
-      if (strcmp (serv->ep.ep_val[i].family, "inet") == 0)
-	{
-	  if (dbp->use_udp)
-	    {
-	      if (strcmp (serv->ep.ep_val[i].proto, "udp") == 0)
-		dbp->addr.sin_addr.s_addr =
-		  inetstr2int (serv->ep.ep_val[i].uaddr);
-	      else
-		continue;
-	    }
-	  else
-	    if (strcmp (serv->ep.ep_val[i].proto, "tcp") == 0)
-	      dbp->addr.sin_addr.s_addr =
-		inetstr2int (serv->ep.ep_val[i].uaddr);
-	}
-      else
-	continue;
-    }
+
+  dbp->addr.sin_addr.s_addr =
+    inetstr2int (serv->ep.ep_val[dbp->current_ep].uaddr);
+
   if (dbp->addr.sin_addr.s_addr == 0)
     return NIS_FAIL;
 
@@ -155,15 +140,15 @@ __bind_connect (dir_binding *dbp)
   else
     dbp->clnt = clnttcp_create (&dbp->addr, NIS_PROG, NIS_VERSION,
 				 &dbp->socket, 0, 0);
-  
+
   if (dbp->clnt == NULL)
     return NIS_RPCERROR;
-  
+
   clnt_control (dbp->clnt, CLSET_TIMEOUT, (caddr_t)&TIMEOUT);
   /* If the program exists, close the socket */
   if (fcntl (dbp->socket, F_SETFD, 1) == -1)
     perror (_("fcntl: F_SETFD"));
-  
+
   if (dbp->use_auth)
     {
 #if defined(HAVE_SECURE_RPC)
@@ -171,7 +156,7 @@ __bind_connect (dir_binding *dbp)
 	{
 	  char netname[MAXNETNAMELEN+1];
 	  char *p;
-	  
+
 	  p = stpcpy (netname, "unix.");
 	  strncpy (p, serv->name,MAXNETNAMELEN-5);
 	  netname[MAXNETNAMELEN] = '\0';
@@ -187,7 +172,7 @@ __bind_connect (dir_binding *dbp)
 	dbp->clnt->cl_auth = authunix_create_default ();
       dbp->use_auth = TRUE;
     }
-  
+
   /* Get port for sanity checks later */
   checklen = sizeof (struct sockaddr_in);
   memset (&check, 0, checklen);
@@ -207,11 +192,11 @@ __bind_create (const nis_server *serv_val, u_int serv_len, u_long flags)
 {
   dir_binding *dbp;
   u_int i;
-  
+
   dbp = calloc (1, sizeof (dir_binding));
   if (dbp == NULL)
     return NULL;
-  
+
   dbp->server_len = serv_len;
   dbp->server_val = calloc (1, sizeof (nis_server) * serv_len);
   if (dbp->server_val == NULL)
@@ -219,17 +204,34 @@ __bind_create (const nis_server *serv_val, u_int serv_len, u_long flags)
       free (dbp);
       return NULL;
     }
-  
+
+  if (flags & USE_DGRAM)
+    dbp->use_udp = TRUE;
+  else
+    dbp->use_udp = FALSE;
+
+  if (flags & NO_AUTHINFO)
+    dbp->use_auth = FALSE;
+  else
+    dbp->use_auth = TRUE;
+
+  if (flags & MASTER_ONLY)
+    dbp->master_only = TRUE;
+  else
+    dbp->master_only = FALSE;
+
+  dbp->trys = 1;
+
   for (i = 0; i < serv_len; ++i)
     {
       if (serv_val[i].name != NULL)
 	dbp->server_val[i].name = strdup (serv_val[i].name);
-      
+
       dbp->server_val[i].ep.ep_len = serv_val[i].ep.ep_len;
       if (dbp->server_val[i].ep.ep_len > 0)
 	{
 	  unsigned long j;
-	  
+
 	  dbp->server_val[i].ep.ep_val =
 	    malloc (serv_val[i].ep.ep_len * sizeof (endpoint));
 	  for (j = 0; j < dbp->server_val[i].ep.ep_len; ++j)
@@ -267,24 +269,12 @@ __bind_create (const nis_server *serv_val, u_int serv_len, u_long flags)
       else
 	dbp->server_val[i].pkey.n_bytes = NULL;
     }
-  
-  dbp->server_used = __nis_ping (dbp->server_val, dbp->server_len);
-  if (flags & USE_DGRAM)
-    dbp->use_udp = TRUE;
-  else
-    dbp->use_udp = FALSE;
-
-  if (flags & NO_AUTHINFO)
-    dbp->use_auth = FALSE;
-  else
-    dbp->use_auth = TRUE;
 
-  if (flags & MASTER_ONLY)
-    dbp->master_only = TRUE;
-  else
-    dbp->master_only = FALSE;
-
-  dbp->trys = 1;
+  if (__nis_findfastest (dbp) < 1)
+    {
+      __bind_destroy (dbp);
+      return NULL;
+    }
 
   return dbp;
 }
@@ -298,10 +288,11 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
   nis_error retcode;
   dir_binding *dbp;
 
-  if (flags & MASTER_ONLY) 
+  if (flags & MASTER_ONLY)
     server_len = 1;
-  
-  dbp = __bind_create (server, server_len, flags);
+
+  if ((dbp = __bind_create (server, server_len, flags)) == NULL)
+    return NIS_UNAVAIL;
   while (__bind_connect (dbp) != NIS_SUCCESS)
     {
       if (__bind_next (dbp) != NIS_SUCCESS)
@@ -315,7 +306,7 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
     {
     again:
       result = clnt_call (dbp->clnt, prog, xargs, req, xres, resp, TIMEOUT);
-      
+
       if (result != RPC_SUCCESS)
 	{
 	  clnt_perror (dbp->clnt, "__do_niscall2: clnt_call");
@@ -336,25 +327,56 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
 	    case NIS_IBREMOVE:
 	    case NIS_IBFIRST:
 	    case NIS_IBNEXT:
-	      if ((((nis_result *)xres)->status != NIS_SUCCESS) &&
-		  (((nis_result *)xres)->status != NIS_S_SUCCESS))
-		if (__bind_next (dbp) == NIS_SUCCESS)
+	      if ((((nis_result *)xres)->status == NIS_NOTFOUND) ||
+		  (((nis_result *)xres)->status == NIS_NOSUCHNAME) ||
+		  (((nis_result *)xres)->status == NIS_NOT_ME))
+		{
+		  if (__bind_next (dbp) == NIS_SUCCESS)
+		    while (__bind_connect (dbp) != NIS_SUCCESS)
+		      {
+			if (__bind_next (dbp) != NIS_SUCCESS)
+			  {
+			    __bind_destroy (dbp);
+			    return NIS_SUCCESS;
+			  }
+		      }
 		  goto again;
+		}
 	    case NIS_FINDDIRECTORY:
-	      if (((fd_result *)xres)->status != NIS_SUCCESS)
-		if (__bind_next (dbp) == NIS_SUCCESS)
+	      if ((((fd_result *)xres)->status == NIS_NOTFOUND) ||
+		  (((fd_result *)xres)->status == NIS_NOSUCHNAME) ||
+		  (((fd_result *)xres)->status == NIS_NOT_ME))
+		{
+		  if (__bind_next (dbp) == NIS_SUCCESS)
+		    while (__bind_connect (dbp) != NIS_SUCCESS)
+		      {
+			if (__bind_next (dbp) != NIS_SUCCESS)
+			  {
+			    __bind_destroy (dbp);
+			    return NIS_SUCCESS;
+			  }
+		      }
 		  goto again;
-	      break;
-#if 0
-	    case NIS_STATUS: /* nis_taglist */
-	    case NIS_SERVSTATE:
+		}
 	      break;
 	    case NIS_DUMPLOG: /* log_result */
 	    case NIS_DUMP:
+	      if ((((log_result *)xres)->lr_status == NIS_NOTFOUND) ||
+		  (((log_result *)xres)->lr_status == NIS_NOSUCHNAME) ||
+		  (((log_result *)xres)->lr_status == NIS_NOT_ME))
+		{
+		  if (__bind_next (dbp) == NIS_SUCCESS)
+		    while (__bind_connect (dbp) != NIS_SUCCESS)
+		      {
+			if (__bind_next (dbp) != NIS_SUCCESS)
+			  {
+			    __bind_destroy (dbp);
+			    return NIS_SUCCESS;
+			  }
+		      }
+		  goto again;
+		}
 	      break;
-	    case NIS_CHECKPOINT: /* cp_result */
-	      break;
-#endif
 	    default:
 	      break;
 	    }
@@ -363,12 +385,13 @@ __do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
 	}
     }
   while ((flags & HARD_LOOKUP) && retcode == NIS_RPCERROR);
-  
-  return retcode; 
+
+  return retcode;
 }
 
 static directory_obj *
-rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
+rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags,
+	       nis_error *status)
 {
   fd_result *fd_res;
   XDR xdrs;
@@ -399,6 +422,7 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
   switch (nis_dir_cmp (domain, dir->do_name))
     {
     case SAME_NAME:
+      *status = NIS_SUCCESS;
       return dir;
     case NOT_SEQUENTIAL:
       /* NOT_SEQUENTIAL means, go one up and try it there ! */
@@ -413,6 +437,7 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
 	   domain ! (Now I understand why a root server must be a
 	   replica of the parent domain) */
 	fd_res = __nis_finddirectory (dir, ndomain);
+	*status = fd_res->status;
 	if (fd_res->status != NIS_SUCCESS)
 	  {
 	    nis_free_directory (dir);
@@ -431,7 +456,7 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
 	    /* We have found a NIS+ server serving ndomain, now
 	       let us search for "name" */
 	    nis_free_directory (dir);
-	    return rec_dirsearch (name, obj, flags);
+	    return rec_dirsearch (name, obj, flags, status);
 	  }
 	else
 	  {
@@ -447,7 +472,7 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
 	char leaf [strlen (name) + 3];
 	char ndomain [strlen (name) + 3];
 	char *cp;
-	
+
 	do
 	  {
 	    if (strlen (domain) == 0)
@@ -463,8 +488,9 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
 	cp = strchr (leaf, '\0');
 	*cp++ = '.';
 	strcpy (cp, domain);
-	
+
 	fd_res = __nis_finddirectory (dir, leaf);
+	*status = fd_res->status;
 	if (fd_res->status != NIS_SUCCESS)
 	  {
 	    nis_free_directory (dir);
@@ -483,15 +509,17 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags)
 	    /* We have found a NIS+ server serving ndomain, now
 	       let us search for "name" */
 	    nis_free_directory (dir);
-	    return rec_dirsearch (name, obj, flags);
+	    return rec_dirsearch (name, obj, flags, status);
 	  }
       }
     break;
     case BAD_NAME:
       nis_free_directory (dir);
+      *status = NIS_BADNAME;
       return NULL;
     }
   nis_free_directory (dir);
+  *status = NIS_FAIL;
   return NULL;
 }
 
@@ -509,19 +537,20 @@ __do_niscall (const_nis_name name, u_long prog, xdrproc_t xargs,
 
   if ((flags & NO_CACHE) !=  NO_CACHE)
     dir = __cache_search (name);
-  
+
   if (dir == NULL)
     {
+      nis_error status;
       dir = readColdStartFile ();
       if (dir == NULL) /* No /var/nis/NIS_COLD_START->no NIS+ installed */
 	return NIS_UNAVAIL;
-      
-      dir = rec_dirsearch (name, dir, flags);
+
+      dir = rec_dirsearch (name, dir, flags, &status);
       if (dir == NULL)
-	return NIS_NOTFOUND;
+	return status;
     }
 
-  if (flags & MASTER_ONLY) 
+  if (flags & MASTER_ONLY)
     {
       server = dir->do_servers.do_servers_val;
       server_len = 1;
@@ -531,11 +560,11 @@ __do_niscall (const_nis_name name, u_long prog, xdrproc_t xargs,
       server = dir->do_servers.do_servers_val;
       server_len = dir->do_servers.do_servers_len;
     }
-  
-  
+
+
   retcode = __do_niscall2 (server, server_len, prog, xargs, req, xres, resp,
 			   flags);
-  
+
   nis_free_directory (dir);
 
   return retcode;
diff --git a/nis/nis_findserv.c b/nis/nis_findserv.c
new file mode 100644
index 0000000000..a04abd8056
--- /dev/null
+++ b/nis/nis_findserv.c
@@ -0,0 +1,251 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <rpcsvc/nis.h>
+
+#include "nis_intern.h"
+
+/* Private data kept per client handle, from sunrpc/clnt_udp.c */
+struct cu_data
+  {
+    int cu_sock;
+    bool_t cu_closeit;
+    struct sockaddr_in cu_raddr;
+    int cu_rlen;
+    struct timeval cu_wait;
+    struct timeval cu_total;
+    struct rpc_err cu_error;
+    XDR cu_outxdrs;
+    u_int cu_xdrpos;
+    u_int cu_sendsz;
+    char *cu_outbuf;
+    u_int cu_recvsz;
+    char cu_inbuf[1];
+  };
+
+
+/* The following is the original routine from sunrpc/pm_getport.c.
+   The only change is the much shorter timeout. */
+/*
+ * pmap_getport.c
+ * Client interface to pmap rpc service.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+/*
+ * Find the mapped port for program,version.
+ * Calls the pmap service remotely to do the lookup.
+ * Returns 0 if no map exists.
+ */
+static u_short
+__pmap_getport (struct sockaddr_in *address, u_long program,
+		u_long version, u_int protocol)
+{
+  const struct timeval timeout = {1, 0};
+  const struct timeval tottimeout = {1, 0};
+  u_short port = 0;
+  int socket = -1;
+  CLIENT *client;
+  struct pmap parms;
+
+  address->sin_port = htons (PMAPPORT);
+  client = clntudp_bufcreate (address, PMAPPROG, PMAPVERS, timeout, &socket,
+			      RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+  if (client != (CLIENT *) NULL)
+    {
+      parms.pm_prog = program;
+      parms.pm_vers = version;
+      parms.pm_prot = protocol;
+      parms.pm_port = 0;	/* not needed or used */
+      if (CLNT_CALL (client, PMAPPROC_GETPORT, (xdrproc_t) xdr_pmap,
+		     (caddr_t) & parms, (xdrproc_t) xdr_u_short,
+		     (caddr_t) & port, tottimeout) != RPC_SUCCESS)
+	{
+	  rpc_createerr.cf_stat = RPC_PMAPFAILURE;
+	  clnt_geterr (client, &rpc_createerr.cf_error);
+	}
+      else if (port == 0)
+	{
+	  rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
+	}
+      CLNT_DESTROY (client);
+    }
+  /* (void)close(socket); CLNT_DESTROY already closed it */
+  address->sin_port = 0;
+  return port;
+}
+
+/* Transmit to NULLPROC, return immediately. */
+static void *
+nis_null_3_send (void *argp, CLIENT * clnt)
+{
+  static char clnt_res;
+  struct timeval TIMEOUT = {0, 0};
+
+  memset ((char *) &clnt_res, 0, sizeof (clnt_res));
+  if (clnt_call (clnt, NULLPROC,
+		 (xdrproc_t) xdr_void, (caddr_t) argp,
+		 (xdrproc_t) xdr_void, (caddr_t) & clnt_res,
+		 TIMEOUT) != RPC_SUCCESS)
+    return NULL;
+  return (void *) &clnt_res;
+}
+
+/* Receive request from NULLPROC asynchronously. */
+static void *
+nis_null_3_recv (void *argp, CLIENT * clnt)
+{
+  static char clnt_res;
+  struct timeval TIMEOUT = {0, 0};
+
+  memset ((char *) &clnt_res, 0, sizeof (clnt_res));
+  if (clnt_call (clnt, NULLPROC,
+		 (xdrproc_t) NULL, (caddr_t) argp,
+		 (xdrproc_t) xdr_void, (caddr_t) & clnt_res,
+		 TIMEOUT) != RPC_SUCCESS)
+    return NULL;
+  return (void *) &clnt_res;
+}
+
+/* This is now the public functions, which should find the fastest server */
+
+struct findserv_req
+{
+  struct sockaddr_in sin;
+  u_long xid;
+  u_int server_nr;
+  u_int server_ep;
+};
+
+long
+__nis_findfastest (dir_binding * bind)
+{
+  struct timeval TIMEOUT = {5, 0};
+  struct findserv_req **pings;
+  struct sockaddr_in sin;
+  int found = -1;
+  time_t xid_seed, xid_lookup;
+  int sock, dontblock = 1;
+  CLIENT *clnt;
+  void *foo = NULL;
+  u_long i, j, pings_count, pings_max;
+  struct cu_data *cu;
+
+  pings_max = bind->server_len * 2;	/* Reserve a little bit more memory
+					   for multihomed hosts */
+  pings_count = 0;
+  pings = malloc (sizeof (struct findserv_req *) * pings_max);
+  xid_seed = time (NULL) ^ getpid ();
+
+  memset (&sin, '\0', sizeof (sin));
+  sin.sin_family = AF_INET;
+  for (i = 0; i < bind->server_len; i++)
+    for (j = 0; j < bind->server_val[i].ep.ep_len; ++j)
+      if (strcmp (bind->server_val[i].ep.ep_val[j].family, "inet") == 0)
+	if (strcmp (bind->server_val[i].ep.ep_val[j].proto, "-") == 0)
+	  {
+	    sin.sin_addr.s_addr =
+	      inetstr2int (bind->server_val[i].ep.ep_val[j].uaddr);
+	    if (sin.sin_addr.s_addr == 0)
+	      continue;
+	    sin.sin_port = htons (__pmap_getport (&sin, NIS_PROG,
+						  NIS_VERSION, IPPROTO_UDP));
+	    if (sin.sin_port == 0)
+	      continue;
+
+	    if (pings_count >= pings_max)
+	      {
+		pings_max += 10;
+		pings = realloc (pings, sizeof (struct findserv_req) *
+				 pings_max);
+	      }
+	    pings[pings_count] = calloc (1, sizeof (struct findserv_req));
+	    memcpy ((char *) &pings[pings_count]->sin, (char *) &sin,
+		    sizeof (sin));
+	    pings[pings_count]->xid = xid_seed;
+	    pings[pings_count]->server_nr = i;
+	    pings[pings_count]->server_ep = j;
+	    ++xid_seed;
+	    ++pings_count;
+	  }
+
+  /* Make sure at least one server was assigned */
+  if (pings_count == 0)
+    {
+      free (pings);
+      return -1;
+    }
+
+  /* Create RPC handle */
+  sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+  clnt = clntudp_create (&sin, NIS_PROG, NIS_VERSION, TIMEOUT, &sock);
+  if (clnt == NULL)
+    {
+      close (sock);
+      for (i = 0; i < pings_count; ++i)
+	free (pings[i]);
+      free (pings);
+      return -1;
+    }
+  clnt->cl_auth = authunix_create_default ();
+  cu = (struct cu_data *) clnt->cl_private;
+  TIMEOUT.tv_sec = 0;
+  clnt_control (clnt, CLSET_TIMEOUT, (char *) &TIMEOUT);
+  ioctl (sock, FIONBIO, &dontblock);
+
+  /* Send to all servers the NULLPROC */
+  for (i = 0; i < pings_count; ++i)
+    {
+      /* clntudp_call() will increment, subtract one */
+      *((u_int32_t *) (cu->cu_outbuf)) = pings[i]->xid - 1;
+      bcopy ((char *) &pings[i]->sin, (char *) &cu->cu_raddr,
+	     sizeof (struct sockaddr_in));
+      nis_null_3_send (foo, clnt);
+    }
+
+  /* Receive reply */
+  nis_null_3_recv (foo, clnt);
+
+  xid_lookup = *((u_int32_t *) (cu->cu_inbuf));
+  for (i = 0; i < pings_count; i++)
+    {
+      if (pings[i]->xid == xid_lookup)
+	{
+	  bind->server_used = pings[i]->server_nr;
+	  bind->current_ep = pings[i]->server_ep;
+	  found = 1;
+	}
+    }
+
+  auth_destroy (clnt->cl_auth);
+  clnt_destroy (clnt);
+  close (sock);
+
+  for (i = 0; i < pings_count; ++i)
+    free (pings[i]);
+  free (pings);
+
+  return found;
+}
diff --git a/nis/nis_intern.h b/nis/nis_intern.h
index a7cb785e40..fdc392ad7f 100644
--- a/nis/nis_intern.h
+++ b/nis/nis_intern.h
@@ -24,12 +24,32 @@
 
 __BEGIN_DECLS
 
+struct dir_binding
+{
+  CLIENT *clnt;                  /* RPC CLIENT handle */
+  nis_server *server_val;        /* List of servers */
+  u_int server_len;              /* # of servers */
+  u_int server_used;             /* Which server we are bind in the moment ? */
+  u_int current_ep;              /* Which endpoint of the server are in use? */
+  u_int trys;                    /* How many server have we tried ? */
+  bool_t master_only;            /* Is only binded to the master */
+  bool_t use_auth;               /* Do we use AUTH ? */
+  bool_t use_udp;                /* Do we use UDP ? */
+  time_t create;                 /* Binding creation time */
+  struct sockaddr_in addr;       /* Server's IP address */
+  int socket;                    /* Server's local socket */
+  unsigned short port;           /* Local port */
+};
+typedef struct dir_binding dir_binding;
+
+extern unsigned long inetstr2int __P ((const char *str));
+extern long __nis_findfastest __P ((dir_binding *bind));
 extern nis_error __do_niscall2 __P ((const nis_server *serv, u_int serv_len,
 				     u_long prog, xdrproc_t xargs, caddr_t req,
-				     xdrproc_t xres, caddr_t resp, 
+				     xdrproc_t xres, caddr_t resp,
 				     u_long flags));
 extern nis_error __do_niscall __P ((const_nis_name name, u_long prog,
-				    xdrproc_t xargs, caddr_t req, 
+				    xdrproc_t xargs, caddr_t req,
 				    xdrproc_t xres, caddr_t resp,
 				    u_long flags));
 #if defined (HAVE_SECURE_RPC)
diff --git a/nis/nis_lookup.c b/nis/nis_lookup.c
index 82db7b0b25..6224b1f2c4 100644
--- a/nis/nis_lookup.c
+++ b/nis/nis_lookup.c
@@ -96,6 +96,10 @@ nis_lookup (const_nis_name name, const u_long flags)
 	  /* XXX Implement CALLBACK here ! */
 	  ++done;
 	  break;
+	case NIS_UNAVAIL:
+	  /* NIS+ is not installed, or all servers are down */
+	  ++done;
+	  break;
 	default:
 	  /* Try the next domainname if we don't follow a link */
 	  if (count_links)
diff --git a/nis/nis_ping.c b/nis/nis_ping.c
index 941adfbda4..4ec34ce4c0 100644
--- a/nis/nis_ping.c
+++ b/nis/nis_ping.c
@@ -34,7 +34,7 @@ nis_ping (const_nis_name dirname, u_long utime, const nis_object *dirobj)
 
   if (dirobj == NULL)
     {
-      res = nis_lookup (dirname, EXPAND_NAME + FOLLOW_LINKS);
+      res = nis_lookup (dirname, MASTER_ONLY);
       if (res->status != NIS_SUCCESS && res->status != NIS_S_SUCCESS)
 	return;
       obj = res->objects.objects_val;
@@ -44,7 +44,11 @@ nis_ping (const_nis_name dirname, u_long utime, const nis_object *dirobj)
 
   /* Check if obj is really a diryectory object */
   if (obj->zo_data.zo_type != DIRECTORY_OBJ)
-    abort ();
+    {
+      if (res != NULL)
+	nis_freeresult (res);
+      return;
+    }
 
   if (dirname == NULL)
     args.dir = obj->DI_data.do_name;
diff --git a/nis/nis_table.c b/nis/nis_table.c
index 16fd1e68ec..a3bfa2c0cc 100644
--- a/nis/nis_table.c
+++ b/nis/nis_table.c
@@ -248,7 +248,11 @@ nis_list (const_nis_name name, u_long flags,
 	  /* XXX Implement CALLBACK here ! */
 	  ++done;
 	  break;
-	default:
+        case NIS_UNAVAIL:  
+          /* NIS+ is not installed, or all servers are down */
+          ++done;
+          break;
+        default:
 	  /* Try the next domainname if we don't follow a link */
 	  if (count_links)
 	    {
diff --git a/nis/nis_util.c b/nis/nis_util.c
index 4e39d6fb6a..b6eef9b227 100644
--- a/nis/nis_util.c
+++ b/nis/nis_util.c
@@ -24,6 +24,7 @@
 fd_result *
 __nis_finddirectory (directory_obj *dir, const_nis_name name)
 {
+  nis_error status;
   fd_args fd_args;
   fd_result *fd_res;
 
@@ -31,13 +32,14 @@ __nis_finddirectory (directory_obj *dir, const_nis_name name)
   fd_args.requester = nis_local_host();
   fd_res = calloc (1, sizeof (fd_result));
       
-  if (__do_niscall2 (dir->do_servers.do_servers_val, 
-		     dir->do_servers.do_servers_len, NIS_FINDDIRECTORY,
-		     (xdrproc_t) xdr_fd_args,
-		     (caddr_t) &fd_args, (xdrproc_t) xdr_fd_result,
-		     (caddr_t) fd_res, NO_AUTHINFO|USE_DGRAM) != NIS_SUCCESS)
-    fd_res->status = NIS_RPCERROR;
-  
+  if ((status = __do_niscall2 (dir->do_servers.do_servers_val, 
+			       dir->do_servers.do_servers_len, 
+			       NIS_FINDDIRECTORY, (xdrproc_t) xdr_fd_args,
+			       (caddr_t) &fd_args, (xdrproc_t) xdr_fd_result,
+			       (caddr_t) fd_res, 
+			       NO_AUTHINFO|USE_DGRAM)) != NIS_SUCCESS)
+    fd_res->status = status;
+      
   return fd_res;
 }
 
diff --git a/nis/nss_compat/compat-grp.c b/nis/nss_compat/compat-grp.c
index 9726784b2d..35ae2f7b02 100644
--- a/nis/nss_compat/compat-grp.c
+++ b/nis/nss_compat/compat-grp.c
@@ -18,6 +18,7 @@
    Boston, MA 02111-1307, USA.  */
 
 #include <errno.h>
+#include <fcntl.h>
 #include <nss.h>
 #include <grp.h>
 #include <ctype.h>
@@ -132,6 +133,26 @@ internal_setgrent (ent_t *ent)
 
       if (ent->stream == NULL)
 	status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
+      else
+	{
+	  /* We have to make sure the file is  `closed on exec'.  */
+	  int result, flags;
+
+	  result = flags = fcntl (fileno (ent->stream), F_GETFD, 0);
+	  if (result >= 0)
+	    {
+	      flags |= FD_CLOEXEC;
+	      result = fcntl (fileno (ent->stream), F_SETFD, flags);
+	    }
+	  if (result < 0)
+	    {
+	      /* Something went wrong.  Close the stream and return a
+		 failure.  */
+	      fclose (ent->stream);
+	      ent->stream = NULL;
+	      status = NSS_STATUS_UNAVAIL;
+	    }
+	}
     }
   else
     rewind (ent->stream);
@@ -277,7 +298,7 @@ getgrent_next_nis (struct group *result, ent_t *ent, char *buffer,
 	  if (!save_nis_first)
 	    free (save_oldkey);
 	}
-      
+
       if (parse_res &&
 	  in_blacklist (result->gr_name, strlen (result->gr_name), ent))
 	parse_res = 0; /* if result->gr_name in blacklist,search next entry */
@@ -297,7 +318,7 @@ getgrent_next_nisplus (struct group *result, ent_t *ent, char *buffer,
     {
       nis_result *save_oldres;
       bool_t save_nis_first;
-      
+
       if (ent->nis_first)
         {
 	  save_oldres = ent->result;
@@ -324,7 +345,7 @@ getgrent_next_nisplus (struct group *result, ent_t *ent, char *buffer,
 	      return niserr2nss (ent->result->status);
             }
         }
-      if ((parse_res = _nss_nisplus_parse_grent (ent->result, 0, result, 
+      if ((parse_res = _nss_nisplus_parse_grent (ent->result, 0, result,
 						 buffer, buflen)) == -1)
 	{
 	  nis_freeresult (ent->result);
@@ -370,7 +391,7 @@ getgrent_next_file_plusgroup (struct group *result, char *buffer,
           nis_freeresult (res);
           return status;
         }
-      if ((parse_res = _nss_nisplus_parse_grent (res, 0, result, buffer, 
+      if ((parse_res = _nss_nisplus_parse_grent (res, 0, result, buffer,
 						 buflen)) == -1)
 	{
 	  __set_errno (ERANGE);
diff --git a/nis/nss_compat/compat-pwd.c b/nis/nss_compat/compat-pwd.c
index af1267922c..6fac0f46c6 100644
--- a/nis/nss_compat/compat-pwd.c
+++ b/nis/nss_compat/compat-pwd.c
@@ -21,6 +21,7 @@
 #include <pwd.h>
 #include <errno.h>
 #include <ctype.h>
+#include <fcntl.h>
 #include <netdb.h>
 #include <string.h>
 #include <bits/libc-lock.h>
@@ -232,6 +233,26 @@ internal_setpwent (ent_t *ent)
 
       if (ent->stream == NULL)
 	status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
+      else
+	{
+	  /* We have to make sure the file is  `closed on exec'.  */
+	  int result, flags;
+
+	  result = flags = fcntl (fileno (ent->stream), F_GETFD, 0);
+	  if (result >= 0)
+	    {
+	      flags |= FD_CLOEXEC;
+	      result = fcntl (fileno (ent->stream), F_SETFD, flags);
+	    }
+	  if (result < 0)
+	    {
+	      /* Something went wrong.  Close the stream and return a
+		 failure.  */
+	      fclose (ent->stream);
+	      ent->stream = NULL;
+	      status = NSS_STATUS_UNAVAIL;
+	    }
+	}
     }
   else
     rewind (ent->stream);
@@ -274,7 +295,7 @@ internal_endpwent (ent_t *ent)
 
   if (ent->netgroup)
     __internal_endnetgrent (&ent->netgrdata);
-  
+
   ent->nis = ent->first = ent->netgroup = 0;
 
   if (ent->oldkey != NULL)
@@ -432,13 +453,13 @@ getpwent_next_nisplus_netgr (struct passwd *result, ent_t *ent, char *group,
 	  give_pwd_free (&ent->pwd);
 	  return NSS_STATUS_RETURN;
 	}
-      
+
       if (user == NULL || user[0] == '-')
 	continue;
-      
+
       if (domain != NULL && strcmp (ypdomain, domain) != 0)
 	continue;
-      
+
       p2len = pwd_need_buflen (&ent->pwd);
       if (p2len > buflen)
 	{
@@ -457,7 +478,7 @@ getpwent_next_nisplus_netgr (struct passwd *result, ent_t *ent, char *group,
 	  nis_freeresult (nisres);
 	  continue;
 	}
-      if ((parse_res = _nss_nisplus_parse_pwent (nisres, result, buffer, 
+      if ((parse_res = _nss_nisplus_parse_pwent (nisres, result, buffer,
 						 buflen)) == -1)
 	{
 	  nis_freeresult (nisres);
@@ -551,7 +572,7 @@ getpwent_next_nisplus (struct passwd *result, ent_t *ent, char *buffer,
 	  if (!saved_first)
 	    nis_freeresult (saved_res);
 	}
-      
+
       if (parse_res &&
 	  in_blacklist (result->pw_name, strlen (result->pw_name), ent))
 	parse_res = 0; /* if result->pw_name in blacklist,search next entry */
@@ -592,7 +613,7 @@ getpwent_next_nis (struct passwd *result, ent_t *ent, char *buffer,
       bool_t saved_first;
       char *saved_oldkey;
       int saved_oldlen;
-      
+
       if (ent->first)
 	{
 	  if (yp_first (domain, "passwd.byname", &outkey, &outkeylen,
@@ -602,7 +623,7 @@ getpwent_next_nis (struct passwd *result, ent_t *ent, char *buffer,
 	      give_pwd_free (&ent->pwd);
 	      return NSS_STATUS_UNAVAIL;
 	    }
-	  
+
 	  saved_first = TRUE;
 	  saved_oldkey = ent->oldkey;
 	  saved_oldlen = ent->oldkeylen;
@@ -699,7 +720,7 @@ getpwent_next_file_plususer (struct passwd *result, char *buffer,
 	  nis_freeresult (res);
 	  return status;
 	}
-      if ((parse_res = _nss_nisplus_parse_pwent (res, result, buffer, 
+      if ((parse_res = _nss_nisplus_parse_pwent (res, result, buffer,
 						 buflen)) == -1)
 	{
 	  nis_freeresult (res);
@@ -713,10 +734,10 @@ getpwent_next_file_plususer (struct passwd *result, char *buffer,
       char *domain;
       char *outval;
       int outvallen;
-      
+
       if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
 	return NSS_STATUS_TRYAGAIN;
-      
+
       if (yp_match (domain, "passwd.byname", &result->pw_name[1],
 		    strlen (result->pw_name) - 1, &outval, &outvallen)
 	  != YPERR_SUCCESS)
diff --git a/nis/nss_compat/compat-spwd.c b/nis/nss_compat/compat-spwd.c
index 61a703c1ea..a4c6201c2d 100644
--- a/nis/nss_compat/compat-spwd.c
+++ b/nis/nss_compat/compat-spwd.c
@@ -20,6 +20,7 @@
 #include <nss.h>
 #include <errno.h>
 #include <ctype.h>
+#include <fcntl.h>
 #include <netdb.h>
 #include <shadow.h>
 #include <string.h>
@@ -184,6 +185,26 @@ internal_setspent (ent_t *ent)
 
       if (ent->stream == NULL)
 	status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
+      else
+	{
+	  /* We have to make sure the file is  `closed on exec'.  */
+	  int result, flags;
+
+	  result = flags = fcntl (fileno (ent->stream), F_GETFD, 0);
+	  if (result >= 0)
+	    {
+	      flags |= FD_CLOEXEC;
+	      result = fcntl (fileno (ent->stream), F_SETFD, flags);
+	    }
+	  if (result < 0)
+	    {
+	      /* Something went wrong.  Close the stream and return a
+		 failure.  */
+	      fclose (ent->stream);
+	      ent->stream = NULL;
+	      status = NSS_STATUS_UNAVAIL;
+	    }
+	}
     }
   else
     rewind (ent->stream);
@@ -305,10 +326,10 @@ getspent_next_nis_netgr (struct spwd *result, ent_t *ent, char *group,
 	  give_spwd_free (&ent->pwd);
 	  return NSS_STATUS_RETURN;
 	}
-      
+
       if (user == NULL || user[0] == '-')
 	continue;
-      
+
       if (domain != NULL && strcmp (ypdomain, domain) != 0)
 	continue;
 
@@ -651,7 +672,7 @@ getspent_next_file_plususer (struct spwd *result, char *buffer,
           nis_freeresult (res);
           return status;
         }
-      if ((parse_res = _nss_nisplus_parse_spent (res, result, buffer, 
+      if ((parse_res = _nss_nisplus_parse_spent (res, result, buffer,
 						 buflen)) == -1)
 	{
 	  nis_freeresult (res);
@@ -735,7 +756,7 @@ getspent_next_file (struct spwd *result, ent_t *ent,
           __set_errno (ERANGE);
           return NSS_STATUS_TRYAGAIN;
         }
-      
+
       if (result->sp_namp[0] != '+' && result->sp_namp[0] != '-')
 	/* This is a real entry.  */
 	break;
diff --git a/nis/ypclnt.c b/nis/ypclnt.c
index 85597144b2..7c9efec70a 100644
--- a/nis/ypclnt.c
+++ b/nis/ypclnt.c
@@ -130,12 +130,15 @@ __yp_bind (const char *domain, dom_binding ** ypdb)
                          (caddr_t) &ypbr, TIMEOUT) != RPC_SUCCESS)
             {
               clnt_destroy (client);
+	      close (clnt_sock);
               if (is_new)
                 free (ysd);
               return YPERR_YPBIND;
             }
 
           clnt_destroy (client);
+	  close (clnt_sock);
+
           if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
             {
               switch (ypbr.ypbind_resp_u.ypbind_error)
@@ -174,7 +177,10 @@ __yp_bind (const char *domain, dom_binding ** ypdb)
         }
 
       if (ysd->dom_client)
-        clnt_destroy (ysd->dom_client);
+	{
+	  clnt_destroy (ysd->dom_client);
+	  close (ysd->dom_socket);
+	}
       ysd->dom_socket = RPC_ANYSOCK;
       ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS,
                                         TIMEOUT, &ysd->dom_socket);
@@ -635,18 +641,16 @@ yp_all (const char *indomain, const char *inmap,
 			  (caddr_t) &req, (xdrproc_t) __xdr_ypresp_all,
 			  (caddr_t) &status, TIMEOUT);
 
+      clnt_destroy (clnt);
+      close (clnt_sock);
       if (result != RPC_SUCCESS)
 	{
 	  clnt_perror (ydb->dom_client, "yp_all: clnt_call");
-	  clnt_destroy (clnt);
 	  __yp_unbind (ydb);
 	  result = YPERR_RPC;
 	}
       else
-	{
-	  clnt_destroy (clnt);
-	  result = YPERR_SUCCESS;
-	}
+	result = YPERR_SUCCESS;
 
       __libc_lock_unlock (ypbindlist_lock);
 
diff --git a/nss/nss_db/db-XXX.c b/nss/nss_db/db-XXX.c
index 0c1b1ada37..54e7a754c3 100644
--- a/nss/nss_db/db-XXX.c
+++ b/nss/nss_db/db-XXX.c
@@ -1,5 +1,5 @@
 /* Common code for DB-based databases in nss_db module.
-   Copyright (C) 1996 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997 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
@@ -66,7 +66,27 @@ internal_setent (int stayopen)
       db = __dbopen (DBFILE, O_RDONLY, 0, DB_BTREE, NULL);
 
       if (db == NULL)
-	status = NSS_STATUS_UNAVAIL;
+	status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
+      else
+	{
+	  /* We have to make sure the file is  `closed on exec'.  */
+	  int result, flags;
+
+	  result = flags = fcntl ((*db->fd) (db), F_GETFD, 0);
+	  if (result >= 0)
+	    {
+	      flags |= FD_CLOEXEC;
+	      result = fcntl ((*db->fd) (db), F_SETFD, flags);
+	    }
+	  if (result < 0)
+	    {
+	      /* Something went wrong.  Close the stream and return a
+		 failure.  */
+	      (*db->close) (db);
+	      db = NULL;
+	      status = NSS_STATUS_UNAVAIL;
+	    }
+	}
     }
 
   /* Remember STAYOPEN flag.  */
diff --git a/nss/nss_db/db-alias.c b/nss/nss_db/db-alias.c
index 8b8cb41238..810fc3aba6 100644
--- a/nss/nss_db/db-alias.c
+++ b/nss/nss_db/db-alias.c
@@ -1,5 +1,5 @@
 /* Mail alias file parser in nss_db module.
-   Copyright (C) 1996 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
@@ -51,6 +51,26 @@ internal_setent (int stayopen)
 
       if (db == NULL)
 	status = NSS_STATUS_UNAVAIL;
+      else
+	{
+	  /* We have to make sure the file is  `closed on exec'.  */
+	  int result, flags;
+
+	  result = flags = fcntl ((*db->fd) (db), F_GETFD, 0);
+	  if (result >= 0)
+	    {
+	      flags |= FD_CLOEXEC;
+	      result = fcntl ((*db->fd) (db), F_SETFD, flags);
+	    }
+	  if (result < 0)
+	    {
+	      /* Something went wrong.  Close the stream and return a
+		 failure.  */
+	      (*db->close) (db);
+	      db = NULL;
+	      status = NSS_STATUS_UNAVAIL;
+	    }
+	}
     }
 
   /* Remember STAYOPEN flag.  */
diff --git a/nss/nss_db/db-netgrp.c b/nss/nss_db/db-netgrp.c
index e716dd00b2..c301789f74 100644
--- a/nss/nss_db/db-netgrp.c
+++ b/nss/nss_db/db-netgrp.c
@@ -53,6 +53,26 @@ _nss_db_setnetgrent (const char *group)
 
       if (db == NULL)
 	status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
+      else
+	{
+	  /* We have to make sure the file is  `closed on exec'.  */
+	  int result, flags;
+
+	  result = flags = fcntl ((*db->fd) (db), F_GETFD, 0);
+	  if (result >= 0)
+	    {
+	      flags |= FD_CLOEXEC;
+	      result = fcntl ((*db->fd) (db), F_SETFD, flags);
+	    }
+	  if (result < 0)
+	    {
+	      /* Something went wrong.  Close the stream and return a
+		 failure.  */
+	      (*db->close) (db);
+	      db = NULL;
+	      status = NSS_STATUS_UNAVAIL;
+	    }
+	}
     }
 
   if (status == NSS_STATUS_SUCCESS)
diff --git a/nss/nss_files/files-XXX.c b/nss/nss_files/files-XXX.c
index 3281580b8f..e80c06d269 100644
--- a/nss/nss_files/files-XXX.c
+++ b/nss/nss_files/files-XXX.c
@@ -21,6 +21,7 @@
 #include <ctype.h>
 #include <assert.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <bits/libc-lock.h>
 #include "nsswitch.h"
 
@@ -72,6 +73,26 @@ internal_setent (int stayopen)
 
       if (stream == NULL)
 	status = NSS_STATUS_UNAVAIL;
+      else
+	{
+	  /* We have to make sure the file is  `closed on exec'.  */
+	  int result, flags;
+
+	  result = flags = fcntl (fileno (stream), F_GETFD, 0);
+	  if (result >= 0)
+	    {
+	      flags |= FD_CLOEXEC;
+	      result = fcntl (fileno (stream), F_SETFD, flags);
+	    }
+	  if (result < 0)
+	    {
+	      /* Something went wrong.  Close the stream and return a
+		 failure.  */
+	      fclose (stream);
+	      stream = NULL;
+	      status = NSS_STATUS_UNAVAIL;
+	    }
+	}
     }
   else
     rewind (stream);
diff --git a/nss/nss_files/files-alias.c b/nss/nss_files/files-alias.c
index 99217fa7c5..0a910aa0fe 100644
--- a/nss/nss_files/files-alias.c
+++ b/nss/nss_files/files-alias.c
@@ -1,5 +1,5 @@
 /* Mail alias file parser in nss_files module.
-   Copyright (C) 1996 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
@@ -21,6 +21,7 @@
 #include <aliases.h>
 #include <ctype.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <bits/libc-lock.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -49,6 +50,26 @@ internal_setent (void)
 
       if (stream == NULL)
 	status = NSS_STATUS_UNAVAIL;
+      else
+	{
+	  /* We have to make sure the file is  `closed on exec'.  */
+	  int result, flags;
+
+	  result = flags = fcntl (fileno (stream), F_GETFD, 0);
+	  if (result >= 0)
+	    {
+	      flags |= FD_CLOEXEC;
+	      result = fcntl (fileno (stream), F_SETFD, flags);
+	    }
+	  if (result < 0)
+	    {
+	      /* Something went wrong.  Close the stream and return a
+		 failure.  */
+	      fclose (stream);
+	      stream = NULL;
+	      status = NSS_STATUS_UNAVAIL;
+	    }
+	}
     }
   else
     rewind (stream);
diff --git a/nss/nss_files/files-hosts.c b/nss/nss_files/files-hosts.c
index 239dea7ebd..d6c4152507 100644
--- a/nss/nss_files/files-hosts.c
+++ b/nss/nss_files/files-hosts.c
@@ -50,12 +50,7 @@ LINE_PARSER
    STRING_FIELD (addr, isspace, 1);
 
    /* Parse address.  */
-   if (inet_pton (AF_INET6, p, entdata->host_addr) > 0)
-     {
-       result->h_addrtype = AF_INET6;
-       result->h_length = IN6ADDRSZ;
-     }
-   else if (inet_pton (AF_INET, addr, entdata->host_addr) > 0)
+   if (inet_pton (AF_INET, addr, entdata->host_addr) > 0)
      {
        if (_res.options & RES_USE_INET6)
 	 {
@@ -70,6 +65,11 @@ LINE_PARSER
 	   result->h_length = INADDRSZ;
 	 }
      }
+   else if (inet_pton (AF_INET6, addr, entdata->host_addr) > 0)
+     {
+       result->h_addrtype = AF_INET6;
+       result->h_length = IN6ADDRSZ;
+     }
    else
      /* Illegal address: ignore line.  */
      return 0;
@@ -85,8 +85,12 @@ LINE_PARSER
 #include "files-XXX.c"
 
 DB_LOOKUP (hostbyname, ,,
-	   LOOKUP_NAME (h_name, h_aliases),
-	   const char *name)
+	   {
+	     if (result->h_addrtype != ((_res.options & RES_USE_INET6)
+					? AF_INET6 : AF_INET))
+	       continue;
+	     LOOKUP_NAME (h_name, h_aliases)
+	   }, const char *name)
 
 DB_LOOKUP (hostbyname2, ,,
 	   {
diff --git a/posix/sys/types.h b/posix/sys/types.h
index f49c996a04..131966029e 100644
--- a/posix/sys/types.h
+++ b/posix/sys/types.h
@@ -68,6 +68,7 @@ typedef __key_t key_t;
 
 #define	__need_size_t
 #include <stddef.h>
+typedef size_t socklen_t;
 
 #ifdef __USE_MISC
 /* Old compatibility names for C types.  */
diff --git a/string/string.h b/string/string.h
index f790a246f9..5621dfb39a 100644
--- a/string/string.h
+++ b/string/string.h
@@ -118,24 +118,24 @@ extern char *strndup __P ((__const char *__string, size_t __n));
 
 #if defined __USE_GNU && defined __GNUC__
 /* Duplicate S, returning an identical alloca'd string.  */
-#define strdupa(s)							      \
+# define strdupa(s)							      \
   (__extension__							      \
     ({									      \
       __const char *__old = (s);					      \
       size_t __len = strlen (__old) + 1;				      \
       char *__new = __builtin_alloca (__len);				      \
-      memcpy (__new, __old, __len);					      \
+      (char *) memcpy (__new, __old, __len);				      \
     }))
 
 /* Return an alloca'd copy of at most N bytes of string.  */
-#define strndupa(s, n)							      \
+# define strndupa(s, n)							      \
   (__extension__							      \
     ({									      \
       __const char *__old = (s);					      \
       size_t __len = strnlen (__old, (n));				      \
       char *__new = __builtin_alloca (__len + 1);			      \
       __new[__len] = '\0';						      \
-      memcpy (__new, __old, __len);					      \
+      (char *) memcpy (__new, __old, __len);				      \
     }))
 #endif
 
@@ -182,14 +182,14 @@ extern size_t strlen __P ((__const char *__s));
    If no '\0' terminator is found in that many characters, return MAXLEN.  */
 extern size_t strnlen __P ((__const char *__string, size_t __maxlen));
 
-#ifdef	__OPTIMIZE__
+# ifdef	__OPTIMIZE__
 extern __inline size_t
 strnlen (__const char *__string, size_t __maxlen)
 {
   __const char *__end = (__const char *) memchr (__string, '\0', __maxlen);
   return __end ? __end - __string : __maxlen;
 }
-#endif
+# endif
 #endif
 
 
@@ -207,6 +207,7 @@ extern char *strerror_r __P ((int __errnum, char *__buf, size_t __buflen));
 extern void bcopy __P ((__const __ptr_t __src, __ptr_t __dest, size_t __n));
 
 /* Set N bytes of S to 0.  */
+extern void __bzero __P ((__ptr_t __s, size_t __n));
 extern void bzero __P ((__ptr_t __s, size_t __n));
 
 /* Compare N bytes of S1 and S2 (same as memcmp).  */
diff --git a/sysdeps/alpha/dl-machine.h b/sysdeps/alpha/dl-machine.h
index 49d6830a65..746cdd236b 100644
--- a/sysdeps/alpha/dl-machine.h
+++ b/sysdeps/alpha/dl-machine.h
@@ -87,7 +87,7 @@ elf_machine_load_address (void)
    entries will jump to the on-demand fixup code in dl-runtime.c.  */
 
 static inline int
-elf_machine_runtime_setup (struct link_map *l, int lazy)
+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 {
   Elf64_Addr plt;
   extern void _dl_runtime_resolve (void);
@@ -348,9 +348,9 @@ static inline void
 elf_machine_rela (struct link_map *map,
 		  const Elf64_Rela *reloc,
 		  const Elf64_Sym *sym,
-		  const struct r_found_version *version)
+		  const struct r_found_version *version,
+		  Elf64_Addr *const reloc_addr)
 {
-  Elf64_Addr * const reloc_addr = (void *)(map->l_addr + reloc->r_offset);
   unsigned long const r_type = ELF64_R_TYPE (reloc->r_info);
 
 #ifndef RTLD_BOOTSTRAP
diff --git a/sysdeps/generic/htons.c b/sysdeps/generic/htons.c
index 8914f74f2e..1bbda3fd6a 100644
--- a/sysdeps/generic/htons.c
+++ b/sysdeps/generic/htons.c
@@ -22,7 +22,7 @@
 #undef	ntohs
 
 u_int16_t
-__htons (x)
+htons (x)
      u_int16_t x;
 {
 #if BYTE_ORDER == BIG_ENDIAN
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index d6fc038411..e517cff0ff 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -81,16 +81,20 @@ elf_machine_load_address (void)
    destroys the passed register information.  */
 static ElfW(Addr) fixup (struct link_map *l, ElfW(Word) reloc_offset)
      __attribute__ ((regparm (2), unused));
+static ElfW(Addr) profile_fixup (struct link_map *l, ElfW(Word) reloc_offset,
+				 ElfW(Addr) retaddr)
+     __attribute__ ((regparm (3), unused));
 #endif
 
 /* Set up the loaded object described by L so its unrelocated PLT
    entries will jump to the on-demand fixup code in dl-runtime.c.  */
 
 static inline int __attribute__ ((unused))
-elf_machine_runtime_setup (struct link_map *l, int lazy)
+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 {
   Elf32_Addr *got;
   extern void _dl_runtime_resolve (Elf32_Word);
+  extern void _dl_runtime_profile (Elf32_Word);
 
   if (l->l_info[DT_JMPREL] && lazy)
     {
@@ -100,9 +104,23 @@ elf_machine_runtime_setup (struct link_map *l, int lazy)
 	 and then jump to _GLOBAL_OFFSET_TABLE[2].  */
       got = (Elf32_Addr *) (l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr);
       got[1] = (Elf32_Addr) l;	/* Identify this shared object.  */
-      /* This function will get called to fix up the GOT entry indicated by
-	 the offset on the stack, and then jump to the resolved address.  */
-      got[2] = (Elf32_Addr) &_dl_runtime_resolve;
+
+      /* The got[2] entry contains the address of a function which gets
+	 called to get the address of a so far unresolved function and
+	 jump to it.  The profiling extension of the dynamic linker allows
+	 to intercept the calls to collect information.  In this case we
+	 don't store the address in the GOT so that all future calls also
+	 end in this function.  */
+      if (profile)
+	{
+	  got[2] = (Elf32_Addr) &_dl_runtime_profile;
+	  /* Say that we really want profiling and the timers are started.  */
+	  _dl_profile_map = l;
+	}
+      else
+	/* This function will get called to fix up the GOT entry indicated by
+	   the offset on the stack, and then jump to the resolved address.  */
+	got[2] = (Elf32_Addr) &_dl_runtime_resolve;
     }
 
   return lazy;
@@ -126,12 +144,31 @@ _dl_runtime_resolve:
 	xchgl %eax, (%esp)	# Get %eax contents end store function address.
 	ret $8			# Jump to function address.
 	.size _dl_runtime_resolve, .-_dl_runtime_resolve
+
+	.globl _dl_runtime_profile
+	.type _dl_runtime_profile, @function
+_dl_runtime_profile:
+	pushl %eax		# Preserve registers otherwise clobbered.
+	pushl %ecx
+	pushl %edx
+	movl 20(%esp), %ecx	# Load return address
+	movl 16(%esp), %edx	# Copy args pushed by PLT in register.  Note
+	movl 12(%esp), %eax	# that `fixup' takes its parameters in regs.
+	call profile_fixup	# Call resolver.
+	popl %edx		# Get register content back.
+	popl %ecx
+	xchgl %eax, (%esp)	# Get %eax contents end store function address.
+	ret $8			# Jump to function address.
+	.size _dl_runtime_profile, .-_dl_runtime_profile
 ");
 #else
 # define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\
 	.globl _dl_runtime_resolve
+	.globl _dl_runtime_profile
 	.type _dl_runtime_resolve, @function
+	.type _dl_runtime_profile, @function
 _dl_runtime_resolve:
+_dl_runtime_profile:
 	pushl %eax		# Preserve registers otherwise clobbered.
 	pushl %ecx
 	pushl %edx
@@ -147,6 +184,7 @@ _dl_runtime_resolve:
 	xchgl %eax, (%esp)	# Get %eax contents end store function address.
 	ret $8			# Jump to function address.
 	.size _dl_runtime_resolve, .-_dl_runtime_resolve
+	.size _dl_runtime_profile, .-_dl_runtime_profile
 ");
 #endif
 /* The PLT uses Elf32_Rel relocs.  */
@@ -261,10 +299,9 @@ extern char **_dl_argv;
 
 static inline void
 elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
-		 const Elf32_Sym *sym, const struct r_found_version *version)
+		 const Elf32_Sym *sym, const struct r_found_version *version,
+		 Elf32_Addr *const reloc_addr)
 {
-  Elf32_Addr *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
-
   if (ELF32_R_TYPE (reloc->r_info) == R_386_RELATIVE)
     {
 #ifndef RTLD_BOOTSTRAP
diff --git a/sysdeps/i386/fpu/bits/mathinline.h b/sysdeps/i386/fpu/bits/mathinline.h
index 4228959d23..2fc5baf81e 100644
--- a/sysdeps/i386/fpu/bits/mathinline.h
+++ b/sysdeps/i386/fpu/bits/mathinline.h
@@ -1,7 +1,7 @@
 /* Inline math functions for i387.
    Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by John C. Bowman <bowman@ipp-garching.mpg.de>, 1995.
+   Contributed by John C. Bowman <bowman@math.ualberta.ca>, 1995.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public License as
@@ -28,45 +28,45 @@
    These must not be inline functions since we have to be able to handle
    all floating-point types.  */
 # define isgreater(x, y) \
-     ({ int result;							      \
+     ({ int __result;							      \
 	__asm__ ("fucompp; fnstsw; andb $0x45, %%ah; setz %%al;"	      \
 		 "andl $0x01, %0"					      \
-		 : "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)");   \
-	result; })
+		 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
+	__result; })
 
 # define isgreaterequal(x, y) \
-     ({ int result;							      \
+     ({ int __result;							      \
 	__asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al;"	      \
 		 "andl $0x01, %0"					      \
-		 : "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)");   \
-	result; })
+		 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
+	__result; })
 
 # define isless(x, y) \
-     ({ int result;							      \
+     ({ int __result;							      \
 	__asm__ ("fucompp; fnstsw; xorb $0x01, %%ah; testb $0x45, %%ah;"      \
 		 "setz %%al; andl $0x01, %0"				      \
-		 : "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)");   \
-	result; })
+		 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
+	__result; })
 
 # define islessequal(x, y) \
-     ({ int result;							      \
+     ({ int __result;							      \
 	__asm__ ("fucompp; fnstsw; xorb $0x01, %%ah; testb $0x05, %%ah;"      \
 		 "setz %%al; andl $0x01, %0"				      \
-		 : "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)");   \
-	result; })
+		 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
+	__result; })
 
 # define islessgreater(x, y) \
-     ({ int result;							      \
+     ({ int __result;							      \
 	__asm__ ("fucompp; fnstsw; testb $0x44, %%ah; setz %%al;"	      \
 		 "andl $0x01, %0"					      \
-		 : "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)");   \
-	result; })
+		 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
+	__result; })
 
 # define isunordered(x, y) \
-     ({ int result;							      \
+     ({ int __result;							      \
 	__asm__ ("fucompp; fnstsw; sahf; setp %%al; andl $0x01, %0"	      \
-		 : "=a" (result) : "u" (y), "t" (x) : "cc", "st", "st(1)");   \
-	result; })
+		 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
+	__result; })
 #endif
 
 
@@ -88,425 +88,328 @@
 # define __MATH_INLINE extern __inline
 #endif
 
-__MATH_INLINE double cos (double);
-__MATH_INLINE double sin (double);
+/* A macro to define float, double, and long double versions of various
+   math functions for the ix87 FPU.  FUNC is the function name (which will
+   be suffixed with f and l for the float and long double version,
+   respectively).  OP is the name of the FPU operation.  */
 
+#if defined __USE_MISC || defined __USE_ISOC9X
+# define __inline_mathop(func, op) \
+  __inline_mathop_ (double, func, op)					      \
+  __inline_mathop_ (float, __CONCAT(func,f), op)			      \
+  __inline_mathop_ (long double, __CONCAT(func,l), op)
+#else
+# define __inline_mathop(func, op) \
+  __inline_mathop_ (double, func, op)
+#endif
 
-__MATH_INLINE double __expm1 (double __x);
-__MATH_INLINE double
-__expm1 (double __x)
-{
-  register double __value, __exponent, __temp;
-  __asm __volatile__
-    ("fldl2e			# e^x - 1 = 2^(x * log2(e)) - 1\n\t"
-     "fmul	%%st(1)		# x * log2(e)\n\t"
-     "fstl	%%st(1)\n\t"
-     "frndint			# int(x * log2(e))\n\t"
-     "fxch\n\t"
-     "fsub	%%st(1)		# fract(x * log2(e))\n\t"
-     "f2xm1			# 2^(fract(x * log2(e))) - 1\n\t"
-     "fscale			# 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t"
-     : "=t" (__value), "=u" (__exponent) : "0" (__x));
-  __asm __volatile__
-    ("fscale			# 2^int(x * log2(e))\n\t"
-     : "=t" (__temp) : "0" (1.0), "u" (__exponent));
-  __temp -= 1.0;
-
-  return __temp + __value;
-}
-
-__MATH_INLINE double __sgn1 (double __x);
-__MATH_INLINE double
-__sgn1 (double __x)
-{
-  return __x >= 0.0 ? 1.0 : -1.0;
-}
-
-__MATH_INLINE double sqrt (double __x);
-__MATH_INLINE double
-sqrt (double __x)
-{
-  register double __value;
-  __asm __volatile__
-    ("fsqrt"
-     : "=t" (__value) : "0" (__x));
-
-  return __value;
-}
-
-__MATH_INLINE double fabs (double __x);
-__MATH_INLINE double
-fabs (double __x)
-{
-  register double __value;
-  __asm __volatile__
-    ("fabs"
-     : "=t" (__value) : "0" (__x));
-
-  return __value;
-}
-
-/* The argument range of this inline version is limited.  */
-__MATH_INLINE double sin (double __x);
-__MATH_INLINE double
-sin (double __x)
-{
-  register double __value;
-  __asm __volatile__
-    ("fsin"
-     : "=t" (__value) : "0" (__x));
-
-  return __value;
-}
-
-/* The argument range of this inline version is limited.  */
-__MATH_INLINE double cos (double __x);
-__MATH_INLINE double
-cos (double __x)
-{
-  register double __value;
-  __asm __volatile__
-    ("fcos"
-     : "=t" (__value): "0" (__x));
-
-  return __value;
-}
-
-__MATH_INLINE double tan (double __x);
-__MATH_INLINE double
-tan (double __x)
-{
-  register double __value;
-  register double __value2 __attribute__ ((unused));
-  __asm __volatile__
-    ("fptan"
-     : "=t" (__value2), "=u" (__value) : "0" (__x));
-
-  return __value;
-}
-
-__MATH_INLINE double atan2 (double __y, double __x);
-__MATH_INLINE double
-atan2 (double __y, double __x)
-{
-  register double __value;
-  __asm __volatile__
-    ("fpatan\n\t"
-     "fldl %%st(0)"
-     : "=t" (__value) : "0" (__x), "u" (__y));
-
-  return __value;
-}
-
-__MATH_INLINE double asin (double __x);
-__MATH_INLINE double
-asin (double __x)
-{
-  return atan2 (__x, sqrt (1.0 - __x * __x));
-}
-
-__MATH_INLINE double acos (double __x);
-__MATH_INLINE double
-acos (double __x)
-{
-  return atan2 (sqrt (1.0 - __x * __x), __x);
-}
-
-__MATH_INLINE double atan (double __x);
-__MATH_INLINE double
-atan (double __x)
-{
-  register double __value;
-  __asm __volatile__
-    ("fld1\n\t"
-     "fpatan"
-     : "=t" (__value) : "0" (__x));
-
-  return __value;
-}
-
-__MATH_INLINE double exp (double __x);
-__MATH_INLINE double
-exp (double __x)
-{
-  register double __value, __exponent;
-  __asm __volatile__
-    ("fldl2e			# e^x = 2^(x * log2(e))\n\t"
-     "fmul	%%st(1)		# x * log2(e)\n\t"
-     "fstl	%%st(1)\n\t"
-     "frndint			# int(x * log2(e))\n\t"
-     "fxch\n\t"
-     "fsub	%%st(1)		# fract(x * log2(e))\n\t"
-     "f2xm1			# 2^(fract(x * log2(e))) - 1\n\t"
-     : "=t" (__value), "=u" (__exponent) : "0" (__x));
-  __value += 1.0;
-  __asm __volatile__
-    ("fscale"
-     : "=t" (__value) : "0" (__value), "u" (__exponent));
-
-  return __value;
-}
-
-__MATH_INLINE double sinh (double __x);
-__MATH_INLINE double
-sinh (double __x)
-{
-  register double __exm1 = __expm1 (fabs (__x));
-
-  return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1 (__x);
-}
-
-__MATH_INLINE double cosh (double __x);
-__MATH_INLINE double
-cosh (double __x)
-{
-  register double __ex = exp (__x);
-
-  return 0.5 * (__ex + 1.0 / __ex);
-}
-
-__MATH_INLINE double tanh (double __x);
-__MATH_INLINE double
-tanh (double __x)
-{
-  register double __exm1 = __expm1 (-fabs (__x + __x));
-
-  return __exm1 / (__exm1 + 2.0) * __sgn1 (-__x);
-}
-
-__MATH_INLINE double log (double __x);
-__MATH_INLINE double
-log (double __x)
-{
-  register double __value;
-  __asm __volatile__
-    ("fldln2\n\t"
-     "fxch\n\t"
-     "fyl2x"
-     : "=t" (__value) : "0" (__x));
-
-  return __value;
-}
-
-__MATH_INLINE double log10 (double __x);
-__MATH_INLINE double
-log10 (double __x)
-{
-  register double __value;
-  __asm __volatile__
-    ("fldlg2\n\t"
-     "fxch\n\t"
-     "fyl2x"
-     : "=t" (__value) : "0" (__x));
-
-  return __value;
-}
-
-__MATH_INLINE double __log2 (double __x);
-__MATH_INLINE double
-__log2 (double __x)
-{
-  register double __value;
-  __asm __volatile__
-    ("fyl2x"
-     : "=t" (__value) : "0" (__x), "u" (1.0));
-
-  return __value;
-}
-
-__MATH_INLINE double fmod (double __x, double __y);
-__MATH_INLINE double
-fmod (double __x, double __y)
-{
-  register double __value;
-  __asm __volatile__
-    ("1:	fprem\n\t"
-     "fstsw	%%ax\n\t"
-     "sahf\n\t"
-     "jp	1b"
-     : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc");
-
-  return __value;
-}
-
-__MATH_INLINE double ldexp (double __x, int __y);
-__MATH_INLINE double
-ldexp (double __x, int __y)
-{
-  register double __value;
-  __asm __volatile__
-    ("fscale"
-     : "=t" (__value) : "0" (__x), "u" ((double) __y));
-
-  return __value;
-}
+#define __inline_mathop_(float_type, func, op) \
+  __inline_mathop_decl_ (float_type, func, op, "0" (__x))
 
-__MATH_INLINE double pow (double __x, double __y);
-__MATH_INLINE double
-pow (double __x, double __y)
-{
-  register double __value, __exponent;
-  long __p = (long) __y;
-
-  if (__x == 0.0 && __y > 0.0)
-    return 0.0;
-  if (__y == (double) __p)
-    {
-      double __r = 1.0;
-      if (__p == 0)
-	return 1.0;
-      if (__p < 0)
-	{
-	  __p = -__p;
-	  __x = 1.0 / __x;
-	}
-      while (1)
-	{
-	  if (__p & 1)
-	    __r *= __x;
-	  __p >>= 1;
-	  if (__p == 0)
-	    return __r;
-	  __x *= __x;
-	}
-      /* NOTREACHED */
-    }
-  __asm __volatile__
-    ("fmul	%%st(1)		# y * log2(x)\n\t"
-     "fstl	%%st(1)\n\t"
-     "frndint			# int(y * log2(x))\n\t"
-     "fxch\n\t"
-     "fsub	%%st(1)		# fract(y * log2(x))\n\t"
-     "f2xm1			# 2^(fract(y * log2(x))) - 1\n\t"
-     : "=t" (__value), "=u" (__exponent) :  "0" (__log2 (__x)), "1" (__y));
-  __value += 1.0;
-  __asm __volatile__
-    ("fscale"
-     : "=t" (__value) : "0" (__value), "u" (__exponent));
-
-  return __value;
-}
 
-__MATH_INLINE double floor (double __x);
-__MATH_INLINE double
-floor (double __x)
-{
-  register double __value;
-  __volatile unsigned short int __cw, __cwtmp;
+#if defined __USE_MISC || defined __USE_ISOC9X
+# define __inline_mathop_decl(func, op, params...) \
+  __inline_mathop_decl_ (double, func, op, params)			      \
+  __inline_mathop_decl_ (float, __CONCAT(func,f), op, params)		      \
+  __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params)
+#else
+# define __inline_mathop_decl(func, op, params...) \
+  __inline_mathop_decl_ (double, func, op, params)
+#endif
 
-  __asm __volatile ("fnstcw %0" : "=m" (__cw));
-  __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */
-  __asm __volatile ("fldcw %0" : : "m" (__cwtmp));
-  __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));
-  __asm __volatile ("fldcw %0" : : "m" (__cw));
+#define __inline_mathop_decl_(float_type, func, op, params...) \
+  __MATHINLINE float_type func (float_type);				      \
+  __MATHINLINE float_type func (float_type __x)				      \
+  {									      \
+    register float_type __result;					      \
+    __asm __volatile__ (op : "=t" (__results) : params);		      \
+    return __result;							      \
+  }
+
+
+#if defined __USE_MISC || defined __USE_ISOC9X
+# define __inline_mathcode(func, arg, code) \
+  __inline_mathcode_ (double, func, arg, code)				      \
+  __inline_mathcode_ (float, __CONCAT(func,f), arg, code)		      \
+  __inline_mathcode_ (long double, __CONCAT(func,l), arg, code)
+#else
+# define __inline_mathcode(func, arg, code) \
+  __inline_mathcode_ (double, func, arg, code)
+#endif
 
-  return __value;
-}
+#define __inline_mathcode_(float_type, func, arg, code) \
+  __MATH_INLINE float_type func (float_type);				      \
+  __MATH_INLINE float_type func (float_type arg)			      \
+  {									      \
+    code;								      \
+  }
 
-__MATH_INLINE double ceil (double __x);
-__MATH_INLINE double
-ceil (double __x)
-{
-  register double __value;
-  __volatile unsigned short int __cw, __cwtmp;
 
-  __asm __volatile ("fnstcw %0" : "=m" (__cw));
-  __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */
-  __asm __volatile ("fldcw %0" : : "m" (__cwtmp));
-  __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));
-  __asm __volatile ("fldcw %0" : : "m" (__cw));
+#if defined __USE_MISC || defined __USE_ISOC9X
+# define __inline_mathcode2(func, arg1, arg2, code)			      \
+  __inline_mathcode2_ (double, func, arg1, arg2, code)			      \
+  __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code)	      \
+  __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code)
+#else
+# define __inline_mathcode2(func, arg1, arg2, code) \
+  __inline_mathcode2_ (double, func, arg1, arg2, code)
+#endif
 
-  return __value;
-}
+#define __inline_mathcode2_(float_type, func, arg1, arg2, code) \
+  __MATH_INLINE float_type func (float_type, float_type);		      \
+  __MATH_INLINE float_type func (float_type arg1, float_type arg2)	      \
+  {									      \
+    code;								      \
+  }
+
+
+/* Optimized inline implementation, sometimes woth reduced precision
+   and/or argument range.  */
+#define __expm1_code \
+  register long double __value;						      \
+  register long double __exponent;					      \
+  register long double __temp;						      \
+  __asm __volatile__							      \
+    ("fldl2e			# e^x - 1 = 2^(x * log2(e)) - 1\n\t"	      \
+     "fmul	%%st(1)		# x * log2(e)\n\t"			      \
+     "fstl	%%st(1)\n\t"						      \
+     "frndint			# int(x * log2(e))\n\t"			      \
+     "fxch\n\t"								      \
+     "fsub	%%st(1)		# fract(x * log2(e))\n\t"		      \
+     "f2xm1			# 2^(fract(x * log2(e))) - 1\n\t"	      \
+     "fscale			# 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \
+     : "=t" (__value), "=u" (__exponent) : "0" (__x));			      \
+  __asm __volatile__							      \
+    ("fscale			# 2^int(x * log2(e))\n\t"		      \
+     : "=t" (__temp) : "0" (1.0), "u" (__exponent));			      \
+  __temp -= 1.0;							      \
+  return __temp + __value
+__inline_mathcode_ (long double, __expm1l, __x, __expm1_code)
+
+
+#define __exp_code \
+  register long double __value;						      \
+  register long double __exponent;					      \
+  __asm __volatile__							      \
+    ("fldl2e			# e^x = 2^(x * log2(e))\n\t"		      \
+     "fmul	%%st(1)		# x * log2(e)\n\t"			      \
+     "fstl	%%st(1)\n\t"						      \
+     "frndint			# int(x * log2(e))\n\t"			      \
+     "fxch\n\t"								      \
+     "fsub	%%st(1)		# fract(x * log2(e))\n\t"		      \
+     "f2xm1			# 2^(fract(x * log2(e))) - 1\n\t"	      \
+     : "=t" (__value), "=u" (__exponent) : "0" (__x));			      \
+  __value += 1.0;							      \
+  __asm __volatile__							      \
+    ("fscale"								      \
+     : "=t" (__value) : "0" (__value), "u" (__exponent));		      \
+  return __value
+__inline_mathcode (exp, __x, __exp_code)
+__inline_mathcode_ (long double, __expl, __x, __exp_code)
+
+
+__inline_mathcode (tan, __x, \
+  register long double __value;						      \
+  register long double __value2 __attribute__ ((unused));		      \
+  __asm __volatile__							      \
+    ("fptan"								      \
+     : "=t" (__value2), "=u" (__value) : "0" (__x));			      \
+  return __value)
+
+
+#define __atan2_code \
+  register long double __value;						      \
+  __asm __volatile__							      \
+    ("fpatan\n\t"							      \
+     : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)");		      \
+  return __value
+__inline_mathcode2 (atan2, __y, __x, __atan2_code)
+__inline_mathcode2_ (long double, __atan2l, __y, __x, __atan2_code)
+
+
+__inline_mathcode2 (fmod, __x, __y, \
+  register long double __value;						      \
+  __asm __volatile__							      \
+    ("1:	fprem\n\t"						      \
+     "fnstsw	%%ax\n\t"						      \
+     "sahf\n\t"								      \
+     "jp	1b"							      \
+     : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc");		      \
+  return __value)
+
+
+__inline_mathcode2 (pow, __x, __y, \
+  register long double __value;						      \
+  register long double __exponent;					      \
+  long int __p = (long int) __y;					      \
+  if (__x == 0.0 && __y > 0.0)						      \
+    return 0.0;								      \
+  if (__y == (double) __p)						      \
+    {									      \
+      long double __r = 1.0;						      \
+      if (__p == 0)							      \
+	return 1.0;							      \
+      if (__p < 0)							      \
+	{								      \
+	  __p = -__p;							      \
+	  __x = 1.0 / __x;						      \
+	}								      \
+      while (1)								      \
+	{								      \
+	  if (__p & 1)							      \
+	    __r *= __x;							      \
+	  __p >>= 1;							      \
+	  if (__p == 0)							      \
+	    return __r;							      \
+	  __x *= __x;							      \
+	}								      \
+      /* NOTREACHED */							      \
+    }									      \
+  __asm __volatile__							      \
+    ("fyl2x" : "=t" (__value) : "0" (__x), "u" (1.0) : "st1");		      \
+  __asm __volatile__							      \
+    ("fmul	%%st(1)		# y * log2(x)\n\t"			      \
+     "fst	%%st(1)\n\t"						      \
+     "frndint			# int(y * log2(x))\n\t"			      \
+     "fxch\n\t"								      \
+     "fsub	%%st(1)		# fract(y * log2(x))\n\t"		      \
+     "f2xm1			# 2^(fract(y * log2(x))) - 1\n\t"	      \
+     : "=t" (__value), "=u" (__exponent) : "0" (__y), "1" (__value));	      \
+  __value += 1.0;							      \
+  __asm __volatile__							      \
+    ("fscale"								      \
+     : "=t" (__value) : "0" (__value), "u" (__exponent));		      \
+  return __value)
+
+
+__inline_mathop (sqrt, "fsqrt")
+__inline_mathop_ (long double, __sqrtl, "fsqrt")
+
+__inline_mathop (fabs, "fabs")
+
+/* The argument range of this inline version is reduced.  */
+__inline_mathop (sin, "fsin")
+/* The argument range of this inline version is reduced.  */
+__inline_mathop (cos, "fcos")
+
+__inline_mathop (atan, "fld1; fpatan")
+__inline_mathop (log, "fldln2; fxch; fyl2x")
+__inline_mathop (log10, "fldlg2; fxch; fyl2x")
+
+__inline_mathcode (asin, __x, return __atan2l (__x, __sqrtl (1.0 - __x * __x)))
+__inline_mathcode (acos, __x, return __atan2l (__sqrtl (1.0 - __x * __x), __x))
+
+__inline_mathcode (__sgn1, __x, return __x >= 0.0 ? 1.0 : -1.0)
+
+
+/* The argument range of the inline version of sinhl is slightly reduced.  */
+__inline_mathcode (sinh, __x, \
+  register long double __exm1 = __expm1l (__builtin_fabsl (__x));	      \
+  return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x))
+
+__inline_mathcode (cosh, __x, \
+  register long double __ex = __expl (__x);				      \
+  return 0.5 * (__ex + 1.0 / __ex))
+
+__inline_mathcode (tanh, __x, \
+  register long double __exm1 = __expm1l (-__builtin_fabsl (__x + __x));      \
+  return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
+
+
+__inline_mathcode (floor, __x, \
+  register long double __value;						      \
+  __volatile unsigned short int __cw;					      \
+  __volatile unsigned short int __cwtmp;				      \
+  __asm __volatile ("fnstcw %0" : "=m" (__cw));				      \
+  __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */		      \
+  __asm __volatile ("fldcw %0" : : "m" (__cwtmp));			      \
+  __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));		      \
+  __asm __volatile ("fldcw %0" : : "m" (__cw));				      \
+  return __value)
+
+__inline_mathcode (ceil, __x, \
+  register long double __value;						      \
+  __volatile unsigned short int __cw;					      \
+  __volatile unsigned short int __cwtmp;				      \
+  __asm __volatile ("fnstcw %0" : "=m" (__cw));				      \
+  __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */			      \
+  __asm __volatile ("fldcw %0" : : "m" (__cwtmp));			      \
+  __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));		      \
+  __asm __volatile ("fldcw %0" : : "m" (__cw));				      \
+  return __value)
 
 
 /* Optimized versions for some non-standardized functions.  */
 #if defined __USE_ISOC9X || defined __USE_MISC
 
-__MATH_INLINE double hypot (double __x, double __y);
-__MATH_INLINE double
-hypot (double __x, double __y)
-{
-  return sqrt (__x * __x + __y * __y);
-}
+__inline_mathop_decl (log2, "fyl2x", "u" (1.0), "0" (__x) : "st(1)")
+
+__inline_mathcode (expm1, __x, __expm1_code)
 
 /* We cannot rely on M_SQRT being defined.  So we do it for ourself
    here.  */
 # define __M_SQRT2	_Mldbl(1.41421356237309504880)	/* sqrt(2) */
 
-__MATH_INLINE double log1p (double __x);
-__MATH_INLINE double
-log1p (double __x)
-{
-  register double __value;
-
-  if (fabs (__x) >= 1.0 - 0.5 * __M_SQRT2)
-    __value = log (1.0 + __x);
-  else
-    __asm __volatile__
-      ("fldln2\n\t"
-       "fxch\n\t"
-       "fyl2xp1"
-       : "=t" (__value) : "0" (__x));
-
-  return __value;
-}
-
-__MATH_INLINE double asinh (double __x);
-__MATH_INLINE double
-asinh (double __x)
-{
-  register double __y = fabs (__x);
-
-  return log1p ((__y * __y / (sqrt (__y * __y + 1.0) + 1.0) + __y)
-		* __sgn1 (__x));
-}
-
-__MATH_INLINE double acosh (double __x);
-__MATH_INLINE double
-acosh (double __x)
-{
-  return log (__x + sqrt (__x - 1.0) * sqrt (__x + 1.0));
-}
-
-__MATH_INLINE double atanh (double __x);
-__MATH_INLINE double
-atanh (double __x)
-{
-  register double __y = fabs (__x);
-
-  return -0.5 * __log1p (-(__y + __y) / (1.0 + __y)) * __sgn1 (__x);
-}
-
-__MATH_INLINE double logb (double __x);
-__MATH_INLINE double
-logb (double __x)
-{
-  register double __value, __junk;
-  __asm __volatile__
-    ("fxtract\n\t"
-     : "=t" (__junk), "=u" (__value) : "0" (__x));
-
-  return __value;
-}
+__inline_mathcode (log1p, __x, \
+  register long double __value;						      \
+  if (__builtin_fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2)			      \
+    __value = logl (1.0 + __x);						      \
+  else									      \
+    __asm __volatile__							      \
+      ("fldln2\n\t"							      \
+       "fxch\n\t"							      \
+       "fyl2xp1"							      \
+       : "=t" (__value) : "0" (__x));					      \
+  return __value)
+
+
+/* The argument range of the inline version of asinhl is slightly reduced.  */
+__inline_mathcode (asinh, __x, \
+  register long double  __y = __builtin_fabsl (__x);			      \
+  return (log1pl (__y * __y / (__sqrtl (__y * __y + 1.0) + 1.0) + __y)	      \
+	  * __sgn1l (__x))
+
+__inline_mathcode (acosh, __x, \
+  return logl (__x + __sqrtl (__x - 1.0) * __sqrtl (__x + 1.0)))
+
+__inline_mathcode (atanh, __x, \
+  register long double __y = __builtin_fabsl (__x);			      \
+  return (-0.5 * log1pl (-(__y + __y) / (1.0 + __y)) *			      \
+	  __sgn1l (__x)))
+
+
+/* The argument range of the inline version of hypotl is slightly reduced.  */
+__inline_mathcode2 (hypot, __x, __y, return __sqrtl (__x * __x + __y * __y))
+
+__inline_mathcode(logb, __x, \
+  register long double __value;						      \
+  register long double __junk;						      \
+  __asm __volatile__							      \
+    ("fxtract\n\t"							      \
+     : "=t" (__junk), "=u" (__value) : "0" (__x));			      \
+  return __value)
+
+
+__inline_mathcode2 (ldexp, __x, __y, \
+  register long double __value;						      \
+  __asm __volatile__							      \
+    ("fscale"								      \
+     : "=t" (__value) : "0" (__x), "u" ((long double) __y));		      \
+  return __value)
 #endif
 
 
 #ifdef __USE_MISC
-__MATH_INLINE double drem (double __x, double __y);
-__MATH_INLINE double
-drem (double __x, double __y)
-{
-  register double __value;
-  __asm __volatile__
-    ("1:	fprem1\n\t"
-     "fstsw	%%ax\n\t"
-     "sahf\n\t"
-     "jp	1b"
-     : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc");
-
-  return __value;
-}
+__inline_mathcode2 (drem, __x, __y, \
+  register double __value;						      \
+  __asm __volatile__							      \
+    ("1:	fprem1\n\t"						      \
+     "fstsw	%%ax\n\t"						      \
+     "sahf\n\t"								      \
+     "jp	1b"							      \
+     : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc");		      \
+  return __value)
+
 
 /* This function is used in the `isfinite' macro.  */
 __MATH_INLINE int __finite (double __x);
@@ -522,82 +425,89 @@ __finite (double __x)
   return __result;
 }
 
-__MATH_INLINE double coshm1 (double __x);
-__MATH_INLINE double
-coshm1 (double __x)
-{
-  register double __exm1 = __expm1 (fabs (__x));
-
-  return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1;
-}
-
-__MATH_INLINE double acosh1p (double __x);
-__MATH_INLINE double
-acosh1p (double __x)
-{
-  return __log1p (__x + sqrt (__x) * sqrt (__x + 2.0));
-}
-
-__MATH_INLINE void sincos (double __x, double *__sinx, double *__cosx);
+/* Miscellaneous functions */
+
+__inline_mathcode (__sgn, __x, \
+  return __x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0))
+
+__inline_mathcode (__coshm1, __x, \
+  register long double __exm1 = __expm1l (__builtin_fabsl (__x));	      \
+  return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1)
+
+__inline_mathcode (__acosh1p, __x, \
+  return log1pl (__x + __sqrtl (__x) * __sqrtl (__x + 2.0)))
+
+__inline_mathcode (__pow2, __x, \
+  register long double __value;						      \
+  register long double __exponent;					      \
+  long int __p = (long int) __x;					      \
+  if (__x == (long double) __p)						      \
+    return ldexpl (1.0, __p);						      \
+  __asm __volatile__							      \
+    ("fldl	%%st(0)\n\t"						      \
+     "frndint			# int(x)\n\t"				      \
+     "fxch\n\t"								      \
+     "fsub	%%st(1)		# fract(x)\n\t"				      \
+     "f2xm1			# 2^(fract(x)) - 1\n\t"			      \
+     : "=t" (__value), "=u" (__exponent) : "0" (__x));			      \
+  __value += 1.0;							      \
+  __asm __volatile__							      \
+    ("fscale"								      \
+     : "=t" (__value) : "0" (__value), "u" (__exponent));		      \
+  return __value)
+
+#define __sincos_code \
+  register long double __cosr;						      \
+  register long double __sinr;						      \
+  __asm __volatile__							      \
+    ("fsincos\n\t"							      \
+     "fnstsw	%%ax\n\t"						      \
+     "testl	$0x400, %%eax\n\t"					      \
+     "jz	1f\n\t"							      \
+     "fldpi\n\t"							      \
+     "fadd	%%st(0)\n\t"						      \
+     "fxch	%%st(1)\n\t"						      \
+     "2: fprem1\n\t"							      \
+     "fnstsw	%%ax\n\t"						      \
+     "testl	$0x400, %%eax\n\t"					      \
+     "jnz	2b\n\t"							      \
+     "fstp	%%st(1)\n\t"						      \
+     "fsincos\n\t"							      \
+     "1:"								      \
+     : "=t" (__cosr), "=u" (__sinr) : "0" (__x));			      \
+  *__sinx = __sinr;							      \
+  *__cosx = __cosr
+
+__MATH_INLINE void __sincos (double __x, double *__sinx, double *__cosx);
 __MATH_INLINE void
-sincos (double __x, double *__sinx, double *__cosx)
+__sincos (double __x, double *__sinx, double *__cosx)
 {
-  register double __cosr, __sinr;
-  __asm __volatile__
-    ("fsincos\n\t"
-     "fnstsw	%%ax\n\t"
-     "testl	$0x400, %%eax\n\t"
-     "jz	1f\n\t"
-     "fldpi\n\t"
-     "fadd	%%st(0)\n\t"
-     "fxch	%%st(1)\n\t"
-     "2: fprem1\n\t"
-     "fnstsw	%%ax\n\t"
-     "testl	$0x400, %%eax\n\t"
-     "jnz	2b\n\t"
-     "fstp	%%st(1)\n\t"
-     "fsincos\n\t"
-     "1:"
-     : "=t" (__cosr), "=u" (__sinr) : "0" (__x));
-
-  *__sinx = __sinr;
-  *__cosx = __cosr;
+  __sincos_code;
 }
 
-__MATH_INLINE double sgn (double __x);
-__MATH_INLINE double
-sgn (double __x)
+__MATH_INLINE void __sincosf (float __x, float *__sinx, float *__cosx);
+__MATH_INLINE void
+__sincosf (float __x, float *__sinx, float *__cosx)
 {
-  return __x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0);
+  __sincos_code;
 }
 
-__MATH_INLINE double pow2 (double __x);
-__MATH_INLINE double
-pow2 (double __x)
+__MATH_INLINE void __sincosl (long double __x, long double *__sinx,
+			      long double *__cosx);
+__MATH_INLINE void
+__sincosl (long double __x, long double *__sinx, long double *__cosx)
 {
-  register double __value, __exponent;
-  long __p = (long) __x;
-
-  if (__x == (double) __p)
-    return ldexp (1.0, __p);
-
-  __asm __volatile__
-    ("fldl	%%st(0)\n\t"
-     "frndint			# int(x)\n\t"
-     "fxch\n\t"
-     "fsub	%%st(1)		# fract(x)\n\t"
-     "f2xm1			# 2^(fract(x)) - 1\n\t"
-     : "=t" (__value), "=u" (__exponent) : "0" (__x));
-  __value += 1.0;
-  __asm __volatile__
-    ("fscale"
-     : "=t" (__value) : "0" (__value), "u" (__exponent));
-
-  return __value;
+  __sincos_code;
 }
 
 #endif /* __USE_MISC  */
 
+/* Undefine some of the large macros which are not used anymore.  */
+#undef __expm1_code
+#undef __exp_code
+#undef __atan2_code
+#undef __sincos_code
+
 #endif /* __NO_MATH_INLINES  */
 #endif /* __GNUC__  */
 
diff --git a/sysdeps/m68k/bits/byteswap.h b/sysdeps/m68k/bits/byteswap.h
new file mode 100644
index 0000000000..54ec0d1920
--- /dev/null
+++ b/sysdeps/m68k/bits/byteswap.h
@@ -0,0 +1,63 @@
+/* Macros to swap the order of bytes in integer values.  m68k version.
+   Copyright (C) 1997 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _BITS_BYTESWAP_H
+#define _BITS_BYTESWAP_H	1
+
+/* Swap bytes in 16 bit value.  We don't provide an assembler version
+   because GCC is smart enough to generate optimal assembler output, and
+   this allows for better cse.  */
+#define __bswap_16(x) \
+  ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
+
+/* Swap bytes in 32 bit value.  */
+#define __bswap_constant_32(x) \
+  ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >>  8) | \
+   (((x) & 0x0000ff00) <<  8) | (((x) & 0x000000ff) << 24))
+
+#if defined __GNUC__ && __GNUC__ >= 2
+#define __bswap_32(x) \
+  __extension__					\
+  ({ unsigned int __v;				\
+     if (__builtin_constant_p (x))		\
+       __v = __bswap_constant_32 (x);		\
+     else					\
+       __asm__ __volatile__ ("ror%.w %#8, %0;"	\
+			     "swap %0;"		\
+			     "ror%.w %#8, %0"	\
+			     : "=d" (__v)	\
+			     : "0" (x));	\
+     __v; })
+#else
+#define __bswap_32(x) __bswap_constant_32 (x)
+#endif
+
+#if defined __GNUC__ && __GNUC__ >= 2
+/* Swap bytes in 64 bit value.  */
+#define __bswap_64(x) \
+  __extension__						\
+  ({ union { unsigned long long int __ll;		\
+	     unsigned long int __l[2]; } __v, __r;	\
+     __v.__ll = (x);					\
+     __r.__l[0] = __bswap_32 (__v.__l[1]);		\
+     __r.__l[1] = __bswap_32 (__v.__l[0]);		\
+     __r.__ll; })
+#endif
+
+#endif /* bits/byteswap.h */
diff --git a/sysdeps/m68k/dl-machine.h b/sysdeps/m68k/dl-machine.h
index c0a17c73c2..7c62aa2aad 100644
--- a/sysdeps/m68k/dl-machine.h
+++ b/sysdeps/m68k/dl-machine.h
@@ -76,7 +76,7 @@ elf_machine_load_address (void)
    entries will jump to the on-demand fixup code in dl-runtime.c.  */
 
 static inline int
-elf_machine_runtime_setup (struct link_map *l, int lazy)
+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 {
   Elf32_Addr *got;
   extern void _dl_runtime_resolve (Elf32_Word);
@@ -211,10 +211,9 @@ _dl_start_user:
 
 static inline void
 elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
-		  const Elf32_Sym *sym, const struct r_found_version *version)
+		  const Elf32_Sym *sym, const struct r_found_version *version,
+		  Elf32_Addr *const reloc_addr)
 {
-  Elf32_Addr *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
-
   if (ELF32_R_TYPE (reloc->r_info) == R_68K_RELATIVE)
     *reloc_addr = map->l_addr + reloc->r_addend;
   else
diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h
index fce7cffb4a..6973f7612a 100644
--- a/sysdeps/mips/dl-machine.h
+++ b/sysdeps/mips/dl-machine.h
@@ -219,7 +219,7 @@ elf_machine_got_rel (struct link_map *map, int lazy)
    will jump to the on-demand fixup code in dl-runtime.c.  */
 
 static inline int
-elf_machine_runtime_setup (struct link_map *l, int lazy)
+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 {
   ElfW(Addr) *got;
   extern void _dl_runtime_resolve (ElfW(Word));
@@ -533,9 +533,9 @@ _RTLD_EPILOGUE(ENTRY_POINT)\
 
 static inline void
 elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
-		 const ElfW(Sym) *sym, const struct r_found_version *version)
+		 const ElfW(Sym) *sym, const struct r_found_version *version,
+		 ElfW(Addr) *const reloc_addr)
 {
-  ElfW(Addr) *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
   ElfW(Addr) loadbase;
   ElfW(Addr) undo __attribute__ ((unused));
 
diff --git a/sysdeps/mips/mips64/dl-machine.h b/sysdeps/mips/mips64/dl-machine.h
index a20835af35..e501a2520e 100644
--- a/sysdeps/mips/mips64/dl-machine.h
+++ b/sysdeps/mips/mips64/dl-machine.h
@@ -219,7 +219,7 @@ elf_machine_got_rel (struct link_map *map, int lazy)
    will jump to the on-demand fixup code in dl-runtime.c.  */
 
 static inline int
-elf_machine_runtime_setup (struct link_map *l, int lazy)
+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 {
   ElfW(Addr) *got;
   extern void _dl_runtime_resolve (ElfW(Word));
@@ -529,9 +529,9 @@ _RTLD_EPILOGUE(ENTRY_POINT) \
 
 static inline void
 elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
-		 const ElfW(Sym) *sym, const struct r_found_version *version)
+		 const ElfW(Sym) *sym, const struct r_found_version *version,
+		 ElfW(Addr) *const reloc_addr)
 {
-  ElfW(Addr) *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
   ElfW(Addr) loadbase;
   ElfW(Addr) undo __attribute__ ((unused));
 
diff --git a/sysdeps/powerpc/dl-machine.h b/sysdeps/powerpc/dl-machine.h
index 12bcf43e4d..c9d1d7332a 100644
--- a/sysdeps/powerpc/dl-machine.h
+++ b/sysdeps/powerpc/dl-machine.h
@@ -391,7 +391,7 @@ static ElfW(Addr) _dl_preferred_address = 1
 	 ELF_MACHINE_RUNTIME_TRAMPOLINE, which resets the PLT entry to
 	 be one of the above two types. These entries are set up here.  */
 static inline int
-elf_machine_runtime_setup (struct link_map *map, int lazy)
+elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
 {
   if (map->l_info[DT_JMPREL])
     {
@@ -510,10 +510,10 @@ elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc)
 
 static inline void
 elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
-		  const Elf32_Sym *sym, const struct r_found_version *version)
+		  const Elf32_Sym *sym, const struct r_found_version *version,
+		  Elf32_addr *const reloc_addr)
 {
   const Elf32_Sym *const refsym = sym;
-  Elf32_Addr *const reloc_addr = (Elf32_Addr *)(map->l_addr + reloc->r_offset);
   Elf32_Word loadbase, finaladdr;
   const int rinfo = ELF32_R_TYPE (reloc->r_info);
 
diff --git a/sysdeps/sparc/dl-machine.h b/sysdeps/sparc/dl-machine.h
index 1d193ae91c..b50549c0ec 100644
--- a/sysdeps/sparc/dl-machine.h
+++ b/sysdeps/sparc/dl-machine.h
@@ -224,7 +224,7 @@ elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc)
    entries will jump to the on-demand fixup code in dl-runtime.c.  */
 
 static inline int
-elf_machine_runtime_setup (struct link_map *l, int lazy)
+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 {
   Elf32_Addr *plt;
   extern void _dl_runtime_resolve (Elf32_Word);
diff --git a/sysdeps/sparc64/dl-machine.h b/sysdeps/sparc64/dl-machine.h
index ad216b79dc..df09c8fc85 100644
--- a/sysdeps/sparc64/dl-machine.h
+++ b/sysdeps/sparc64/dl-machine.h
@@ -68,9 +68,9 @@ elf_machine_load_address (void)
 
 static inline void
 elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
-		  const Elf64_Sym *sym, const struct r_found_version *version)
+		  const Elf64_Sym *sym, const struct r_found_version *version,
+		  Elf64_Addr *const reloc_addr)
 {
-  Elf64_Addr *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
   Elf64_Addr loadbase;
 
 #ifndef RTLD_BOOTSTRAP
@@ -200,7 +200,7 @@ elf_machine_lazy_rel (struct link_map *map, const Elf64_Rela *reloc)
    entries will jump to the on-demand fixup code in dl-runtime.c.  */
 
 static inline int
-elf_machine_runtime_setup (struct link_map *l, int lazy)
+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 {
   Elf64_Addr *got;
   extern void _dl_runtime_resolve (Elf64_Word);
diff --git a/sysdeps/unix/sysv/linux/bits/socket.h b/sysdeps/unix/sysv/linux/bits/socket.h
index e3f53a97be..a17c37fd8e 100644
--- a/sysdeps/unix/sysv/linux/bits/socket.h
+++ b/sysdeps/unix/sysv/linux/bits/socket.h
@@ -28,6 +28,7 @@
 #define __need_NULL
 #include <stddef.h>
 
+#include <sys/types.h>
 
 __BEGIN_DECLS
 
@@ -130,25 +131,26 @@ struct msghdr
   {
     __ptr_t msg_name;		/* Address to send to/receive from.  */
     int msg_namelen;		/* Length of address data.  */
-    /* XXX Should be type `size_t' according to POSIX.1g.  */
+    /* XXX Should be type `socklen_t' according to POSIX.1g.  */
 
     struct iovec *msg_iov;	/* Vector of data to send/receive into.  */
     size_t msg_iovlen;		/* Number of elements in the vector.  */
 
     __ptr_t msg_control;	/* Ancillary data (eg BSD filedesc passing). */
-    size_t msg_controllen;	/* Ancillary data buffer length.  */
+    socklen_t msg_controllen;	/* Ancillary data buffer length.  */
     int msg_flags;		/* Flags on received message.  */
   };
 
 /* Structure used for storage of ancillary data object information.  */
 struct cmsghdr
   {
-    size_t cmsg_len;		/* Length of data in cmsg_data plus length
+    socklen_t cmsg_len;		/* Length of data in cmsg_data plus length
 				   of cmsghdr structure.  */
     int cmsg_level;		/* Originating protocol.  */
     int cmsg_type;		/* Protocol specific type.  */
 #if !defined __STRICT_ANSI__ && defined __GNUC__ && __GNUC__ >= 2
     unsigned char __cmsg_data[0]; /* Ancillary data.  */
+    /* XXX Perhaps this should be removed.  */
 #endif
   };