1999-10-27  Andreas Jaeger  <aj@suse.de>

	* sysdeps/generic/ifreq.h: New file.

	* resolv/res_hconf.c: Add missing includes to get all prototypes.
	(_res_hconf_reorder_addrs): Rewrite.  This never worked before.
	Reported by John DiMarco <jdd@cs.toronto.edu>.

	(_res_hconf_reorder_addrs): Made thread safe.
	(free_mem): New function, needed for malloc debugging.

1999-10-29  Andreas Jaeger  <aj@suse.de>

	* sysdeps/unix/sysv/linux/if_index.c (opensock): Move function to ...
	* sysdeps/generic/opensock.c (__opensock): ...here in a new file.
	* sysdeps/unix/sysv/linux/if_index.c: Change all callers of
	opensock to use __opensock.

	* socket/Makefile (routines): Add opensock.

	* include/sys/socket.h (__opensock): Add prototype declaration.
This commit is contained in:
Ulrich Drepper 1999-10-29 21:40:21 +00:00
parent 26d63253e1
commit f720d3d212
7 changed files with 267 additions and 113 deletions

View File

@ -1,3 +1,25 @@
1999-10-27 Andreas Jaeger <aj@suse.de>
* sysdeps/generic/ifreq.h: New file.
* resolv/res_hconf.c: Add missing includes to get all prototypes.
(_res_hconf_reorder_addrs): Rewrite. This never worked before.
Reported by John DiMarco <jdd@cs.toronto.edu>.
(_res_hconf_reorder_addrs): Made thread safe.
(free_mem): New function, needed for malloc debugging.
1999-10-29 Andreas Jaeger <aj@suse.de>
* sysdeps/unix/sysv/linux/if_index.c (opensock): Move function to ...
* sysdeps/generic/opensock.c (__opensock): ...here in a new file.
* sysdeps/unix/sysv/linux/if_index.c: Change all callers of
opensock to use __opensock.
* socket/Makefile (routines): Add opensock.
* include/sys/socket.h (__opensock): Add prototype declaration.
1999-10-29 Andreas Jaeger <aj@suse.de>
* sysdeps/unix/sysv/linux/mips/bits/ioctl-types.h: Added missing

View File

@ -3,4 +3,9 @@
/* Now define the internal interfaces. */
extern int __socket (int __domain, int __type, int __protocol) __THROW;
/* Return a socket of any type. The socket can be used in subsequent
ioctl calls to talk to the kernel. */
extern int __opensock (void) internal_function;
#endif

View File

@ -17,9 +17,9 @@
Boston, MA 02111-1307, USA. */
/* This file provides a Linux /etc/host.conf compatible front end to
the various name resolvers (/etc/hosts, named, NIS server, etc.).
Though mostly compatibly, the following differences exist compared
to the original implementation:
the various name resolvers (/etc/hosts, named, NIS server, etc.).
Though mostly compatibly, the following differences exist compared
to the original implementation:
- new command "spoof" takes an arguments like RESOLV_SPOOF_CHECK
environment variable (i.e., `off', `nowarn', or `warn').
@ -27,13 +27,19 @@ to the original implementation:
- line comments can appear anywhere (not just at the beginning of
a line)
*/
#include <errno.h>
#include <ctype.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netinet/in.h>
#include <bits/libc-lock.h>
#include "ifreq.h"
#include "res_hconf.h"
#define _PATH_HOSTCONF "/etc/host.conf"
@ -374,113 +380,118 @@ _res_hconf_init (void)
}
/* List of known interfaces. */
static struct netaddr
{
int addrtype;
union
{
struct
{
u_int32_t addr;
u_int32_t mask;
} ipv4;
} u;
} *ifaddrs;
/* We need to protect the dynamic buffer handling. */
__libc_lock_define_initialized (static, lock);
/* Reorder addresses returned in a hostent such that the first address
is an address on the local subnet, if there is such an address.
Otherwise, nothing is changed. */
Otherwise, nothing is changed.
Note that this function currently only handles IPv4 addresses. */
void
_res_hconf_reorder_addrs (struct hostent *hp)
{
#if defined SIOCGIFCONF && defined SIOCGIFNETMASK
static int num_ifs = -1; /* number of interfaces */
static struct netaddr
{
int addrtype;
union
{
struct
{
u_int32_t addr;
u_int32_t mask;
} ipv4
} u;
} *ifaddrs;
int i, j;
/* Number of interfaces. */
static int num_ifs = -1;
/* Only reorder if we're supposed to. */
if ((_res_hconf.flags & HCONF_FLAG_REORDER) == 0)
return;
/* Can't deal with anything but IPv4 for now... */
if (hp->h_addrtype != AF_INET)
return; /* can't deal with anything but IPv4 for now... */
return;
if (num_ifs <= 0)
{
struct ifconf ifs;
struct ifreq *ifr;
size_t size, num;
int sd;
struct ifreq *ifr, *cur_ifr;
int sd, num, i;
/* Save errno. */
int save = errno;
/* initialize interface table: */
/* Initialize interface table. */
num_ifs = 0;
sd = __socket (AF_INET, SOCK_DGRAM, 0);
sd = __opensock ();
if (sd < 0)
return;
/* Now get list of interfaces. Since we don't know how many
interfaces there are, we keep increasing the buffer size
until we have at least sizeof(struct ifreq) too many bytes.
That implies that the ioctl() return because it ran out of
interfaces, not memory */
size = 0;
ifs.ifc_buf = 0;
do
{
size += 4 * sizeof (struct ifreq);
ifs.ifc_buf = realloc (ifs.ifs_buf, size);
if (ifs.ifc_buf == NULL)
{
close (sd);
return;
}
ifs.ifc_len = size;
if (__ioctl (sd, SIOCGIFCONF, &ifs) < 0)
goto cleanup;
}
while (size - ifs.ifc_len < sizeof (struct ifreq));
/* Get lock. */
__libc_lock_lock (lock);
num = ifs.ifc_len / sizeof (struct ifreq);
/* Get a list of interfaces. */
__ifreq (&ifr, &num);
if (!ifr)
goto cleanup;
ifaddrs = malloc (num * sizeof (ifaddrs[0]));
if (!ifaddrs)
goto cleanup;
goto cleanup1;
ifr = ifs.ifc_req;
for (i = 0; i < num; ++i)
/* Copy usable interfaces in ifaddrs structure. */
for (cur_ifr = ifr, i = 0; i < num; ++cur_ifr, ++i)
{
if (ifr->ifr_addr.sa_family != AF_INET)
if (cur_ifr->ifr_addr.sa_family != AF_INET)
continue;
ifaddrs[num_ifs].addrtype = AF_INET;
ifaddrs[num_ifs].u.ipv4.addr =
((struct sockaddr_in *) &cur_ifr->ifr_addr)->sin_addr.s_addr;
memcpy (&ifaddrs[num_ifs].u.ipv4.addr,
&((struct sockaddr_in *)ifr->ifr_addr)->sin_addr, 4);
if (__ioctl (sd, SIOCGIFNETMASK, if) < 0)
if (__ioctl (sd, SIOCGIFNETMASK, cur_ifr) < 0)
continue;
memcpy (&ifaddrs[num_ifs].u.ipv4.mask,
((struct sockaddr_in *)ifr->ifr_mask)->sin_addr, 4);
++num_ifs; /* now we're committed to this entry */
ifaddrs[num_ifs].u.ipv4.mask =
((struct sockaddr_in *) &cur_ifr->ifr_netmask)->sin_addr.s_addr;
/* Now we're committed to this entry. */
++num_ifs;
}
/* just keep enough memory to hold all the interfaces we want: */
/* Just keep enough memory to hold all the interfaces we want. */
ifaddrs = realloc (ifaddrs, num_ifs * sizeof (ifaddrs[0]));
cleanup1:
__if_freereq (ifr);
cleanup:
/* Release lock, preserve error value, and close socket. */
save = errno;
__libc_lock_unlock (lock);
close (sd);
free (ifs.ifc_buf);
}
if (num_ifs == 0)
return;
/* find an address for which we have a direct connection: */
/* Find an address for which we have a direct connection. */
for (i = 0; hp->h_addr_list[i]; ++i)
{
h_addr = (struct in_addr *) hp->h_addr_list[i];
struct in_addr *haddr = (struct in_addr *) hp->h_addr_list[i];
for (j = 0; j < num_ifs; ++j)
{
if_addr = ifaddrs[j].u.ipv4.addr;
if_netmask = ifaddrs[j].u.ipv4.mask;
u_int32_t if_addr = ifaddrs[j].u.ipv4.addr;
u_int32_t if_netmask = ifaddrs[j].u.ipv4.mask;
if (((h_addr->s_addr ^ if_addr) & if_netmask) == 0)
if (((haddr->s_addr ^ if_addr) & if_netmask) == 0)
{
void *tmp;
@ -537,3 +548,14 @@ _res_hconf_trim_domains (struct hostent *hp)
for (i = 0; hp->h_aliases[i]; ++i)
_res_hconf_trim_domain (hp->h_aliases[i]);
}
/* Free all resources if necessary. */
static void __attribute__ ((unused))
free_mem (void)
{
if (ifaddrs != NULL)
free (ifaddrs);
}
text_set_element (__libc_subfreeres, free_mem);

View File

@ -26,6 +26,6 @@ headers := sys/socket.h sys/un.h bits/sockaddr.h bits/socket.h \
routines := accept bind connect getpeername getsockname getsockopt \
listen recv recvfrom recvmsg send sendmsg sendto \
setsockopt shutdown socket socketpair isfdtype
setsockopt shutdown socket socketpair isfdtype opensock
include ../Rules

76
sysdeps/generic/ifreq.h Normal file
View File

@ -0,0 +1,76 @@
/* Copyright (C) 1999 Free Software Foundation, Inc.
Contributed by Andreas Jaeger <aj@suse.de>.
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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
static inline void
__ifreq (struct ifreq **ifreqs, int *num_ifs)
{
int fd = __opensock ();
struct ifconf ifc;
int rq_len;
int nifs;
# define RQ_IFS 4
if (fd < 0)
{
*num_ifs = 0;
*ifreqs = NULL;
return;
}
ifc.ifc_buf = NULL;
rq_len = RQ_IFS * sizeof (struct ifreq);
do
{
ifc.ifc_len = rq_len;
ifc.ifc_buf = realloc (ifc.ifc_buf, ifc.ifc_len);
if (ifc.ifc_buf == NULL || __ioctl (fd, SIOCGIFCONF, &ifc) < 0)
{
if (ifc.ifc_buf)
free (ifc.ifc_buf);
__close (fd);
*num_ifs = 0;
*ifreqs = NULL;
return;
}
rq_len *= 2;
}
while (rq_len < sizeof (struct ifreq) + ifc.ifc_len);
nifs = ifc.ifc_len / sizeof (struct ifreq);
__close (fd);
*num_ifs = nifs;
*ifreqs = realloc (ifc.ifc_buf, nifs * sizeof (struct ifreq));
}
static inline void
__if_freereq (struct ifreq *ifreqs)
{
free (ifreqs);
}

View File

@ -0,0 +1,70 @@
/* Copyright (C) 1999 Free Software Foundation, Inc.
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 <stdio.h>
#include <sys/socket.h>
#include <bits/libc-lock.h>
/* Return a socket of any type. The socket can be used in subsequent
ioctl calls to talk to the kernel. */
int internal_function
__opensock (void)
{
/* Cache the last AF that worked, to avoid many redundant calls to
socket(). */
static int sock_af = -1;
int fd = -1;
__libc_lock_define_initialized (static, lock);
if (sock_af != -1)
{
fd = __socket (sock_af, SOCK_DGRAM, 0);
if (fd != -1)
return fd;
}
__libc_lock_lock (lock);
if (sock_af != -1)
fd = __socket (sock_af, SOCK_DGRAM, 0);
if (fd == -1)
{
#ifdef AF_INET
fd = __socket (sock_af = AF_INET, SOCK_DGRAM, 0);
#endif
#ifdef AF_INET6
if (fd < 0)
fd = __socket (sock_af = AF_INET6, SOCK_DGRAM, 0);
#endif
#ifdef AF_IPX
if (fd < 0)
fd = __socket (sock_af = AF_IPX, SOCK_DGRAM, 0);
#endif
#ifdef AF_AX25
if (fd < 0)
fd = __socket (sock_af = AF_AX25, SOCK_DGRAM, 0);
#endif
#ifdef AF_APPLETALK
if (fd < 0)
fd = __socket (sock_af = AF_APPLETALK, SOCK_DGRAM, 0);
#endif
}
__libc_lock_unlock (lock);
return fd;
}

View File

@ -35,47 +35,6 @@ static int old_siocgifconf;
# define old_siocgifconf 0
#endif
/* Try to get a socket to talk to the kernel. */
#if defined SIOCGIFINDEX || defined SIOCGIFNAME
static int
internal_function
opensock (void)
{
/* Cache the last AF that worked, to avoid many redundant calls to
socket(). */
static int sock_af = -1;
int fd = -1;
__libc_lock_define_initialized (static, lock);
if (sock_af != -1)
{
fd = __socket (sock_af, SOCK_DGRAM, 0);
if (fd != -1)
return fd;
}
__libc_lock_lock (lock);
if (sock_af != -1)
fd = __socket (sock_af, SOCK_DGRAM, 0);
if (fd == -1)
{
fd = __socket (sock_af = AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
fd = __socket (sock_af = AF_INET6, SOCK_DGRAM, 0);
if (fd < 0)
fd = __socket (sock_af = AF_IPX, SOCK_DGRAM, 0);
if (fd < 0)
fd = __socket (sock_af = AF_AX25, SOCK_DGRAM, 0);
if (fd < 0)
fd = __socket (sock_af = AF_APPLETALK, SOCK_DGRAM, 0);
}
__libc_lock_unlock (lock);
return fd;
}
#endif
unsigned int
if_nametoindex (const char *ifname)
@ -85,7 +44,7 @@ if_nametoindex (const char *ifname)
return 0;
#else
struct ifreq ifr;
int fd = opensock ();
int fd = __opensock ();
if (fd < 0)
return 0;
@ -124,7 +83,7 @@ if_nameindex (void)
__set_errno (ENOSYS);
return NULL;
#else
int fd = opensock ();
int fd = __opensock ();
struct ifconf ifc;
unsigned int nifs, i;
int rq_len;
@ -235,7 +194,7 @@ if_indextoname (unsigned int ifindex, char *ifname)
# endif
int status;
fd = opensock ();
fd = __opensock ();
if (fd < 0)
return NULL;
@ -285,7 +244,7 @@ void
internal_function
__protocol_available (int *have_inet, int *have_inet6)
{
int fd = opensock ();
int fd = __opensock ();
unsigned int nifs;
int rq_len;
struct ifconf ifc;