mirror of
git://sourceware.org/git/glibc.git
synced 2024-11-21 01:12:26 +08:00
Update.
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.
This commit is contained in:
parent
0a54e4010f
commit
3996f34b46
108
ChangeLog
108
ChangeLog
@ -1,3 +1,111 @@
|
||||
1997-07-28 23:35 Ulrich Drepper <drepper@cygnus.com>
|
||||
|
||||
* csu/gmon-start.c (__gmon_start__): Call __monstartup not
|
||||
monstartup.
|
||||
* gmon/gmon.c: Rename moncontrol to __moncontrol and monstartup
|
||||
to __monstartup.
|
||||
* gmon/sys/gmon.h: Fix prototypes.
|
||||
* gmon/sys/gmon_out.h: Pretty print.
|
||||
|
||||
* gmon/bb_exit_func.c (__bb_exit_func): Use memcpy instead of bcopy.
|
||||
* gmon/gmon.c (__monstartup): Likewise.
|
||||
(write_hist): Remove dependency on 32 int.
|
||||
(_mcleanup): Don't call perror, use fprintf.
|
||||
|
||||
* elf/dl-load.c: Fix handling of current directory in search path.
|
||||
|
||||
* elf/Makefile (dl-routines): Add dl-profile.
|
||||
* elf/dl-profile.c: New file.
|
||||
* elf/dl-runtime.c (fixup): Add new parameter with address to store
|
||||
relocation result in to elf_machine_relplt.
|
||||
(profile_fixup): New function.
|
||||
* elf/do-rel.h (elf_dynamic_do_rel): Add new parameter with address
|
||||
to store relocation result in to elf_machine_relplt.
|
||||
* elf/dl-support.c: Define _dl_profile and _dl_profile_map.
|
||||
* elf/dynamic-link.h (ELF_DYNAMIC_RELOCATE): Add new parameter and
|
||||
call elf_machine_runtime_setup with extra argument.
|
||||
* elf/dl-reloc.c (_dl_relocate_object): Add new argument to
|
||||
ELF_DYNAMIC_RELOCATE.
|
||||
* elf/link.h: Add prototypes for new functions and variables.
|
||||
* elf/rtld.c: Parse LD_PROFILE and LD_PROFILE_OUTPUT environment
|
||||
variables and call _dl_start_profile if necessary.
|
||||
* include/sys/gmon_out.h: New file.
|
||||
* sysdeps/alpha/dl-machine.h (elf_machine_runtime_setup): Add
|
||||
new parameter to enable profiling.
|
||||
(elf_machine_rela): Add new parameter to specify place to store
|
||||
result in.
|
||||
* sysdeps/m68k/dl-machine.h: Likewise.
|
||||
* sysdeps/mips/dl-machine.h: Likewise.
|
||||
* sysdeps/mips/mips64/dl-machine.h: Likewise.
|
||||
* sysdeps/powerpc/dl-machine.h: Likewise.
|
||||
* sysdeps/sparc/dl-machine.h: Likewise.
|
||||
* sysdeps/sparc64/dl-machine.h: Likewise.
|
||||
* sysdeps/i386/dl-machine.h: Likewise.
|
||||
(elf_machine_runtime_setup): Setup got[2] to _dl_runtime_resolve if
|
||||
we do profiling.
|
||||
(ELF_MACHINE_RUNTIME_TRAMPOLINE): Add code for _dl_runtime_profile.
|
||||
|
||||
* nis/nss_compat/compat-grp.c (internal_setgrent): Set FD_CLOEXEC
|
||||
for stream on input file.
|
||||
* nis/nss_compat/compat-pwd.c (internal_setpwent): Likewise.
|
||||
* nis/nss_compat/compat-spwd.c (internal_setspent): Likewise.
|
||||
* nss/nss_db/db-XXX.c (internal_setent): Likewise.
|
||||
* nss/nss_db/db-alias.c (internal_setent): Likewise.
|
||||
* nss/nss_db/db-netgrp.c (internal_setent): Likewise.
|
||||
* nss/nss_files/files-XXX.c (internal_setent): Likewise.
|
||||
* nss/nss_files/files-alias.c (internal_setent): Likewise.
|
||||
* nss/nss_files/files-netgrp.c (internal_setent): Likewise.
|
||||
|
||||
* string/string.h: Pretty print.
|
||||
|
||||
* sysdeps/i386/fpu/bits/mathinline.h: Major update by John Bowman.
|
||||
Add float and long double versions.
|
||||
|
||||
1997-07-27 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
|
||||
|
||||
* elf/rtld.c (print_unresolved): Replace empty object name by main
|
||||
program name.
|
||||
|
||||
1997-07-27 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
|
||||
|
||||
* sysdeps/generic/htons.c (htons): Renamed from __htons.
|
||||
|
||||
1997-07-27 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
|
||||
|
||||
* sysdeps/m68k/bits/byteswap.h: New file.
|
||||
|
||||
1997-07-27 23:50 Philip Blundell <Philip.Blundell@pobox.com>
|
||||
|
||||
* inet/netinet/icmp6.h: Update for new drafts of POSIX.1g and IPv6
|
||||
advanced API.
|
||||
* inet/netinet/in.h: Likewise.
|
||||
* inet/netinet/ip6.h: Likewise.
|
||||
* sysdeps/unix/sysv/linux/bits/socket.h: Likewise.
|
||||
* posix/sys/types.h: Add socklen_t.
|
||||
|
||||
* manual/socket.texi: Document some more IPv6 things.
|
||||
* manual/libc.texinfo: Likewise.
|
||||
|
||||
1997-07-26 Andreas Jaeger <aj@arthur.rhein-neckar.de>
|
||||
|
||||
* libc.map: Define missing symbol.
|
||||
|
||||
1997-07-27 14:31 Thorsten Kukuk <kukuk@vt.uni-paderborn.de>
|
||||
|
||||
* nis/Makefile: Add nis_findserv.
|
||||
* nis/lckcache.c: Fix typo.
|
||||
* nis/nis_call.c: Fix problems with multihomed servers.
|
||||
* nis/nis_findserv.c: New file.
|
||||
* nis/nis_intern.h: Add more prototypes.
|
||||
* nis/nis_lookup.c (nis_lookup): Don't try the next server if network
|
||||
is unreachable.
|
||||
* nis/nis_table.c (nis_list): Likewise.
|
||||
* nis/nis_ping.c (nis_ping): Use MASTER_ONLY, don't call abort()
|
||||
in error case.
|
||||
* nis/nis_util.c (__nis_finddirectory): Give the right error code
|
||||
back.
|
||||
* nis/ypclnt.c: Make sure, that all sockets are closed.
|
||||
|
||||
1997-07-26 04:14 Ulrich Drepper <drepper@cygnus.com>
|
||||
|
||||
* elf/Makefile (distribute): Add genrtldtbl.awk.
|
||||
|
30
aout/Makefile
Normal file
30
aout/Makefile
Normal file
@ -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
|
||||
|
12
config.guess
vendored
12
config.guess
vendored
@ -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 ;;
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
267
elf/dl-profile.c
Normal file
267
elf/dl-profile.c
Normal file
@ -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;
|
||||
}
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
13
elf/link.h
13
elf/link.h
@ -225,6 +225,11 @@ extern size_t _dl_pagesize;
|
||||
/* File descriptor referring to the zero-fill device. */
|
||||
extern int _dl_zerofd;
|
||||
|
||||
/* Name of the shared object to be profiled (if any). */
|
||||
extern const char *_dl_profile;
|
||||
/* Map of shared object to be profiled. */
|
||||
extern struct link_map *_dl_profile_map;
|
||||
|
||||
/* OS-dependent function to open the zero-fill device. */
|
||||
extern int _dl_sysdep_open_zero_fill (void); /* dl-sysdep.c */
|
||||
|
||||
@ -430,8 +435,14 @@ extern void _dl_debug_state (void);
|
||||
extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase);
|
||||
|
||||
/* Initialize the basic data structure for the search paths. */
|
||||
void _dl_init_paths (void);
|
||||
extern void _dl_init_paths (void);
|
||||
|
||||
/* Gather the information needed to install the profiling tables and start
|
||||
the timers. */
|
||||
extern void _dl_start_profile (struct link_map *map, const char *output_dir);
|
||||
|
||||
/* The actual functions used to keep book on the calls. */
|
||||
extern void _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
32
elf/rtld.c
32
elf/rtld.c
@ -61,6 +61,9 @@ int _dl_verbose;
|
||||
const char *_dl_platform;
|
||||
size_t _dl_platformlen;
|
||||
struct r_search_path *_dl_search_paths;
|
||||
const char *_dl_profile;
|
||||
const char *_dl_profile_output;
|
||||
struct link_map *_dl_profile_map;
|
||||
|
||||
/* Set nonzero during loading and initialization of executable and
|
||||
libraries, cleared before the executable's entry point runs. This
|
||||
@ -109,7 +112,7 @@ _dl_start (void *arg)
|
||||
/* Relocate ourselves so we can do normal function calls and
|
||||
data access using the global offset table. */
|
||||
|
||||
ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0);
|
||||
ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0);
|
||||
|
||||
/* Now life is sane; we can call functions and access global data.
|
||||
Set up to use the operating system facilities, and find out from
|
||||
@ -269,6 +272,26 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
else
|
||||
lazy = !__libc_enable_secure && *(getenv ("LD_BIND_NOW") ?: "") == '\0';
|
||||
|
||||
/* See whether we want to use profiling. */
|
||||
_dl_profile = getenv ("LD_PROFILE");
|
||||
if (_dl_profile != NULL)
|
||||
if (_dl_profile[0] == '\0')
|
||||
/* An empty string is of not much help. Disable profiling. */
|
||||
_dl_profile = NULL;
|
||||
else
|
||||
{
|
||||
/* OK, we have the name of a shared object we want to
|
||||
profile. It's up to the user to provide a good name, it
|
||||
must match the file name or soname of one of the loaded
|
||||
objects. Now let's see where we are supposed to place the
|
||||
result. */
|
||||
_dl_profile_output = getenv ("LD_PROFILE_OUTPUT");
|
||||
|
||||
if (_dl_profile_output == NULL || _dl_profile_output[0] == '\0')
|
||||
/* This is the default place. */
|
||||
_dl_profile_output = "/var/tmp";
|
||||
}
|
||||
|
||||
/* Set up a flag which tells we are just starting. */
|
||||
_dl_starting_up = 1;
|
||||
|
||||
@ -814,6 +837,11 @@ of this helper program; chances are you did not intend to run this program.\n",
|
||||
_dl_debug_state ();
|
||||
}
|
||||
|
||||
/* Now enable profiling if needed. */
|
||||
if (_dl_profile_map != NULL)
|
||||
/* We must prepare the profiling. */
|
||||
_dl_start_profile (_dl_profile_map, _dl_profile_output);
|
||||
|
||||
/* Once we return, _dl_sysdep_start will invoke
|
||||
the DT_INIT functions and then *USER_ENTRY. */
|
||||
}
|
||||
@ -824,6 +852,8 @@ static void
|
||||
print_unresolved (int errcode __attribute__ ((unused)), const char *objname,
|
||||
const char *errstring)
|
||||
{
|
||||
if (objname[0] == '\0')
|
||||
objname = _dl_argv[0] ?: "<main program>";
|
||||
_dl_sysdep_error (errstring, " (", objname, ")\n", NULL);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
26
gmon/gmon.c
26
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: */
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
1
include/sys/gmon_out.h
Normal file
1
include/sys/gmon_out.h
Normal file
@ -0,0 +1 @@
|
||||
#include <gmon/sys/gmon_out.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;
|
||||
};
|
||||
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 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 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 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 ICMP6_DST_UNREACH 1
|
||||
#define ICMP6_PACKET_TOO_BIG 2
|
||||
#define ICMP6_TIME_EXCEEDED 3
|
||||
#define ICMP6_PARAM_PROB 4
|
||||
|
||||
#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 ICMP6_INFOMSG_MASK 0x80 /* all informational messages */
|
||||
|
||||
#define ICMPV6_FILTER_WILLPASS(type, filterp) \
|
||||
#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]
|
||||
|
||||
struct nd_opt_hdr /* Neighbor discovery option header */
|
||||
{
|
||||
uint8_t nd_opt_type;
|
||||
uint8_t nd_opt_len; /* in units of 8 octets */
|
||||
/* followed by option specific data */
|
||||
};
|
||||
|
||||
#define nadv6_flags nadv6_hdr.icmpv6_data32[0]
|
||||
#define ND6_NADVERFLAG_ISROUTER 0x80
|
||||
#define ND6_NADVERFLAG_SOLICITED 0x40
|
||||
#define ND6_NADVERFLAG_OVERRIDE 0x20
|
||||
#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 nd6_redirect /* redirect */
|
||||
struct nd_opt_prefix_info /* prefix information */
|
||||
{
|
||||
struct icmpv6hdr redirect_hdr;
|
||||
struct in6_addr redirect_target;
|
||||
struct in6_addr redirect_destination;
|
||||
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;
|
||||
};
|
||||
|
||||
struct nd6_opt_prefix_info /* prefix information */
|
||||
#define ND_OPT_PI_FLAG_ONLINK 0x80
|
||||
#define ND_OPT_PI_FLAG_AUTO 0x40
|
||||
|
||||
struct nd_opt_rd_hdr /* redirected header */
|
||||
{
|
||||
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_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 */
|
||||
};
|
||||
|
||||
#define ND6_OPT_PI_L_BIT 0x80
|
||||
#define ND6_OPT_PI_A_BIT 0x40
|
||||
|
||||
struct nd6_opt_mtu /* MTU option */
|
||||
struct nd_opt_mtu /* MTU option */
|
||||
{
|
||||
u_int8_t opt_type;
|
||||
u_int8_t opt_length;
|
||||
u_int16_t opt_reserved;
|
||||
u_int32_t opt_mtu;
|
||||
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 */
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
2
libc.map
2
libc.map
@ -7,7 +7,7 @@ GLIBC_2.0 {
|
||||
_nl_msg_cat_cntr; __environ; _environ; _res;
|
||||
___brk_addr; __curbrk; _nl_current_LC_CTYPE; _libc_intl_domainname;
|
||||
_sys_errlist; _sys_siglist; __progname; _nl_default_dirname;
|
||||
__timezone; __daylight;
|
||||
__timezone; __daylight; __tzname;
|
||||
_nl_current_LC_COLLATE; __collate_element_hash;
|
||||
__collate_element_strings; __collate_symbol_classes;
|
||||
__collate_symbol_hash; __collate_symbol_strings;
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
@ -929,6 +1017,14 @@ The @code{gethostbyname} function returns information about the host
|
||||
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})
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
1
nis/TODO
1
nis/TODO
@ -9,4 +9,3 @@
|
||||
* Missing flags:
|
||||
- FOLLOW_PATH (nis_list, not supported)
|
||||
- ALL_RESULTS (nis_list, not supported, needs server callback)
|
||||
- NO_CACHE (__do_niscall, cache not supported yet)
|
||||
|
@ -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);
|
||||
}
|
||||
|
251
nis/nis_call.c
251
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;
|
||||
|
251
nis/nis_findserv.c
Normal file
251
nis/nis_findserv.c
Normal file
@ -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;
|
||||
}
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
16
nis/ypclnt.c
16
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);
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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. */
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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, ,,
|
||||
{
|
||||
|
@ -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. */
|
||||
|
@ -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). */
|
||||
|
@ -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
|
||||
|
@ -22,7 +22,7 @@
|
||||
#undef ntohs
|
||||
|
||||
u_int16_t
|
||||
__htons (x)
|
||||
htons (x)
|
||||
u_int16_t x;
|
||||
{
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
#define __inline_mathop_(float_type, func, op) \
|
||||
__inline_mathop_decl_ (float_type, func, op, "0" (__x))
|
||||
|
||||
|
||||
__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;
|
||||
#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
|
||||
|
||||
return __temp + __value;
|
||||
}
|
||||
#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; \
|
||||
}
|
||||
|
||||
__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));
|
||||
#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 fabs (double __x);
|
||||
__MATH_INLINE double
|
||||
fabs (double __x)
|
||||
{
|
||||
register double __value;
|
||||
__asm __volatile__
|
||||
("fabs"
|
||||
: "=t" (__value) : "0" (__x));
|
||||
|
||||
return __value;
|
||||
}
|
||||
#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
|
||||
|
||||
/* 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));
|
||||
#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; \
|
||||
}
|
||||
|
||||
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));
|
||||
/* 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)
|
||||
|
||||
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));
|
||||
#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)
|
||||
|
||||
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));
|
||||
__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)
|
||||
|
||||
return __value;
|
||||
}
|
||||
|
||||
__MATH_INLINE double asin (double __x);
|
||||
__MATH_INLINE double
|
||||
asin (double __x)
|
||||
{
|
||||
return atan2 (__x, sqrt (1.0 - __x * __x));
|
||||
}
|
||||
#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)
|
||||
|
||||
__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));
|
||||
__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)
|
||||
|
||||
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));
|
||||
__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)
|
||||
|
||||
return __value;
|
||||
}
|
||||
|
||||
__MATH_INLINE double sinh (double __x);
|
||||
__MATH_INLINE double
|
||||
sinh (double __x)
|
||||
{
|
||||
register double __exm1 = __expm1 (fabs (__x));
|
||||
__inline_mathop (sqrt, "fsqrt")
|
||||
__inline_mathop_ (long double, __sqrtl, "fsqrt")
|
||||
|
||||
return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1 (__x);
|
||||
}
|
||||
__inline_mathop (fabs, "fabs")
|
||||
|
||||
__MATH_INLINE double cosh (double __x);
|
||||
__MATH_INLINE double
|
||||
cosh (double __x)
|
||||
{
|
||||
register double __ex = exp (__x);
|
||||
/* 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")
|
||||
|
||||
return 0.5 * (__ex + 1.0 / __ex);
|
||||
}
|
||||
__inline_mathop (atan, "fld1; fpatan")
|
||||
__inline_mathop (log, "fldln2; fxch; fyl2x")
|
||||
__inline_mathop (log10, "fldlg2; fxch; fyl2x")
|
||||
|
||||
__MATH_INLINE double tanh (double __x);
|
||||
__MATH_INLINE double
|
||||
tanh (double __x)
|
||||
{
|
||||
register double __exm1 = __expm1 (-fabs (__x + __x));
|
||||
__inline_mathcode (asin, __x, return __atan2l (__x, __sqrtl (1.0 - __x * __x)))
|
||||
__inline_mathcode (acos, __x, return __atan2l (__sqrtl (1.0 - __x * __x), __x))
|
||||
|
||||
return __exm1 / (__exm1 + 2.0) * __sgn1 (-__x);
|
||||
}
|
||||
__inline_mathcode (__sgn1, __x, return __x >= 0.0 ? 1.0 : -1.0)
|
||||
|
||||
__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;
|
||||
}
|
||||
/* 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))
|
||||
|
||||
__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));
|
||||
__inline_mathcode (cosh, __x, \
|
||||
register long double __ex = __expl (__x); \
|
||||
return 0.5 * (__ex + 1.0 / __ex))
|
||||
|
||||
return __value;
|
||||
}
|
||||
__inline_mathcode (tanh, __x, \
|
||||
register long double __exm1 = __expm1l (-__builtin_fabsl (__x + __x)); \
|
||||
return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
|
||||
|
||||
__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;
|
||||
}
|
||||
__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)
|
||||
|
||||
__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;
|
||||
}
|
||||
|
||||
__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;
|
||||
|
||||
__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;
|
||||
}
|
||||
|
||||
__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));
|
||||
|
||||
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;
|
||||
__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)
|
||||
|
||||
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;
|
||||
}
|
||||
/* 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))
|
||||
|
||||
__MATH_INLINE double asinh (double __x);
|
||||
__MATH_INLINE double
|
||||
asinh (double __x)
|
||||
{
|
||||
register double __y = fabs (__x);
|
||||
__inline_mathcode (acosh, __x, \
|
||||
return logl (__x + __sqrtl (__x - 1.0) * __sqrtl (__x + 1.0)))
|
||||
|
||||
return log1p ((__y * __y / (sqrt (__y * __y + 1.0) + 1.0) + __y)
|
||||
* __sgn1 (__x));
|
||||
}
|
||||
__inline_mathcode (atanh, __x, \
|
||||
register long double __y = __builtin_fabsl (__x); \
|
||||
return (-0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * \
|
||||
__sgn1l (__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);
|
||||
/* The argument range of the inline version of hypotl is slightly reduced. */
|
||||
__inline_mathcode2 (hypot, __x, __y, return __sqrtl (__x * __x + __y * __y))
|
||||
|
||||
return -0.5 * __log1p (-(__y + __y) / (1.0 + __y)) * __sgn1 (__x);
|
||||
}
|
||||
__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)
|
||||
|
||||
__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_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");
|
||||
__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)
|
||||
|
||||
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));
|
||||
/* Miscellaneous functions */
|
||||
|
||||
return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1;
|
||||
}
|
||||
__inline_mathcode (__sgn, __x, \
|
||||
return __x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0))
|
||||
|
||||
__MATH_INLINE double acosh1p (double __x);
|
||||
__MATH_INLINE double
|
||||
acosh1p (double __x)
|
||||
{
|
||||
return __log1p (__x + sqrt (__x) * sqrt (__x + 2.0));
|
||||
}
|
||||
__inline_mathcode (__coshm1, __x, \
|
||||
register long double __exm1 = __expm1l (__builtin_fabsl (__x)); \
|
||||
return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1)
|
||||
|
||||
__MATH_INLINE void sincos (double __x, double *__sinx, double *__cosx);
|
||||
__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__ */
|
||||
|
||||
|
63
sysdeps/m68k/bits/byteswap.h
Normal file
63
sysdeps/m68k/bits/byteswap.h
Normal file
@ -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 */
|
@ -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
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user