2000-07-03 04:43:14 +00:00
|
|
|
/* $KAME: name6.c,v 1.25 2000/06/26 16:44:40 itojun Exp $ */
|
2000-05-10 00:47:20 +00:00
|
|
|
|
1999-12-28 02:37:14 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. Neither the name of the project nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
2000-05-10 00:47:20 +00:00
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* ++Copyright++ 1985, 1988, 1993
|
|
|
|
* -
|
|
|
|
* Copyright (c) 1985, 1988, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
1999-12-28 02:37:14 +00:00
|
|
|
*
|
2000-05-10 00:47:20 +00:00
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by the University of
|
|
|
|
* California, Berkeley and its contributors.
|
|
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
* -
|
|
|
|
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies, and that
|
|
|
|
* the name of Digital Equipment Corporation not be used in advertising or
|
|
|
|
* publicity pertaining to distribution of the document or software without
|
|
|
|
* specific, written prior permission.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
|
|
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
|
|
|
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
|
|
|
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
|
|
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
|
|
|
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
|
|
|
* SOFTWARE.
|
|
|
|
* -
|
|
|
|
* --Copyright--
|
1999-12-28 02:37:14 +00:00
|
|
|
*/
|
2000-05-10 00:47:20 +00:00
|
|
|
|
1999-12-28 02:37:14 +00:00
|
|
|
/*
|
|
|
|
* Atsushi Onoe <onoe@sm.sony.co.jp>
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TODO for thread safe
|
|
|
|
* use mutex for _hostconf, _hostconf_init.
|
|
|
|
* rewrite resolvers to be thread safe
|
|
|
|
*/
|
|
|
|
|
2002-03-22 21:53:29 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
2001-01-24 13:01:12 +00:00
|
|
|
#include "namespace.h"
|
1999-12-28 02:37:14 +00:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/time.h>
|
2000-04-20 03:31:40 +00:00
|
|
|
#include <sys/queue.h>
|
1999-12-28 02:37:14 +00:00
|
|
|
#include <netinet/in.h>
|
2004-02-20 17:59:33 +00:00
|
|
|
#ifdef INET6
|
|
|
|
#include <net/if.h>
|
|
|
|
#include <net/if_var.h>
|
|
|
|
#include <sys/sysctl.h>
|
2004-06-02 06:49:36 +00:00
|
|
|
#include <sys/ioctl.h>
|
2004-02-20 17:59:33 +00:00
|
|
|
#include <netinet6/in6_var.h> /* XXX */
|
|
|
|
#endif
|
1999-12-28 02:37:14 +00:00
|
|
|
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <arpa/nameser.h>
|
|
|
|
|
2000-04-20 03:31:40 +00:00
|
|
|
#include <errno.h>
|
1999-12-28 02:37:14 +00:00
|
|
|
#include <netdb.h>
|
|
|
|
#include <resolv.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
#include <stdarg.h>
|
|
|
|
#include <nsswitch.h>
|
2003-05-04 22:36:46 +00:00
|
|
|
#include <pthread.h>
|
1999-12-28 02:37:14 +00:00
|
|
|
#include <unistd.h>
|
2001-01-24 13:01:12 +00:00
|
|
|
#include "un-namespace.h"
|
1999-12-28 02:37:14 +00:00
|
|
|
|
|
|
|
#ifndef _PATH_HOSTS
|
|
|
|
#define _PATH_HOSTS "/etc/hosts"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MAXALIASES
|
|
|
|
#define MAXALIASES 10
|
|
|
|
#endif
|
|
|
|
#ifndef MAXADDRS
|
|
|
|
#define MAXADDRS 20
|
|
|
|
#endif
|
|
|
|
#ifndef MAXDNAME
|
|
|
|
#define MAXDNAME 1025
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef INET6
|
|
|
|
#define ADDRLEN(af) ((af) == AF_INET6 ? sizeof(struct in6_addr) : \
|
|
|
|
sizeof(struct in_addr))
|
|
|
|
#else
|
|
|
|
#define ADDRLEN(af) sizeof(struct in_addr)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define MAPADDR(ab, ina) \
|
|
|
|
do { \
|
|
|
|
memcpy(&(ab)->map_inaddr, ina, sizeof(struct in_addr)); \
|
|
|
|
memset((ab)->map_zero, 0, sizeof((ab)->map_zero)); \
|
|
|
|
memset((ab)->map_one, 0xff, sizeof((ab)->map_one)); \
|
|
|
|
} while (0)
|
|
|
|
#define MAPADDRENABLED(flags) \
|
|
|
|
(((flags) & AI_V4MAPPED) || \
|
|
|
|
(((flags) & AI_V4MAPPED_CFG) && _mapped_addr_enabled()))
|
|
|
|
|
|
|
|
union inx_addr {
|
|
|
|
struct in_addr in_addr;
|
|
|
|
#ifdef INET6
|
|
|
|
struct in6_addr in6_addr;
|
|
|
|
#endif
|
|
|
|
struct {
|
|
|
|
u_char mau_zero[10];
|
|
|
|
u_char mau_one[2];
|
|
|
|
struct in_addr mau_inaddr;
|
|
|
|
} map_addr_un;
|
|
|
|
#define map_zero map_addr_un.mau_zero
|
|
|
|
#define map_one map_addr_un.mau_one
|
|
|
|
#define map_inaddr map_addr_un.mau_inaddr
|
|
|
|
};
|
|
|
|
|
2004-02-20 17:59:33 +00:00
|
|
|
struct policyqueue {
|
|
|
|
TAILQ_ENTRY(policyqueue) pc_entry;
|
|
|
|
#ifdef INET6
|
|
|
|
struct in6_addrpolicy pc_policy;
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
TAILQ_HEAD(policyhead, policyqueue);
|
|
|
|
|
2004-06-02 06:49:36 +00:00
|
|
|
#define AIO_SRCFLAG_DEPRECATED 0x1
|
|
|
|
|
|
|
|
struct hp_order {
|
|
|
|
union {
|
|
|
|
struct sockaddr_storage aiou_ss;
|
|
|
|
struct sockaddr aiou_sa;
|
|
|
|
} aio_src_un;
|
|
|
|
#define aio_srcsa aio_src_un.aiou_sa
|
|
|
|
u_int32_t aio_srcflag;
|
|
|
|
int aio_srcscope;
|
|
|
|
int aio_dstscope;
|
|
|
|
struct policyqueue *aio_srcpolicy;
|
|
|
|
struct policyqueue *aio_dstpolicy;
|
|
|
|
union {
|
|
|
|
struct sockaddr_storage aiou_ss;
|
|
|
|
struct sockaddr aiou_sa;
|
|
|
|
} aio_un;
|
|
|
|
#define aio_sa aio_un.aiou_sa
|
|
|
|
int aio_matchlen;
|
|
|
|
u_char *aio_h_addr;
|
|
|
|
};
|
|
|
|
|
1999-12-28 02:37:14 +00:00
|
|
|
static struct hostent *_hpcopy(struct hostent *hp, int *errp);
|
|
|
|
static struct hostent *_hpaddr(int af, const char *name, void *addr, int *errp);
|
|
|
|
static struct hostent *_hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp);
|
|
|
|
#ifdef INET6
|
|
|
|
static struct hostent *_hpmapv6(struct hostent *hp, int *errp);
|
|
|
|
#endif
|
|
|
|
static struct hostent *_hpsort(struct hostent *hp);
|
|
|
|
static struct hostent *_ghbyname(const char *name, int af, int flags, int *errp);
|
|
|
|
static char *_hgetword(char **pp);
|
|
|
|
static int _mapped_addr_enabled(void);
|
|
|
|
|
2004-02-20 17:59:33 +00:00
|
|
|
static struct hostent *_hpreorder(struct hostent *hp);
|
|
|
|
static int get_addrselectpolicy(struct policyhead *);
|
|
|
|
static void free_addrselectpolicy(struct policyhead *);
|
|
|
|
static struct policyqueue *match_addrselectpolicy(struct sockaddr *,
|
|
|
|
struct policyhead *);
|
2004-06-02 06:49:36 +00:00
|
|
|
static void set_source(struct hp_order *, struct policyhead *);
|
|
|
|
static int matchlen(struct sockaddr *, struct sockaddr *);
|
|
|
|
static int comp_dst(const void *, const void *);
|
|
|
|
static int gai_addr2scopetype(struct sockaddr *);
|
2004-02-20 17:59:33 +00:00
|
|
|
|
1999-12-28 02:37:14 +00:00
|
|
|
static FILE *_files_open(int *errp);
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
static int _files_ghbyname(void *, void *, va_list);
|
|
|
|
static int _files_ghbyaddr(void *, void *, va_list);
|
2000-05-10 00:47:20 +00:00
|
|
|
#ifdef YP
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
static int _nis_ghbyname(void *, void *, va_list);
|
|
|
|
static int _nis_ghbyaddr(void *, void *, va_list);
|
2000-05-10 00:47:20 +00:00
|
|
|
#endif
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
static int _dns_ghbyname(void *, void *, va_list);
|
|
|
|
static int _dns_ghbyaddr(void *, void *, va_list);
|
2003-02-16 17:29:11 +00:00
|
|
|
static void _dns_shent(int stayopen) __unused;
|
|
|
|
static void _dns_ehent(void) __unused;
|
1999-12-28 02:37:14 +00:00
|
|
|
#ifdef ICMPNL
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
static int _icmp_ghbyaddr(void *, void *, va_list);
|
1999-12-28 02:37:14 +00:00
|
|
|
#endif /* ICMPNL */
|
|
|
|
|
2002-10-06 08:43:35 +00:00
|
|
|
/*
|
Make the resolver(3) and many associated interfaces much more reentrant.
The getaddrinfo(3), getipnodebyname(3) and resolver(3) can coincide now
with what should be totally reentrant, and h_errno values will now
be preserved correctly, but this does not affect interfaces such as
gethostbyname(3) which are still mostly non-reentrant.
In all of these relevant functions, the thread-safety has been pushed
down as far as it seems possible right now. This means that operations
that are selected via nsdispatch(3) (i.e. files, yp, dns) are protected
still under global locks that getaddrinfo(3) defines, but where possible
the locking is greatly reduced. The most noticeable improvement is
that multiple DNS lookups can now be run at the same time, and this
shows major improvement in performance of DNS-lookup threaded programs,
and solves the "Mozilla tab serialization" problem.
No single-threaded applications need to be recompiled. Multi-threaded
applications that reference "_res" to change resolver(3) options will
need to be recompiled, and ones which reference "h_errno" will also
if they desire the correct h_errno values. If the applications already
understood that _res and h_errno were not thread-safe and had their own
locking, they will see no performance improvement but will not
actually break in any way.
Please note that when NSS modules are used, or when nsdispatch(3)
defaults to adding any lookups of its own to the individual libc
_nsdispatch() calls, those MUST be reentrant as well.
2004-02-25 21:03:46 +00:00
|
|
|
* XXX: Many dependencies are not thread-safe. So, we share lock between
|
2002-10-06 08:43:35 +00:00
|
|
|
* getaddrinfo() and getipnodeby*(). Still, we cannot use
|
|
|
|
* getaddrinfo() and getipnodeby*() in conjunction with other
|
Make the resolver(3) and many associated interfaces much more reentrant.
The getaddrinfo(3), getipnodebyname(3) and resolver(3) can coincide now
with what should be totally reentrant, and h_errno values will now
be preserved correctly, but this does not affect interfaces such as
gethostbyname(3) which are still mostly non-reentrant.
In all of these relevant functions, the thread-safety has been pushed
down as far as it seems possible right now. This means that operations
that are selected via nsdispatch(3) (i.e. files, yp, dns) are protected
still under global locks that getaddrinfo(3) defines, but where possible
the locking is greatly reduced. The most noticeable improvement is
that multiple DNS lookups can now be run at the same time, and this
shows major improvement in performance of DNS-lookup threaded programs,
and solves the "Mozilla tab serialization" problem.
No single-threaded applications need to be recompiled. Multi-threaded
applications that reference "_res" to change resolver(3) options will
need to be recompiled, and ones which reference "h_errno" will also
if they desire the correct h_errno values. If the applications already
understood that _res and h_errno were not thread-safe and had their own
locking, they will see no performance improvement but will not
actually break in any way.
Please note that when NSS modules are used, or when nsdispatch(3)
defaults to adding any lookups of its own to the individual libc
_nsdispatch() calls, those MUST be reentrant as well.
2004-02-25 21:03:46 +00:00
|
|
|
* functions which call them.
|
2002-10-06 08:43:35 +00:00
|
|
|
*/
|
2003-05-04 22:36:46 +00:00
|
|
|
#include "libc_private.h"
|
|
|
|
extern pthread_mutex_t __getaddrinfo_thread_lock;
|
2002-10-06 08:43:35 +00:00
|
|
|
#define THREAD_LOCK() \
|
2003-05-04 22:36:46 +00:00
|
|
|
if (__isthreaded) _pthread_mutex_lock(&__getaddrinfo_thread_lock);
|
2002-10-06 08:43:35 +00:00
|
|
|
#define THREAD_UNLOCK() \
|
2003-05-04 22:36:46 +00:00
|
|
|
if (__isthreaded) _pthread_mutex_unlock(&__getaddrinfo_thread_lock);
|
2002-10-06 08:43:35 +00:00
|
|
|
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
/* Host lookup order if nsswitch.conf is broken or nonexistant */
|
|
|
|
static const ns_src default_src[] = {
|
|
|
|
{ NSSRC_FILES, NS_SUCCESS },
|
|
|
|
{ NSSRC_DNS, NS_SUCCESS },
|
1999-12-28 02:37:14 +00:00
|
|
|
#ifdef ICMPNL
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
#define NSSRC_ICMP "icmp"
|
|
|
|
{ NSSRC_ICMP, NS_SUCCESS },
|
2000-05-10 00:47:20 +00:00
|
|
|
#endif
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
{ 0 }
|
|
|
|
};
|
1999-12-28 02:37:14 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if kernel supports mapped address.
|
|
|
|
* implementation dependent
|
|
|
|
*/
|
|
|
|
#ifdef __KAME__
|
|
|
|
#include <sys/sysctl.h>
|
|
|
|
#endif /* __KAME__ */
|
|
|
|
|
|
|
|
static int
|
|
|
|
_mapped_addr_enabled(void)
|
|
|
|
{
|
|
|
|
/* implementation dependent check */
|
|
|
|
#if defined(__KAME__) && defined(IPV6CTL_MAPPED_ADDR)
|
|
|
|
int mib[4];
|
|
|
|
size_t len;
|
|
|
|
int val;
|
|
|
|
|
|
|
|
mib[0] = CTL_NET;
|
|
|
|
mib[1] = PF_INET6;
|
|
|
|
mib[2] = IPPROTO_IPV6;
|
|
|
|
mib[3] = IPV6CTL_MAPPED_ADDR;
|
|
|
|
len = sizeof(val);
|
|
|
|
if (sysctl(mib, 4, &val, &len, 0, 0) == 0 && val != 0)
|
|
|
|
return 1;
|
|
|
|
#endif /* __KAME__ && IPV6CTL_MAPPED_ADDR */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Functions defined in RFC2553
|
2000-05-10 00:47:20 +00:00
|
|
|
* getipnodebyname, getipnodebyaddr, freehostent
|
1999-12-28 02:37:14 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
static struct hostent *
|
|
|
|
_ghbyname(const char *name, int af, int flags, int *errp)
|
|
|
|
{
|
|
|
|
struct hostent *hp;
|
2000-09-07 02:18:22 +00:00
|
|
|
int rval;
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
|
|
|
|
static const ns_dtab dtab[] = {
|
|
|
|
NS_FILES_CB(_files_ghbyname, NULL)
|
|
|
|
{ NSSRC_DNS, _dns_ghbyname, NULL },
|
|
|
|
NS_NIS_CB(_nis_ghbyname, NULL)
|
|
|
|
{ 0 }
|
|
|
|
};
|
1999-12-28 02:37:14 +00:00
|
|
|
|
|
|
|
if (flags & AI_ADDRCONFIG) {
|
|
|
|
int s;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TODO:
|
|
|
|
* Note that implementation dependent test for address
|
|
|
|
* configuration should be done everytime called
|
|
|
|
* (or apropriate interval),
|
|
|
|
* because addresses will be dynamically assigned or deleted.
|
|
|
|
*/
|
2000-04-20 03:31:40 +00:00
|
|
|
if (af == AF_UNSPEC) {
|
2001-01-24 13:01:12 +00:00
|
|
|
if ((s = _socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
|
2000-04-20 03:31:40 +00:00
|
|
|
af = AF_INET;
|
|
|
|
else {
|
|
|
|
_close(s);
|
2001-01-24 13:01:12 +00:00
|
|
|
if ((s = _socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
2000-04-20 03:31:40 +00:00
|
|
|
af = AF_INET6;
|
|
|
|
else
|
|
|
|
_close(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
if (af != AF_UNSPEC) {
|
2001-01-24 13:01:12 +00:00
|
|
|
if ((s = _socket(af, SOCK_DGRAM, 0)) < 0)
|
2000-04-20 03:31:40 +00:00
|
|
|
return NULL;
|
|
|
|
_close(s);
|
|
|
|
}
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
|
|
|
|
2003-04-24 17:41:20 +00:00
|
|
|
rval = _nsdispatch(&hp, dtab, NSDB_HOSTS, "ghbyname", default_src,
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
name, af, errp);
|
|
|
|
return (rval == NS_SUCCESS) ? hp : NULL;
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
|
|
|
|
2000-04-20 03:31:40 +00:00
|
|
|
/* getipnodebyname() internal routine for multiple query(PF_UNSPEC) support. */
|
2005-01-27 15:01:05 +00:00
|
|
|
static struct hostent *
|
2000-04-20 03:31:40 +00:00
|
|
|
_getipnodebyname_multi(const char *name, int af, int flags, int *errp)
|
1999-12-28 02:37:14 +00:00
|
|
|
{
|
|
|
|
struct hostent *hp;
|
|
|
|
union inx_addr addrbuf;
|
|
|
|
|
2000-04-20 03:31:40 +00:00
|
|
|
/* XXX: PF_UNSPEC is only supposed to be passed from getaddrinfo() */
|
1999-12-28 02:37:14 +00:00
|
|
|
if (af != AF_INET
|
|
|
|
#ifdef INET6
|
|
|
|
&& af != AF_INET6
|
|
|
|
#endif
|
2000-04-20 03:31:40 +00:00
|
|
|
&& af != PF_UNSPEC
|
1999-12-28 02:37:14 +00:00
|
|
|
)
|
|
|
|
{
|
|
|
|
*errp = NO_RECOVERY;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef INET6
|
|
|
|
/* special case for literal address */
|
|
|
|
if (inet_pton(AF_INET6, name, &addrbuf) == 1) {
|
|
|
|
if (af != AF_INET6) {
|
|
|
|
*errp = HOST_NOT_FOUND;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return _hpaddr(af, name, &addrbuf, errp);
|
|
|
|
}
|
|
|
|
#endif
|
2000-02-10 02:59:50 +00:00
|
|
|
if (inet_aton(name, (struct in_addr *)&addrbuf) == 1) {
|
1999-12-28 02:37:14 +00:00
|
|
|
if (af != AF_INET) {
|
|
|
|
if (MAPADDRENABLED(flags)) {
|
|
|
|
MAPADDR(&addrbuf, &addrbuf.in_addr);
|
|
|
|
} else {
|
|
|
|
*errp = HOST_NOT_FOUND;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return _hpaddr(af, name, &addrbuf, errp);
|
|
|
|
}
|
|
|
|
|
|
|
|
*errp = HOST_NOT_FOUND;
|
|
|
|
hp = _ghbyname(name, af, flags, errp);
|
|
|
|
|
|
|
|
#ifdef INET6
|
|
|
|
if (af == AF_INET6
|
|
|
|
&& ((flags & AI_ALL) || hp == NULL)
|
|
|
|
&& (MAPADDRENABLED(flags))) {
|
|
|
|
struct hostent *hp2 = _ghbyname(name, AF_INET, flags, errp);
|
|
|
|
if (hp == NULL)
|
|
|
|
hp = _hpmapv6(hp2, errp);
|
|
|
|
else {
|
|
|
|
if (hp2 && strcmp(hp->h_name, hp2->h_name) != 0) {
|
|
|
|
freehostent(hp2);
|
|
|
|
hp2 = NULL;
|
|
|
|
}
|
|
|
|
hp = _hpmerge(hp, hp2, errp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2004-02-20 17:59:33 +00:00
|
|
|
return _hpreorder(_hpsort(hp));
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
|
|
|
|
2000-04-20 03:31:40 +00:00
|
|
|
struct hostent *
|
|
|
|
getipnodebyname(const char *name, int af, int flags, int *errp)
|
|
|
|
{
|
|
|
|
if (af != AF_INET
|
|
|
|
#ifdef INET6
|
|
|
|
&& af != AF_INET6
|
|
|
|
#endif
|
|
|
|
)
|
|
|
|
{
|
|
|
|
*errp = NO_RECOVERY;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return(_getipnodebyname_multi(name, af ,flags, errp));
|
|
|
|
}
|
|
|
|
|
1999-12-28 02:37:14 +00:00
|
|
|
struct hostent *
|
|
|
|
getipnodebyaddr(const void *src, size_t len, int af, int *errp)
|
|
|
|
{
|
|
|
|
struct hostent *hp;
|
2000-09-07 02:18:22 +00:00
|
|
|
int rval;
|
1999-12-28 02:37:14 +00:00
|
|
|
#ifdef INET6
|
|
|
|
struct in6_addr addrbuf;
|
|
|
|
#else
|
|
|
|
struct in_addr addrbuf;
|
|
|
|
#endif
|
|
|
|
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
static const ns_dtab dtab[] = {
|
|
|
|
NS_FILES_CB(_files_ghbyaddr, NULL)
|
|
|
|
{ NSSRC_DNS, _dns_ghbyaddr, NULL },
|
|
|
|
NS_NIS_CB(_nis_ghbyaddr, NULL)
|
|
|
|
#ifdef ICMPNL
|
|
|
|
{ NSSRC_ICMP, _icmp_ghbyaddr, NULL },
|
|
|
|
#endif
|
|
|
|
{ 0 }
|
|
|
|
};
|
|
|
|
|
1999-12-28 02:37:14 +00:00
|
|
|
*errp = HOST_NOT_FOUND;
|
|
|
|
|
|
|
|
switch (af) {
|
|
|
|
case AF_INET:
|
|
|
|
if (len != sizeof(struct in_addr)) {
|
|
|
|
*errp = NO_RECOVERY;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if ((long)src & ~(sizeof(struct in_addr) - 1)) {
|
|
|
|
memcpy(&addrbuf, src, len);
|
|
|
|
src = &addrbuf;
|
|
|
|
}
|
|
|
|
if (((struct in_addr *)src)->s_addr == 0)
|
|
|
|
return NULL;
|
|
|
|
break;
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
|
|
|
if (len != sizeof(struct in6_addr)) {
|
|
|
|
*errp = NO_RECOVERY;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if ((long)src & ~(sizeof(struct in6_addr) / 2 - 1)) { /*XXX*/
|
|
|
|
memcpy(&addrbuf, src, len);
|
|
|
|
src = &addrbuf;
|
|
|
|
}
|
2000-01-13 05:47:11 +00:00
|
|
|
if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)src))
|
|
|
|
return NULL;
|
1999-12-28 02:37:14 +00:00
|
|
|
if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src)
|
|
|
|
|| IN6_IS_ADDR_V4COMPAT((struct in6_addr *)src)) {
|
|
|
|
src = (char *)src +
|
|
|
|
(sizeof(struct in6_addr) - sizeof(struct in_addr));
|
|
|
|
af = AF_INET;
|
|
|
|
len = sizeof(struct in_addr);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
*errp = NO_RECOVERY;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2003-04-24 17:41:20 +00:00
|
|
|
rval = _nsdispatch(&hp, dtab, NSDB_HOSTS, "ghbyaddr", default_src,
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
src, len, af, errp);
|
|
|
|
return (rval == NS_SUCCESS) ? hp : NULL;
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
freehostent(struct hostent *ptr)
|
|
|
|
{
|
|
|
|
free(ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
|
|
|
/* XXX: should be deprecated */
|
|
|
|
struct hostent *
|
|
|
|
getnodebyname(const char *name, int af, int flags)
|
|
|
|
{
|
|
|
|
return getipnodebyname(name, af, flags, &h_errno);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef __warn_references
|
|
|
|
__warn_references(getnodebyname,
|
|
|
|
"warning: getnodebyname() deprecated, "
|
|
|
|
"should use getaddrinfo() or getipnodebyname()");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
struct hostent *
|
|
|
|
getnodebyaddr(const void *src, size_t len, int af)
|
|
|
|
{
|
|
|
|
return getipnodebyaddr(src, len, af, &h_errno);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef __warn_references
|
|
|
|
__warn_references(getnodebyaddr,
|
|
|
|
"warning: getnodebyaddr() deprecated, "
|
|
|
|
"should use getnameinfo() or getipnodebyaddr()");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Private utility functions
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* _hpcopy: allocate and copy hostent structure
|
|
|
|
*/
|
|
|
|
static struct hostent *
|
|
|
|
_hpcopy(struct hostent *hp, int *errp)
|
|
|
|
{
|
|
|
|
struct hostent *nhp;
|
|
|
|
char *cp, **pp;
|
|
|
|
int size, addrsize;
|
|
|
|
int nalias = 0, naddr = 0;
|
|
|
|
int al_off;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (hp == NULL)
|
|
|
|
return hp;
|
|
|
|
|
|
|
|
/* count size to be allocated */
|
|
|
|
size = sizeof(struct hostent);
|
2000-07-19 06:22:01 +00:00
|
|
|
if (hp->h_name != NULL)
|
1999-12-28 02:37:14 +00:00
|
|
|
size += strlen(hp->h_name) + 1;
|
|
|
|
if ((pp = hp->h_aliases) != NULL) {
|
|
|
|
for (i = 0; *pp != NULL; i++, pp++) {
|
|
|
|
if (**pp != '\0') {
|
|
|
|
size += strlen(*pp) + 1;
|
|
|
|
nalias++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* adjust alignment */
|
|
|
|
size = ALIGN(size);
|
|
|
|
al_off = size;
|
|
|
|
size += sizeof(char *) * (nalias + 1);
|
|
|
|
addrsize = ALIGN(hp->h_length);
|
|
|
|
if ((pp = hp->h_addr_list) != NULL) {
|
|
|
|
while (*pp++ != NULL)
|
|
|
|
naddr++;
|
|
|
|
}
|
|
|
|
size += addrsize * naddr;
|
|
|
|
size += sizeof(char *) * (naddr + 1);
|
|
|
|
|
|
|
|
/* copy */
|
|
|
|
if ((nhp = (struct hostent *)malloc(size)) == NULL) {
|
|
|
|
*errp = TRY_AGAIN;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
cp = (char *)&nhp[1];
|
2000-07-19 06:22:01 +00:00
|
|
|
if (hp->h_name != NULL) {
|
1999-12-28 02:37:14 +00:00
|
|
|
nhp->h_name = cp;
|
|
|
|
strcpy(cp, hp->h_name);
|
|
|
|
cp += strlen(cp) + 1;
|
|
|
|
} else
|
|
|
|
nhp->h_name = NULL;
|
|
|
|
nhp->h_aliases = (char **)((char *)nhp + al_off);
|
|
|
|
if ((pp = hp->h_aliases) != NULL) {
|
|
|
|
for (i = 0; *pp != NULL; pp++) {
|
|
|
|
if (**pp != '\0') {
|
|
|
|
nhp->h_aliases[i++] = cp;
|
|
|
|
strcpy(cp, *pp);
|
|
|
|
cp += strlen(cp) + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nhp->h_aliases[nalias] = NULL;
|
|
|
|
cp = (char *)&nhp->h_aliases[nalias + 1];
|
|
|
|
nhp->h_addrtype = hp->h_addrtype;
|
|
|
|
nhp->h_length = hp->h_length;
|
|
|
|
nhp->h_addr_list = (char **)cp;
|
|
|
|
if ((pp = hp->h_addr_list) != NULL) {
|
|
|
|
cp = (char *)&nhp->h_addr_list[naddr + 1];
|
|
|
|
for (i = 0; *pp != NULL; pp++) {
|
|
|
|
nhp->h_addr_list[i++] = cp;
|
|
|
|
memcpy(cp, *pp, hp->h_length);
|
|
|
|
cp += addrsize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nhp->h_addr_list[naddr] = NULL;
|
|
|
|
return nhp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* _hpaddr: construct hostent structure with one address
|
|
|
|
*/
|
|
|
|
static struct hostent *
|
|
|
|
_hpaddr(int af, const char *name, void *addr, int *errp)
|
|
|
|
{
|
|
|
|
struct hostent *hp, hpbuf;
|
|
|
|
char *addrs[2];
|
|
|
|
|
|
|
|
hp = &hpbuf;
|
|
|
|
hp->h_name = (char *)name;
|
|
|
|
hp->h_aliases = NULL;
|
|
|
|
hp->h_addrtype = af;
|
|
|
|
hp->h_length = ADDRLEN(af);
|
|
|
|
hp->h_addr_list = addrs;
|
|
|
|
addrs[0] = (char *)addr;
|
|
|
|
addrs[1] = NULL;
|
|
|
|
return _hpcopy(hp, errp);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* _hpmerge: merge 2 hostent structure, arguments will be freed
|
|
|
|
*/
|
|
|
|
static struct hostent *
|
|
|
|
_hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp)
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
int naddr, nalias;
|
|
|
|
char **pp;
|
|
|
|
struct hostent *hp, hpbuf;
|
|
|
|
char *aliases[MAXALIASES + 1], *addrs[MAXADDRS + 1];
|
|
|
|
union inx_addr addrbuf[MAXADDRS];
|
|
|
|
|
|
|
|
if (hp1 == NULL)
|
|
|
|
return hp2;
|
|
|
|
if (hp2 == NULL)
|
|
|
|
return hp1;
|
|
|
|
|
|
|
|
#define HP(i) (i == 1 ? hp1 : hp2)
|
|
|
|
hp = &hpbuf;
|
|
|
|
hp->h_name = (hp1->h_name != NULL ? hp1->h_name : hp2->h_name);
|
|
|
|
hp->h_aliases = aliases;
|
|
|
|
nalias = 0;
|
|
|
|
for (i = 1; i <= 2; i++) {
|
|
|
|
if ((pp = HP(i)->h_aliases) == NULL)
|
|
|
|
continue;
|
|
|
|
for (; nalias < MAXALIASES && *pp != NULL; pp++) {
|
|
|
|
/* check duplicates */
|
|
|
|
for (j = 0; j < nalias; j++)
|
|
|
|
if (strcasecmp(*pp, aliases[j]) == 0)
|
|
|
|
break;
|
|
|
|
if (j == nalias)
|
|
|
|
aliases[nalias++] = *pp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
aliases[nalias] = NULL;
|
|
|
|
#ifdef INET6
|
|
|
|
if (hp1->h_length != hp2->h_length) {
|
|
|
|
hp->h_addrtype = AF_INET6;
|
|
|
|
hp->h_length = sizeof(struct in6_addr);
|
|
|
|
} else {
|
|
|
|
#endif
|
|
|
|
hp->h_addrtype = hp1->h_addrtype;
|
|
|
|
hp->h_length = hp1->h_length;
|
|
|
|
#ifdef INET6
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
hp->h_addr_list = addrs;
|
|
|
|
naddr = 0;
|
|
|
|
for (i = 1; i <= 2; i++) {
|
|
|
|
if ((pp = HP(i)->h_addr_list) == NULL)
|
|
|
|
continue;
|
|
|
|
if (HP(i)->h_length == hp->h_length) {
|
|
|
|
while (naddr < MAXADDRS && *pp != NULL)
|
|
|
|
addrs[naddr++] = *pp++;
|
|
|
|
} else {
|
|
|
|
/* copy IPv4 addr as mapped IPv6 addr */
|
|
|
|
while (naddr < MAXADDRS && *pp != NULL) {
|
|
|
|
MAPADDR(&addrbuf[naddr], *pp++);
|
|
|
|
addrs[naddr] = (char *)&addrbuf[naddr];
|
|
|
|
naddr++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
addrs[naddr] = NULL;
|
|
|
|
hp = _hpcopy(hp, errp);
|
|
|
|
freehostent(hp1);
|
|
|
|
freehostent(hp2);
|
|
|
|
return hp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* _hpmapv6: convert IPv4 hostent into IPv4-mapped IPv6 addresses
|
|
|
|
*/
|
|
|
|
#ifdef INET6
|
|
|
|
static struct hostent *
|
|
|
|
_hpmapv6(struct hostent *hp, int *errp)
|
|
|
|
{
|
|
|
|
struct hostent *hp6;
|
|
|
|
|
|
|
|
if (hp == NULL)
|
|
|
|
return NULL;
|
|
|
|
if (hp->h_addrtype == AF_INET6)
|
|
|
|
return hp;
|
|
|
|
|
|
|
|
/* make dummy hostent to convert IPv6 address */
|
|
|
|
if ((hp6 = (struct hostent *)malloc(sizeof(struct hostent))) == NULL) {
|
|
|
|
*errp = TRY_AGAIN;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
hp6->h_name = NULL;
|
|
|
|
hp6->h_aliases = NULL;
|
|
|
|
hp6->h_addrtype = AF_INET6;
|
|
|
|
hp6->h_length = sizeof(struct in6_addr);
|
|
|
|
hp6->h_addr_list = NULL;
|
|
|
|
return _hpmerge(hp6, hp, errp);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* _hpsort: sort address by sortlist
|
|
|
|
*/
|
|
|
|
static struct hostent *
|
|
|
|
_hpsort(struct hostent *hp)
|
|
|
|
{
|
|
|
|
int i, j, n;
|
|
|
|
u_char *ap, *sp, *mp, **pp;
|
|
|
|
char t;
|
|
|
|
char order[MAXADDRS];
|
|
|
|
int nsort = _res.nsort;
|
|
|
|
|
|
|
|
if (hp == NULL || hp->h_addr_list[1] == NULL || nsort == 0)
|
|
|
|
return hp;
|
|
|
|
for (i = 0; (ap = (u_char *)hp->h_addr_list[i]); i++) {
|
|
|
|
for (j = 0; j < nsort; j++) {
|
|
|
|
#ifdef INET6
|
|
|
|
if (_res_ext.sort_list[j].af != hp->h_addrtype)
|
|
|
|
continue;
|
|
|
|
sp = (u_char *)&_res_ext.sort_list[j].addr;
|
|
|
|
mp = (u_char *)&_res_ext.sort_list[j].mask;
|
|
|
|
#else
|
|
|
|
sp = (u_char *)&_res.sort_list[j].addr;
|
|
|
|
mp = (u_char *)&_res.sort_list[j].mask;
|
|
|
|
#endif
|
|
|
|
for (n = 0; n < hp->h_length; n++) {
|
|
|
|
if ((ap[n] & mp[n]) != sp[n])
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (n == hp->h_length)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
order[i] = j;
|
|
|
|
}
|
|
|
|
n = i;
|
|
|
|
pp = (u_char **)hp->h_addr_list;
|
|
|
|
for (i = 0; i < n - 1; i++) {
|
|
|
|
for (j = i + 1; j < n; j++) {
|
|
|
|
if (order[i] > order[j]) {
|
|
|
|
ap = pp[i];
|
|
|
|
pp[i] = pp[j];
|
|
|
|
pp[j] = ap;
|
|
|
|
t = order[i];
|
|
|
|
order[i] = order[j];
|
|
|
|
order[j] = t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return hp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
_hgetword(char **pp)
|
|
|
|
{
|
|
|
|
char c, *p, *ret;
|
|
|
|
const char *sp;
|
|
|
|
static const char sep[] = "# \t\n";
|
|
|
|
|
|
|
|
ret = NULL;
|
|
|
|
for (p = *pp; (c = *p) != '\0'; p++) {
|
|
|
|
for (sp = sep; *sp != '\0'; sp++) {
|
|
|
|
if (c == *sp)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (c == '#')
|
|
|
|
p[1] = '\0'; /* ignore rest of line */
|
|
|
|
if (ret == NULL) {
|
|
|
|
if (*sp == '\0')
|
|
|
|
ret = p;
|
|
|
|
} else {
|
|
|
|
if (*sp != '\0') {
|
|
|
|
*p++ = '\0';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*pp = p;
|
|
|
|
if (ret == NULL || *ret == '\0')
|
|
|
|
return NULL;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2004-02-20 17:59:33 +00:00
|
|
|
/*
|
|
|
|
* _hpreorder: sort address by default address selection
|
|
|
|
*/
|
|
|
|
static struct hostent *
|
|
|
|
_hpreorder(struct hostent *hp)
|
|
|
|
{
|
2004-06-02 06:49:36 +00:00
|
|
|
struct hp_order *aio;
|
|
|
|
int i, n;
|
|
|
|
u_char *ap;
|
|
|
|
struct sockaddr *sa;
|
2004-02-20 17:59:33 +00:00
|
|
|
struct policyhead policyhead;
|
|
|
|
|
2004-06-02 06:49:36 +00:00
|
|
|
if (hp == NULL)
|
|
|
|
return hp;
|
|
|
|
|
|
|
|
switch (hp->h_addrtype) {
|
|
|
|
case AF_INET:
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
free_addrselectpolicy(&policyhead);
|
|
|
|
return hp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* count the number of addrinfo elements for sorting. */
|
|
|
|
for (n = 0; hp->h_addr_list[n] != NULL; n++)
|
|
|
|
;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the number is small enough, we can skip the reordering process.
|
|
|
|
*/
|
|
|
|
if (n <= 1)
|
2004-02-20 17:59:33 +00:00
|
|
|
return hp;
|
|
|
|
|
2004-06-02 06:49:36 +00:00
|
|
|
/* allocate a temporary array for sort and initialization of it. */
|
|
|
|
if ((aio = malloc(sizeof(*aio) * n)) == NULL)
|
|
|
|
return hp; /* give up reordering */
|
|
|
|
memset(aio, 0, sizeof(*aio) * n);
|
|
|
|
|
2004-02-20 17:59:33 +00:00
|
|
|
/* retrieve address selection policy from the kernel */
|
|
|
|
TAILQ_INIT(&policyhead);
|
|
|
|
if (!get_addrselectpolicy(&policyhead)) {
|
|
|
|
/* no policy is installed into kernel, we don't sort. */
|
2004-06-02 06:49:36 +00:00
|
|
|
free(aio);
|
2004-02-20 17:59:33 +00:00
|
|
|
return hp;
|
|
|
|
}
|
|
|
|
|
2004-06-02 06:49:36 +00:00
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
ap = (u_char *)hp->h_addr_list[i];
|
|
|
|
aio[i].aio_h_addr = ap;
|
|
|
|
sa = &aio[i].aio_sa;
|
|
|
|
switch (hp->h_addrtype) {
|
|
|
|
case AF_INET:
|
|
|
|
sa->sa_family = AF_INET;
|
|
|
|
sa->sa_len = sizeof(struct sockaddr_in);
|
|
|
|
memcpy(&((struct sockaddr_in *)sa)->sin_addr, ap,
|
2004-02-20 17:59:33 +00:00
|
|
|
sizeof(struct in_addr));
|
2004-06-02 06:49:36 +00:00
|
|
|
break;
|
2004-02-20 17:59:33 +00:00
|
|
|
#ifdef INET6
|
2004-06-02 06:49:36 +00:00
|
|
|
case AF_INET6:
|
2004-02-20 17:59:33 +00:00
|
|
|
if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
|
2004-06-02 06:49:36 +00:00
|
|
|
sa->sa_family = AF_INET;
|
|
|
|
sa->sa_len = sizeof(struct sockaddr_in);
|
|
|
|
memcpy(&((struct sockaddr_in *)sa)->sin_addr,
|
2004-02-20 17:59:33 +00:00
|
|
|
&ap[12], sizeof(struct in_addr));
|
|
|
|
} else {
|
2004-06-02 06:49:36 +00:00
|
|
|
sa->sa_family = AF_INET6;
|
|
|
|
sa->sa_len = sizeof(struct sockaddr_in6);
|
|
|
|
memcpy(&((struct sockaddr_in6 *)sa)->sin6_addr,
|
2004-02-20 17:59:33 +00:00
|
|
|
ap, sizeof(struct in6_addr));
|
|
|
|
}
|
2004-06-02 06:49:36 +00:00
|
|
|
break;
|
2004-02-20 17:59:33 +00:00
|
|
|
#endif
|
2004-06-02 06:49:36 +00:00
|
|
|
}
|
|
|
|
aio[i].aio_dstscope = gai_addr2scopetype(sa);
|
|
|
|
aio[i].aio_dstpolicy = match_addrselectpolicy(sa, &policyhead);
|
|
|
|
set_source(&aio[i], &policyhead);
|
2004-02-20 17:59:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* perform sorting. */
|
2004-06-02 06:49:36 +00:00
|
|
|
qsort(aio, n, sizeof(*aio), comp_dst);
|
|
|
|
|
|
|
|
/* reorder the h_addr_list. */
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
hp->h_addr_list[i] = aio[i].aio_h_addr;
|
2004-02-20 17:59:33 +00:00
|
|
|
|
|
|
|
/* cleanup and return */
|
2004-06-02 06:49:36 +00:00
|
|
|
free(aio);
|
2004-02-20 17:59:33 +00:00
|
|
|
free_addrselectpolicy(&policyhead);
|
|
|
|
return hp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
get_addrselectpolicy(head)
|
|
|
|
struct policyhead *head;
|
|
|
|
{
|
|
|
|
#ifdef INET6
|
|
|
|
int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_ADDRCTLPOLICY };
|
|
|
|
size_t l;
|
|
|
|
char *buf;
|
|
|
|
struct in6_addrpolicy *pol, *ep;
|
|
|
|
|
|
|
|
if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0)
|
|
|
|
return (0);
|
|
|
|
if ((buf = malloc(l)) == NULL)
|
|
|
|
return (0);
|
|
|
|
if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) {
|
|
|
|
free(buf);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
ep = (struct in6_addrpolicy *)(buf + l);
|
|
|
|
for (pol = (struct in6_addrpolicy *)buf; pol + 1 <= ep; pol++) {
|
|
|
|
struct policyqueue *new;
|
|
|
|
|
|
|
|
if ((new = malloc(sizeof(*new))) == NULL) {
|
|
|
|
free_addrselectpolicy(head); /* make the list empty */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
new->pc_policy = *pol;
|
|
|
|
TAILQ_INSERT_TAIL(head, new, pc_entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(buf);
|
|
|
|
return (1);
|
|
|
|
#else
|
|
|
|
return (0);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
free_addrselectpolicy(head)
|
|
|
|
struct policyhead *head;
|
|
|
|
{
|
|
|
|
struct policyqueue *ent, *nent;
|
|
|
|
|
|
|
|
for (ent = TAILQ_FIRST(head); ent; ent = nent) {
|
|
|
|
nent = TAILQ_NEXT(ent, pc_entry);
|
|
|
|
TAILQ_REMOVE(head, ent, pc_entry);
|
|
|
|
free(ent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct policyqueue *
|
|
|
|
match_addrselectpolicy(addr, head)
|
|
|
|
struct sockaddr *addr;
|
|
|
|
struct policyhead *head;
|
|
|
|
{
|
|
|
|
#ifdef INET6
|
|
|
|
struct policyqueue *ent, *bestent = NULL;
|
|
|
|
struct in6_addrpolicy *pol;
|
|
|
|
int matchlen, bestmatchlen = -1;
|
|
|
|
u_char *mp, *ep, *k, *p, m;
|
|
|
|
struct sockaddr_in6 key;
|
|
|
|
|
|
|
|
switch(addr->sa_family) {
|
|
|
|
case AF_INET6:
|
|
|
|
key = *(struct sockaddr_in6 *)addr;
|
|
|
|
break;
|
|
|
|
case AF_INET:
|
|
|
|
/* convert the address into IPv4-mapped IPv6 address. */
|
|
|
|
memset(&key, 0, sizeof(key));
|
|
|
|
key.sin6_family = AF_INET6;
|
|
|
|
key.sin6_len = sizeof(key);
|
|
|
|
key.sin6_addr.s6_addr[10] = 0xff;
|
|
|
|
key.sin6_addr.s6_addr[11] = 0xff;
|
|
|
|
memcpy(&key.sin6_addr.s6_addr[12],
|
|
|
|
&((struct sockaddr_in *)addr)->sin_addr, 4);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (ent = TAILQ_FIRST(head); ent; ent = TAILQ_NEXT(ent, pc_entry)) {
|
|
|
|
pol = &ent->pc_policy;
|
|
|
|
matchlen = 0;
|
|
|
|
|
|
|
|
mp = (u_char *)&pol->addrmask.sin6_addr;
|
|
|
|
ep = mp + 16; /* XXX: scope field? */
|
|
|
|
k = (u_char *)&key.sin6_addr;
|
|
|
|
p = (u_char *)&pol->addr.sin6_addr;
|
|
|
|
for (; mp < ep && *mp; mp++, k++, p++) {
|
|
|
|
m = *mp;
|
|
|
|
if ((*k & m) != *p)
|
|
|
|
goto next; /* not match */
|
|
|
|
if (m == 0xff) /* short cut for a typical case */
|
|
|
|
matchlen += 8;
|
|
|
|
else {
|
|
|
|
while (m >= 0x80) {
|
|
|
|
matchlen++;
|
|
|
|
m <<= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* matched. check if this is better than the current best. */
|
|
|
|
if (matchlen > bestmatchlen) {
|
|
|
|
bestent = ent;
|
|
|
|
bestmatchlen = matchlen;
|
|
|
|
}
|
|
|
|
|
|
|
|
next:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
return(bestent);
|
|
|
|
#else
|
|
|
|
return(NULL);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2004-06-02 06:49:36 +00:00
|
|
|
static void
|
|
|
|
set_source(aio, ph)
|
|
|
|
struct hp_order *aio;
|
|
|
|
struct policyhead *ph;
|
|
|
|
{
|
|
|
|
struct sockaddr_storage ss = aio->aio_un.aiou_ss;
|
|
|
|
int s, srclen;
|
|
|
|
|
|
|
|
/* set unspec ("no source is available"), just in case */
|
|
|
|
aio->aio_srcsa.sa_family = AF_UNSPEC;
|
|
|
|
aio->aio_srcscope = -1;
|
|
|
|
|
|
|
|
switch(ss.ss_family) {
|
|
|
|
case AF_INET:
|
|
|
|
((struct sockaddr_in *)&ss)->sin_port = htons(1);
|
|
|
|
break;
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
|
|
|
((struct sockaddr_in6 *)&ss)->sin6_port = htons(1);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default: /* ignore unsupported AFs explicitly */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* open a socket to get the source address for the given dst */
|
|
|
|
if ((s = _socket(ss.ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0)
|
|
|
|
return; /* give up */
|
|
|
|
if (_connect(s, (struct sockaddr *)&ss, ss.ss_len) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
srclen = ss.ss_len;
|
|
|
|
if (_getsockname(s, &aio->aio_srcsa, &srclen) < 0) {
|
|
|
|
aio->aio_srcsa.sa_family = AF_UNSPEC;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
aio->aio_srcscope = gai_addr2scopetype(&aio->aio_srcsa);
|
|
|
|
aio->aio_srcpolicy = match_addrselectpolicy(&aio->aio_srcsa, ph);
|
|
|
|
aio->aio_matchlen = matchlen(&aio->aio_srcsa, (struct sockaddr *)&ss);
|
|
|
|
#ifdef INET6
|
|
|
|
if (ss.ss_family == AF_INET6) {
|
|
|
|
struct in6_ifreq ifr6;
|
|
|
|
u_int32_t flags6;
|
|
|
|
|
|
|
|
/* XXX: interface name should not be hardcoded */
|
|
|
|
strncpy(ifr6.ifr_name, "lo0", sizeof(ifr6.ifr_name));
|
|
|
|
memset(&ifr6, 0, sizeof(ifr6));
|
|
|
|
memcpy(&ifr6.ifr_addr, &ss, ss.ss_len);
|
|
|
|
if (_ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == 0) {
|
|
|
|
flags6 = ifr6.ifr_ifru.ifru_flags6;
|
|
|
|
if ((flags6 & IN6_IFF_DEPRECATED))
|
|
|
|
aio->aio_srcflag |= AIO_SRCFLAG_DEPRECATED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
_close(s);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
matchlen(src, dst)
|
|
|
|
struct sockaddr *src, *dst;
|
|
|
|
{
|
|
|
|
int match = 0;
|
|
|
|
u_char *s, *d;
|
|
|
|
u_char *lim, r;
|
|
|
|
int addrlen;
|
|
|
|
|
|
|
|
switch (src->sa_family) {
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
|
|
|
s = (u_char *)&((struct sockaddr_in6 *)src)->sin6_addr;
|
|
|
|
d = (u_char *)&((struct sockaddr_in6 *)dst)->sin6_addr;
|
|
|
|
addrlen = sizeof(struct in6_addr);
|
|
|
|
lim = s + addrlen;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case AF_INET:
|
|
|
|
s = (u_char *)&((struct sockaddr_in6 *)src)->sin6_addr;
|
|
|
|
d = (u_char *)&((struct sockaddr_in6 *)dst)->sin6_addr;
|
|
|
|
addrlen = sizeof(struct in_addr);
|
|
|
|
lim = s + addrlen;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (s < lim)
|
|
|
|
if ((r = (*d++ ^ *s++)) != 0) {
|
|
|
|
while (r < addrlen * 8) {
|
|
|
|
match++;
|
|
|
|
r <<= 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
} else
|
|
|
|
match += 8;
|
|
|
|
return(match);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
comp_dst(arg1, arg2)
|
|
|
|
const void *arg1, *arg2;
|
|
|
|
{
|
|
|
|
const struct hp_order *dst1 = arg1, *dst2 = arg2;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Rule 1: Avoid unusable destinations.
|
|
|
|
* XXX: we currently do not consider if an appropriate route exists.
|
|
|
|
*/
|
|
|
|
if (dst1->aio_srcsa.sa_family != AF_UNSPEC &&
|
|
|
|
dst2->aio_srcsa.sa_family == AF_UNSPEC) {
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
if (dst1->aio_srcsa.sa_family == AF_UNSPEC &&
|
|
|
|
dst2->aio_srcsa.sa_family != AF_UNSPEC) {
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Rule 2: Prefer matching scope. */
|
|
|
|
if (dst1->aio_dstscope == dst1->aio_srcscope &&
|
|
|
|
dst2->aio_dstscope != dst2->aio_srcscope) {
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
if (dst1->aio_dstscope != dst1->aio_srcscope &&
|
|
|
|
dst2->aio_dstscope == dst2->aio_srcscope) {
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Rule 3: Avoid deprecated addresses. */
|
|
|
|
if (dst1->aio_srcsa.sa_family != AF_UNSPEC &&
|
|
|
|
dst2->aio_srcsa.sa_family != AF_UNSPEC) {
|
|
|
|
if (!(dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) &&
|
|
|
|
(dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) {
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
if ((dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) &&
|
|
|
|
!(dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) {
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Rule 4: Prefer home addresses. */
|
|
|
|
/* XXX: not implemented yet */
|
|
|
|
|
|
|
|
/* Rule 5: Prefer matching label. */
|
|
|
|
#ifdef INET6
|
|
|
|
if (dst1->aio_srcpolicy && dst1->aio_dstpolicy &&
|
|
|
|
dst1->aio_srcpolicy->pc_policy.label ==
|
|
|
|
dst1->aio_dstpolicy->pc_policy.label &&
|
|
|
|
(dst2->aio_srcpolicy == NULL || dst2->aio_dstpolicy == NULL ||
|
|
|
|
dst2->aio_srcpolicy->pc_policy.label !=
|
|
|
|
dst2->aio_dstpolicy->pc_policy.label)) {
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
if (dst2->aio_srcpolicy && dst2->aio_dstpolicy &&
|
|
|
|
dst2->aio_srcpolicy->pc_policy.label ==
|
|
|
|
dst2->aio_dstpolicy->pc_policy.label &&
|
|
|
|
(dst1->aio_srcpolicy == NULL || dst1->aio_dstpolicy == NULL ||
|
|
|
|
dst1->aio_srcpolicy->pc_policy.label !=
|
|
|
|
dst1->aio_dstpolicy->pc_policy.label)) {
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Rule 6: Prefer higher precedence. */
|
|
|
|
#ifdef INET6
|
|
|
|
if (dst1->aio_dstpolicy &&
|
|
|
|
(dst2->aio_dstpolicy == NULL ||
|
|
|
|
dst1->aio_dstpolicy->pc_policy.preced >
|
|
|
|
dst2->aio_dstpolicy->pc_policy.preced)) {
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
if (dst2->aio_dstpolicy &&
|
|
|
|
(dst1->aio_dstpolicy == NULL ||
|
|
|
|
dst2->aio_dstpolicy->pc_policy.preced >
|
|
|
|
dst1->aio_dstpolicy->pc_policy.preced)) {
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Rule 7: Prefer native transport. */
|
|
|
|
/* XXX: not implemented yet */
|
|
|
|
|
|
|
|
/* Rule 8: Prefer smaller scope. */
|
|
|
|
if (dst1->aio_dstscope >= 0 &&
|
|
|
|
dst1->aio_dstscope < dst2->aio_dstscope) {
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
if (dst2->aio_dstscope >= 0 &&
|
|
|
|
dst2->aio_dstscope < dst1->aio_dstscope) {
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Rule 9: Use longest matching prefix.
|
|
|
|
* We compare the match length in a same AF only.
|
|
|
|
*/
|
|
|
|
if (dst1->aio_sa.sa_family == dst2->aio_sa.sa_family) {
|
|
|
|
if (dst1->aio_matchlen > dst2->aio_matchlen) {
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
if (dst1->aio_matchlen < dst2->aio_matchlen) {
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Rule 10: Otherwise, leave the order unchanged. */
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy from scope.c.
|
|
|
|
* XXX: we should standardize the functions and link them as standard
|
|
|
|
* library.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
gai_addr2scopetype(sa)
|
|
|
|
struct sockaddr *sa;
|
|
|
|
{
|
|
|
|
#ifdef INET6
|
|
|
|
struct sockaddr_in6 *sa6;
|
|
|
|
#endif
|
|
|
|
struct sockaddr_in *sa4;
|
|
|
|
|
|
|
|
switch(sa->sa_family) {
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
|
|
|
sa6 = (struct sockaddr_in6 *)sa;
|
|
|
|
if (IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr)) {
|
|
|
|
/* just use the scope field of the multicast address */
|
|
|
|
return(sa6->sin6_addr.s6_addr[2] & 0x0f);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Unicast addresses: map scope type to corresponding scope
|
|
|
|
* value defined for multcast addresses.
|
|
|
|
* XXX: hardcoded scope type values are bad...
|
|
|
|
*/
|
|
|
|
if (IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr))
|
|
|
|
return(1); /* node local scope */
|
|
|
|
if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr))
|
|
|
|
return(2); /* link-local scope */
|
|
|
|
if (IN6_IS_ADDR_SITELOCAL(&sa6->sin6_addr))
|
|
|
|
return(5); /* site-local scope */
|
|
|
|
return(14); /* global scope */
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case AF_INET:
|
|
|
|
/*
|
|
|
|
* IPv4 pseudo scoping according to RFC 3484.
|
|
|
|
*/
|
|
|
|
sa4 = (struct sockaddr_in *)sa;
|
|
|
|
/* IPv4 autoconfiguration addresses have link-local scope. */
|
|
|
|
if (((u_char *)&sa4->sin_addr)[0] == 169 &&
|
|
|
|
((u_char *)&sa4->sin_addr)[1] == 254)
|
|
|
|
return(2);
|
|
|
|
/* Private addresses have site-local scope. */
|
|
|
|
if (((u_char *)&sa4->sin_addr)[0] == 10 ||
|
|
|
|
(((u_char *)&sa4->sin_addr)[0] == 172 &&
|
|
|
|
(((u_char *)&sa4->sin_addr)[1] & 0xf0) == 16) ||
|
|
|
|
(((u_char *)&sa4->sin_addr)[0] == 192 &&
|
|
|
|
((u_char *)&sa4->sin_addr)[1] == 168))
|
|
|
|
return(14); /* XXX: It should be 5 unless NAT */
|
|
|
|
/* Loopback addresses have link-local scope. */
|
|
|
|
if (((u_char *)&sa4->sin_addr)[0] == 127)
|
|
|
|
return(2);
|
|
|
|
return(14);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
errno = EAFNOSUPPORT; /* is this a good error? */
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-12-28 02:37:14 +00:00
|
|
|
/*
|
|
|
|
* FILES (/etc/hosts)
|
|
|
|
*/
|
|
|
|
|
|
|
|
static FILE *
|
|
|
|
_files_open(int *errp)
|
|
|
|
{
|
|
|
|
FILE *fp;
|
|
|
|
fp = fopen(_PATH_HOSTS, "r");
|
|
|
|
if (fp == NULL)
|
|
|
|
*errp = NO_RECOVERY;
|
|
|
|
return fp;
|
|
|
|
}
|
|
|
|
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
static int
|
|
|
|
_files_ghbyname(void *rval, void *cb_data, va_list ap)
|
1999-12-28 02:37:14 +00:00
|
|
|
{
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
const char *name;
|
|
|
|
int af;
|
|
|
|
int *errp;
|
1999-12-28 02:37:14 +00:00
|
|
|
int match, nalias;
|
|
|
|
char *p, *line, *addrstr, *cname;
|
|
|
|
FILE *fp;
|
|
|
|
struct hostent *rethp, *hp, hpbuf;
|
|
|
|
char *aliases[MAXALIASES + 1], *addrs[2];
|
|
|
|
union inx_addr addrbuf;
|
|
|
|
char buf[BUFSIZ];
|
2000-09-07 02:18:22 +00:00
|
|
|
int af0;
|
1999-12-28 02:37:14 +00:00
|
|
|
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
name = va_arg(ap, const char *);
|
|
|
|
af = va_arg(ap, int);
|
|
|
|
errp = va_arg(ap, int *);
|
|
|
|
|
|
|
|
*(struct hostent **)rval = NULL;
|
|
|
|
|
1999-12-28 02:37:14 +00:00
|
|
|
if ((fp = _files_open(errp)) == NULL)
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
return NS_UNAVAIL;
|
1999-12-28 02:37:14 +00:00
|
|
|
rethp = hp = NULL;
|
|
|
|
|
2000-09-07 02:18:22 +00:00
|
|
|
af0 = af;
|
1999-12-28 02:37:14 +00:00
|
|
|
while (fgets(buf, sizeof(buf), fp)) {
|
|
|
|
line = buf;
|
|
|
|
if ((addrstr = _hgetword(&line)) == NULL
|
|
|
|
|| (cname = _hgetword(&line)) == NULL)
|
|
|
|
continue;
|
|
|
|
match = (strcasecmp(cname, name) == 0);
|
|
|
|
nalias = 0;
|
|
|
|
while ((p = _hgetword(&line)) != NULL) {
|
|
|
|
if (!match)
|
|
|
|
match = (strcasecmp(p, name) == 0);
|
|
|
|
if (nalias < MAXALIASES)
|
|
|
|
aliases[nalias++] = p;
|
|
|
|
}
|
|
|
|
if (!match)
|
|
|
|
continue;
|
2000-04-20 03:31:40 +00:00
|
|
|
switch (af0) {
|
|
|
|
case AF_INET:
|
|
|
|
if (inet_aton(addrstr, (struct in_addr *)&addrbuf)
|
|
|
|
!= 1) {
|
|
|
|
*errp = NO_DATA; /* name found */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
af = af0;
|
|
|
|
break;
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
|
|
|
if (inet_pton(af, addrstr, &addrbuf) != 1) {
|
|
|
|
*errp = NO_DATA; /* name found */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
af = af0;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case AF_UNSPEC:
|
|
|
|
if (inet_aton(addrstr, (struct in_addr *)&addrbuf)
|
|
|
|
== 1) {
|
|
|
|
af = AF_INET;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#ifdef INET6
|
|
|
|
if (inet_pton(AF_INET6, addrstr, &addrbuf) == 1) {
|
|
|
|
af = AF_INET6;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
1999-12-28 02:37:14 +00:00
|
|
|
*errp = NO_DATA; /* name found */
|
|
|
|
continue;
|
2000-04-20 03:31:40 +00:00
|
|
|
/* NOTREACHED */
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
|
|
|
hp = &hpbuf;
|
|
|
|
hp->h_name = cname;
|
|
|
|
hp->h_aliases = aliases;
|
|
|
|
aliases[nalias] = NULL;
|
|
|
|
hp->h_addrtype = af;
|
|
|
|
hp->h_length = ADDRLEN(af);
|
|
|
|
hp->h_addr_list = addrs;
|
|
|
|
addrs[0] = (char *)&addrbuf;
|
|
|
|
addrs[1] = NULL;
|
|
|
|
hp = _hpcopy(hp, errp);
|
|
|
|
rethp = _hpmerge(rethp, hp, errp);
|
|
|
|
}
|
|
|
|
fclose(fp);
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
*(struct hostent **)rval = rethp;
|
|
|
|
return (rethp != NULL) ? NS_SUCCESS : NS_NOTFOUND;
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
|
|
|
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
static int
|
|
|
|
_files_ghbyaddr(void *rval, void *cb_data, va_list ap)
|
1999-12-28 02:37:14 +00:00
|
|
|
{
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
const void *addr;
|
|
|
|
int addrlen;
|
|
|
|
int af;
|
|
|
|
int *errp;
|
1999-12-28 02:37:14 +00:00
|
|
|
int nalias;
|
|
|
|
char *p, *line;
|
|
|
|
FILE *fp;
|
|
|
|
struct hostent *hp, hpbuf;
|
|
|
|
char *aliases[MAXALIASES + 1], *addrs[2];
|
|
|
|
union inx_addr addrbuf;
|
|
|
|
char buf[BUFSIZ];
|
|
|
|
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
addr = va_arg(ap, const void *);
|
|
|
|
addrlen = va_arg(ap, int);
|
|
|
|
af = va_arg(ap, int);
|
|
|
|
errp = va_arg(ap, int *);
|
|
|
|
|
|
|
|
*(struct hostent**)rval = NULL;
|
|
|
|
|
1999-12-28 02:37:14 +00:00
|
|
|
if ((fp = _files_open(errp)) == NULL)
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
return NS_UNAVAIL;
|
1999-12-28 02:37:14 +00:00
|
|
|
hp = NULL;
|
|
|
|
while (fgets(buf, sizeof(buf), fp)) {
|
|
|
|
line = buf;
|
|
|
|
if ((p = _hgetword(&line)) == NULL
|
2000-02-10 02:59:50 +00:00
|
|
|
|| (af == AF_INET
|
|
|
|
? inet_aton(p, (struct in_addr *)&addrbuf)
|
|
|
|
: inet_pton(af, p, &addrbuf)) != 1
|
1999-12-28 02:37:14 +00:00
|
|
|
|| memcmp(addr, &addrbuf, addrlen) != 0
|
|
|
|
|| (p = _hgetword(&line)) == NULL)
|
|
|
|
continue;
|
|
|
|
hp = &hpbuf;
|
|
|
|
hp->h_name = p;
|
|
|
|
hp->h_aliases = aliases;
|
|
|
|
nalias = 0;
|
|
|
|
while ((p = _hgetword(&line)) != NULL) {
|
|
|
|
if (nalias < MAXALIASES)
|
|
|
|
aliases[nalias++] = p;
|
|
|
|
}
|
|
|
|
aliases[nalias] = NULL;
|
|
|
|
hp->h_addrtype = af;
|
|
|
|
hp->h_length = addrlen;
|
|
|
|
hp->h_addr_list = addrs;
|
|
|
|
addrs[0] = (char *)&addrbuf;
|
|
|
|
addrs[1] = NULL;
|
|
|
|
hp = _hpcopy(hp, errp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
fclose(fp);
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
*(struct hostent **)rval = hp;
|
|
|
|
return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND;
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
|
|
|
|
2000-05-10 00:47:20 +00:00
|
|
|
#ifdef YP
|
2000-03-09 22:52:30 +00:00
|
|
|
/*
|
|
|
|
* NIS
|
|
|
|
*
|
|
|
|
* XXX actually a hack, these are INET4 specific.
|
|
|
|
*/
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
static int
|
|
|
|
_nis_ghbyname(void *rval, void *cb_data, va_list ap)
|
2000-03-09 22:52:30 +00:00
|
|
|
{
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
const char *name;
|
|
|
|
int af;
|
|
|
|
int *errp;
|
2000-03-15 15:04:54 +00:00
|
|
|
struct hostent *hp = NULL;
|
2000-03-09 22:52:30 +00:00
|
|
|
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
name = va_arg(ap, const char *);
|
|
|
|
af = va_arg(ap, int);
|
|
|
|
errp = va_arg(ap, int *);
|
|
|
|
|
2000-04-20 03:31:40 +00:00
|
|
|
if (af == AF_UNSPEC)
|
|
|
|
af = AF_INET;
|
2000-03-09 22:52:30 +00:00
|
|
|
if (af == AF_INET) {
|
Make the resolver(3) and many associated interfaces much more reentrant.
The getaddrinfo(3), getipnodebyname(3) and resolver(3) can coincide now
with what should be totally reentrant, and h_errno values will now
be preserved correctly, but this does not affect interfaces such as
gethostbyname(3) which are still mostly non-reentrant.
In all of these relevant functions, the thread-safety has been pushed
down as far as it seems possible right now. This means that operations
that are selected via nsdispatch(3) (i.e. files, yp, dns) are protected
still under global locks that getaddrinfo(3) defines, but where possible
the locking is greatly reduced. The most noticeable improvement is
that multiple DNS lookups can now be run at the same time, and this
shows major improvement in performance of DNS-lookup threaded programs,
and solves the "Mozilla tab serialization" problem.
No single-threaded applications need to be recompiled. Multi-threaded
applications that reference "_res" to change resolver(3) options will
need to be recompiled, and ones which reference "h_errno" will also
if they desire the correct h_errno values. If the applications already
understood that _res and h_errno were not thread-safe and had their own
locking, they will see no performance improvement but will not
actually break in any way.
Please note that when NSS modules are used, or when nsdispatch(3)
defaults to adding any lookups of its own to the individual libc
_nsdispatch() calls, those MUST be reentrant as well.
2004-02-25 21:03:46 +00:00
|
|
|
THREAD_LOCK();
|
2000-03-09 22:52:30 +00:00
|
|
|
hp = _gethostbynisname(name, af);
|
|
|
|
if (hp != NULL)
|
|
|
|
hp = _hpcopy(hp, errp);
|
Make the resolver(3) and many associated interfaces much more reentrant.
The getaddrinfo(3), getipnodebyname(3) and resolver(3) can coincide now
with what should be totally reentrant, and h_errno values will now
be preserved correctly, but this does not affect interfaces such as
gethostbyname(3) which are still mostly non-reentrant.
In all of these relevant functions, the thread-safety has been pushed
down as far as it seems possible right now. This means that operations
that are selected via nsdispatch(3) (i.e. files, yp, dns) are protected
still under global locks that getaddrinfo(3) defines, but where possible
the locking is greatly reduced. The most noticeable improvement is
that multiple DNS lookups can now be run at the same time, and this
shows major improvement in performance of DNS-lookup threaded programs,
and solves the "Mozilla tab serialization" problem.
No single-threaded applications need to be recompiled. Multi-threaded
applications that reference "_res" to change resolver(3) options will
need to be recompiled, and ones which reference "h_errno" will also
if they desire the correct h_errno values. If the applications already
understood that _res and h_errno were not thread-safe and had their own
locking, they will see no performance improvement but will not
actually break in any way.
Please note that when NSS modules are used, or when nsdispatch(3)
defaults to adding any lookups of its own to the individual libc
_nsdispatch() calls, those MUST be reentrant as well.
2004-02-25 21:03:46 +00:00
|
|
|
THREAD_UNLOCK();
|
2000-03-09 22:52:30 +00:00
|
|
|
}
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
|
|
|
|
*(struct hostent **)rval = hp;
|
|
|
|
return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND;
|
2000-03-09 22:52:30 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
static int
|
|
|
|
_nis_ghbyaddr(void *rval, void *cb_data, va_list ap)
|
2000-03-09 22:52:30 +00:00
|
|
|
{
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
const void *addr;
|
|
|
|
int addrlen;
|
|
|
|
int af;
|
|
|
|
int *errp;
|
2000-03-09 22:52:30 +00:00
|
|
|
struct hostent *hp = NULL;
|
|
|
|
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
addr = va_arg(ap, const void *);
|
|
|
|
addrlen = va_arg(ap, int);
|
|
|
|
af = va_arg(ap, int);
|
|
|
|
|
2000-03-09 22:52:30 +00:00
|
|
|
if (af == AF_INET) {
|
Make the resolver(3) and many associated interfaces much more reentrant.
The getaddrinfo(3), getipnodebyname(3) and resolver(3) can coincide now
with what should be totally reentrant, and h_errno values will now
be preserved correctly, but this does not affect interfaces such as
gethostbyname(3) which are still mostly non-reentrant.
In all of these relevant functions, the thread-safety has been pushed
down as far as it seems possible right now. This means that operations
that are selected via nsdispatch(3) (i.e. files, yp, dns) are protected
still under global locks that getaddrinfo(3) defines, but where possible
the locking is greatly reduced. The most noticeable improvement is
that multiple DNS lookups can now be run at the same time, and this
shows major improvement in performance of DNS-lookup threaded programs,
and solves the "Mozilla tab serialization" problem.
No single-threaded applications need to be recompiled. Multi-threaded
applications that reference "_res" to change resolver(3) options will
need to be recompiled, and ones which reference "h_errno" will also
if they desire the correct h_errno values. If the applications already
understood that _res and h_errno were not thread-safe and had their own
locking, they will see no performance improvement but will not
actually break in any way.
Please note that when NSS modules are used, or when nsdispatch(3)
defaults to adding any lookups of its own to the individual libc
_nsdispatch() calls, those MUST be reentrant as well.
2004-02-25 21:03:46 +00:00
|
|
|
THREAD_LOCK();
|
2000-03-09 22:52:30 +00:00
|
|
|
hp = _gethostbynisaddr(addr, addrlen, af);
|
|
|
|
if (hp != NULL)
|
|
|
|
hp = _hpcopy(hp, errp);
|
Make the resolver(3) and many associated interfaces much more reentrant.
The getaddrinfo(3), getipnodebyname(3) and resolver(3) can coincide now
with what should be totally reentrant, and h_errno values will now
be preserved correctly, but this does not affect interfaces such as
gethostbyname(3) which are still mostly non-reentrant.
In all of these relevant functions, the thread-safety has been pushed
down as far as it seems possible right now. This means that operations
that are selected via nsdispatch(3) (i.e. files, yp, dns) are protected
still under global locks that getaddrinfo(3) defines, but where possible
the locking is greatly reduced. The most noticeable improvement is
that multiple DNS lookups can now be run at the same time, and this
shows major improvement in performance of DNS-lookup threaded programs,
and solves the "Mozilla tab serialization" problem.
No single-threaded applications need to be recompiled. Multi-threaded
applications that reference "_res" to change resolver(3) options will
need to be recompiled, and ones which reference "h_errno" will also
if they desire the correct h_errno values. If the applications already
understood that _res and h_errno were not thread-safe and had their own
locking, they will see no performance improvement but will not
actually break in any way.
Please note that when NSS modules are used, or when nsdispatch(3)
defaults to adding any lookups of its own to the individual libc
_nsdispatch() calls, those MUST be reentrant as well.
2004-02-25 21:03:46 +00:00
|
|
|
THREAD_UNLOCK();
|
2000-03-09 22:52:30 +00:00
|
|
|
}
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
*(struct hostent **)rval = hp;
|
|
|
|
return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND;
|
2000-03-09 22:52:30 +00:00
|
|
|
}
|
1999-12-28 02:37:14 +00:00
|
|
|
#endif
|
|
|
|
|
2000-04-20 03:31:40 +00:00
|
|
|
struct __res_type_list {
|
2000-05-26 02:09:24 +00:00
|
|
|
SLIST_ENTRY(__res_type_list) rtl_entry;
|
2000-04-20 03:31:40 +00:00
|
|
|
int rtl_type;
|
|
|
|
};
|
|
|
|
|
2002-09-16 13:19:47 +00:00
|
|
|
#define MAXPACKET (64*1024)
|
2000-05-10 00:47:20 +00:00
|
|
|
|
|
|
|
typedef union {
|
|
|
|
HEADER hdr;
|
|
|
|
u_char buf[MAXPACKET];
|
|
|
|
} querybuf;
|
|
|
|
|
2002-03-22 09:22:15 +00:00
|
|
|
static struct hostent *getanswer(const querybuf *, int, const char *, int,
|
|
|
|
struct hostent *, int *);
|
2000-05-10 00:47:20 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* we don't need to take care about sorting, nor IPv4 mapped address here.
|
|
|
|
*/
|
1999-12-28 02:37:14 +00:00
|
|
|
static struct hostent *
|
2000-05-10 00:47:20 +00:00
|
|
|
getanswer(answer, anslen, qname, qtype, template, errp)
|
|
|
|
const querybuf *answer;
|
2000-04-20 03:31:40 +00:00
|
|
|
int anslen;
|
2000-05-10 00:47:20 +00:00
|
|
|
const char *qname;
|
2000-04-20 03:31:40 +00:00
|
|
|
int qtype;
|
2000-05-10 00:47:20 +00:00
|
|
|
struct hostent *template;
|
2000-04-20 03:31:40 +00:00
|
|
|
int *errp;
|
1999-12-28 02:37:14 +00:00
|
|
|
{
|
2002-03-21 18:49:23 +00:00
|
|
|
const HEADER *hp;
|
|
|
|
const u_char *cp;
|
|
|
|
int n;
|
2000-05-10 00:47:20 +00:00
|
|
|
const u_char *eom, *erdata;
|
2002-06-26 08:18:05 +00:00
|
|
|
char *bp, *ep, **ap, **hap;
|
|
|
|
int type, class, ancount, qdcount;
|
2000-05-10 00:47:20 +00:00
|
|
|
int haveanswer, had_error;
|
|
|
|
char tbuf[MAXDNAME];
|
|
|
|
const char *tname;
|
2002-03-21 22:49:10 +00:00
|
|
|
int (*name_ok)(const char *);
|
2000-05-10 00:47:20 +00:00
|
|
|
static char *h_addr_ptrs[MAXADDRS + 1];
|
|
|
|
static char *host_aliases[MAXALIASES];
|
|
|
|
static char hostbuf[8*1024];
|
|
|
|
|
|
|
|
#define BOUNDED_INCR(x) \
|
|
|
|
do { \
|
|
|
|
cp += x; \
|
|
|
|
if (cp > eom) { \
|
|
|
|
*errp = NO_RECOVERY; \
|
|
|
|
return (NULL); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define BOUNDS_CHECK(ptr, count) \
|
|
|
|
do { \
|
|
|
|
if ((ptr) + (count) > eom) { \
|
|
|
|
*errp = NO_RECOVERY; \
|
|
|
|
return (NULL); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
2000-07-03 04:43:14 +00:00
|
|
|
/* XXX do {} while (0) cannot be put here */
|
2000-05-10 00:47:20 +00:00
|
|
|
#define DNS_ASSERT(x) \
|
2000-07-03 04:43:14 +00:00
|
|
|
{ \
|
2000-05-10 00:47:20 +00:00
|
|
|
if (!(x)) { \
|
|
|
|
cp += n; \
|
|
|
|
continue; \
|
|
|
|
} \
|
2000-07-03 04:43:14 +00:00
|
|
|
}
|
2000-05-10 00:47:20 +00:00
|
|
|
|
2000-07-03 04:43:14 +00:00
|
|
|
/* XXX do {} while (0) cannot be put here */
|
2000-05-10 00:47:20 +00:00
|
|
|
#define DNS_FATAL(x) \
|
2000-07-03 04:43:14 +00:00
|
|
|
{ \
|
2000-05-10 00:47:20 +00:00
|
|
|
if (!(x)) { \
|
|
|
|
had_error++; \
|
|
|
|
continue; \
|
|
|
|
} \
|
2000-07-03 04:43:14 +00:00
|
|
|
}
|
2000-05-10 00:47:20 +00:00
|
|
|
|
|
|
|
tname = qname;
|
|
|
|
template->h_name = NULL;
|
|
|
|
eom = answer->buf + anslen;
|
|
|
|
switch (qtype) {
|
|
|
|
case T_A:
|
|
|
|
case T_AAAA:
|
|
|
|
name_ok = res_hnok;
|
|
|
|
break;
|
|
|
|
case T_PTR:
|
|
|
|
name_ok = res_dnok;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return (NULL); /* XXX should be abort(); */
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* find first satisfactory answer
|
|
|
|
*/
|
|
|
|
hp = &answer->hdr;
|
1999-12-28 02:37:14 +00:00
|
|
|
ancount = ntohs(hp->ancount);
|
|
|
|
qdcount = ntohs(hp->qdcount);
|
|
|
|
bp = hostbuf;
|
2002-06-26 08:18:05 +00:00
|
|
|
ep = hostbuf + sizeof hostbuf;
|
2000-05-10 00:47:20 +00:00
|
|
|
cp = answer->buf;
|
|
|
|
BOUNDED_INCR(HFIXEDSZ);
|
|
|
|
if (qdcount != 1) {
|
|
|
|
*errp = NO_RECOVERY;
|
|
|
|
return (NULL);
|
|
|
|
}
|
2002-06-26 08:18:05 +00:00
|
|
|
n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
|
2000-05-10 00:47:20 +00:00
|
|
|
if ((n < 0) || !(*name_ok)(bp)) {
|
|
|
|
*errp = NO_RECOVERY;
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
BOUNDED_INCR(n + QFIXEDSZ);
|
|
|
|
if (qtype == T_A || qtype == T_AAAA) {
|
|
|
|
/* res_send() has already verified that the query name is the
|
|
|
|
* same as the one we sent; this just gets the expanded name
|
|
|
|
* (i.e., with the succeeding search-domain tacked on).
|
|
|
|
*/
|
|
|
|
n = strlen(bp) + 1; /* for the \0 */
|
|
|
|
if (n >= MAXHOSTNAMELEN) {
|
|
|
|
*errp = NO_RECOVERY;
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
template->h_name = bp;
|
|
|
|
bp += n;
|
|
|
|
/* The qname can be abbreviated, but h_name is now absolute. */
|
|
|
|
qname = template->h_name;
|
|
|
|
}
|
|
|
|
ap = host_aliases;
|
|
|
|
*ap = NULL;
|
|
|
|
template->h_aliases = host_aliases;
|
|
|
|
hap = h_addr_ptrs;
|
|
|
|
*hap = NULL;
|
|
|
|
template->h_addr_list = h_addr_ptrs;
|
|
|
|
haveanswer = 0;
|
|
|
|
had_error = 0;
|
|
|
|
while (ancount-- > 0 && cp < eom && !had_error) {
|
2002-06-26 08:18:05 +00:00
|
|
|
n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
|
2000-05-10 00:47:20 +00:00
|
|
|
DNS_FATAL(n >= 0);
|
|
|
|
DNS_FATAL((*name_ok)(bp));
|
|
|
|
cp += n; /* name */
|
|
|
|
BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
|
1999-12-28 02:37:14 +00:00
|
|
|
type = _getshort(cp);
|
2000-05-10 00:47:20 +00:00
|
|
|
cp += INT16SZ; /* type */
|
1999-12-28 02:37:14 +00:00
|
|
|
class = _getshort(cp);
|
2000-05-10 00:47:20 +00:00
|
|
|
cp += INT16SZ + INT32SZ; /* class, TTL */
|
1999-12-28 02:37:14 +00:00
|
|
|
n = _getshort(cp);
|
2000-05-10 00:47:20 +00:00
|
|
|
cp += INT16SZ; /* len */
|
|
|
|
BOUNDS_CHECK(cp, n);
|
|
|
|
erdata = cp + n;
|
1999-12-28 02:37:14 +00:00
|
|
|
DNS_ASSERT(class == C_IN);
|
2000-05-10 00:47:20 +00:00
|
|
|
if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
|
|
|
|
if (ap >= &host_aliases[MAXALIASES-1])
|
|
|
|
continue;
|
|
|
|
n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
|
|
|
|
DNS_FATAL(n >= 0);
|
|
|
|
DNS_FATAL((*name_ok)(tbuf));
|
1999-12-28 02:37:14 +00:00
|
|
|
cp += n;
|
2000-05-10 00:47:20 +00:00
|
|
|
if (cp != erdata) {
|
|
|
|
*errp = NO_RECOVERY;
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
/* Store alias. */
|
|
|
|
*ap++ = bp;
|
|
|
|
n = strlen(bp) + 1; /* for the \0 */
|
|
|
|
DNS_FATAL(n < MAXHOSTNAMELEN);
|
1999-12-28 02:37:14 +00:00
|
|
|
bp += n;
|
2000-05-10 00:47:20 +00:00
|
|
|
/* Get canonical name. */
|
|
|
|
n = strlen(tbuf) + 1; /* for the \0 */
|
2002-06-26 08:18:05 +00:00
|
|
|
DNS_FATAL(n <= ep - bp);
|
2000-05-10 00:47:20 +00:00
|
|
|
DNS_FATAL(n < MAXHOSTNAMELEN);
|
|
|
|
strcpy(bp, tbuf);
|
|
|
|
template->h_name = bp;
|
|
|
|
bp += n;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (qtype == T_PTR && type == T_CNAME) {
|
|
|
|
n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
|
|
|
|
if (n < 0 || !res_dnok(tbuf)) {
|
|
|
|
had_error++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
cp += n;
|
|
|
|
if (cp != erdata) {
|
|
|
|
*errp = NO_RECOVERY;
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
/* Get canonical name. */
|
|
|
|
n = strlen(tbuf) + 1; /* for the \0 */
|
2002-06-26 08:18:05 +00:00
|
|
|
if (n > ep - bp || n >= MAXHOSTNAMELEN) {
|
2000-05-10 00:47:20 +00:00
|
|
|
had_error++;
|
|
|
|
continue;
|
|
|
|
}
|
1999-12-28 02:37:14 +00:00
|
|
|
strcpy(bp, tbuf);
|
2000-07-03 04:43:14 +00:00
|
|
|
tname = bp;
|
1999-12-28 02:37:14 +00:00
|
|
|
bp += n;
|
2000-05-10 00:47:20 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
DNS_ASSERT(type == qtype);
|
|
|
|
switch (type) {
|
|
|
|
case T_PTR:
|
|
|
|
DNS_ASSERT(strcasecmp(tname, bp) == 0);
|
2002-06-26 08:18:05 +00:00
|
|
|
n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
|
2000-05-10 00:47:20 +00:00
|
|
|
DNS_FATAL(n >= 0);
|
|
|
|
DNS_FATAL(res_hnok(bp));
|
|
|
|
#if MULTI_PTRS_ARE_ALIASES
|
|
|
|
cp += n;
|
|
|
|
if (cp != erdata) {
|
|
|
|
*errp = NO_RECOVERY;
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
if (!haveanswer)
|
|
|
|
template->h_name = bp;
|
|
|
|
else if (ap < &host_aliases[MAXALIASES-1])
|
|
|
|
*ap++ = bp;
|
|
|
|
else
|
|
|
|
n = -1;
|
|
|
|
if (n != -1) {
|
|
|
|
n = strlen(bp) + 1; /* for the \0 */
|
|
|
|
if (n >= MAXHOSTNAMELEN) {
|
|
|
|
had_error++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
bp += n;
|
|
|
|
}
|
1999-12-28 02:37:14 +00:00
|
|
|
break;
|
2000-05-10 00:47:20 +00:00
|
|
|
#else
|
|
|
|
template->h_name = bp;
|
|
|
|
*errp = NETDB_SUCCESS;
|
|
|
|
return (template);
|
|
|
|
#endif
|
1999-12-28 02:37:14 +00:00
|
|
|
case T_A:
|
|
|
|
case T_AAAA:
|
2000-05-10 00:47:20 +00:00
|
|
|
DNS_ASSERT(strcasecmp(template->h_name, bp) == 0);
|
|
|
|
DNS_ASSERT(n == template->h_length);
|
|
|
|
if (!haveanswer) {
|
2002-03-21 18:49:23 +00:00
|
|
|
int nn;
|
2000-05-10 00:47:20 +00:00
|
|
|
|
|
|
|
template->h_name = bp;
|
|
|
|
nn = strlen(bp) + 1; /* for the \0 */
|
|
|
|
bp += nn;
|
|
|
|
}
|
1999-12-28 02:37:14 +00:00
|
|
|
bp = (char *)ALIGN(bp);
|
2000-05-10 00:47:20 +00:00
|
|
|
|
2002-06-26 08:18:05 +00:00
|
|
|
DNS_FATAL(bp + n < ep);
|
2000-05-10 00:47:20 +00:00
|
|
|
DNS_ASSERT(hap < &h_addr_ptrs[MAXADDRS-1]);
|
|
|
|
#ifdef FILTER_V4MAPPED
|
|
|
|
if (type == T_AAAA) {
|
|
|
|
struct in6_addr in6;
|
|
|
|
memcpy(&in6, cp, sizeof(in6));
|
|
|
|
DNS_ASSERT(IN6_IS_ADDR_V4MAPPED(&in6) == 0);
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
2000-05-10 00:47:20 +00:00
|
|
|
#endif
|
|
|
|
bcopy(cp, *hap++ = bp, n);
|
|
|
|
bp += n;
|
1999-12-28 02:37:14 +00:00
|
|
|
cp += n;
|
2000-05-10 00:47:20 +00:00
|
|
|
if (cp != erdata) {
|
|
|
|
*errp = NO_RECOVERY;
|
|
|
|
return (NULL);
|
|
|
|
}
|
1999-12-28 02:37:14 +00:00
|
|
|
break;
|
|
|
|
default:
|
2000-05-10 00:47:20 +00:00
|
|
|
abort();
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
2000-05-10 00:47:20 +00:00
|
|
|
if (!had_error)
|
|
|
|
haveanswer++;
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
2000-05-10 00:47:20 +00:00
|
|
|
if (haveanswer) {
|
|
|
|
*ap = NULL;
|
|
|
|
*hap = NULL;
|
|
|
|
if (!template->h_name) {
|
|
|
|
n = strlen(qname) + 1; /* for the \0 */
|
2002-06-26 08:18:05 +00:00
|
|
|
if (n > ep - bp || n >= MAXHOSTNAMELEN)
|
2000-05-10 00:47:20 +00:00
|
|
|
goto no_recovery;
|
|
|
|
strcpy(bp, qname);
|
|
|
|
template->h_name = bp;
|
|
|
|
bp += n;
|
|
|
|
}
|
|
|
|
*errp = NETDB_SUCCESS;
|
|
|
|
return (template);
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
2000-05-10 00:47:20 +00:00
|
|
|
no_recovery:
|
|
|
|
*errp = NO_RECOVERY;
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
#undef BOUNDED_INCR
|
|
|
|
#undef BOUNDS_CHECK
|
|
|
|
#undef DNS_ASSERT
|
|
|
|
#undef DNS_FATAL
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
|
|
|
|
2000-04-20 03:31:40 +00:00
|
|
|
/* res_search() variant with multiple query support. */
|
|
|
|
static struct hostent *
|
|
|
|
_res_search_multi(name, rtl, errp)
|
|
|
|
const char *name; /* domain name */
|
|
|
|
struct __res_type_list *rtl; /* list of query types */
|
|
|
|
int *errp;
|
|
|
|
{
|
|
|
|
const char *cp, * const *domain;
|
|
|
|
struct hostent *hp0 = NULL, *hp;
|
2000-05-10 00:47:20 +00:00
|
|
|
struct hostent hpbuf;
|
2000-04-20 03:31:40 +00:00
|
|
|
u_int dots;
|
|
|
|
int trailing_dot, ret, saved_herrno;
|
|
|
|
int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
|
|
|
|
struct __res_type_list *rtl0 = rtl;
|
2002-09-16 13:19:47 +00:00
|
|
|
querybuf *buf;
|
2000-04-20 03:31:40 +00:00
|
|
|
|
|
|
|
if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
|
|
|
|
*errp = NETDB_INTERNAL;
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
dots = 0;
|
|
|
|
for (cp = name; *cp; cp++)
|
|
|
|
dots += (*cp == '.');
|
|
|
|
trailing_dot = 0;
|
|
|
|
if (cp > name && *--cp == '.')
|
|
|
|
trailing_dot++;
|
|
|
|
|
2002-09-16 13:19:47 +00:00
|
|
|
buf = malloc(sizeof(*buf));
|
|
|
|
if (buf == NULL) {
|
|
|
|
*errp = NETDB_INTERNAL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2000-04-20 03:31:40 +00:00
|
|
|
/* If there aren't any dots, it could be a user-level alias */
|
|
|
|
if (!dots && (cp = hostalias(name)) != NULL) {
|
|
|
|
for(rtl = rtl0; rtl != NULL;
|
|
|
|
rtl = SLIST_NEXT(rtl, rtl_entry)) {
|
2002-09-16 13:19:47 +00:00
|
|
|
ret = res_query(cp, C_IN, rtl->rtl_type, buf->buf,
|
|
|
|
sizeof(buf->buf));
|
|
|
|
if (ret > 0 && ret < sizeof(buf->buf)) {
|
2000-05-10 00:47:20 +00:00
|
|
|
hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA)
|
|
|
|
? AF_INET6 : AF_INET;
|
|
|
|
hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype);
|
2002-09-16 13:19:47 +00:00
|
|
|
hp = getanswer(buf, ret, name, rtl->rtl_type,
|
2000-05-10 00:47:20 +00:00
|
|
|
&hpbuf, errp);
|
2000-07-03 04:43:14 +00:00
|
|
|
if (!hp)
|
|
|
|
continue;
|
2000-05-10 00:47:20 +00:00
|
|
|
hp = _hpcopy(&hpbuf, errp);
|
2000-04-20 03:31:40 +00:00
|
|
|
hp0 = _hpmerge(hp0, hp, errp);
|
2004-04-06 09:31:22 +00:00
|
|
|
} else
|
|
|
|
*errp = h_errno;
|
2000-04-20 03:31:40 +00:00
|
|
|
}
|
2002-09-16 13:19:47 +00:00
|
|
|
free(buf);
|
2000-04-20 03:31:40 +00:00
|
|
|
return (hp0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If there are dots in the name already, let's just give it a try
|
|
|
|
* 'as is'. The threshold can be set with the "ndots" option.
|
|
|
|
*/
|
|
|
|
saved_herrno = -1;
|
|
|
|
if (dots >= _res.ndots) {
|
|
|
|
for(rtl = rtl0; rtl != NULL;
|
|
|
|
rtl = SLIST_NEXT(rtl, rtl_entry)) {
|
|
|
|
ret = res_querydomain(name, NULL, C_IN, rtl->rtl_type,
|
2002-09-16 13:19:47 +00:00
|
|
|
buf->buf, sizeof(buf->buf));
|
|
|
|
if (ret > 0 && ret < sizeof(buf->buf)) {
|
2000-05-10 00:47:20 +00:00
|
|
|
hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA)
|
|
|
|
? AF_INET6 : AF_INET;
|
|
|
|
hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype);
|
2002-09-16 13:19:47 +00:00
|
|
|
hp = getanswer(buf, ret, name, rtl->rtl_type,
|
2000-05-10 00:47:20 +00:00
|
|
|
&hpbuf, errp);
|
2000-07-03 04:43:14 +00:00
|
|
|
if (!hp)
|
|
|
|
continue;
|
2000-05-10 00:47:20 +00:00
|
|
|
hp = _hpcopy(&hpbuf, errp);
|
2000-04-20 03:31:40 +00:00
|
|
|
hp0 = _hpmerge(hp0, hp, errp);
|
2004-04-05 20:18:48 +00:00
|
|
|
} else
|
|
|
|
*errp = h_errno;
|
2000-04-20 03:31:40 +00:00
|
|
|
}
|
2002-09-16 13:19:47 +00:00
|
|
|
if (hp0 != NULL) {
|
|
|
|
free(buf);
|
2000-04-20 03:31:40 +00:00
|
|
|
return (hp0);
|
2002-09-16 13:19:47 +00:00
|
|
|
}
|
2000-04-20 03:31:40 +00:00
|
|
|
saved_herrno = *errp;
|
|
|
|
tried_as_is++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We do at least one level of search if
|
|
|
|
* - there is no dot and RES_DEFNAME is set, or
|
|
|
|
* - there is at least one dot, there is no trailing dot,
|
|
|
|
* and RES_DNSRCH is set.
|
|
|
|
*/
|
|
|
|
if ((!dots && (_res.options & RES_DEFNAMES)) ||
|
|
|
|
(dots && !trailing_dot && (_res.options & RES_DNSRCH))) {
|
|
|
|
int done = 0;
|
|
|
|
|
|
|
|
for (domain = (const char * const *)_res.dnsrch;
|
|
|
|
*domain && !done;
|
|
|
|
domain++) {
|
|
|
|
|
|
|
|
for(rtl = rtl0; rtl != NULL;
|
|
|
|
rtl = SLIST_NEXT(rtl, rtl_entry)) {
|
|
|
|
ret = res_querydomain(name, *domain, C_IN,
|
|
|
|
rtl->rtl_type,
|
2002-09-16 13:19:47 +00:00
|
|
|
buf->buf, sizeof(buf->buf));
|
|
|
|
if (ret > 0 && ret < sizeof(buf->buf)) {
|
2000-05-10 00:47:20 +00:00
|
|
|
hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA)
|
|
|
|
? AF_INET6 : AF_INET;
|
|
|
|
hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype);
|
2002-09-16 13:19:47 +00:00
|
|
|
hp = getanswer(buf, ret, name,
|
2000-05-10 00:47:20 +00:00
|
|
|
rtl->rtl_type, &hpbuf, errp);
|
2000-07-03 04:43:14 +00:00
|
|
|
if (!hp)
|
|
|
|
continue;
|
2000-05-10 00:47:20 +00:00
|
|
|
hp = _hpcopy(&hpbuf, errp);
|
2000-04-20 03:31:40 +00:00
|
|
|
hp0 = _hpmerge(hp0, hp, errp);
|
2004-04-05 20:18:48 +00:00
|
|
|
} else
|
|
|
|
*errp = h_errno;
|
2000-04-20 03:31:40 +00:00
|
|
|
}
|
2002-09-16 13:19:47 +00:00
|
|
|
if (hp0 != NULL) {
|
|
|
|
free(buf);
|
2000-04-20 03:31:40 +00:00
|
|
|
return (hp0);
|
2002-09-16 13:19:47 +00:00
|
|
|
}
|
2000-04-20 03:31:40 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If no server present, give up.
|
|
|
|
* If name isn't found in this domain,
|
|
|
|
* keep trying higher domains in the search list
|
|
|
|
* (if that's enabled).
|
|
|
|
* On a NO_DATA error, keep trying, otherwise
|
|
|
|
* a wildcard entry of another type could keep us
|
|
|
|
* from finding this entry higher in the domain.
|
|
|
|
* If we get some other error (negative answer or
|
|
|
|
* server failure), then stop searching up,
|
|
|
|
* but try the input name below in case it's
|
|
|
|
* fully-qualified.
|
|
|
|
*/
|
|
|
|
if (errno == ECONNREFUSED) {
|
2002-09-16 13:19:47 +00:00
|
|
|
free(buf);
|
2000-04-20 03:31:40 +00:00
|
|
|
*errp = TRY_AGAIN;
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (*errp) {
|
|
|
|
case NO_DATA:
|
|
|
|
got_nodata++;
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
case HOST_NOT_FOUND:
|
|
|
|
/* keep trying */
|
|
|
|
break;
|
|
|
|
case TRY_AGAIN:
|
2002-09-16 13:19:47 +00:00
|
|
|
if (buf->hdr.rcode == SERVFAIL) {
|
2000-04-20 03:31:40 +00:00
|
|
|
/* try next search element, if any */
|
|
|
|
got_servfail++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
default:
|
|
|
|
/* anything else implies that we're done */
|
|
|
|
done++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if we got here for some reason other than DNSRCH,
|
|
|
|
* we only wanted one iteration of the loop, so stop.
|
|
|
|
*/
|
|
|
|
if (!(_res.options & RES_DNSRCH))
|
|
|
|
done++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we have not already tried the name "as is", do that now.
|
|
|
|
* note that we do this regardless of how many dots were in the
|
|
|
|
* name or whether it ends with a dot unless NOTLDQUERY is set.
|
|
|
|
*/
|
|
|
|
if (!tried_as_is && (dots || !(_res.options & RES_NOTLDQUERY))) {
|
|
|
|
for(rtl = rtl0; rtl != NULL;
|
|
|
|
rtl = SLIST_NEXT(rtl, rtl_entry)) {
|
|
|
|
ret = res_querydomain(name, NULL, C_IN, rtl->rtl_type,
|
2002-09-16 13:19:47 +00:00
|
|
|
buf->buf, sizeof(buf->buf));
|
|
|
|
if (ret > 0 && ret < sizeof(buf->buf)) {
|
2000-05-10 00:47:20 +00:00
|
|
|
hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA)
|
|
|
|
? AF_INET6 : AF_INET;
|
|
|
|
hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype);
|
2002-09-16 13:19:47 +00:00
|
|
|
hp = getanswer(buf, ret, name, rtl->rtl_type,
|
2000-05-10 00:47:20 +00:00
|
|
|
&hpbuf, errp);
|
2000-07-03 04:43:14 +00:00
|
|
|
if (!hp)
|
|
|
|
continue;
|
2000-05-10 00:47:20 +00:00
|
|
|
hp = _hpcopy(&hpbuf, errp);
|
2000-04-20 03:31:40 +00:00
|
|
|
hp0 = _hpmerge(hp0, hp, errp);
|
2004-04-05 20:18:48 +00:00
|
|
|
} else
|
|
|
|
*errp = h_errno;
|
2000-04-20 03:31:40 +00:00
|
|
|
}
|
2002-09-16 13:19:47 +00:00
|
|
|
if (hp0 != NULL) {
|
|
|
|
free(buf);
|
2000-04-20 03:31:40 +00:00
|
|
|
return (hp0);
|
2002-09-16 13:19:47 +00:00
|
|
|
}
|
2000-04-20 03:31:40 +00:00
|
|
|
}
|
|
|
|
|
2002-09-16 13:19:47 +00:00
|
|
|
free(buf);
|
|
|
|
|
2000-04-20 03:31:40 +00:00
|
|
|
/* if we got here, we didn't satisfy the search.
|
|
|
|
* if we did an initial full query, return that query's h_errno
|
|
|
|
* (note that we wouldn't be here if that query had succeeded).
|
|
|
|
* else if we ever got a nodata, send that back as the reason.
|
|
|
|
* else send back meaningless h_errno, that being the one from
|
|
|
|
* the last DNSRCH we did.
|
|
|
|
*/
|
|
|
|
if (saved_herrno != -1)
|
|
|
|
*errp = saved_herrno;
|
|
|
|
else if (got_nodata)
|
|
|
|
*errp = NO_DATA;
|
|
|
|
else if (got_servfail)
|
|
|
|
*errp = TRY_AGAIN;
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
static int
|
|
|
|
_dns_ghbyname(void *rval, void *cb_data, va_list ap)
|
2000-04-20 03:31:40 +00:00
|
|
|
{
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
const char *name;
|
|
|
|
int af;
|
|
|
|
int *errp;
|
2000-04-20 03:31:40 +00:00
|
|
|
struct __res_type_list *rtl, rtl4;
|
|
|
|
#ifdef INET6
|
|
|
|
struct __res_type_list rtl6;
|
|
|
|
#endif
|
|
|
|
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
name = va_arg(ap, const char *);
|
|
|
|
af = va_arg(ap, int);
|
|
|
|
errp = va_arg(ap, int *);
|
|
|
|
|
2000-04-20 03:31:40 +00:00
|
|
|
#ifdef INET6
|
|
|
|
switch (af) {
|
|
|
|
case AF_UNSPEC:
|
|
|
|
SLIST_NEXT(&rtl4, rtl_entry) = NULL; rtl4.rtl_type = T_A;
|
|
|
|
SLIST_NEXT(&rtl6, rtl_entry) = &rtl4; rtl6.rtl_type = T_AAAA;
|
|
|
|
rtl = &rtl6;
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
SLIST_NEXT(&rtl6, rtl_entry) = NULL; rtl6.rtl_type = T_AAAA;
|
|
|
|
rtl = &rtl6;
|
|
|
|
break;
|
|
|
|
case AF_INET:
|
|
|
|
SLIST_NEXT(&rtl4, rtl_entry) = NULL; rtl4.rtl_type = T_A;
|
|
|
|
rtl = &rtl4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
SLIST_NEXT(&rtl4, rtl_entry) = NULL; rtl4.rtl_type = T_A;
|
|
|
|
rtl = &rtl4;
|
|
|
|
#endif
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
*(struct hostent **)rval = _res_search_multi(name, rtl, errp);
|
2004-04-05 20:18:48 +00:00
|
|
|
if (*(struct hostent **)rval != NULL)
|
|
|
|
return NS_SUCCESS;
|
|
|
|
else if (*errp == TRY_AGAIN)
|
|
|
|
return NS_TRYAGAIN;
|
|
|
|
else
|
|
|
|
return NS_NOTFOUND;
|
2000-04-20 03:31:40 +00:00
|
|
|
}
|
|
|
|
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
static int
|
|
|
|
_dns_ghbyaddr(void *rval, void *cb_data, va_list ap)
|
1999-12-28 02:37:14 +00:00
|
|
|
{
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
const void *addr;
|
|
|
|
int addrlen;
|
|
|
|
int af;
|
|
|
|
int *errp;
|
1999-12-28 02:37:14 +00:00
|
|
|
int n;
|
2002-10-23 10:45:09 +00:00
|
|
|
int err;
|
2000-05-10 00:47:20 +00:00
|
|
|
struct hostent *hp;
|
|
|
|
u_char c, *cp;
|
1999-12-28 02:37:14 +00:00
|
|
|
char *bp;
|
|
|
|
struct hostent hbuf;
|
|
|
|
int na;
|
|
|
|
#ifdef INET6
|
|
|
|
static const char hex[] = "0123456789abcdef";
|
|
|
|
#endif
|
2002-09-16 13:19:47 +00:00
|
|
|
querybuf *buf;
|
2000-05-10 00:47:20 +00:00
|
|
|
char qbuf[MAXDNAME+1];
|
|
|
|
char *hlist[2];
|
2004-07-21 17:26:40 +00:00
|
|
|
char *tld6[] = { "ip6.arpa", NULL };
|
2002-10-23 10:45:09 +00:00
|
|
|
char *tld4[] = { "in-addr.arpa", NULL };
|
|
|
|
char **tld;
|
1999-12-28 02:37:14 +00:00
|
|
|
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
addr = va_arg(ap, const void *);
|
|
|
|
addrlen = va_arg(ap, int);
|
|
|
|
af = va_arg(ap, int);
|
|
|
|
errp = va_arg(ap, int *);
|
|
|
|
|
|
|
|
*(struct hostent **)rval = NULL;
|
|
|
|
|
1999-12-28 02:37:14 +00:00
|
|
|
#ifdef INET6
|
|
|
|
/* XXX */
|
|
|
|
if (af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr))
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
return NS_NOTFOUND;
|
1999-12-28 02:37:14 +00:00
|
|
|
#endif
|
|
|
|
|
2002-10-23 10:45:09 +00:00
|
|
|
switch (af) {
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
|
|
|
tld = tld6;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case AF_INET:
|
|
|
|
tld = tld4;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NS_NOTFOUND;
|
|
|
|
}
|
|
|
|
|
1999-12-28 02:37:14 +00:00
|
|
|
if ((_res.options & RES_INIT) == 0) {
|
|
|
|
if (res_init() < 0) {
|
|
|
|
*errp = h_errno;
|
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
2000-09-06 18:16:48 +00:00
|
|
|
return NS_UNAVAIL;
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
|
|
|
}
|
2000-05-10 00:47:20 +00:00
|
|
|
memset(&hbuf, 0, sizeof(hbuf));
|
1999-12-28 02:37:14 +00:00
|
|
|
hbuf.h_name = NULL;
|
|
|
|
hbuf.h_addrtype = af;
|
|
|
|
hbuf.h_length = addrlen;
|
|
|
|
na = 0;
|
|
|
|
|
2002-09-16 13:19:47 +00:00
|
|
|
buf = malloc(sizeof(*buf));
|
|
|
|
if (buf == NULL) {
|
|
|
|
*errp = NETDB_INTERNAL;
|
|
|
|
return NS_UNAVAIL;
|
|
|
|
}
|
2002-10-23 10:45:09 +00:00
|
|
|
err = NS_SUCCESS;
|
|
|
|
for (/* nothing */; *tld; tld++) {
|
|
|
|
/*
|
|
|
|
* XXX assumes that MAXDNAME is big enough - error checks
|
|
|
|
* has been made by callers
|
|
|
|
*/
|
|
|
|
n = 0;
|
|
|
|
bp = qbuf;
|
|
|
|
cp = (u_char *)addr+addrlen-1;
|
|
|
|
switch (af) {
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
|
|
|
for (; n < addrlen; n++, cp--) {
|
|
|
|
c = *cp;
|
|
|
|
*bp++ = hex[c & 0xf];
|
|
|
|
*bp++ = '.';
|
|
|
|
*bp++ = hex[c >> 4];
|
|
|
|
*bp++ = '.';
|
|
|
|
}
|
|
|
|
strcpy(bp, *tld);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case AF_INET:
|
|
|
|
for (; n < addrlen; n++, cp--) {
|
|
|
|
c = *cp;
|
|
|
|
if (c >= 100)
|
|
|
|
*bp++ = '0' + c / 100;
|
|
|
|
if (c >= 10)
|
|
|
|
*bp++ = '0' + (c % 100) / 10;
|
|
|
|
*bp++ = '0' + c % 10;
|
|
|
|
*bp++ = '.';
|
|
|
|
}
|
|
|
|
strcpy(bp, *tld);
|
|
|
|
break;
|
|
|
|
}
|
2002-09-16 13:19:47 +00:00
|
|
|
|
2002-10-23 10:45:09 +00:00
|
|
|
n = res_query(qbuf, C_IN, T_PTR, buf->buf, sizeof buf->buf);
|
|
|
|
if (n < 0) {
|
|
|
|
*errp = h_errno;
|
|
|
|
err = NS_UNAVAIL;
|
|
|
|
continue;
|
|
|
|
} else if (n > sizeof(buf->buf)) {
|
2002-09-15 16:51:09 +00:00
|
|
|
#if 0
|
2002-10-23 10:45:09 +00:00
|
|
|
errno = ERANGE; /* XXX is it OK to set errno here? */
|
2002-09-15 16:51:09 +00:00
|
|
|
#endif
|
2002-10-23 10:45:09 +00:00
|
|
|
*errp = NETDB_INTERNAL;
|
|
|
|
err = NS_UNAVAIL;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
hp = getanswer(buf, n, qbuf, T_PTR, &hbuf, errp);
|
|
|
|
if (!hp) {
|
|
|
|
err = NS_NOTFOUND;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
free(buf);
|
|
|
|
hbuf.h_addrtype = af;
|
|
|
|
hbuf.h_length = addrlen;
|
|
|
|
hbuf.h_addr_list = hlist;
|
|
|
|
hlist[0] = (char *)addr;
|
|
|
|
hlist[1] = NULL;
|
|
|
|
*(struct hostent **)rval = _hpcopy(&hbuf, errp);
|
|
|
|
return NS_SUCCESS;
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
2002-09-16 13:19:47 +00:00
|
|
|
free(buf);
|
2002-10-23 10:45:09 +00:00
|
|
|
return err;
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
|
|
|
|
2000-05-10 00:47:20 +00:00
|
|
|
static void
|
|
|
|
_dns_shent(int stayopen)
|
|
|
|
{
|
|
|
|
if ((_res.options & RES_INIT) == 0) {
|
|
|
|
if (res_init() < 0)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (stayopen)
|
|
|
|
_res.options |= RES_STAYOPEN | RES_USEVC;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_dns_ehent(void)
|
|
|
|
{
|
|
|
|
_res.options &= ~(RES_STAYOPEN | RES_USEVC);
|
|
|
|
res_close();
|
|
|
|
}
|
|
|
|
|
1999-12-28 02:37:14 +00:00
|
|
|
#ifdef ICMPNL
|
|
|
|
|
|
|
|
/*
|
|
|
|
* experimental:
|
|
|
|
* draft-ietf-ipngwg-icmp-namelookups-02.txt
|
|
|
|
* ifindex is assumed to be encoded in addr.
|
|
|
|
*/
|
|
|
|
#include <sys/uio.h>
|
|
|
|
#include <netinet/ip6.h>
|
|
|
|
#include <netinet/icmp6.h>
|
|
|
|
|
|
|
|
struct _icmp_host_cache {
|
|
|
|
struct _icmp_host_cache *hc_next;
|
|
|
|
int hc_ifindex;
|
|
|
|
struct in6_addr hc_addr;
|
|
|
|
char *hc_name;
|
|
|
|
};
|
|
|
|
|
|
|
|
static char *
|
|
|
|
_icmp_fqdn_query(const struct in6_addr *addr, int ifindex)
|
|
|
|
{
|
|
|
|
int s;
|
|
|
|
struct icmp6_filter filter;
|
|
|
|
struct msghdr msg;
|
|
|
|
struct cmsghdr *cmsg;
|
|
|
|
struct in6_pktinfo *pkt;
|
|
|
|
char cbuf[256];
|
|
|
|
char buf[1024];
|
|
|
|
int cc;
|
|
|
|
struct icmp6_fqdn_query *fq;
|
|
|
|
struct icmp6_fqdn_reply *fr;
|
|
|
|
struct _icmp_host_cache *hc;
|
|
|
|
struct sockaddr_in6 sin6;
|
|
|
|
struct iovec iov;
|
|
|
|
fd_set s_fds, fds;
|
|
|
|
struct timeval tout;
|
|
|
|
int len;
|
|
|
|
char *name;
|
|
|
|
static struct _icmp_host_cache *hc_head;
|
|
|
|
|
Make the resolver(3) and many associated interfaces much more reentrant.
The getaddrinfo(3), getipnodebyname(3) and resolver(3) can coincide now
with what should be totally reentrant, and h_errno values will now
be preserved correctly, but this does not affect interfaces such as
gethostbyname(3) which are still mostly non-reentrant.
In all of these relevant functions, the thread-safety has been pushed
down as far as it seems possible right now. This means that operations
that are selected via nsdispatch(3) (i.e. files, yp, dns) are protected
still under global locks that getaddrinfo(3) defines, but where possible
the locking is greatly reduced. The most noticeable improvement is
that multiple DNS lookups can now be run at the same time, and this
shows major improvement in performance of DNS-lookup threaded programs,
and solves the "Mozilla tab serialization" problem.
No single-threaded applications need to be recompiled. Multi-threaded
applications that reference "_res" to change resolver(3) options will
need to be recompiled, and ones which reference "h_errno" will also
if they desire the correct h_errno values. If the applications already
understood that _res and h_errno were not thread-safe and had their own
locking, they will see no performance improvement but will not
actually break in any way.
Please note that when NSS modules are used, or when nsdispatch(3)
defaults to adding any lookups of its own to the individual libc
_nsdispatch() calls, those MUST be reentrant as well.
2004-02-25 21:03:46 +00:00
|
|
|
THREAD_LOCK();
|
1999-12-28 02:37:14 +00:00
|
|
|
for (hc = hc_head; hc; hc = hc->hc_next) {
|
|
|
|
if (hc->hc_ifindex == ifindex
|
Make the resolver(3) and many associated interfaces much more reentrant.
The getaddrinfo(3), getipnodebyname(3) and resolver(3) can coincide now
with what should be totally reentrant, and h_errno values will now
be preserved correctly, but this does not affect interfaces such as
gethostbyname(3) which are still mostly non-reentrant.
In all of these relevant functions, the thread-safety has been pushed
down as far as it seems possible right now. This means that operations
that are selected via nsdispatch(3) (i.e. files, yp, dns) are protected
still under global locks that getaddrinfo(3) defines, but where possible
the locking is greatly reduced. The most noticeable improvement is
that multiple DNS lookups can now be run at the same time, and this
shows major improvement in performance of DNS-lookup threaded programs,
and solves the "Mozilla tab serialization" problem.
No single-threaded applications need to be recompiled. Multi-threaded
applications that reference "_res" to change resolver(3) options will
need to be recompiled, and ones which reference "h_errno" will also
if they desire the correct h_errno values. If the applications already
understood that _res and h_errno were not thread-safe and had their own
locking, they will see no performance improvement but will not
actually break in any way.
Please note that when NSS modules are used, or when nsdispatch(3)
defaults to adding any lookups of its own to the individual libc
_nsdispatch() calls, those MUST be reentrant as well.
2004-02-25 21:03:46 +00:00
|
|
|
&& IN6_ARE_ADDR_EQUAL(&hc->hc_addr, addr)) {
|
|
|
|
THREAD_UNLOCK();
|
|
|
|
return hc->hc_name; /* XXX: never freed */
|
|
|
|
}
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ICMP6_FILTER_SETBLOCKALL(&filter);
|
|
|
|
ICMP6_FILTER_SETPASS(ICMP6_FQDN_REPLY, &filter);
|
|
|
|
|
|
|
|
FD_ZERO(&s_fds);
|
|
|
|
tout.tv_sec = 0;
|
|
|
|
tout.tv_usec = 200000; /*XXX: 200ms*/
|
|
|
|
|
|
|
|
fq = (struct icmp6_fqdn_query *)buf;
|
|
|
|
fq->icmp6_fqdn_type = ICMP6_FQDN_QUERY;
|
|
|
|
fq->icmp6_fqdn_code = 0;
|
|
|
|
fq->icmp6_fqdn_cksum = 0;
|
Make the resolver(3) and many associated interfaces much more reentrant.
The getaddrinfo(3), getipnodebyname(3) and resolver(3) can coincide now
with what should be totally reentrant, and h_errno values will now
be preserved correctly, but this does not affect interfaces such as
gethostbyname(3) which are still mostly non-reentrant.
In all of these relevant functions, the thread-safety has been pushed
down as far as it seems possible right now. This means that operations
that are selected via nsdispatch(3) (i.e. files, yp, dns) are protected
still under global locks that getaddrinfo(3) defines, but where possible
the locking is greatly reduced. The most noticeable improvement is
that multiple DNS lookups can now be run at the same time, and this
shows major improvement in performance of DNS-lookup threaded programs,
and solves the "Mozilla tab serialization" problem.
No single-threaded applications need to be recompiled. Multi-threaded
applications that reference "_res" to change resolver(3) options will
need to be recompiled, and ones which reference "h_errno" will also
if they desire the correct h_errno values. If the applications already
understood that _res and h_errno were not thread-safe and had their own
locking, they will see no performance improvement but will not
actually break in any way.
Please note that when NSS modules are used, or when nsdispatch(3)
defaults to adding any lookups of its own to the individual libc
_nsdispatch() calls, those MUST be reentrant as well.
2004-02-25 21:03:46 +00:00
|
|
|
fq->icmp6_fqdn_id = (u_short)getpid();
|
1999-12-28 02:37:14 +00:00
|
|
|
fq->icmp6_fqdn_unused = 0;
|
|
|
|
fq->icmp6_fqdn_cookie[0] = 0;
|
|
|
|
fq->icmp6_fqdn_cookie[1] = 0;
|
|
|
|
|
|
|
|
memset(&sin6, 0, sizeof(sin6));
|
|
|
|
sin6.sin6_family = AF_INET6;
|
|
|
|
sin6.sin6_addr = *addr;
|
|
|
|
|
|
|
|
memset(&msg, 0, sizeof(msg));
|
|
|
|
msg.msg_name = (caddr_t)&sin6;
|
|
|
|
msg.msg_namelen = sizeof(sin6);
|
|
|
|
msg.msg_iov = &iov;
|
|
|
|
msg.msg_iovlen = 1;
|
|
|
|
msg.msg_control = NULL;
|
|
|
|
msg.msg_controllen = 0;
|
|
|
|
iov.iov_base = (caddr_t)buf;
|
|
|
|
iov.iov_len = sizeof(struct icmp6_fqdn_query);
|
|
|
|
|
|
|
|
if (ifindex) {
|
|
|
|
msg.msg_control = cbuf;
|
|
|
|
msg.msg_controllen = sizeof(cbuf);
|
|
|
|
cmsg = CMSG_FIRSTHDR(&msg);
|
|
|
|
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
|
|
|
|
cmsg->cmsg_level = IPPROTO_IPV6;
|
|
|
|
cmsg->cmsg_type = IPV6_PKTINFO;
|
|
|
|
pkt = (struct in6_pktinfo *)&cmsg[1];
|
|
|
|
memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr));
|
|
|
|
pkt->ipi6_ifindex = ifindex;
|
|
|
|
cmsg = CMSG_NXTHDR(&msg, cmsg);
|
|
|
|
msg.msg_controllen = (char *)cmsg - cbuf;
|
|
|
|
}
|
|
|
|
|
2001-01-24 13:01:12 +00:00
|
|
|
if ((s = _socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0)
|
1999-12-28 02:37:14 +00:00
|
|
|
return NULL;
|
2001-01-24 13:01:12 +00:00
|
|
|
(void)_setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER,
|
1999-12-28 02:37:14 +00:00
|
|
|
(char *)&filter, sizeof(filter));
|
2001-01-24 13:01:12 +00:00
|
|
|
cc = _sendmsg(s, &msg, 0);
|
1999-12-28 02:37:14 +00:00
|
|
|
if (cc < 0) {
|
Simplify sytem call renaming. Instead of _foo() <-- _libc_foo <-- foo(),
just use _foo() <-- foo(). In the case of a libpthread that doesn't do
call conversion (such as linuxthreads and our upcoming libpthread), this
is adequate. In the case of libc_r, we still need three names, which are
now _thread_sys_foo() <-- _foo() <-- foo().
Convert all internal libc usage of: aio_suspend(), close(), fsync(), msync(),
nanosleep(), open(), fcntl(), read(), and write() to _foo() instead of foo().
Remove all internal libc usage of: creat(), pause(), sleep(), system(),
tcdrain(), wait(), and waitpid().
Make thread cancellation fully POSIX-compliant.
Suggested by: deischen
2000-01-27 23:07:25 +00:00
|
|
|
_close(s);
|
1999-12-28 02:37:14 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
FD_SET(s, &s_fds);
|
|
|
|
for (;;) {
|
|
|
|
fds = s_fds;
|
2001-01-24 13:01:12 +00:00
|
|
|
if (_select(s + 1, &fds, NULL, NULL, &tout) <= 0) {
|
Simplify sytem call renaming. Instead of _foo() <-- _libc_foo <-- foo(),
just use _foo() <-- foo(). In the case of a libpthread that doesn't do
call conversion (such as linuxthreads and our upcoming libpthread), this
is adequate. In the case of libc_r, we still need three names, which are
now _thread_sys_foo() <-- _foo() <-- foo().
Convert all internal libc usage of: aio_suspend(), close(), fsync(), msync(),
nanosleep(), open(), fcntl(), read(), and write() to _foo() instead of foo().
Remove all internal libc usage of: creat(), pause(), sleep(), system(),
tcdrain(), wait(), and waitpid().
Make thread cancellation fully POSIX-compliant.
Suggested by: deischen
2000-01-27 23:07:25 +00:00
|
|
|
_close(s);
|
1999-12-28 02:37:14 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
len = sizeof(sin6);
|
2001-01-24 13:01:12 +00:00
|
|
|
cc = _recvfrom(s, buf, sizeof(buf), 0,
|
1999-12-28 02:37:14 +00:00
|
|
|
(struct sockaddr *)&sin6, &len);
|
|
|
|
if (cc <= 0) {
|
Simplify sytem call renaming. Instead of _foo() <-- _libc_foo <-- foo(),
just use _foo() <-- foo(). In the case of a libpthread that doesn't do
call conversion (such as linuxthreads and our upcoming libpthread), this
is adequate. In the case of libc_r, we still need three names, which are
now _thread_sys_foo() <-- _foo() <-- foo().
Convert all internal libc usage of: aio_suspend(), close(), fsync(), msync(),
nanosleep(), open(), fcntl(), read(), and write() to _foo() instead of foo().
Remove all internal libc usage of: creat(), pause(), sleep(), system(),
tcdrain(), wait(), and waitpid().
Make thread cancellation fully POSIX-compliant.
Suggested by: deischen
2000-01-27 23:07:25 +00:00
|
|
|
_close(s);
|
1999-12-28 02:37:14 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (cc < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr))
|
|
|
|
continue;
|
|
|
|
if (!IN6_ARE_ADDR_EQUAL(addr, &sin6.sin6_addr))
|
|
|
|
continue;
|
|
|
|
fr = (struct icmp6_fqdn_reply *)(buf + sizeof(struct ip6_hdr));
|
|
|
|
if (fr->icmp6_fqdn_type == ICMP6_FQDN_REPLY)
|
|
|
|
break;
|
|
|
|
}
|
Simplify sytem call renaming. Instead of _foo() <-- _libc_foo <-- foo(),
just use _foo() <-- foo(). In the case of a libpthread that doesn't do
call conversion (such as linuxthreads and our upcoming libpthread), this
is adequate. In the case of libc_r, we still need three names, which are
now _thread_sys_foo() <-- _foo() <-- foo().
Convert all internal libc usage of: aio_suspend(), close(), fsync(), msync(),
nanosleep(), open(), fcntl(), read(), and write() to _foo() instead of foo().
Remove all internal libc usage of: creat(), pause(), sleep(), system(),
tcdrain(), wait(), and waitpid().
Make thread cancellation fully POSIX-compliant.
Suggested by: deischen
2000-01-27 23:07:25 +00:00
|
|
|
_close(s);
|
1999-12-28 02:37:14 +00:00
|
|
|
if (fr->icmp6_fqdn_cookie[1] != 0) {
|
|
|
|
/* rfc1788 type */
|
|
|
|
name = buf + sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) + 4;
|
|
|
|
len = (buf + cc) - name;
|
|
|
|
} else {
|
|
|
|
len = fr->icmp6_fqdn_namelen;
|
|
|
|
name = fr->icmp6_fqdn_name;
|
|
|
|
}
|
|
|
|
if (len <= 0)
|
|
|
|
return NULL;
|
|
|
|
name[len] = 0;
|
|
|
|
|
|
|
|
if ((hc = (struct _icmp_host_cache *)malloc(sizeof(*hc))) == NULL)
|
|
|
|
return NULL;
|
|
|
|
/* XXX: limit number of cached entries */
|
|
|
|
hc->hc_ifindex = ifindex;
|
|
|
|
hc->hc_addr = *addr;
|
|
|
|
hc->hc_name = strdup(name);
|
Make the resolver(3) and many associated interfaces much more reentrant.
The getaddrinfo(3), getipnodebyname(3) and resolver(3) can coincide now
with what should be totally reentrant, and h_errno values will now
be preserved correctly, but this does not affect interfaces such as
gethostbyname(3) which are still mostly non-reentrant.
In all of these relevant functions, the thread-safety has been pushed
down as far as it seems possible right now. This means that operations
that are selected via nsdispatch(3) (i.e. files, yp, dns) are protected
still under global locks that getaddrinfo(3) defines, but where possible
the locking is greatly reduced. The most noticeable improvement is
that multiple DNS lookups can now be run at the same time, and this
shows major improvement in performance of DNS-lookup threaded programs,
and solves the "Mozilla tab serialization" problem.
No single-threaded applications need to be recompiled. Multi-threaded
applications that reference "_res" to change resolver(3) options will
need to be recompiled, and ones which reference "h_errno" will also
if they desire the correct h_errno values. If the applications already
understood that _res and h_errno were not thread-safe and had their own
locking, they will see no performance improvement but will not
actually break in any way.
Please note that when NSS modules are used, or when nsdispatch(3)
defaults to adding any lookups of its own to the individual libc
_nsdispatch() calls, those MUST be reentrant as well.
2004-02-25 21:03:46 +00:00
|
|
|
THREAD_LOCK();
|
1999-12-28 02:37:14 +00:00
|
|
|
hc->hc_next = hc_head;
|
|
|
|
hc_head = hc;
|
Make the resolver(3) and many associated interfaces much more reentrant.
The getaddrinfo(3), getipnodebyname(3) and resolver(3) can coincide now
with what should be totally reentrant, and h_errno values will now
be preserved correctly, but this does not affect interfaces such as
gethostbyname(3) which are still mostly non-reentrant.
In all of these relevant functions, the thread-safety has been pushed
down as far as it seems possible right now. This means that operations
that are selected via nsdispatch(3) (i.e. files, yp, dns) are protected
still under global locks that getaddrinfo(3) defines, but where possible
the locking is greatly reduced. The most noticeable improvement is
that multiple DNS lookups can now be run at the same time, and this
shows major improvement in performance of DNS-lookup threaded programs,
and solves the "Mozilla tab serialization" problem.
No single-threaded applications need to be recompiled. Multi-threaded
applications that reference "_res" to change resolver(3) options will
need to be recompiled, and ones which reference "h_errno" will also
if they desire the correct h_errno values. If the applications already
understood that _res and h_errno were not thread-safe and had their own
locking, they will see no performance improvement but will not
actually break in any way.
Please note that when NSS modules are used, or when nsdispatch(3)
defaults to adding any lookups of its own to the individual libc
_nsdispatch() calls, those MUST be reentrant as well.
2004-02-25 21:03:46 +00:00
|
|
|
THREAD_UNLOCK();
|
1999-12-28 02:37:14 +00:00
|
|
|
return hc->hc_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct hostent *
|
|
|
|
_icmp_ghbyaddr(const void *addr, int addrlen, int af, int *errp)
|
|
|
|
{
|
|
|
|
char *hname;
|
|
|
|
int ifindex;
|
|
|
|
struct in6_addr addr6;
|
|
|
|
|
|
|
|
if (af != AF_INET6) {
|
|
|
|
/*
|
|
|
|
* Note: rfc1788 defines Who Are You for IPv4,
|
|
|
|
* but no one implements it.
|
|
|
|
*/
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(&addr6, addr, addrlen);
|
|
|
|
ifindex = (addr6.s6_addr[2] << 8) | addr6.s6_addr[3];
|
|
|
|
addr6.s6_addr[2] = addr6.s6_addr[3] = 0;
|
|
|
|
|
|
|
|
if (!IN6_IS_ADDR_LINKLOCAL(&addr6))
|
|
|
|
return NULL; /*XXX*/
|
|
|
|
|
|
|
|
if ((hname = _icmp_fqdn_query(&addr6, ifindex)) == NULL)
|
|
|
|
return NULL;
|
|
|
|
return _hpaddr(af, hname, &addr6, errp);
|
|
|
|
}
|
|
|
|
#endif /* ICMPNL */
|