diff options
60 files changed, 2180 insertions, 919 deletions
@@ -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 0000000..b1e2d64 --- /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 a73a8d9..ee2742b 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 02c44e2..8c66905 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 e447114..904099c 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 1301e73..f7c2c53 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 0000000..cc25b61 --- /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 5b22a50..4f6eff8 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 7a44ea4..1b34026 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 3333bf1..41997cc 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 766e62c..7f4b125 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 3377ee7..4a946f8 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 @@ -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 @@ -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 dc9def2..53ddbfd 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 d484ec2..6b7ef81 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 2eff69b..8368ca1 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 bb80a1a..c84f945 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 0000000..249f834 --- /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 224fb64..38c1bc1 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 d2a366b..9eda281 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 2930578..cd42ef6 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 */ @@ -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 7d81247..2d79d96 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 c122106..6efc54d 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 fd306fa..813d3c2 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 c10c175..e7dd50c 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 @@ -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 ead5773..f8c0a97 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 f25b801..1dfb129 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 0000000..a04abd8 --- /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 a7cb785..fdc392a 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 82db7b0..6224b1f 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 941adfb..4ec34ce 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 16fd1e6..a3bfa2c 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 4e39d6f..b6eef9b 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 9726784..35ae2f7 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 af12679..6fac0f4 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 61a703c..a4c6201 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 8559714..7c9efec 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 0c1b1ad..54e7a75 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 8b8cb41..810fc3a 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 e716dd0..c301789 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 3281580..e80c06d 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 99217fa..0a910aa 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 239dea7..d6c4152 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 f49c996..1319660 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 f790a24..5621dfb 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 49d6830..746cdd2 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 8914f74..1bbda3f 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 d6fc038..e517cff 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 4228959..2fc5baf 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 0000000..54ec0d1 --- /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 c0a17c7..7c62aa2 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 fce7cff..6973f76 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 a20835a..e501a25 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 12bcf43..c9d1d73 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 1d193ae..b50549c 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 ad216b7..df09c8f 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 e3f53a9..a17c37f 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 }; |