2003-10-24 18:43:24 +00:00
|
|
|
/* $KAME: getaddrinfo.c,v 1.15 2000/07/09 04:37:24 itojun Exp $ */
|
2000-07-05 05:07:23 +00:00
|
|
|
|
1999-12-28 02:37:14 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 1995, 1996, 1997, and 1998 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
|
|
|
|
*
|
|
|
|
* Issues to be discussed:
|
|
|
|
* - Return values. There are nonstandard return values defined and used
|
|
|
|
* in the source code. This is because RFC2553 is silent about which error
|
|
|
|
* code must be returned for which situation.
|
2000-06-20 16:33:33 +00:00
|
|
|
* - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is
|
2002-10-25 16:24:28 +00:00
|
|
|
* invalid. current code - SEGV on freeaddrinfo(NULL)
|
|
|
|
*
|
2000-01-26 08:37:29 +00:00
|
|
|
* Note:
|
|
|
|
* - The code filters out AFs that are not supported by the kernel,
|
|
|
|
* when globbing NULL hostname (to loopback, or wildcard). Is it the right
|
|
|
|
* thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG
|
|
|
|
* in ai_flags?
|
2000-06-20 16:33:33 +00:00
|
|
|
* - (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
|
|
|
|
* (1) what should we do against numeric hostname (2) what should we do
|
|
|
|
* against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready?
|
|
|
|
* non-loopback address configured? global address configured?
|
2002-10-25 16:24:28 +00:00
|
|
|
*
|
|
|
|
* OS specific notes for freebsd4:
|
|
|
|
* - FreeBSD supported $GAI. The code does not.
|
1999-12-28 02:37:14 +00:00
|
|
|
*/
|
|
|
|
|
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/types.h>
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <net/if.h>
|
|
|
|
#include <netinet/in.h>
|
2003-10-30 17:36:53 +00:00
|
|
|
#include <sys/queue.h>
|
|
|
|
#ifdef INET6
|
|
|
|
#include <net/if_var.h>
|
|
|
|
#include <sys/sysctl.h>
|
2004-05-31 19:27:54 +00:00
|
|
|
#include <sys/ioctl.h>
|
2003-10-30 17:36:53 +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>
|
2003-10-24 18:43:24 +00:00
|
|
|
#include <rpc/rpc.h>
|
|
|
|
#include <rpcsvc/yp_prot.h>
|
|
|
|
#include <rpcsvc/ypclnt.h>
|
1999-12-28 02:37:14 +00:00
|
|
|
#include <netdb.h>
|
|
|
|
#include <resolv.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdio.h>
|
2000-06-20 16:33:33 +00:00
|
|
|
#include <errno.h>
|
2002-08-21 19:57:53 +00:00
|
|
|
|
|
|
|
#include "res_config.h"
|
|
|
|
|
2001-06-10 20:25:24 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
#include <syslog.h>
|
|
|
|
#endif
|
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
|
|
|
#include <stdarg.h>
|
|
|
|
#include <nsswitch.h>
|
2001-01-24 13:01:12 +00:00
|
|
|
#include "un-namespace.h"
|
2003-02-27 13:40:01 +00:00
|
|
|
#include "libc_private.h"
|
2006-04-28 12:03:38 +00:00
|
|
|
#ifdef NS_CACHING
|
|
|
|
#include "nscache.h"
|
|
|
|
#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
|
|
|
|
1999-12-28 02:37:14 +00:00
|
|
|
#if defined(__KAME__) && defined(INET6)
|
|
|
|
# define FAITH
|
|
|
|
#endif
|
|
|
|
|
2002-10-25 16:24:28 +00:00
|
|
|
#define ANY 0
|
|
|
|
#define YES 1
|
|
|
|
#define NO 0
|
1999-12-28 02:37:14 +00:00
|
|
|
|
|
|
|
static const char in_addrany[] = { 0, 0, 0, 0 };
|
2002-10-25 16:24:28 +00:00
|
|
|
static const char in_loopback[] = { 127, 0, 0, 1 };
|
|
|
|
#ifdef INET6
|
1999-12-28 02:37:14 +00:00
|
|
|
static const char in6_addrany[] = {
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
|
|
};
|
|
|
|
static const char in6_loopback[] = {
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
|
|
|
|
};
|
2002-10-25 16:24:28 +00:00
|
|
|
#endif
|
1999-12-28 02:37:14 +00:00
|
|
|
|
2003-10-30 17:36:53 +00:00
|
|
|
struct policyqueue {
|
|
|
|
TAILQ_ENTRY(policyqueue) pc_entry;
|
|
|
|
#ifdef INET6
|
|
|
|
struct in6_addrpolicy pc_policy;
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
TAILQ_HEAD(policyhead, policyqueue);
|
|
|
|
|
1999-12-28 02:37:14 +00:00
|
|
|
static const struct afd {
|
|
|
|
int a_af;
|
|
|
|
int a_addrlen;
|
2005-05-15 20:15:15 +00:00
|
|
|
socklen_t a_socklen;
|
1999-12-28 02:37:14 +00:00
|
|
|
int a_off;
|
|
|
|
const char *a_addrany;
|
2001-03-05 10:39:03 +00:00
|
|
|
const char *a_loopback;
|
1999-12-28 02:37:14 +00:00
|
|
|
int a_scoped;
|
|
|
|
} afdl [] = {
|
|
|
|
#ifdef INET6
|
|
|
|
#define N_INET6 0
|
|
|
|
{PF_INET6, sizeof(struct in6_addr),
|
|
|
|
sizeof(struct sockaddr_in6),
|
|
|
|
offsetof(struct sockaddr_in6, sin6_addr),
|
|
|
|
in6_addrany, in6_loopback, 1},
|
|
|
|
#define N_INET 1
|
|
|
|
#else
|
|
|
|
#define N_INET 0
|
|
|
|
#endif
|
|
|
|
{PF_INET, sizeof(struct in_addr),
|
|
|
|
sizeof(struct sockaddr_in),
|
|
|
|
offsetof(struct sockaddr_in, sin_addr),
|
|
|
|
in_addrany, in_loopback, 0},
|
|
|
|
{0, 0, 0, 0, NULL, NULL, 0},
|
|
|
|
};
|
|
|
|
|
|
|
|
struct explore {
|
2000-06-20 16:33:33 +00:00
|
|
|
int e_af;
|
1999-12-28 02:37:14 +00:00
|
|
|
int e_socktype;
|
|
|
|
int e_protocol;
|
|
|
|
const char *e_protostr;
|
|
|
|
int e_wild;
|
2002-10-25 16:24:28 +00:00
|
|
|
#define WILD_AF(ex) ((ex)->e_wild & 0x01)
|
|
|
|
#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
|
|
|
|
#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
|
1999-12-28 02:37:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const struct explore explore[] = {
|
2000-06-20 16:33:33 +00:00
|
|
|
#if 0
|
2009-03-25 16:23:43 +00:00
|
|
|
{ PF_LOCAL, ANY, ANY, NULL, 0x01 },
|
2000-06-20 16:33:33 +00:00
|
|
|
#endif
|
|
|
|
#ifdef INET6
|
2003-10-24 18:43:24 +00:00
|
|
|
{ PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
|
|
|
|
{ PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
|
2009-03-25 16:23:43 +00:00
|
|
|
{ PF_INET6, SOCK_STREAM, IPPROTO_SCTP, "sctp", 0x03 },
|
|
|
|
{ PF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, "sctp", 0x07 },
|
2003-10-24 18:43:24 +00:00
|
|
|
{ PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
|
2000-06-20 16:33:33 +00:00
|
|
|
#endif
|
2003-10-24 18:43:24 +00:00
|
|
|
{ PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
|
|
|
|
{ PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
|
2009-03-25 16:23:43 +00:00
|
|
|
{ PF_INET, SOCK_STREAM, IPPROTO_SCTP, "sctp", 0x03 },
|
|
|
|
{ PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP, "sctp", 0x07 },
|
2003-10-24 18:43:24 +00:00
|
|
|
{ PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
|
2000-06-20 16:33:33 +00:00
|
|
|
{ -1, 0, 0, NULL, 0 },
|
1999-12-28 02:37:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef INET6
|
2002-10-25 16:24:28 +00:00
|
|
|
#define PTON_MAX 16
|
1999-12-28 02:37:14 +00:00
|
|
|
#else
|
2002-10-25 16:24:28 +00:00
|
|
|
#define PTON_MAX 4
|
1999-12-28 02:37:14 +00:00
|
|
|
#endif
|
|
|
|
|
2003-10-30 17:36:53 +00:00
|
|
|
#define AIO_SRCFLAG_DEPRECATED 0x1
|
|
|
|
|
|
|
|
struct ai_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;
|
|
|
|
struct addrinfo *aio_ai;
|
|
|
|
int aio_matchlen;
|
|
|
|
};
|
|
|
|
|
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_src default_dns_files[] = {
|
|
|
|
{ NSSRC_FILES, NS_SUCCESS },
|
|
|
|
{ NSSRC_DNS, NS_SUCCESS },
|
|
|
|
{ 0 }
|
|
|
|
};
|
|
|
|
|
2000-06-20 16:33:33 +00:00
|
|
|
struct res_target {
|
|
|
|
struct res_target *next;
|
|
|
|
const char *name; /* domain name */
|
2000-07-05 05:07:23 +00:00
|
|
|
int qclass, qtype; /* class and type of query */
|
2000-06-20 16:33:33 +00:00
|
|
|
u_char *answer; /* buffer to put answer */
|
|
|
|
int anslen; /* size of answer buffer */
|
|
|
|
int n; /* result length */
|
|
|
|
};
|
|
|
|
|
2003-10-23 14:32:03 +00:00
|
|
|
#define MAXPACKET (64*1024)
|
|
|
|
|
|
|
|
typedef union {
|
|
|
|
HEADER hdr;
|
|
|
|
u_char buf[MAXPACKET];
|
|
|
|
} querybuf;
|
|
|
|
|
2006-07-23 15:31:03 +00:00
|
|
|
static int str2number(const char *, int *);
|
2009-03-29 17:55:11 +00:00
|
|
|
static int explore_copy(const struct addrinfo *, const struct addrinfo *,
|
|
|
|
struct addrinfo **);
|
2002-03-22 09:22:15 +00:00
|
|
|
static int explore_null(const struct addrinfo *,
|
|
|
|
const char *, struct addrinfo **);
|
|
|
|
static int explore_numeric(const struct addrinfo *, const char *,
|
2005-01-27 14:41:56 +00:00
|
|
|
const char *, struct addrinfo **, const char *);
|
2002-03-22 09:22:15 +00:00
|
|
|
static int explore_numeric_scope(const struct addrinfo *, const char *,
|
|
|
|
const char *, struct addrinfo **);
|
|
|
|
static int get_canonname(const struct addrinfo *,
|
|
|
|
struct addrinfo *, const char *);
|
|
|
|
static struct addrinfo *get_ai(const struct addrinfo *,
|
|
|
|
const struct afd *, const char *);
|
2009-03-29 17:55:11 +00:00
|
|
|
static struct addrinfo *copy_ai(const struct addrinfo *);
|
2002-03-21 22:49:10 +00:00
|
|
|
static int get_portmatch(const struct addrinfo *, const char *);
|
|
|
|
static int get_port(struct addrinfo *, const char *, int);
|
|
|
|
static const struct afd *find_afd(int);
|
2003-10-24 18:43:24 +00:00
|
|
|
static int addrconfig(struct addrinfo *);
|
2004-05-31 19:27:54 +00:00
|
|
|
static void set_source(struct ai_order *, struct policyhead *);
|
2003-10-30 17:36:53 +00:00
|
|
|
static int comp_dst(const void *, const void *);
|
2000-06-20 16:33:33 +00:00
|
|
|
#ifdef INET6
|
2002-10-25 17:07:02 +00:00
|
|
|
static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *);
|
2000-06-20 16:33:33 +00:00
|
|
|
#endif
|
2003-10-30 17:36:53 +00:00
|
|
|
static int gai_addr2scopetype(struct sockaddr *);
|
2000-06-20 16:33:33 +00:00
|
|
|
|
2003-10-23 14:32:03 +00:00
|
|
|
static int explore_fqdn(const struct addrinfo *, const char *,
|
|
|
|
const char *, struct addrinfo **);
|
|
|
|
|
2003-10-30 17:36:53 +00:00
|
|
|
static int reorder(struct addrinfo *);
|
|
|
|
static int get_addrselectpolicy(struct policyhead *);
|
|
|
|
static void free_addrselectpolicy(struct policyhead *);
|
|
|
|
static struct policyqueue *match_addrselectpolicy(struct sockaddr *,
|
|
|
|
struct policyhead *);
|
2004-05-31 19:27:54 +00:00
|
|
|
static int matchlen(struct sockaddr *, struct sockaddr *);
|
2003-10-30 17:36:53 +00:00
|
|
|
|
2002-03-22 09:22:15 +00:00
|
|
|
static struct addrinfo *getanswer(const querybuf *, int, const char *, int,
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
const struct addrinfo *, res_state);
|
2003-10-23 14:32:03 +00:00
|
|
|
#if defined(RESOLVSORT)
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
static int addr4sort(struct addrinfo *, res_state);
|
2003-10-23 14:32:03 +00:00
|
|
|
#endif
|
2002-10-25 17:07:02 +00:00
|
|
|
static int _dns_getaddrinfo(void *, void *, va_list);
|
2005-04-04 19:45:27 +00:00
|
|
|
static void _sethtent(FILE **);
|
|
|
|
static void _endhtent(FILE **);
|
|
|
|
static struct addrinfo *_gethtent(FILE **, const char *,
|
|
|
|
const struct addrinfo *);
|
2002-03-21 22:49:10 +00:00
|
|
|
static int _files_getaddrinfo(void *, void *, va_list);
|
2000-06-20 16:33:33 +00:00
|
|
|
#ifdef YP
|
2002-03-21 22:49:10 +00:00
|
|
|
static struct addrinfo *_yphostent(char *, const struct addrinfo *);
|
|
|
|
static int _yp_getaddrinfo(void *, void *, va_list);
|
2000-06-20 16:33:33 +00:00
|
|
|
#endif
|
2006-04-28 12:03:38 +00:00
|
|
|
#ifdef NS_CACHING
|
|
|
|
static int addrinfo_id_func(char *, size_t *, va_list, void *);
|
|
|
|
static int addrinfo_marshal_func(char *, size_t *, void *, va_list, void *);
|
|
|
|
static int addrinfo_unmarshal_func(char *, size_t, void *, va_list, void *);
|
|
|
|
#endif
|
2000-06-20 16:33:33 +00:00
|
|
|
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
static int res_queryN(const char *, struct res_target *, res_state);
|
|
|
|
static int res_searchN(const char *, struct res_target *, res_state);
|
2002-03-22 09:22:15 +00:00
|
|
|
static int res_querydomainN(const char *, const char *,
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
struct res_target *, res_state);
|
1999-12-28 02:37:14 +00:00
|
|
|
|
|
|
|
/* XXX macros that make external reference is BAD. */
|
|
|
|
|
2002-10-25 16:24:28 +00:00
|
|
|
#define GET_AI(ai, afd, addr) \
|
1999-12-28 02:37:14 +00:00
|
|
|
do { \
|
|
|
|
/* external reference: pai, error, and label free */ \
|
|
|
|
(ai) = get_ai(pai, (afd), (addr)); \
|
|
|
|
if ((ai) == NULL) { \
|
|
|
|
error = EAI_MEMORY; \
|
|
|
|
goto free; \
|
|
|
|
} \
|
2000-06-20 16:33:33 +00:00
|
|
|
} while (/*CONSTCOND*/0)
|
1999-12-28 02:37:14 +00:00
|
|
|
|
2002-10-25 16:24:28 +00:00
|
|
|
#define GET_PORT(ai, serv) \
|
1999-12-28 02:37:14 +00:00
|
|
|
do { \
|
|
|
|
/* external reference: error and label free */ \
|
|
|
|
error = get_port((ai), (serv), 0); \
|
|
|
|
if (error != 0) \
|
|
|
|
goto free; \
|
2000-06-20 16:33:33 +00:00
|
|
|
} while (/*CONSTCOND*/0)
|
1999-12-28 02:37:14 +00:00
|
|
|
|
2002-10-25 16:24:28 +00:00
|
|
|
#define GET_CANONNAME(ai, str) \
|
1999-12-28 02:37:14 +00:00
|
|
|
do { \
|
|
|
|
/* external reference: pai, error and label free */ \
|
|
|
|
error = get_canonname(pai, (ai), (str)); \
|
|
|
|
if (error != 0) \
|
|
|
|
goto free; \
|
2000-06-20 16:33:33 +00:00
|
|
|
} while (/*CONSTCOND*/0)
|
1999-12-28 02:37:14 +00:00
|
|
|
|
2002-10-25 16:24:28 +00:00
|
|
|
#define ERR(err) \
|
1999-12-28 02:37:14 +00:00
|
|
|
do { \
|
|
|
|
/* external reference: error, and label bad */ \
|
|
|
|
error = (err); \
|
|
|
|
goto bad; \
|
2000-06-20 16:33:33 +00:00
|
|
|
/*NOTREACHED*/ \
|
|
|
|
} while (/*CONSTCOND*/0)
|
1999-12-28 02:37:14 +00:00
|
|
|
|
2002-10-25 16:24:28 +00:00
|
|
|
#define MATCH_FAMILY(x, y, w) \
|
2000-06-20 16:33:33 +00:00
|
|
|
((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
|
2002-10-25 16:24:28 +00:00
|
|
|
#define MATCH(x, y, w) \
|
2000-06-20 16:33:33 +00:00
|
|
|
((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
|
1999-12-28 02:37:14 +00:00
|
|
|
|
|
|
|
void
|
2006-03-25 11:46:37 +00:00
|
|
|
freeaddrinfo(struct addrinfo *ai)
|
1999-12-28 02:37:14 +00:00
|
|
|
{
|
|
|
|
struct addrinfo *next;
|
|
|
|
|
|
|
|
do {
|
|
|
|
next = ai->ai_next;
|
|
|
|
if (ai->ai_canonname)
|
|
|
|
free(ai->ai_canonname);
|
|
|
|
/* no need to free(ai->ai_addr) */
|
|
|
|
free(ai);
|
2000-06-20 16:33:33 +00:00
|
|
|
ai = next;
|
|
|
|
} while (ai);
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-07-23 15:31:03 +00:00
|
|
|
str2number(const char *p, int *portp)
|
1999-12-28 02:37:14 +00:00
|
|
|
{
|
2000-07-09 06:10:01 +00:00
|
|
|
char *ep;
|
2005-01-27 14:45:11 +00:00
|
|
|
unsigned long v;
|
2000-07-09 06:10:01 +00:00
|
|
|
|
|
|
|
if (*p == '\0')
|
2005-01-27 14:45:11 +00:00
|
|
|
return -1;
|
2000-07-09 06:10:01 +00:00
|
|
|
ep = NULL;
|
2002-10-25 17:07:02 +00:00
|
|
|
errno = 0;
|
2005-01-27 14:45:11 +00:00
|
|
|
v = strtoul(p, &ep, 10);
|
2006-07-23 15:31:03 +00:00
|
|
|
if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX) {
|
|
|
|
*portp = v;
|
|
|
|
return 0;
|
|
|
|
} else
|
2005-01-27 14:45:11 +00:00
|
|
|
return -1;
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2006-03-25 11:46:37 +00:00
|
|
|
getaddrinfo(const char *hostname, const char *servname,
|
|
|
|
const struct addrinfo *hints, struct addrinfo **res)
|
1999-12-28 02:37:14 +00:00
|
|
|
{
|
|
|
|
struct addrinfo sentinel;
|
|
|
|
struct addrinfo *cur;
|
|
|
|
int error = 0;
|
2009-03-29 17:55:11 +00:00
|
|
|
struct addrinfo ai, ai0, *afai;
|
1999-12-28 02:37:14 +00:00
|
|
|
struct addrinfo *pai;
|
2009-03-29 17:55:11 +00:00
|
|
|
const struct afd *afd;
|
1999-12-28 02:37:14 +00:00
|
|
|
const struct explore *ex;
|
2009-03-29 17:55:11 +00:00
|
|
|
struct addrinfo *afailist[sizeof(afdl)/sizeof(afdl[0])];
|
|
|
|
struct addrinfo *afai_unspec;
|
|
|
|
int found;
|
2003-10-30 17:36:53 +00:00
|
|
|
int numeric = 0;
|
1999-12-28 02:37:14 +00:00
|
|
|
|
2009-03-29 17:55:11 +00:00
|
|
|
/* ensure we return NULL on errors */
|
|
|
|
*res = NULL;
|
|
|
|
|
|
|
|
memset(&ai, 0, sizeof(ai));
|
|
|
|
|
|
|
|
memset(afailist, 0, sizeof(afailist));
|
|
|
|
afai_unspec = NULL;
|
|
|
|
|
2000-06-20 16:33:33 +00:00
|
|
|
memset(&sentinel, 0, sizeof(sentinel));
|
1999-12-28 02:37:14 +00:00
|
|
|
cur = &sentinel;
|
|
|
|
pai = &ai;
|
|
|
|
pai->ai_flags = 0;
|
|
|
|
pai->ai_family = PF_UNSPEC;
|
|
|
|
pai->ai_socktype = ANY;
|
|
|
|
pai->ai_protocol = ANY;
|
|
|
|
pai->ai_addrlen = 0;
|
|
|
|
pai->ai_canonname = NULL;
|
|
|
|
pai->ai_addr = NULL;
|
|
|
|
pai->ai_next = NULL;
|
|
|
|
|
|
|
|
if (hostname == NULL && servname == NULL)
|
|
|
|
return EAI_NONAME;
|
|
|
|
if (hints) {
|
|
|
|
/* error check for hints */
|
|
|
|
if (hints->ai_addrlen || hints->ai_canonname ||
|
|
|
|
hints->ai_addr || hints->ai_next)
|
|
|
|
ERR(EAI_BADHINTS); /* xxx */
|
|
|
|
if (hints->ai_flags & ~AI_MASK)
|
|
|
|
ERR(EAI_BADFLAGS);
|
|
|
|
switch (hints->ai_family) {
|
|
|
|
case PF_UNSPEC:
|
|
|
|
case PF_INET:
|
|
|
|
#ifdef INET6
|
|
|
|
case PF_INET6:
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ERR(EAI_FAMILY);
|
|
|
|
}
|
|
|
|
memcpy(pai, hints, sizeof(*pai));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* if both socktype/protocol are specified, check if they
|
|
|
|
* are meaningful combination.
|
|
|
|
*/
|
|
|
|
if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
|
2000-06-20 16:33:33 +00:00
|
|
|
for (ex = explore; ex->e_af >= 0; ex++) {
|
2009-03-29 17:55:11 +00:00
|
|
|
if (!MATCH_FAMILY(pai->ai_family, ex->e_af,
|
|
|
|
WILD_AF(ex)))
|
2000-06-20 16:33:33 +00:00
|
|
|
continue;
|
2009-03-29 17:55:11 +00:00
|
|
|
if (!MATCH(pai->ai_socktype, ex->e_socktype,
|
|
|
|
WILD_SOCKTYPE(ex)))
|
1999-12-28 02:37:14 +00:00
|
|
|
continue;
|
2009-03-29 17:55:11 +00:00
|
|
|
if (!MATCH(pai->ai_protocol, ex->e_protocol,
|
|
|
|
WILD_PROTOCOL(ex)))
|
1999-12-28 02:37:14 +00:00
|
|
|
continue;
|
2009-03-29 17:55:11 +00:00
|
|
|
|
|
|
|
/* matched */
|
|
|
|
break;
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
2009-03-25 16:23:43 +00:00
|
|
|
|
|
|
|
if (ex->e_af < 0)
|
|
|
|
ERR(EAI_BADHINTS);
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2000-06-20 16:33:33 +00:00
|
|
|
* check for special cases. (1) numeric servname is disallowed if
|
|
|
|
* socktype/protocol are left unspecified. (2) servname is disallowed
|
|
|
|
* for raw and other inet{,6} sockets.
|
1999-12-28 02:37:14 +00:00
|
|
|
*/
|
|
|
|
if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
|
2000-06-20 16:33:33 +00:00
|
|
|
#ifdef PF_INET6
|
2003-10-24 18:43:24 +00:00
|
|
|
|| MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
|
1999-12-28 02:37:14 +00:00
|
|
|
#endif
|
|
|
|
) {
|
2000-06-20 16:33:33 +00:00
|
|
|
ai0 = *pai; /* backup *pai */
|
1999-12-28 02:37:14 +00:00
|
|
|
|
2000-06-20 16:33:33 +00:00
|
|
|
if (pai->ai_family == PF_UNSPEC) {
|
|
|
|
#ifdef PF_INET6
|
1999-12-28 02:37:14 +00:00
|
|
|
pai->ai_family = PF_INET6;
|
|
|
|
#else
|
|
|
|
pai->ai_family = PF_INET;
|
|
|
|
#endif
|
2000-06-20 16:33:33 +00:00
|
|
|
}
|
1999-12-28 02:37:14 +00:00
|
|
|
error = get_portmatch(pai, servname);
|
|
|
|
if (error)
|
2012-06-06 21:16:26 +00:00
|
|
|
goto bad;
|
2000-06-20 16:33:33 +00:00
|
|
|
|
|
|
|
*pai = ai0;
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
|
|
|
|
2000-06-20 16:33:33 +00:00
|
|
|
ai0 = *pai;
|
|
|
|
|
2009-03-29 17:55:11 +00:00
|
|
|
/*
|
|
|
|
* NULL hostname, or numeric hostname.
|
|
|
|
* If numeric representation of AF1 can be interpreted as FQDN
|
|
|
|
* representation of AF2, we need to think again about the code below.
|
|
|
|
*/
|
|
|
|
found = 0;
|
|
|
|
for (afd = afdl; afd->a_af; afd++) {
|
1999-12-28 02:37:14 +00:00
|
|
|
*pai = ai0;
|
|
|
|
|
2009-03-29 17:55:11 +00:00
|
|
|
if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1))
|
1999-12-28 02:37:14 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (pai->ai_family == PF_UNSPEC)
|
2009-03-29 17:55:11 +00:00
|
|
|
pai->ai_family = afd->a_af;
|
1999-12-28 02:37:14 +00:00
|
|
|
|
2009-03-29 17:55:11 +00:00
|
|
|
if (hostname == NULL) {
|
|
|
|
error = explore_null(pai, servname,
|
|
|
|
&afailist[afd - afdl]);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Errors from explore_null should be unexpected and
|
|
|
|
* be caught to avoid returning an incomplete result.
|
|
|
|
*/
|
|
|
|
if (error != 0)
|
|
|
|
goto bad;
|
|
|
|
} else {
|
2005-01-27 14:41:56 +00:00
|
|
|
error = explore_numeric_scope(pai, hostname, servname,
|
2009-03-29 17:55:11 +00:00
|
|
|
&afailist[afd - afdl]);
|
2003-10-24 18:43:24 +00:00
|
|
|
|
2009-03-29 17:55:11 +00:00
|
|
|
/*
|
|
|
|
* explore_numeric_scope returns an error for address
|
|
|
|
* families that do not match that of hostname.
|
|
|
|
* Thus we should not catch the error at this moment.
|
|
|
|
*/
|
|
|
|
}
|
2003-10-24 18:43:24 +00:00
|
|
|
|
2009-03-29 17:55:11 +00:00
|
|
|
if (!error && afailist[afd - afdl])
|
|
|
|
found++;
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
2009-03-29 17:55:11 +00:00
|
|
|
if (found) {
|
2003-10-30 17:36:53 +00:00
|
|
|
numeric = 1;
|
2009-03-29 17:55:11 +00:00
|
|
|
goto globcopy;
|
2003-10-30 17:36:53 +00:00
|
|
|
}
|
2003-10-24 18:43:24 +00:00
|
|
|
|
2003-10-23 13:55:36 +00:00
|
|
|
if (hostname == NULL)
|
|
|
|
ERR(EAI_NONAME); /* used to be EAI_NODATA */
|
1999-12-28 02:37:14 +00:00
|
|
|
if (pai->ai_flags & AI_NUMERICHOST)
|
2002-02-01 08:35:16 +00:00
|
|
|
ERR(EAI_NONAME);
|
1999-12-28 02:37:14 +00:00
|
|
|
|
2003-10-24 18:43:24 +00:00
|
|
|
if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && !addrconfig(&ai0))
|
|
|
|
ERR(EAI_FAIL);
|
|
|
|
|
2000-06-20 16:33:33 +00:00
|
|
|
/*
|
|
|
|
* hostname as alphabetical name.
|
|
|
|
*/
|
2009-03-29 17:55:11 +00:00
|
|
|
*pai = ai0;
|
|
|
|
error = explore_fqdn(pai, hostname, servname, &afai_unspec);
|
|
|
|
|
|
|
|
globcopy:
|
2000-06-20 16:33:33 +00:00
|
|
|
for (ex = explore; ex->e_af >= 0; ex++) {
|
|
|
|
*pai = ai0;
|
1999-12-28 02:37:14 +00:00
|
|
|
|
2009-03-29 17:55:11 +00:00
|
|
|
if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
|
2000-06-20 16:33:33 +00:00
|
|
|
continue;
|
2003-10-24 18:43:24 +00:00
|
|
|
if (!MATCH(pai->ai_socktype, ex->e_socktype,
|
2009-03-29 17:55:11 +00:00
|
|
|
WILD_SOCKTYPE(ex)))
|
2000-06-20 16:33:33 +00:00
|
|
|
continue;
|
2003-10-24 18:43:24 +00:00
|
|
|
if (!MATCH(pai->ai_protocol, ex->e_protocol,
|
2009-03-29 17:55:11 +00:00
|
|
|
WILD_PROTOCOL(ex)))
|
2000-06-20 16:33:33 +00:00
|
|
|
continue;
|
|
|
|
|
2009-03-29 17:55:11 +00:00
|
|
|
if (pai->ai_family == PF_UNSPEC)
|
|
|
|
pai->ai_family = ex->e_af;
|
2000-06-20 16:33:33 +00:00
|
|
|
if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
|
|
|
|
pai->ai_socktype = ex->e_socktype;
|
|
|
|
if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
|
|
|
|
pai->ai_protocol = ex->e_protocol;
|
|
|
|
|
2009-03-29 17:55:11 +00:00
|
|
|
/*
|
|
|
|
* if the servname does not match socktype/protocol, ignore it.
|
|
|
|
*/
|
|
|
|
if (get_portmatch(pai, servname) != 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (afai_unspec)
|
|
|
|
afai = afai_unspec;
|
|
|
|
else {
|
|
|
|
if ((afd = find_afd(pai->ai_family)) == NULL)
|
|
|
|
continue;
|
|
|
|
/* XXX assumes that afd points inside afdl[] */
|
|
|
|
afai = afailist[afd - afdl];
|
|
|
|
}
|
|
|
|
if (!afai)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
error = explore_copy(pai, afai, &cur->ai_next);
|
|
|
|
if (error != 0)
|
|
|
|
goto bad;
|
2000-06-20 16:33:33 +00:00
|
|
|
|
|
|
|
while (cur && cur->ai_next)
|
|
|
|
cur = cur->ai_next;
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
|
|
|
|
2003-10-30 17:36:53 +00:00
|
|
|
/*
|
|
|
|
* ensure we return either:
|
|
|
|
* - error == 0, non-NULL *res
|
|
|
|
* - error != 0, NULL *res
|
|
|
|
*/
|
2000-06-20 16:33:33 +00:00
|
|
|
if (error == 0) {
|
|
|
|
if (sentinel.ai_next) {
|
2003-10-30 17:36:53 +00:00
|
|
|
/*
|
|
|
|
* If the returned entry is for an active connection,
|
|
|
|
* and the given name is not numeric, reorder the
|
|
|
|
* list, so that the application would try the list
|
2007-09-05 18:08:14 +00:00
|
|
|
* in the most efficient order. Since the head entry
|
|
|
|
* of the original list may contain ai_canonname and
|
|
|
|
* that entry may be moved elsewhere in the new list,
|
|
|
|
* we keep the pointer and will restore it in the new
|
|
|
|
* head entry. (Note that RFC3493 requires the head
|
|
|
|
* entry store it when requested by the caller).
|
2003-10-30 17:36:53 +00:00
|
|
|
*/
|
|
|
|
if (hints == NULL || !(hints->ai_flags & AI_PASSIVE)) {
|
2007-09-05 18:08:14 +00:00
|
|
|
if (!numeric) {
|
|
|
|
char *canonname;
|
|
|
|
|
|
|
|
canonname =
|
|
|
|
sentinel.ai_next->ai_canonname;
|
|
|
|
sentinel.ai_next->ai_canonname = NULL;
|
2003-10-30 17:36:53 +00:00
|
|
|
(void)reorder(&sentinel);
|
2007-09-05 18:08:14 +00:00
|
|
|
if (sentinel.ai_next->ai_canonname ==
|
|
|
|
NULL) {
|
|
|
|
sentinel.ai_next->ai_canonname
|
|
|
|
= canonname;
|
|
|
|
} else if (canonname != NULL)
|
|
|
|
free(canonname);
|
|
|
|
}
|
2003-10-30 17:36:53 +00:00
|
|
|
}
|
2000-06-20 16:33:33 +00:00
|
|
|
*res = sentinel.ai_next;
|
|
|
|
} else
|
|
|
|
error = EAI_FAIL;
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
2009-03-29 17:55:11 +00:00
|
|
|
|
2003-10-30 17:36:53 +00:00
|
|
|
bad:
|
2009-03-29 17:55:11 +00:00
|
|
|
if (afai_unspec)
|
|
|
|
freeaddrinfo(afai_unspec);
|
|
|
|
for (afd = afdl; afd->a_af; afd++) {
|
|
|
|
if (afailist[afd - afdl])
|
|
|
|
freeaddrinfo(afailist[afd - afdl]);
|
|
|
|
}
|
|
|
|
if (!*res)
|
|
|
|
if (sentinel.ai_next)
|
|
|
|
freeaddrinfo(sentinel.ai_next);
|
|
|
|
|
|
|
|
return (error);
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
|
|
|
|
2003-10-30 17:36:53 +00:00
|
|
|
static int
|
2006-03-25 11:46:37 +00:00
|
|
|
reorder(struct addrinfo *sentinel)
|
2003-10-30 17:36:53 +00:00
|
|
|
{
|
|
|
|
struct addrinfo *ai, **aip;
|
|
|
|
struct ai_order *aio;
|
|
|
|
int i, n;
|
|
|
|
struct policyhead policyhead;
|
|
|
|
|
|
|
|
/* count the number of addrinfo elements for sorting. */
|
|
|
|
for (n = 0, ai = sentinel->ai_next; ai != NULL; ai = ai->ai_next, n++)
|
|
|
|
;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the number is small enough, we can skip the reordering process.
|
|
|
|
*/
|
|
|
|
if (n <= 1)
|
|
|
|
return(n);
|
|
|
|
|
|
|
|
/* allocate a temporary array for sort and initialization of it. */
|
|
|
|
if ((aio = malloc(sizeof(*aio) * n)) == NULL)
|
|
|
|
return(n); /* give up reordering */
|
|
|
|
memset(aio, 0, sizeof(*aio) * n);
|
|
|
|
|
|
|
|
/* retrieve address selection policy from the kernel */
|
|
|
|
TAILQ_INIT(&policyhead);
|
|
|
|
if (!get_addrselectpolicy(&policyhead)) {
|
|
|
|
/* no policy is installed into kernel, we don't sort. */
|
|
|
|
free(aio);
|
|
|
|
return (n);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0, ai = sentinel->ai_next; i < n; ai = ai->ai_next, i++) {
|
|
|
|
aio[i].aio_ai = ai;
|
|
|
|
aio[i].aio_dstscope = gai_addr2scopetype(ai->ai_addr);
|
|
|
|
aio[i].aio_dstpolicy = match_addrselectpolicy(ai->ai_addr,
|
|
|
|
&policyhead);
|
2004-05-31 19:27:54 +00:00
|
|
|
set_source(&aio[i], &policyhead);
|
2003-10-30 17:36:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* perform sorting. */
|
|
|
|
qsort(aio, n, sizeof(*aio), comp_dst);
|
|
|
|
|
|
|
|
/* reorder the addrinfo chain. */
|
|
|
|
for (i = 0, aip = &sentinel->ai_next; i < n; i++) {
|
|
|
|
*aip = aio[i].aio_ai;
|
|
|
|
aip = &aio[i].aio_ai->ai_next;
|
|
|
|
}
|
|
|
|
*aip = NULL;
|
|
|
|
|
|
|
|
/* cleanup and return */
|
|
|
|
free(aio);
|
|
|
|
free_addrselectpolicy(&policyhead);
|
|
|
|
return(n);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-03-25 11:46:37 +00:00
|
|
|
get_addrselectpolicy(struct policyhead *head)
|
2003-10-30 17:36:53 +00:00
|
|
|
{
|
|
|
|
#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
|
2006-03-25 11:46:37 +00:00
|
|
|
free_addrselectpolicy(struct policyhead *head)
|
2003-10-30 17:36:53 +00:00
|
|
|
{
|
|
|
|
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 *
|
2006-03-25 11:46:37 +00:00
|
|
|
match_addrselectpolicy(struct sockaddr *addr, struct policyhead *head)
|
2003-10-30 17:36:53 +00:00
|
|
|
{
|
|
|
|
#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-05-31 19:27:54 +00:00
|
|
|
static void
|
2006-03-25 11:46:37 +00:00
|
|
|
set_source(struct ai_order *aio, struct policyhead *ph)
|
2004-05-31 19:27:54 +00:00
|
|
|
{
|
|
|
|
struct addrinfo ai = *aio->aio_ai;
|
|
|
|
struct sockaddr_storage ss;
|
2005-05-02 04:43:32 +00:00
|
|
|
socklen_t srclen;
|
|
|
|
int s;
|
2004-05-31 19:27:54 +00:00
|
|
|
|
|
|
|
/* set unspec ("no source is available"), just in case */
|
|
|
|
aio->aio_srcsa.sa_family = AF_UNSPEC;
|
|
|
|
aio->aio_srcscope = -1;
|
|
|
|
|
|
|
|
switch(ai.ai_family) {
|
|
|
|
case AF_INET:
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
default: /* ignore unsupported AFs explicitly */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX: make a dummy addrinfo to call connect() */
|
|
|
|
ai.ai_socktype = SOCK_DGRAM;
|
|
|
|
ai.ai_protocol = IPPROTO_UDP; /* is UDP too specific? */
|
|
|
|
ai.ai_next = NULL;
|
|
|
|
memset(&ss, 0, sizeof(ss));
|
|
|
|
memcpy(&ss, ai.ai_addr, ai.ai_addrlen);
|
|
|
|
ai.ai_addr = (struct sockaddr *)&ss;
|
|
|
|
get_port(&ai, "1", 0);
|
|
|
|
|
|
|
|
/* open a socket to get the source address for the given dst */
|
|
|
|
if ((s = _socket(ai.ai_family, ai.ai_socktype, ai.ai_protocol)) < 0)
|
|
|
|
return; /* give up */
|
|
|
|
if (_connect(s, ai.ai_addr, ai.ai_addrlen) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
srclen = ai.ai_addrlen;
|
|
|
|
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, aio->aio_ai->ai_addr);
|
|
|
|
#ifdef INET6
|
|
|
|
if (ai.ai_family == AF_INET6) {
|
|
|
|
struct in6_ifreq ifr6;
|
|
|
|
u_int32_t flags6;
|
|
|
|
|
|
|
|
memset(&ifr6, 0, sizeof(ifr6));
|
|
|
|
memcpy(&ifr6.ifr_addr, ai.ai_addr, ai.ai_addrlen);
|
|
|
|
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
|
2006-03-25 11:46:37 +00:00
|
|
|
matchlen(struct sockaddr *src, struct sockaddr *dst)
|
2004-05-31 19:27:54 +00:00
|
|
|
{
|
|
|
|
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:
|
2005-05-14 19:43:10 +00:00
|
|
|
s = (u_char *)&((struct sockaddr_in *)src)->sin_addr;
|
|
|
|
d = (u_char *)&((struct sockaddr_in *)dst)->sin_addr;
|
2004-05-31 19:27:54 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2003-10-30 17:36:53 +00:00
|
|
|
static int
|
2006-03-25 11:46:37 +00:00
|
|
|
comp_dst(const void *arg1, const void *arg2)
|
2003-10-30 17:36:53 +00:00
|
|
|
{
|
|
|
|
const struct ai_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_ai->ai_addr->sa_family ==
|
|
|
|
dst2->aio_ai->ai_addr->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
|
2006-03-25 11:46:37 +00:00
|
|
|
gai_addr2scopetype(struct sockaddr *sa)
|
2003-10-30 17:36:53 +00:00
|
|
|
{
|
|
|
|
#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))
|
2004-05-31 21:09:14 +00:00
|
|
|
return(14); /* XXX: It should be 5 unless NAT */
|
2003-10-30 17:36:53 +00:00
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-29 17:55:11 +00:00
|
|
|
static int
|
|
|
|
explore_copy(const struct addrinfo *pai, const struct addrinfo *src0,
|
|
|
|
struct addrinfo **res)
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
struct addrinfo sentinel, *cur;
|
|
|
|
const struct addrinfo *src;
|
|
|
|
|
|
|
|
error = 0;
|
|
|
|
sentinel.ai_next = NULL;
|
|
|
|
cur = &sentinel;
|
|
|
|
|
|
|
|
for (src = src0; src != NULL; src = src->ai_next) {
|
|
|
|
if (src->ai_family != pai->ai_family)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
cur->ai_next = copy_ai(src);
|
|
|
|
if (!cur->ai_next) {
|
|
|
|
error = EAI_MEMORY;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
cur->ai_next->ai_socktype = pai->ai_socktype;
|
|
|
|
cur->ai_next->ai_protocol = pai->ai_protocol;
|
|
|
|
cur = cur->ai_next;
|
|
|
|
}
|
|
|
|
|
|
|
|
*res = sentinel.ai_next;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
freeaddrinfo(sentinel.ai_next);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
1999-12-28 02:37:14 +00:00
|
|
|
/*
|
|
|
|
* hostname == NULL.
|
|
|
|
* passive socket -> anyaddr (0.0.0.0 or ::)
|
|
|
|
* non-passive socket -> localhost (127.0.0.1 or ::1)
|
|
|
|
*/
|
|
|
|
static int
|
2006-03-25 11:46:37 +00:00
|
|
|
explore_null(const struct addrinfo *pai, const char *servname,
|
|
|
|
struct addrinfo **res)
|
1999-12-28 02:37:14 +00:00
|
|
|
{
|
2003-10-24 18:43:24 +00:00
|
|
|
int s;
|
1999-12-28 02:37:14 +00:00
|
|
|
const struct afd *afd;
|
2006-07-21 18:57:44 +00:00
|
|
|
struct addrinfo *ai;
|
1999-12-28 02:37:14 +00:00
|
|
|
int error;
|
|
|
|
|
|
|
|
*res = NULL;
|
2006-07-21 18:57:44 +00:00
|
|
|
ai = NULL;
|
1999-12-28 02:37:14 +00:00
|
|
|
|
2003-10-24 18:43:24 +00:00
|
|
|
/*
|
|
|
|
* filter out AFs that are not supported by the kernel
|
|
|
|
* XXX errno?
|
|
|
|
*/
|
|
|
|
s = _socket(pai->ai_family, SOCK_DGRAM, 0);
|
|
|
|
if (s < 0) {
|
|
|
|
if (errno != EMFILE)
|
|
|
|
return 0;
|
|
|
|
} else
|
|
|
|
_close(s);
|
|
|
|
|
1999-12-28 02:37:14 +00:00
|
|
|
afd = find_afd(pai->ai_family);
|
|
|
|
if (afd == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2000-06-20 16:33:33 +00:00
|
|
|
if (pai->ai_flags & AI_PASSIVE) {
|
2006-07-21 18:57:44 +00:00
|
|
|
GET_AI(ai, afd, afd->a_addrany);
|
|
|
|
GET_PORT(ai, servname);
|
2000-06-20 16:33:33 +00:00
|
|
|
} else {
|
2006-07-21 18:57:44 +00:00
|
|
|
GET_AI(ai, afd, afd->a_loopback);
|
|
|
|
GET_PORT(ai, servname);
|
2000-06-20 16:33:33 +00:00
|
|
|
}
|
1999-12-28 02:37:14 +00:00
|
|
|
|
2006-07-21 18:57:44 +00:00
|
|
|
*res = ai;
|
1999-12-28 02:37:14 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
free:
|
2006-07-21 18:57:44 +00:00
|
|
|
if (ai != NULL)
|
|
|
|
freeaddrinfo(ai);
|
1999-12-28 02:37:14 +00:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* numeric hostname
|
|
|
|
*/
|
|
|
|
static int
|
2006-03-25 11:46:37 +00:00
|
|
|
explore_numeric(const struct addrinfo *pai, const char *hostname,
|
|
|
|
const char *servname, struct addrinfo **res, const char *canonname)
|
1999-12-28 02:37:14 +00:00
|
|
|
{
|
|
|
|
const struct afd *afd;
|
2006-07-21 18:57:44 +00:00
|
|
|
struct addrinfo *ai;
|
1999-12-28 02:37:14 +00:00
|
|
|
int error;
|
|
|
|
char pton[PTON_MAX];
|
|
|
|
|
|
|
|
*res = NULL;
|
2006-07-21 18:57:44 +00:00
|
|
|
ai = NULL;
|
1999-12-28 02:37:14 +00:00
|
|
|
|
|
|
|
afd = find_afd(pai->ai_family);
|
|
|
|
if (afd == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2000-07-05 05:07:23 +00:00
|
|
|
switch (afd->a_af) {
|
|
|
|
case AF_INET:
|
2006-07-21 19:00:22 +00:00
|
|
|
/*
|
|
|
|
* RFC3493 requires getaddrinfo() to accept AF_INET formats
|
|
|
|
* that are accepted by inet_addr() and its family. The
|
|
|
|
* accepted forms includes the "classful" one, which inet_pton
|
|
|
|
* does not accept. So we need to separate the case for
|
|
|
|
* AF_INET.
|
|
|
|
*/
|
2006-07-21 19:02:28 +00:00
|
|
|
if (inet_aton(hostname, (struct in_addr *)pton) != 1)
|
|
|
|
return 0;
|
2000-07-05 05:07:23 +00:00
|
|
|
break;
|
|
|
|
default:
|
2006-07-21 19:02:28 +00:00
|
|
|
if (inet_pton(afd->a_af, hostname, pton) != 1)
|
|
|
|
return 0;
|
2000-07-05 05:07:23 +00:00
|
|
|
break;
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
|
|
|
|
2006-07-21 19:02:28 +00:00
|
|
|
if (pai->ai_family == afd->a_af) {
|
|
|
|
GET_AI(ai, afd, pton);
|
|
|
|
GET_PORT(ai, servname);
|
|
|
|
if ((pai->ai_flags & AI_CANONNAME)) {
|
|
|
|
/*
|
|
|
|
* Set the numeric address itself as the canonical
|
|
|
|
* name, based on a clarification in RFC3493.
|
|
|
|
*/
|
|
|
|
GET_CANONNAME(ai, canonname);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* XXX: This should not happen since we already matched the AF
|
|
|
|
* by find_afd.
|
|
|
|
*/
|
|
|
|
ERR(EAI_FAMILY);
|
|
|
|
}
|
|
|
|
|
2006-07-21 18:57:44 +00:00
|
|
|
*res = ai;
|
1999-12-28 02:37:14 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
free:
|
|
|
|
bad:
|
2006-07-21 18:57:44 +00:00
|
|
|
if (ai != NULL)
|
|
|
|
freeaddrinfo(ai);
|
1999-12-28 02:37:14 +00:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* numeric hostname with scope
|
|
|
|
*/
|
|
|
|
static int
|
2006-03-25 11:46:37 +00:00
|
|
|
explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
|
|
|
|
const char *servname, struct addrinfo **res)
|
1999-12-28 02:37:14 +00:00
|
|
|
{
|
2000-06-20 16:33:33 +00:00
|
|
|
#if !defined(SCOPE_DELIMITER) || !defined(INET6)
|
2005-01-27 14:41:56 +00:00
|
|
|
return explore_numeric(pai, hostname, servname, res, hostname);
|
1999-12-28 02:37:14 +00:00
|
|
|
#else
|
|
|
|
const struct afd *afd;
|
|
|
|
struct addrinfo *cur;
|
|
|
|
int error;
|
2000-06-20 16:33:33 +00:00
|
|
|
char *cp, *hostname2 = NULL, *scope, *addr;
|
1999-12-28 02:37:14 +00:00
|
|
|
struct sockaddr_in6 *sin6;
|
|
|
|
|
|
|
|
afd = find_afd(pai->ai_family);
|
|
|
|
if (afd == NULL)
|
|
|
|
return 0;
|
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
|
|
|
|
1999-12-28 02:37:14 +00:00
|
|
|
if (!afd->a_scoped)
|
2005-01-27 14:41:56 +00:00
|
|
|
return explore_numeric(pai, hostname, servname, res, hostname);
|
1999-12-28 02:37:14 +00:00
|
|
|
|
|
|
|
cp = strchr(hostname, SCOPE_DELIMITER);
|
|
|
|
if (cp == NULL)
|
2005-01-27 14:41:56 +00:00
|
|
|
return explore_numeric(pai, hostname, servname, res, hostname);
|
1999-12-28 02:37:14 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Handle special case of <scoped_address><delimiter><scope id>
|
|
|
|
*/
|
|
|
|
hostname2 = strdup(hostname);
|
|
|
|
if (hostname2 == NULL)
|
|
|
|
return EAI_MEMORY;
|
|
|
|
/* terminate at the delimiter */
|
|
|
|
hostname2[cp - hostname] = '\0';
|
2000-06-20 16:33:33 +00:00
|
|
|
addr = hostname2;
|
|
|
|
scope = cp + 1;
|
1999-12-28 02:37:14 +00:00
|
|
|
|
2005-01-27 14:41:56 +00:00
|
|
|
error = explore_numeric(pai, addr, servname, res, hostname);
|
1999-12-28 02:37:14 +00:00
|
|
|
if (error == 0) {
|
2002-10-25 17:07:02 +00:00
|
|
|
u_int32_t scopeid;
|
2000-06-20 16:33:33 +00:00
|
|
|
|
1999-12-28 02:37:14 +00:00
|
|
|
for (cur = *res; cur; cur = cur->ai_next) {
|
|
|
|
if (cur->ai_family != AF_INET6)
|
|
|
|
continue;
|
2000-06-20 16:33:33 +00:00
|
|
|
sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
|
2002-10-25 17:07:02 +00:00
|
|
|
if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
|
2000-06-20 16:33:33 +00:00
|
|
|
free(hostname2);
|
2009-03-29 17:55:11 +00:00
|
|
|
freeaddrinfo(*res);
|
|
|
|
*res = NULL;
|
2003-10-23 13:55:36 +00:00
|
|
|
return(EAI_NONAME); /* XXX: is return OK? */
|
2000-06-20 16:33:33 +00:00
|
|
|
}
|
|
|
|
sin6->sin6_scope_id = scopeid;
|
1999-12-28 02:37:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(hostname2);
|
|
|
|
|
2009-03-29 17:55:11 +00:00
|
|
|
if (error && *res) {
|
|
|
|
freeaddrinfo(*res);
|
|
|
|
*res = NULL;
|
|
|
|
}
|
1999-12-28 02:37:14 +00:00
|
|
|
return error;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-03-25 11:46:37 +00:00
|
|
|
get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str)
|
1999-12-28 02:37:14 +00:00
|
|
|
{
|
|
|
|
if ((pai->ai_flags & AI_CANONNAME) != 0) {
|
2005-01-28 19:35:42 +00:00
|
|
|
ai->ai_canonname = strdup(str);
|
1999-12-28 02:37:14 +00:00
|
|
|
if (ai->ai_canonname == NULL)
|
|
|
|
return EAI_MEMORY;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct addrinfo *
|
2006-03-25 11:46:37 +00:00
|
|
|
get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
|
1999-12-28 02:37:14 +00:00
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
struct addrinfo *ai;
|
|
|
|
#ifdef FAITH
|
|
|
|
struct in6_addr faith_prefix;
|
|
|
|
char *fp_str;
|
|
|
|
int translate = 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef FAITH
|
|
|
|
/*
|
|
|
|
* Transfrom an IPv4 addr into a special IPv6 addr format for
|
|
|
|
* IPv6->IPv4 translation gateway. (only TCP is supported now)
|
|
|
|
*
|
|
|
|
* +-----------------------------------+------------+
|
|
|
|
* | faith prefix part (12 bytes) | embedded |
|
|
|
|
* | | IPv4 addr part (4 bytes)
|
|
|
|
* +-----------------------------------+------------+
|
|
|
|
*
|
|
|
|
* faith prefix part is specified as ascii IPv6 addr format
|
|
|
|
* in environmental variable GAI.
|
|
|
|
* For FAITH to work correctly, routing to faith prefix must be
|
|
|
|
* setup toward a machine where a FAITH daemon operates.
|
|
|
|
* Also, the machine must enable some mechanizm
|
|
|
|
* (e.g. faith interface hack) to divert those packet with
|
|
|
|
* faith prefixed destination addr to user-land FAITH daemon.
|
|
|
|
*/
|
|
|
|
fp_str = getenv("GAI");
|
|
|
|
if (fp_str && inet_pton(AF_INET6, fp_str, &faith_prefix) == 1 &&
|
|
|
|
afd->a_af == AF_INET && pai->ai_socktype == SOCK_STREAM) {
|
|
|
|
u_int32_t v4a;
|
|
|
|
u_int8_t v4a_top;
|
|
|
|
|
|
|
|
memcpy(&v4a, addr, sizeof v4a);
|
|
|
|
v4a_top = v4a >> IN_CLASSA_NSHIFT;
|
|
|
|
if (!IN_MULTICAST(v4a) && !IN_EXPERIMENTAL(v4a) &&
|
|
|
|
v4a_top != 0 && v4a != IN_LOOPBACKNET) {
|
|
|
|
afd = &afdl[N_INET6];
|
|
|
|
memcpy(&faith_prefix.s6_addr[12], addr,
|
|
|
|
sizeof(struct in_addr));
|
|
|
|
translate = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
|
|
|
|
+ (afd->a_socklen));
|
|
|
|
if (ai == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
memcpy(ai, pai, sizeof(struct addrinfo));
|
2000-06-20 16:33:33 +00:00
|
|
|
ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
|
|
|
|
memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
|
1999-12-28 02:37:14 +00:00
|
|
|
ai->ai_addr->sa_len = afd->a_socklen;
|
|
|
|
ai->ai_addrlen = afd->a_socklen;
|
|
|
|
ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
|
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
|
|
|
p = (char *)(void *)(ai->ai_addr);
|
1999-12-28 02:37:14 +00:00
|
|
|
#ifdef FAITH
|
|
|
|
if (translate == 1)
|
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
|
|
|
memcpy(p + afd->a_off, &faith_prefix, (size_t)afd->a_addrlen);
|
1999-12-28 02:37:14 +00:00
|
|
|
else
|
|
|
|
#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
|
|
|
memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
|
1999-12-28 02:37:14 +00:00
|
|
|
return ai;
|
|
|
|
}
|
|
|
|
|
2009-03-29 17:55:11 +00:00
|
|
|
/* XXX need to malloc() the same way we do from other functions! */
|
|
|
|
static struct addrinfo *
|
|
|
|
copy_ai(const struct addrinfo *pai)
|
|
|
|
{
|
|
|
|
struct addrinfo *ai;
|
|
|
|
size_t l;
|
|
|
|
|
|
|
|
l = sizeof(*ai) + pai->ai_addrlen;
|
|
|
|
if ((ai = (struct addrinfo *)malloc(l)) == NULL)
|
|
|
|
return NULL;
|
|
|
|
memset(ai, 0, l);
|
|
|
|
memcpy(ai, pai, sizeof(*ai));
|
|
|
|
ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
|
|
|
|
memcpy(ai->ai_addr, pai->ai_addr, pai->ai_addrlen);
|
|
|
|
|
|
|
|
if (pai->ai_canonname) {
|
|
|
|
l = strlen(pai->ai_canonname) + 1;
|
|
|
|
if ((ai->ai_canonname = malloc(l)) == NULL) {
|
|
|
|
free(ai);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
strlcpy(ai->ai_canonname, pai->ai_canonname, l);
|
|
|
|
} else {
|
|
|
|
/* just to make sure */
|
|
|
|
ai->ai_canonname = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ai->ai_next = NULL;
|
|
|
|
|
|
|
|
return ai;
|
|
|
|
}
|
|
|
|
|
1999-12-28 02:37:14 +00:00
|
|
|
static int
|
2006-03-25 11:46:37 +00:00
|
|
|
get_portmatch(const struct addrinfo *ai, const char *servname)
|
1999-12-28 02:37:14 +00:00
|
|
|
{
|
2000-06-20 16:33:33 +00:00
|
|
|
|
2005-01-27 14:45:11 +00:00
|
|
|
/* get_port does not touch first argument when matchonly == 1. */
|
2000-06-20 16:33:33 +00:00
|
|
|
/* LINTED const cast */
|
1999-12-28 02:37:14 +00:00
|
|
|
return get_port((struct addrinfo *)ai, servname, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-03-25 11:46:37 +00:00
|
|
|
get_port(struct addrinfo *ai, const char *servname, int matchonly)
|
1999-12-28 02:37:14 +00:00
|
|
|
{
|
|
|
|
const char *proto;
|
|
|
|
struct servent *sp;
|
2006-07-23 15:31:03 +00:00
|
|
|
int port, error;
|
1999-12-28 02:37:14 +00:00
|
|
|
int allownumeric;
|
|
|
|
|
|
|
|
if (servname == NULL)
|
|
|
|
return 0;
|
2000-06-20 16:33:33 +00:00
|
|
|
switch (ai->ai_family) {
|
|
|
|
case AF_INET:
|
|
|
|
#ifdef AF_INET6
|
|
|
|
case AF_INET6:
|
1999-12-28 02:37:14 +00:00
|
|
|
#endif
|
2000-06-20 16:33:33 +00:00
|
|
|
break;
|
|
|
|
default:
|
1999-12-28 02:37:14 +00:00
|
|
|
return 0;
|
2000-06-20 16:33:33 +00:00
|
|
|
}
|
1999-12-28 02:37:14 +00:00
|
|
|
|
|
|
|
switch (ai->ai_socktype) {
|
|
|
|
case SOCK_RAW:
|
|
|
|
return EAI_SERVICE;
|
|
|
|
case SOCK_DGRAM:
|
|
|
|
case SOCK_STREAM:
|
2009-03-25 16:23:43 +00:00
|
|
|
case SOCK_SEQPACKET:
|
1999-12-28 02:37:14 +00:00
|
|
|
allownumeric = 1;
|
|
|
|
break;
|
|
|
|
case ANY:
|
2009-03-24 17:47:24 +00:00
|
|
|
switch (ai->ai_family) {
|
|
|
|
case AF_INET:
|
|
|
|
#ifdef AF_INET6
|
|
|
|
case AF_INET6:
|
|
|
|
#endif
|
|
|
|
allownumeric = 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
allownumeric = 0;
|
|
|
|
break;
|
|
|
|
}
|
1999-12-28 02:37:14 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return EAI_SOCKTYPE;
|
|
|
|
}
|
|
|
|
|
2006-07-23 15:31:03 +00:00
|
|
|
error = str2number(servname, &port);
|
|
|
|
if (error == 0) {
|
1999-12-28 02:37:14 +00:00
|
|
|
if (!allownumeric)
|
|
|
|
return EAI_SERVICE;
|
|
|
|
if (port < 0 || port > 65535)
|
|
|
|
return EAI_SERVICE;
|
2002-10-25 16:24:28 +00:00
|
|
|
port = htons(port);
|
1999-12-28 02:37:14 +00:00
|
|
|
} else {
|
2005-01-27 14:45:11 +00:00
|
|
|
if (ai->ai_flags & AI_NUMERICSERV)
|
|
|
|
return EAI_NONAME;
|
2009-03-25 16:23:43 +00:00
|
|
|
|
|
|
|
switch (ai->ai_protocol) {
|
|
|
|
case IPPROTO_UDP:
|
1999-12-28 02:37:14 +00:00
|
|
|
proto = "udp";
|
|
|
|
break;
|
2009-03-25 16:23:43 +00:00
|
|
|
case IPPROTO_TCP:
|
1999-12-28 02:37:14 +00:00
|
|
|
proto = "tcp";
|
|
|
|
break;
|
2009-03-25 16:23:43 +00:00
|
|
|
case IPPROTO_SCTP:
|
|
|
|
proto = "sctp";
|
|
|
|
break;
|
1999-12-28 02:37:14 +00:00
|
|
|
default:
|
|
|
|
proto = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-04-15 18:15:12 +00:00
|
|
|
if ((sp = getservbyname(servname, proto)) == NULL)
|
1999-12-28 02:37:14 +00:00
|
|
|
return EAI_SERVICE;
|
|
|
|
port = sp->s_port;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!matchonly) {
|
|
|
|
switch (ai->ai_family) {
|
|
|
|
case AF_INET:
|
2000-06-20 16:33:33 +00:00
|
|
|
((struct sockaddr_in *)(void *)
|
|
|
|
ai->ai_addr)->sin_port = port;
|
1999-12-28 02:37:14 +00:00
|
|
|
break;
|
|
|
|
#ifdef INET6
|
|
|
|
case AF_INET6:
|
2000-06-20 16:33:33 +00:00
|
|
|
((struct sockaddr_in6 *)(void *)
|
|
|
|
ai->ai_addr)->sin6_port = port;
|
1999-12-28 02:37:14 +00:00
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct afd *
|
2006-03-25 11:46:37 +00:00
|
|
|
find_afd(int af)
|
1999-12-28 02:37:14 +00:00
|
|
|
{
|
|
|
|
const struct afd *afd;
|
|
|
|
|
|
|
|
if (af == PF_UNSPEC)
|
|
|
|
return NULL;
|
|
|
|
for (afd = afdl; afd->a_af; afd++) {
|
|
|
|
if (afd->a_af == af)
|
|
|
|
return afd;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2000-06-20 16:33:33 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend
|
|
|
|
* will take care of it.
|
|
|
|
* the semantics of AI_ADDRCONFIG is not defined well. we are not sure
|
|
|
|
* if the code is right or not.
|
2003-10-24 18:43:24 +00:00
|
|
|
*
|
|
|
|
* XXX PF_UNSPEC -> PF_INET6 + PF_INET mapping needs to be in sync with
|
|
|
|
* _dns_getaddrinfo.
|
2000-06-20 16:33:33 +00:00
|
|
|
*/
|
|
|
|
static int
|
2006-03-25 11:46:37 +00:00
|
|
|
addrconfig(struct addrinfo *pai)
|
2000-06-20 16:33:33 +00:00
|
|
|
{
|
2003-10-24 18:43:24 +00:00
|
|
|
int s, af;
|
2000-06-20 16:33:33 +00:00
|
|
|
|
2003-10-24 18:43:24 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
af = pai->ai_family;
|
|
|
|
if (af == AF_UNSPEC) {
|
|
|
|
if ((s = _socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
|
|
|
|
af = AF_INET;
|
|
|
|
else {
|
|
|
|
_close(s);
|
|
|
|
if ((s = _socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
|
|
|
af = AF_INET6;
|
|
|
|
else
|
|
|
|
_close(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (af != AF_UNSPEC) {
|
|
|
|
if ((s = _socket(af, SOCK_DGRAM, 0)) < 0)
|
2000-06-20 16:33:33 +00:00
|
|
|
return 0;
|
2003-10-24 18:43:24 +00:00
|
|
|
_close(s);
|
|
|
|
}
|
|
|
|
pai->ai_family = af;
|
2000-06-20 16:33:33 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef INET6
|
|
|
|
/* convert a string to a scope identifier. XXX: IPv6 specific */
|
|
|
|
static int
|
2006-03-25 11:46:37 +00:00
|
|
|
ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid)
|
2000-06-20 16:33:33 +00:00
|
|
|
{
|
2002-10-25 17:07:02 +00:00
|
|
|
u_long lscopeid;
|
2003-10-24 18:43:24 +00:00
|
|
|
struct in6_addr *a6;
|
2000-06-20 16:33:33 +00:00
|
|
|
char *ep;
|
|
|
|
|
2003-10-24 18:43:24 +00:00
|
|
|
a6 = &sin6->sin6_addr;
|
|
|
|
|
2000-07-09 06:10:01 +00:00
|
|
|
/* empty scopeid portion is invalid */
|
|
|
|
if (*scope == '\0')
|
|
|
|
return -1;
|
|
|
|
|
2012-01-07 09:01:19 +00:00
|
|
|
if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6) ||
|
|
|
|
IN6_IS_ADDR_MC_NODELOCAL(a6)) {
|
2000-06-20 16:33:33 +00:00
|
|
|
/*
|
|
|
|
* We currently assume a one-to-one mapping between links
|
|
|
|
* and interfaces, so we simply use interface indices for
|
|
|
|
* like-local scopes.
|
|
|
|
*/
|
2002-10-25 17:07:02 +00:00
|
|
|
*scopeid = if_nametoindex(scope);
|
|
|
|
if (*scopeid == 0)
|
2000-06-20 16:33:33 +00:00
|
|
|
goto trynumeric;
|
2002-10-25 17:07:02 +00:00
|
|
|
return 0;
|
2000-06-20 16:33:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* still unclear about literal, allow numeric only - placeholder */
|
|
|
|
if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
|
|
|
|
goto trynumeric;
|
|
|
|
if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
|
|
|
|
goto trynumeric;
|
|
|
|
else
|
|
|
|
goto trynumeric; /* global */
|
|
|
|
|
|
|
|
/* try to convert to a numeric id as a last resort */
|
2003-10-24 18:43:24 +00:00
|
|
|
trynumeric:
|
2002-10-25 17:07:02 +00:00
|
|
|
errno = 0;
|
|
|
|
lscopeid = strtoul(scope, &ep, 10);
|
|
|
|
*scopeid = (u_int32_t)(lscopeid & 0xffffffffUL);
|
|
|
|
if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid)
|
|
|
|
return 0;
|
2000-06-20 16:33:33 +00:00
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-04-28 12:03:38 +00:00
|
|
|
|
|
|
|
#ifdef NS_CACHING
|
|
|
|
static int
|
|
|
|
addrinfo_id_func(char *buffer, size_t *buffer_size, va_list ap,
|
|
|
|
void *cache_mdata)
|
|
|
|
{
|
|
|
|
res_state statp;
|
|
|
|
u_long res_options;
|
|
|
|
|
|
|
|
const int op_id = 0; /* identifies the getaddrinfo for the cache */
|
|
|
|
char *hostname;
|
|
|
|
struct addrinfo *hints;
|
|
|
|
|
|
|
|
char *p;
|
|
|
|
int ai_flags, ai_family, ai_socktype, ai_protocol;
|
|
|
|
size_t desired_size, size;
|
|
|
|
|
|
|
|
statp = __res_state();
|
|
|
|
res_options = statp->options & (RES_RECURSE | RES_DEFNAMES |
|
|
|
|
RES_DNSRCH | RES_NOALIASES | RES_USE_INET6);
|
|
|
|
|
|
|
|
hostname = va_arg(ap, char *);
|
|
|
|
hints = va_arg(ap, struct addrinfo *);
|
|
|
|
|
|
|
|
desired_size = sizeof(res_options) + sizeof(int) + sizeof(int) * 4;
|
|
|
|
if (hostname != NULL) {
|
|
|
|
size = strlen(hostname);
|
|
|
|
desired_size += size + 1;
|
|
|
|
} else
|
|
|
|
size = 0;
|
|
|
|
|
|
|
|
if (desired_size > *buffer_size) {
|
|
|
|
*buffer_size = desired_size;
|
|
|
|
return (NS_RETURN);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hints == NULL)
|
|
|
|
ai_flags = ai_family = ai_socktype = ai_protocol = 0;
|
|
|
|
else {
|
|
|
|
ai_flags = hints->ai_flags;
|
|
|
|
ai_family = hints->ai_family;
|
|
|
|
ai_socktype = hints->ai_socktype;
|
|
|
|
ai_protocol = hints->ai_protocol;
|
|
|
|
}
|
|
|
|
|
|
|
|
p = buffer;
|
|
|
|
memcpy(p, &res_options, sizeof(res_options));
|
|
|
|
p += sizeof(res_options);
|
|
|
|
|
|
|
|
memcpy(p, &op_id, sizeof(int));
|
|
|
|
p += sizeof(int);
|
|
|
|
|
|
|
|
memcpy(p, &ai_flags, sizeof(int));
|
|
|
|
p += sizeof(int);
|
|
|
|
|
|
|
|
memcpy(p, &ai_family, sizeof(int));
|
|
|
|
p += sizeof(int);
|
|
|
|
|
|
|
|
memcpy(p, &ai_socktype, sizeof(int));
|
|
|
|
p += sizeof(int);
|
|
|
|
|
|
|
|
memcpy(p, &ai_protocol, sizeof(int));
|
|
|
|
p += sizeof(int);
|
|
|
|
|
|
|
|
if (hostname != NULL)
|
|
|
|
memcpy(p, hostname, size);
|
|
|
|
|
|
|
|
*buffer_size = desired_size;
|
|
|
|
return (NS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
addrinfo_marshal_func(char *buffer, size_t *buffer_size, void *retval,
|
|
|
|
va_list ap, void *cache_mdata)
|
|
|
|
{
|
|
|
|
struct addrinfo *ai, *cai;
|
|
|
|
char *p;
|
|
|
|
size_t desired_size, size, ai_size;
|
|
|
|
|
|
|
|
ai = *((struct addrinfo **)retval);
|
|
|
|
|
|
|
|
desired_size = sizeof(size_t);
|
|
|
|
ai_size = 0;
|
|
|
|
for (cai = ai; cai != NULL; cai = cai->ai_next) {
|
|
|
|
desired_size += sizeof(struct addrinfo) + cai->ai_addrlen;
|
|
|
|
if (cai->ai_canonname != NULL)
|
|
|
|
desired_size += sizeof(size_t) +
|
|
|
|
strlen(cai->ai_canonname);
|
|
|
|
++ai_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (desired_size > *buffer_size) {
|
|
|
|
/* this assignment is here for future use */
|
|
|
|
errno = ERANGE;
|
|
|
|
*buffer_size = desired_size;
|
|
|
|
return (NS_RETURN);
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(buffer, 0, desired_size);
|
|
|
|
p = buffer;
|
|
|
|
|
|
|
|
memcpy(p, &ai_size, sizeof(size_t));
|
|
|
|
p += sizeof(size_t);
|
|
|
|
for (cai = ai; cai != NULL; cai = cai->ai_next) {
|
|
|
|
memcpy(p, cai, sizeof(struct addrinfo));
|
|
|
|
p += sizeof(struct addrinfo);
|
|
|
|
|
|
|
|
memcpy(p, cai->ai_addr, cai->ai_addrlen);
|
|
|
|
p += cai->ai_addrlen;
|
|
|
|
|
|
|
|
if (cai->ai_canonname != NULL) {
|
|
|
|
size = strlen(cai->ai_canonname);
|
|
|
|
memcpy(p, &size, sizeof(size_t));
|
|
|
|
p += sizeof(size_t);
|
|
|
|
|
|
|
|
memcpy(p, cai->ai_canonname, size);
|
|
|
|
p += size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (NS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
addrinfo_unmarshal_func(char *buffer, size_t buffer_size, void *retval,
|
|
|
|
va_list ap, void *cache_mdata)
|
|
|
|
{
|
|
|
|
struct addrinfo new_ai, *result, *sentinel, *lasts;
|
|
|
|
|
|
|
|
char *p;
|
|
|
|
size_t ai_size, ai_i, size;
|
|
|
|
|
|
|
|
p = buffer;
|
|
|
|
memcpy(&ai_size, p, sizeof(size_t));
|
|
|
|
p += sizeof(size_t);
|
|
|
|
|
|
|
|
result = NULL;
|
|
|
|
lasts = NULL;
|
|
|
|
for (ai_i = 0; ai_i < ai_size; ++ai_i) {
|
|
|
|
memcpy(&new_ai, p, sizeof(struct addrinfo));
|
|
|
|
p += sizeof(struct addrinfo);
|
|
|
|
size = new_ai.ai_addrlen + sizeof(struct addrinfo) +
|
|
|
|
_ALIGNBYTES;
|
|
|
|
|
|
|
|
sentinel = (struct addrinfo *)malloc(size);
|
|
|
|
memset(sentinel, 0, size);
|
|
|
|
|
|
|
|
memcpy(sentinel, &new_ai, sizeof(struct addrinfo));
|
|
|
|
sentinel->ai_addr = (struct sockaddr *)_ALIGN((char *)sentinel +
|
|
|
|
sizeof(struct addrinfo));
|
|
|
|
|
|
|
|
memcpy(sentinel->ai_addr, p, new_ai.ai_addrlen);
|
|
|
|
p += new_ai.ai_addrlen;
|
|
|
|
|
|
|
|
if (new_ai.ai_canonname != NULL) {
|
|
|
|
memcpy(&size, p, sizeof(size_t));
|
|
|
|
p += sizeof(size_t);
|
|
|
|
|
|
|
|
sentinel->ai_canonname = (char *)malloc(size + 1);
|
|
|
|
memset(sentinel->ai_canonname, 0, size + 1);
|
|
|
|
|
|
|
|
memcpy(sentinel->ai_canonname, p, size);
|
|
|
|
p += size;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result == NULL) {
|
|
|
|
result = sentinel;
|
|
|
|
lasts = sentinel;
|
|
|
|
} else {
|
|
|
|
lasts->ai_next = sentinel;
|
|
|
|
lasts = sentinel;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*((struct addrinfo **)retval) = result;
|
|
|
|
return (NS_SUCCESS);
|
|
|
|
}
|
|
|
|
#endif /* NS_CACHING */
|
|
|
|
|
2003-10-23 14:32:03 +00:00
|
|
|
/*
|
|
|
|
* FQDN hostname, DNS lookup
|
|
|
|
*/
|
2002-08-21 19:57:53 +00:00
|
|
|
static int
|
2006-03-25 11:46:37 +00:00
|
|
|
explore_fqdn(const struct addrinfo *pai, const char *hostname,
|
|
|
|
const char *servname, struct addrinfo **res)
|
2002-08-21 19:57:53 +00:00
|
|
|
{
|
2003-10-23 14:32:03 +00:00
|
|
|
struct addrinfo *result;
|
|
|
|
struct addrinfo *cur;
|
|
|
|
int error = 0;
|
2006-04-28 12:03:38 +00:00
|
|
|
|
|
|
|
#ifdef NS_CACHING
|
|
|
|
static const nss_cache_info cache_info =
|
|
|
|
NS_COMMON_CACHE_INFO_INITIALIZER(
|
|
|
|
hosts, NULL, addrinfo_id_func, addrinfo_marshal_func,
|
|
|
|
addrinfo_unmarshal_func);
|
|
|
|
#endif
|
2003-10-23 14:32:03 +00:00
|
|
|
static const ns_dtab dtab[] = {
|
|
|
|
NS_FILES_CB(_files_getaddrinfo, NULL)
|
|
|
|
{ NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */
|
|
|
|
NS_NIS_CB(_yp_getaddrinfo, NULL)
|
2006-04-28 12:03:38 +00:00
|
|
|
#ifdef NS_CACHING
|
|
|
|
NS_CACHE_CB(&cache_info)
|
|
|
|
#endif
|
2003-10-23 14:32:03 +00:00
|
|
|
{ 0 }
|
|
|
|
};
|
2002-08-21 19:57:53 +00:00
|
|
|
|
2003-10-23 14:32:03 +00:00
|
|
|
result = NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* if the servname does not match socktype/protocol, ignore it.
|
|
|
|
*/
|
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
|
|
|
if (get_portmatch(pai, servname) != 0)
|
2002-08-21 19:57:53 +00:00
|
|
|
return 0;
|
|
|
|
|
2003-10-23 14:32:03 +00:00
|
|
|
switch (_nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",
|
|
|
|
default_dns_files, hostname, pai)) {
|
|
|
|
case NS_TRYAGAIN:
|
|
|
|
error = EAI_AGAIN;
|
|
|
|
goto free;
|
|
|
|
case NS_UNAVAIL:
|
|
|
|
error = EAI_FAIL;
|
|
|
|
goto free;
|
|
|
|
case NS_NOTFOUND:
|
|
|
|
error = EAI_NONAME;
|
|
|
|
goto free;
|
|
|
|
case NS_SUCCESS:
|
|
|
|
error = 0;
|
|
|
|
for (cur = result; cur; cur = cur->ai_next) {
|
|
|
|
GET_PORT(cur, servname);
|
|
|
|
/* canonname should be filled already */
|
|
|
|
}
|
|
|
|
break;
|
2002-08-21 19:57:53 +00:00
|
|
|
}
|
2003-10-23 14:32:03 +00:00
|
|
|
|
|
|
|
*res = result;
|
2002-08-21 19:57:53 +00:00
|
|
|
|
|
|
|
return 0;
|
2003-10-23 14:32:03 +00:00
|
|
|
|
|
|
|
free:
|
|
|
|
if (result)
|
|
|
|
freeaddrinfo(result);
|
|
|
|
return error;
|
2002-08-21 19:57:53 +00:00
|
|
|
}
|
|
|
|
|
2000-06-20 16:33:33 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
static const char AskedForGot[] =
|
|
|
|
"gethostby*.getanswer: asked for \"%s\", got \"%s\"";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static struct addrinfo *
|
2006-03-25 11:46:37 +00:00
|
|
|
getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
|
|
|
|
const struct addrinfo *pai, res_state res)
|
2000-06-20 16:33:33 +00:00
|
|
|
{
|
|
|
|
struct addrinfo sentinel, *cur;
|
|
|
|
struct addrinfo ai;
|
|
|
|
const struct afd *afd;
|
|
|
|
char *canonname;
|
|
|
|
const HEADER *hp;
|
|
|
|
const u_char *cp;
|
|
|
|
int n;
|
|
|
|
const u_char *eom;
|
2002-10-25 16:24:28 +00:00
|
|
|
char *bp, *ep;
|
|
|
|
int type, class, ancount, qdcount;
|
2000-06-20 16:33:33 +00:00
|
|
|
int haveanswer, had_error;
|
|
|
|
char tbuf[MAXDNAME];
|
2002-03-21 22:49:10 +00:00
|
|
|
int (*name_ok)(const char *);
|
2000-06-20 16:33:33 +00:00
|
|
|
char hostbuf[8*1024];
|
|
|
|
|
|
|
|
memset(&sentinel, 0, sizeof(sentinel));
|
|
|
|
cur = &sentinel;
|
|
|
|
|
|
|
|
canonname = NULL;
|
|
|
|
eom = answer->buf + anslen;
|
|
|
|
switch (qtype) {
|
|
|
|
case T_A:
|
|
|
|
case T_AAAA:
|
|
|
|
case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/
|
|
|
|
name_ok = res_hnok;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return (NULL); /* XXX should be abort(); */
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* find first satisfactory answer
|
|
|
|
*/
|
|
|
|
hp = &answer->hdr;
|
|
|
|
ancount = ntohs(hp->ancount);
|
|
|
|
qdcount = ntohs(hp->qdcount);
|
|
|
|
bp = hostbuf;
|
2002-10-25 16:24:28 +00:00
|
|
|
ep = hostbuf + sizeof hostbuf;
|
2000-06-20 16:33:33 +00:00
|
|
|
cp = answer->buf + HFIXEDSZ;
|
|
|
|
if (qdcount != 1) {
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, NO_RECOVERY);
|
2000-06-20 16:33:33 +00:00
|
|
|
return (NULL);
|
|
|
|
}
|
2002-10-25 16:24:28 +00:00
|
|
|
n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
|
2000-06-20 16:33:33 +00:00
|
|
|
if ((n < 0) || !(*name_ok)(bp)) {
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, NO_RECOVERY);
|
2000-06-20 16:33:33 +00:00
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
cp += n + QFIXEDSZ;
|
|
|
|
if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
|
|
|
|
/* 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) {
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, NO_RECOVERY);
|
2000-06-20 16:33:33 +00:00
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
canonname = bp;
|
|
|
|
bp += n;
|
|
|
|
/* The qname can be abbreviated, but h_name is now absolute. */
|
|
|
|
qname = canonname;
|
|
|
|
}
|
|
|
|
haveanswer = 0;
|
|
|
|
had_error = 0;
|
|
|
|
while (ancount-- > 0 && cp < eom && !had_error) {
|
2002-10-25 16:24:28 +00:00
|
|
|
n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
|
2000-06-20 16:33:33 +00:00
|
|
|
if ((n < 0) || !(*name_ok)(bp)) {
|
|
|
|
had_error++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
cp += n; /* name */
|
|
|
|
type = _getshort(cp);
|
|
|
|
cp += INT16SZ; /* type */
|
|
|
|
class = _getshort(cp);
|
|
|
|
cp += INT16SZ + INT32SZ; /* class, TTL */
|
|
|
|
n = _getshort(cp);
|
|
|
|
cp += INT16SZ; /* len */
|
|
|
|
if (class != C_IN) {
|
|
|
|
/* XXX - debug? syslog? */
|
|
|
|
cp += n;
|
|
|
|
continue; /* XXX - had_error++ ? */
|
|
|
|
}
|
|
|
|
if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
|
|
|
|
type == T_CNAME) {
|
|
|
|
n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
|
|
|
|
if ((n < 0) || !(*name_ok)(tbuf)) {
|
|
|
|
had_error++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
cp += n;
|
|
|
|
/* Get canonical name. */
|
|
|
|
n = strlen(tbuf) + 1; /* for the \0 */
|
2002-10-25 16:24:28 +00:00
|
|
|
if (n > ep - bp || n >= MAXHOSTNAMELEN) {
|
2000-06-20 16:33:33 +00:00
|
|
|
had_error++;
|
|
|
|
continue;
|
|
|
|
}
|
2003-05-01 19:03:14 +00:00
|
|
|
strlcpy(bp, tbuf, ep - bp);
|
2000-06-20 16:33:33 +00:00
|
|
|
canonname = bp;
|
|
|
|
bp += n;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (qtype == T_ANY) {
|
|
|
|
if (!(type == T_A || type == T_AAAA)) {
|
|
|
|
cp += n;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else if (type != qtype) {
|
|
|
|
#ifdef DEBUG
|
2009-02-08 16:58:05 +00:00
|
|
|
if (type != T_KEY && type != T_SIG &&
|
|
|
|
type != ns_t_dname)
|
2000-06-20 16:33:33 +00:00
|
|
|
syslog(LOG_NOTICE|LOG_AUTH,
|
|
|
|
"gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
|
|
|
|
qname, p_class(C_IN), p_type(qtype),
|
|
|
|
p_type(type));
|
|
|
|
#endif
|
|
|
|
cp += n;
|
|
|
|
continue; /* XXX - had_error++ ? */
|
|
|
|
}
|
|
|
|
switch (type) {
|
|
|
|
case T_A:
|
|
|
|
case T_AAAA:
|
|
|
|
if (strcasecmp(canonname, bp) != 0) {
|
|
|
|
#ifdef DEBUG
|
|
|
|
syslog(LOG_NOTICE|LOG_AUTH,
|
|
|
|
AskedForGot, canonname, bp);
|
|
|
|
#endif
|
|
|
|
cp += n;
|
|
|
|
continue; /* XXX - had_error++ ? */
|
|
|
|
}
|
|
|
|
if (type == T_A && n != INADDRSZ) {
|
|
|
|
cp += n;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (type == T_AAAA && n != IN6ADDRSZ) {
|
|
|
|
cp += n;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#ifdef FILTER_V4MAPPED
|
|
|
|
if (type == T_AAAA) {
|
|
|
|
struct in6_addr in6;
|
|
|
|
memcpy(&in6, cp, sizeof(in6));
|
|
|
|
if (IN6_IS_ADDR_V4MAPPED(&in6)) {
|
|
|
|
cp += n;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (!haveanswer) {
|
|
|
|
int nn;
|
|
|
|
|
|
|
|
canonname = bp;
|
|
|
|
nn = strlen(bp) + 1; /* for the \0 */
|
|
|
|
bp += nn;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* don't overwrite pai */
|
|
|
|
ai = *pai;
|
|
|
|
ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
|
|
|
|
afd = find_afd(ai.ai_family);
|
|
|
|
if (afd == NULL) {
|
|
|
|
cp += n;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
cur->ai_next = get_ai(&ai, afd, (const char *)cp);
|
|
|
|
if (cur->ai_next == NULL)
|
|
|
|
had_error++;
|
|
|
|
while (cur && cur->ai_next)
|
|
|
|
cur = cur->ai_next;
|
|
|
|
cp += n;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
if (!had_error)
|
|
|
|
haveanswer++;
|
|
|
|
}
|
|
|
|
if (haveanswer) {
|
2002-08-21 19:57:53 +00:00
|
|
|
#if defined(RESOLVSORT)
|
|
|
|
/*
|
|
|
|
* We support only IPv4 address for backward
|
|
|
|
* compatibility against gethostbyname(3).
|
|
|
|
*/
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
if (res->nsort && qtype == T_A) {
|
|
|
|
if (addr4sort(&sentinel, res) < 0) {
|
2002-08-21 19:57:53 +00:00
|
|
|
freeaddrinfo(sentinel.ai_next);
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, NO_RECOVERY);
|
2002-08-21 19:57:53 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /*RESOLVSORT*/
|
2000-06-20 16:33:33 +00:00
|
|
|
if (!canonname)
|
|
|
|
(void)get_canonname(pai, sentinel.ai_next, qname);
|
|
|
|
else
|
|
|
|
(void)get_canonname(pai, sentinel.ai_next, canonname);
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, NETDB_SUCCESS);
|
2000-06-20 16:33:33 +00:00
|
|
|
return sentinel.ai_next;
|
|
|
|
}
|
|
|
|
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, NO_RECOVERY);
|
2000-06-20 16:33:33 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2003-10-23 14:32:03 +00:00
|
|
|
#ifdef RESOLVSORT
|
|
|
|
struct addr_ptr {
|
|
|
|
struct addrinfo *ai;
|
|
|
|
int aval;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
addr4sort(struct addrinfo *sentinel, res_state res)
|
2003-10-23 14:32:03 +00:00
|
|
|
{
|
|
|
|
struct addrinfo *ai;
|
|
|
|
struct addr_ptr *addrs, addr;
|
|
|
|
struct sockaddr_in *sin;
|
|
|
|
int naddrs, i, j;
|
|
|
|
int needsort = 0;
|
|
|
|
|
|
|
|
if (!sentinel)
|
|
|
|
return -1;
|
|
|
|
naddrs = 0;
|
|
|
|
for (ai = sentinel->ai_next; ai; ai = ai->ai_next)
|
|
|
|
naddrs++;
|
|
|
|
if (naddrs < 2)
|
|
|
|
return 0; /* We don't need sorting. */
|
|
|
|
if ((addrs = malloc(sizeof(struct addr_ptr) * naddrs)) == NULL)
|
|
|
|
return -1;
|
|
|
|
i = 0;
|
|
|
|
for (ai = sentinel->ai_next; ai; ai = ai->ai_next) {
|
|
|
|
sin = (struct sockaddr_in *)ai->ai_addr;
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
for (j = 0; (unsigned)j < res->nsort; j++) {
|
2006-03-25 11:46:37 +00:00
|
|
|
if (res->sort_list[j].addr.s_addr ==
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
(sin->sin_addr.s_addr & res->sort_list[j].mask))
|
2003-10-23 14:32:03 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
addrs[i].ai = ai;
|
|
|
|
addrs[i].aval = j;
|
|
|
|
if (needsort == 0 && i > 0 && j < addrs[i - 1].aval)
|
|
|
|
needsort = i;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if (!needsort) {
|
|
|
|
free(addrs);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (needsort < naddrs) {
|
2006-04-01 15:53:39 +00:00
|
|
|
for (j = needsort - 1; j >= 0; j--) {
|
|
|
|
if (addrs[j].aval > addrs[j+1].aval) {
|
|
|
|
addr = addrs[j];
|
|
|
|
addrs[j] = addrs[j + 1];
|
|
|
|
addrs[j + 1] = addr;
|
|
|
|
} else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
needsort++;
|
2003-10-23 14:32:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ai = sentinel;
|
|
|
|
for (i = 0; i < naddrs; ++i) {
|
|
|
|
ai->ai_next = addrs[i].ai;
|
|
|
|
ai = ai->ai_next;
|
|
|
|
}
|
|
|
|
ai->ai_next = NULL;
|
|
|
|
free(addrs);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif /*RESOLVSORT*/
|
|
|
|
|
2000-06-20 16:33:33 +00:00
|
|
|
/*ARGSUSED*/
|
|
|
|
static int
|
2006-03-25 11:46:37 +00:00
|
|
|
_dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
|
2000-06-20 16:33:33 +00:00
|
|
|
{
|
|
|
|
struct addrinfo *ai;
|
2002-09-15 20:36:38 +00:00
|
|
|
querybuf *buf, *buf2;
|
2004-06-16 16:41:23 +00:00
|
|
|
const char *hostname;
|
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 struct addrinfo *pai;
|
2000-06-20 16:33:33 +00:00
|
|
|
struct addrinfo sentinel, *cur;
|
|
|
|
struct res_target q, q2;
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
res_state res;
|
2000-06-20 16:33:33 +00:00
|
|
|
|
2004-06-16 16:41:23 +00:00
|
|
|
hostname = va_arg(ap, char *);
|
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
|
|
|
pai = va_arg(ap, const struct addrinfo *);
|
|
|
|
|
2006-03-21 12:39:29 +00:00
|
|
|
memset(&q, 0, sizeof(q));
|
2000-06-20 16:33:33 +00:00
|
|
|
memset(&q2, 0, sizeof(q2));
|
|
|
|
memset(&sentinel, 0, sizeof(sentinel));
|
|
|
|
cur = &sentinel;
|
|
|
|
|
2002-09-15 20:36:38 +00:00
|
|
|
buf = malloc(sizeof(*buf));
|
|
|
|
if (!buf) {
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, NETDB_INTERNAL);
|
2002-09-15 20:36:38 +00:00
|
|
|
return NS_NOTFOUND;
|
|
|
|
}
|
|
|
|
buf2 = malloc(sizeof(*buf2));
|
|
|
|
if (!buf2) {
|
|
|
|
free(buf);
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, NETDB_INTERNAL);
|
2002-09-15 20:36:38 +00:00
|
|
|
return NS_NOTFOUND;
|
|
|
|
}
|
|
|
|
|
2000-06-20 16:33:33 +00:00
|
|
|
switch (pai->ai_family) {
|
|
|
|
case AF_UNSPEC:
|
2004-06-16 16:41:23 +00:00
|
|
|
q.name = hostname;
|
2000-07-05 05:07:23 +00:00
|
|
|
q.qclass = C_IN;
|
2005-01-27 08:03:46 +00:00
|
|
|
q.qtype = T_A;
|
2002-09-15 20:36:38 +00:00
|
|
|
q.answer = buf->buf;
|
|
|
|
q.anslen = sizeof(buf->buf);
|
2000-06-20 16:33:33 +00:00
|
|
|
q.next = &q2;
|
2004-06-16 16:41:23 +00:00
|
|
|
q2.name = hostname;
|
2000-07-05 05:07:23 +00:00
|
|
|
q2.qclass = C_IN;
|
2005-01-27 08:03:46 +00:00
|
|
|
q2.qtype = T_AAAA;
|
2002-09-15 20:36:38 +00:00
|
|
|
q2.answer = buf2->buf;
|
|
|
|
q2.anslen = sizeof(buf2->buf);
|
2000-06-20 16:33:33 +00:00
|
|
|
break;
|
|
|
|
case AF_INET:
|
2004-06-16 16:41:23 +00:00
|
|
|
q.name = hostname;
|
2000-07-05 05:07:23 +00:00
|
|
|
q.qclass = C_IN;
|
|
|
|
q.qtype = T_A;
|
2002-09-15 20:36:38 +00:00
|
|
|
q.answer = buf->buf;
|
|
|
|
q.anslen = sizeof(buf->buf);
|
2000-06-20 16:33:33 +00:00
|
|
|
break;
|
|
|
|
case AF_INET6:
|
2004-06-16 16:41:23 +00:00
|
|
|
q.name = hostname;
|
2000-07-05 05:07:23 +00:00
|
|
|
q.qclass = C_IN;
|
|
|
|
q.qtype = T_AAAA;
|
2002-09-15 20:36:38 +00:00
|
|
|
q.answer = buf->buf;
|
|
|
|
q.anslen = sizeof(buf->buf);
|
2000-06-20 16:33:33 +00:00
|
|
|
break;
|
|
|
|
default:
|
2002-09-15 20:36:38 +00:00
|
|
|
free(buf);
|
|
|
|
free(buf2);
|
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;
|
2000-06-20 16:33:33 +00:00
|
|
|
}
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
|
|
|
|
res = __res_state();
|
|
|
|
if ((res->options & RES_INIT) == 0 && res_ninit(res) == -1) {
|
|
|
|
RES_SET_H_ERRNO(res, NETDB_INTERNAL);
|
|
|
|
free(buf);
|
|
|
|
free(buf2);
|
|
|
|
return NS_NOTFOUND;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (res_searchN(hostname, &q, res) < 0) {
|
2002-09-15 20:36:38 +00:00
|
|
|
free(buf);
|
|
|
|
free(buf2);
|
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;
|
2002-09-15 20:36:38 +00:00
|
|
|
}
|
2005-01-27 08:03:46 +00:00
|
|
|
/* prefer IPv6 */
|
2000-06-20 16:33:33 +00:00
|
|
|
if (q.next) {
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai, res);
|
2005-01-27 08:03:46 +00:00
|
|
|
if (ai) {
|
2000-06-20 16:33:33 +00:00
|
|
|
cur->ai_next = ai;
|
2005-01-27 08:03:46 +00:00
|
|
|
while (cur && cur->ai_next)
|
|
|
|
cur = cur->ai_next;
|
|
|
|
}
|
2000-06-20 16:33:33 +00:00
|
|
|
}
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
ai = getanswer(buf, q.n, q.name, q.qtype, pai, res);
|
2005-01-27 08:03:46 +00:00
|
|
|
if (ai)
|
|
|
|
cur->ai_next = ai;
|
2002-09-15 20:36:38 +00:00
|
|
|
free(buf);
|
|
|
|
free(buf2);
|
2000-06-20 16:33:33 +00:00
|
|
|
if (sentinel.ai_next == NULL)
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
switch (res->res_h_errno) {
|
2000-06-20 16:33:33 +00:00
|
|
|
case HOST_NOT_FOUND:
|
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;
|
2000-06-20 16:33:33 +00:00
|
|
|
case TRY_AGAIN:
|
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_TRYAGAIN;
|
2000-06-20 16:33:33 +00:00
|
|
|
default:
|
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;
|
2000-06-20 16:33:33 +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 addrinfo **)rv) = sentinel.ai_next;
|
|
|
|
return NS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2005-04-04 19:45:27 +00:00
|
|
|
_sethtent(FILE **hostf)
|
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
|
|
|
{
|
2005-04-04 19:45:27 +00:00
|
|
|
if (!*hostf)
|
|
|
|
*hostf = fopen(_PATH_HOSTS, "r");
|
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
|
|
|
else
|
2005-04-04 19:45:27 +00:00
|
|
|
rewind(*hostf);
|
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 void
|
2005-04-04 19:45:27 +00:00
|
|
|
_endhtent(FILE **hostf)
|
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
|
|
|
{
|
2005-04-04 19:45:27 +00:00
|
|
|
if (*hostf) {
|
|
|
|
(void) fclose(*hostf);
|
|
|
|
*hostf = 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
|
|
|
}
|
2000-06-20 16:33:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct addrinfo *
|
2005-04-04 19:45:27 +00:00
|
|
|
_gethtent(FILE **hostf, const char *name, const struct addrinfo *pai)
|
2000-06-20 16:33:33 +00:00
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
char *cp, *tname, *cname;
|
|
|
|
struct addrinfo hints, *res0, *res;
|
|
|
|
int error;
|
|
|
|
const char *addr;
|
|
|
|
char hostbuf[8*1024];
|
|
|
|
|
2005-04-04 19:45:27 +00:00
|
|
|
if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "r")))
|
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 (NULL);
|
2002-10-25 16:24:28 +00:00
|
|
|
again:
|
2005-04-04 19:45:27 +00:00
|
|
|
if (!(p = fgets(hostbuf, sizeof hostbuf, *hostf)))
|
2000-06-20 16:33:33 +00:00
|
|
|
return (NULL);
|
|
|
|
if (*p == '#')
|
|
|
|
goto again;
|
2005-01-03 11:07:45 +00:00
|
|
|
cp = strpbrk(p, "#\n");
|
|
|
|
if (cp != NULL)
|
|
|
|
*cp = '\0';
|
2000-06-20 16:33:33 +00:00
|
|
|
if (!(cp = strpbrk(p, " \t")))
|
|
|
|
goto again;
|
|
|
|
*cp++ = '\0';
|
|
|
|
addr = p;
|
|
|
|
cname = NULL;
|
|
|
|
/* if this is not something we're looking for, skip it. */
|
|
|
|
while (cp && *cp) {
|
|
|
|
if (*cp == ' ' || *cp == '\t') {
|
|
|
|
cp++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
tname = cp;
|
|
|
|
if (cname == NULL)
|
|
|
|
cname = cp;
|
|
|
|
if ((cp = strpbrk(cp, " \t")) != NULL)
|
|
|
|
*cp++ = '\0';
|
|
|
|
if (strcasecmp(name, tname) == 0)
|
|
|
|
goto found;
|
|
|
|
}
|
|
|
|
goto again;
|
|
|
|
|
|
|
|
found:
|
2002-10-25 16:24:28 +00:00
|
|
|
/* we should not glob socktype/protocol here */
|
|
|
|
memset(&hints, 0, sizeof(hints));
|
|
|
|
hints.ai_family = pai->ai_family;
|
|
|
|
hints.ai_socktype = SOCK_DGRAM;
|
|
|
|
hints.ai_protocol = 0;
|
2000-06-20 16:33:33 +00:00
|
|
|
hints.ai_flags = AI_NUMERICHOST;
|
2002-10-25 16:24:28 +00:00
|
|
|
error = getaddrinfo(addr, "0", &hints, &res0);
|
2000-06-20 16:33:33 +00:00
|
|
|
if (error)
|
|
|
|
goto again;
|
|
|
|
#ifdef FILTER_V4MAPPED
|
|
|
|
/* XXX should check all items in the chain */
|
|
|
|
if (res0->ai_family == AF_INET6 &&
|
|
|
|
IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)res0->ai_addr)->sin6_addr)) {
|
|
|
|
freeaddrinfo(res0);
|
|
|
|
goto again;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
for (res = res0; res; res = res->ai_next) {
|
|
|
|
/* cover it up */
|
|
|
|
res->ai_flags = pai->ai_flags;
|
2002-10-25 16:24:28 +00:00
|
|
|
res->ai_socktype = pai->ai_socktype;
|
|
|
|
res->ai_protocol = pai->ai_protocol;
|
2000-06-20 16:33:33 +00:00
|
|
|
|
|
|
|
if (pai->ai_flags & AI_CANONNAME) {
|
|
|
|
if (get_canonname(pai, res, cname) != 0) {
|
|
|
|
freeaddrinfo(res0);
|
|
|
|
goto again;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*ARGSUSED*/
|
|
|
|
static int
|
2006-03-25 11:46:37 +00:00
|
|
|
_files_getaddrinfo(void *rv, void *cb_data, va_list ap)
|
2000-06-20 16:33:33 +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;
|
|
|
|
const struct addrinfo *pai;
|
2000-06-20 16:33:33 +00:00
|
|
|
struct addrinfo sentinel, *cur;
|
|
|
|
struct addrinfo *p;
|
2005-04-04 19:45:27 +00:00
|
|
|
FILE *hostf = NULL;
|
2000-06-20 16:33:33 +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, char *);
|
|
|
|
pai = va_arg(ap, struct addrinfo *);
|
|
|
|
|
|
|
|
memset(&sentinel, 0, sizeof(sentinel));
|
2000-06-20 16:33:33 +00:00
|
|
|
cur = &sentinel;
|
|
|
|
|
2005-04-04 19:45:27 +00:00
|
|
|
_sethtent(&hostf);
|
|
|
|
while ((p = _gethtent(&hostf, name, pai)) != NULL) {
|
2000-06-20 16:33:33 +00:00
|
|
|
cur->ai_next = p;
|
|
|
|
while (cur && cur->ai_next)
|
|
|
|
cur = cur->ai_next;
|
|
|
|
}
|
2005-04-04 19:45:27 +00:00
|
|
|
_endhtent(&hostf);
|
2000-06-20 16:33:33 +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 addrinfo **)rv) = sentinel.ai_next;
|
|
|
|
if (sentinel.ai_next == NULL)
|
|
|
|
return NS_NOTFOUND;
|
|
|
|
return NS_SUCCESS;
|
2000-06-20 16:33:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef YP
|
|
|
|
/*ARGSUSED*/
|
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 struct addrinfo *
|
2006-03-25 11:46:37 +00:00
|
|
|
_yphostent(char *line, const struct addrinfo *pai)
|
2000-06-20 16:33:33 +00:00
|
|
|
{
|
|
|
|
struct addrinfo sentinel, *cur;
|
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 addrinfo hints, *res, *res0;
|
2000-06-20 16:33:33 +00:00
|
|
|
int error;
|
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
|
|
|
char *p = line;
|
|
|
|
const char *addr, *canonname;
|
|
|
|
char *nextline;
|
|
|
|
char *cp;
|
2000-06-20 16:33:33 +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 = canonname = NULL;
|
|
|
|
|
|
|
|
memset(&sentinel, 0, sizeof(sentinel));
|
2000-06-20 16:33:33 +00:00
|
|
|
cur = &sentinel;
|
|
|
|
|
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
|
|
|
nextline:
|
|
|
|
/* terminate line */
|
|
|
|
cp = strchr(p, '\n');
|
|
|
|
if (cp) {
|
|
|
|
*cp++ = '\0';
|
|
|
|
nextline = cp;
|
|
|
|
} else
|
|
|
|
nextline = NULL;
|
2000-06-20 16:33:33 +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
|
|
|
cp = strpbrk(p, " \t");
|
|
|
|
if (cp == NULL) {
|
|
|
|
if (canonname == NULL)
|
|
|
|
return (NULL);
|
|
|
|
else
|
|
|
|
goto done;
|
2000-06-20 16:33:33 +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
|
|
|
*cp++ = '\0';
|
2000-06-20 16:33:33 +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 = p;
|
2000-06-20 16:33:33 +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
|
|
|
while (cp && *cp) {
|
|
|
|
if (*cp == ' ' || *cp == '\t') {
|
|
|
|
cp++;
|
2000-06-20 16:33:33 +00:00
|
|
|
continue;
|
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
|
|
|
}
|
|
|
|
if (!canonname)
|
|
|
|
canonname = cp;
|
|
|
|
if ((cp = strpbrk(cp, " \t")) != NULL)
|
|
|
|
*cp++ = '\0';
|
|
|
|
}
|
2000-06-20 16:33:33 +00:00
|
|
|
|
2003-10-24 18:43:24 +00:00
|
|
|
hints = *pai;
|
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
|
|
|
hints.ai_flags = AI_NUMERICHOST;
|
2003-10-24 18:43:24 +00:00
|
|
|
error = getaddrinfo(addr, NULL, &hints, &res0);
|
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
|
|
|
if (error == 0) {
|
|
|
|
for (res = res0; res; res = res->ai_next) {
|
|
|
|
/* cover it up */
|
|
|
|
res->ai_flags = pai->ai_flags;
|
2000-06-20 16:33:33 +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
|
|
|
if (pai->ai_flags & AI_CANONNAME)
|
|
|
|
(void)get_canonname(pai, res, canonname);
|
2000-06-20 16:33:33 +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
|
|
|
} else
|
|
|
|
res0 = NULL;
|
|
|
|
if (res0) {
|
|
|
|
cur->ai_next = res0;
|
2000-06-20 16:33:33 +00:00
|
|
|
while (cur && cur->ai_next)
|
|
|
|
cur = cur->ai_next;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
if (nextline) {
|
|
|
|
p = nextline;
|
|
|
|
goto nextline;
|
|
|
|
}
|
2000-06-20 16:33:33 +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
|
|
|
done:
|
|
|
|
return sentinel.ai_next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*ARGSUSED*/
|
|
|
|
static int
|
2006-03-25 11:46:37 +00:00
|
|
|
_yp_getaddrinfo(void *rv, void *cb_data, va_list ap)
|
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 addrinfo sentinel, *cur;
|
|
|
|
struct addrinfo *ai = NULL;
|
2005-04-05 18:25:23 +00:00
|
|
|
char *ypbuf;
|
|
|
|
int ypbuflen, r;
|
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;
|
|
|
|
const struct addrinfo *pai;
|
2005-04-05 18:25:23 +00:00
|
|
|
char *ypdomain;
|
|
|
|
|
|
|
|
if (_yp_check(&ypdomain) == 0)
|
|
|
|
return NS_UNAVAIL;
|
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, char *);
|
|
|
|
pai = va_arg(ap, const struct addrinfo *);
|
|
|
|
|
|
|
|
memset(&sentinel, 0, sizeof(sentinel));
|
|
|
|
cur = &sentinel;
|
|
|
|
|
|
|
|
/* hosts.byname is only for IPv4 (Solaris8) */
|
|
|
|
if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) {
|
2005-04-05 18:25:23 +00:00
|
|
|
r = yp_match(ypdomain, "hosts.byname", name,
|
|
|
|
(int)strlen(name), &ypbuf, &ypbuflen);
|
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
|
|
|
if (r == 0) {
|
|
|
|
struct addrinfo ai4;
|
|
|
|
|
|
|
|
ai4 = *pai;
|
|
|
|
ai4.ai_family = AF_INET;
|
2005-04-05 18:25:23 +00:00
|
|
|
ai = _yphostent(ypbuf, &ai4);
|
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
|
|
|
if (ai) {
|
|
|
|
cur->ai_next = ai;
|
|
|
|
while (cur && cur->ai_next)
|
|
|
|
cur = cur->ai_next;
|
|
|
|
}
|
2005-05-13 17:30:03 +00:00
|
|
|
free(ypbuf);
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ipnodes.byname can hold both IPv4/v6 */
|
2005-04-05 18:25:23 +00:00
|
|
|
r = yp_match(ypdomain, "ipnodes.byname", name,
|
|
|
|
(int)strlen(name), &ypbuf, &ypbuflen);
|
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
|
|
|
if (r == 0) {
|
2005-04-05 18:25:23 +00:00
|
|
|
ai = _yphostent(ypbuf, pai);
|
|
|
|
if (ai)
|
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
|
|
|
cur->ai_next = ai;
|
2005-04-05 18:25:23 +00:00
|
|
|
free(ypbuf);
|
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
|
|
|
}
|
|
|
|
|
|
|
|
if (sentinel.ai_next == NULL) {
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(__res_state(), HOST_NOT_FOUND);
|
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;
|
|
|
|
}
|
|
|
|
*((struct addrinfo **)rv) = sentinel.ai_next;
|
|
|
|
return NS_SUCCESS;
|
2000-06-20 16:33:33 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* resolver logic */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Formulate a normal query, send, and await answer.
|
|
|
|
* Returned answer is placed in supplied buffer "answer".
|
|
|
|
* Perform preliminary check of answer, returning success only
|
|
|
|
* if no error is indicated and the answer count is nonzero.
|
|
|
|
* Return the size of the response on success, -1 on error.
|
|
|
|
* Error number is left in h_errno.
|
|
|
|
*
|
|
|
|
* Caller must parse answer and determine whether it answers the question.
|
|
|
|
*/
|
|
|
|
static int
|
2006-03-25 11:46:37 +00:00
|
|
|
res_queryN(const char *name, struct res_target *target, res_state res)
|
2000-06-20 16:33:33 +00:00
|
|
|
{
|
2002-09-15 20:36:38 +00:00
|
|
|
u_char *buf;
|
2000-06-20 16:33:33 +00:00
|
|
|
HEADER *hp;
|
|
|
|
int n;
|
2006-03-28 07:42:57 +00:00
|
|
|
u_int oflags;
|
2000-06-20 16:33:33 +00:00
|
|
|
struct res_target *t;
|
|
|
|
int rcode;
|
|
|
|
int ancount;
|
|
|
|
|
|
|
|
rcode = NOERROR;
|
|
|
|
ancount = 0;
|
|
|
|
|
2002-09-15 20:36:38 +00:00
|
|
|
buf = malloc(MAXPACKET);
|
|
|
|
if (!buf) {
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, NETDB_INTERNAL);
|
2002-09-15 20:36:38 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2000-06-20 16:33:33 +00:00
|
|
|
for (t = target; t; t = t->next) {
|
|
|
|
int class, type;
|
|
|
|
u_char *answer;
|
|
|
|
int anslen;
|
|
|
|
|
|
|
|
hp = (HEADER *)(void *)t->answer;
|
|
|
|
|
|
|
|
/* make it easier... */
|
2000-07-05 05:07:23 +00:00
|
|
|
class = t->qclass;
|
|
|
|
type = t->qtype;
|
2000-06-20 16:33:33 +00:00
|
|
|
answer = t->answer;
|
|
|
|
anslen = t->anslen;
|
2006-03-28 07:42:57 +00:00
|
|
|
|
|
|
|
oflags = res->_flags;
|
|
|
|
|
|
|
|
again:
|
|
|
|
hp->rcode = NOERROR; /* default */
|
|
|
|
|
2000-06-20 16:33:33 +00:00
|
|
|
#ifdef DEBUG
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
if (res->options & RES_DEBUG)
|
2000-06-20 16:33:33 +00:00
|
|
|
printf(";; res_query(%s, %d, %d)\n", name, class, type);
|
|
|
|
#endif
|
|
|
|
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL,
|
2002-09-15 20:36:38 +00:00
|
|
|
buf, MAXPACKET);
|
2006-03-28 07:42:57 +00:00
|
|
|
if (n > 0 && (res->_flags & RES_F_EDNS0ERR) == 0 &&
|
|
|
|
(res->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0U)
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
n = res_nopt(res, n, buf, MAXPACKET, anslen);
|
2000-06-20 16:33:33 +00:00
|
|
|
if (n <= 0) {
|
|
|
|
#ifdef DEBUG
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
if (res->options & RES_DEBUG)
|
2000-06-20 16:33:33 +00:00
|
|
|
printf(";; res_query: mkquery failed\n");
|
|
|
|
#endif
|
2002-09-15 20:36:38 +00:00
|
|
|
free(buf);
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, NO_RECOVERY);
|
2000-06-20 16:33:33 +00:00
|
|
|
return (n);
|
|
|
|
}
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
n = res_nsend(res, buf, n, answer, anslen);
|
2000-06-20 16:33:33 +00:00
|
|
|
if (n < 0) {
|
2006-03-28 07:42:57 +00:00
|
|
|
/*
|
|
|
|
* if the query choked with EDNS0, retry
|
|
|
|
* without EDNS0
|
|
|
|
*/
|
|
|
|
if ((res->options & (RES_USE_EDNS0|RES_USE_DNSSEC))
|
|
|
|
!= 0U &&
|
|
|
|
((oflags ^ res->_flags) & RES_F_EDNS0ERR) != 0) {
|
|
|
|
res->_flags |= RES_F_EDNS0ERR;
|
|
|
|
if (res->options & RES_DEBUG)
|
|
|
|
printf(";; res_nquery: retry without EDNS0\n");
|
|
|
|
goto again;
|
|
|
|
}
|
|
|
|
rcode = hp->rcode; /* record most recent error */
|
2000-06-20 16:33:33 +00:00
|
|
|
#ifdef DEBUG
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
if (res->options & RES_DEBUG)
|
2000-06-20 16:33:33 +00:00
|
|
|
printf(";; res_query: send error\n");
|
|
|
|
#endif
|
2006-03-28 07:42:57 +00:00
|
|
|
continue;
|
2000-06-20 16:33:33 +00:00
|
|
|
}
|
|
|
|
|
2006-03-24 04:49:30 +00:00
|
|
|
if (n > anslen)
|
2002-09-15 16:51:09 +00:00
|
|
|
hp->rcode = FORMERR; /* XXX not very informative */
|
2006-03-28 07:42:57 +00:00
|
|
|
if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
|
2000-06-20 16:33:33 +00:00
|
|
|
rcode = hp->rcode; /* record most recent error */
|
|
|
|
#ifdef DEBUG
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
if (res->options & RES_DEBUG)
|
2002-10-25 16:24:28 +00:00
|
|
|
printf(";; rcode = %u, ancount=%u\n", hp->rcode,
|
2000-06-20 16:33:33 +00:00
|
|
|
ntohs(hp->ancount));
|
|
|
|
#endif
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
ancount += ntohs(hp->ancount);
|
|
|
|
|
|
|
|
t->n = n;
|
|
|
|
}
|
|
|
|
|
2002-09-15 20:36:38 +00:00
|
|
|
free(buf);
|
|
|
|
|
2000-06-20 16:33:33 +00:00
|
|
|
if (ancount == 0) {
|
|
|
|
switch (rcode) {
|
|
|
|
case NXDOMAIN:
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, HOST_NOT_FOUND);
|
2000-06-20 16:33:33 +00:00
|
|
|
break;
|
|
|
|
case SERVFAIL:
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, TRY_AGAIN);
|
2000-06-20 16:33:33 +00:00
|
|
|
break;
|
|
|
|
case NOERROR:
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, NO_DATA);
|
2000-06-20 16:33:33 +00:00
|
|
|
break;
|
|
|
|
case FORMERR:
|
|
|
|
case NOTIMP:
|
|
|
|
case REFUSED:
|
|
|
|
default:
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, NO_RECOVERY);
|
2000-06-20 16:33:33 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
return (ancount);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Formulate a normal query, send, and retrieve answer in supplied buffer.
|
|
|
|
* Return the size of the response on success, -1 on error.
|
|
|
|
* If enabled, implement search rules until answer or unrecoverable failure
|
|
|
|
* is detected. Error code, if any, is left in h_errno.
|
|
|
|
*/
|
|
|
|
static int
|
2006-03-25 11:46:37 +00:00
|
|
|
res_searchN(const char *name, struct res_target *target, res_state res)
|
2000-06-20 16:33:33 +00:00
|
|
|
{
|
|
|
|
const char *cp, * const *domain;
|
|
|
|
HEADER *hp = (HEADER *)(void *)target->answer; /*XXX*/
|
|
|
|
u_int dots;
|
|
|
|
int trailing_dot, ret, saved_herrno;
|
2006-02-24 16:53:42 +00:00
|
|
|
int got_nodata = 0, got_servfail = 0, root_on_list = 0;
|
|
|
|
int tried_as_is = 0;
|
|
|
|
int searched = 0;
|
2005-04-15 14:42:29 +00:00
|
|
|
char abuf[MAXDNAME];
|
2000-06-20 16:33:33 +00:00
|
|
|
|
|
|
|
errno = 0;
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, HOST_NOT_FOUND); /* default, if we never query */
|
2000-06-20 16:33:33 +00:00
|
|
|
dots = 0;
|
|
|
|
for (cp = name; *cp; cp++)
|
|
|
|
dots += (*cp == '.');
|
|
|
|
trailing_dot = 0;
|
|
|
|
if (cp > name && *--cp == '.')
|
|
|
|
trailing_dot++;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* if there aren't any dots, it could be a user-level alias
|
|
|
|
*/
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
if (!dots &&
|
|
|
|
(cp = res_hostalias(res, name, abuf, sizeof(abuf))) != NULL)
|
|
|
|
return (res_queryN(cp, target, res));
|
2000-06-20 16:33:33 +00:00
|
|
|
|
|
|
|
/*
|
2006-02-24 16:53:42 +00:00
|
|
|
* If there are enough dots in the name, let's just give it a
|
|
|
|
* try 'as is'. The threshold can be set with the "ndots" option.
|
|
|
|
* Also, query 'as is', if there is a trailing dot in the name.
|
2000-06-20 16:33:33 +00:00
|
|
|
*/
|
|
|
|
saved_herrno = -1;
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
if (dots >= res->ndots || trailing_dot) {
|
|
|
|
ret = res_querydomainN(name, NULL, target, res);
|
2006-02-24 16:53:42 +00:00
|
|
|
if (ret > 0 || trailing_dot)
|
2000-06-20 16:33:33 +00:00
|
|
|
return (ret);
|
2006-03-01 15:53:49 +00:00
|
|
|
if (errno == ECONNREFUSED) {
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, TRY_AGAIN);
|
2006-03-01 15:53:49 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
switch (res->res_h_errno) {
|
2006-03-01 15:53:49 +00:00
|
|
|
case NO_DATA:
|
|
|
|
case HOST_NOT_FOUND:
|
|
|
|
break;
|
2006-03-24 13:30:10 +00:00
|
|
|
case TRY_AGAIN:
|
|
|
|
if (hp->rcode == SERVFAIL)
|
|
|
|
break;
|
|
|
|
/* FALLTHROUGH */
|
2006-03-01 15:53:49 +00:00
|
|
|
default:
|
|
|
|
return (-1);
|
|
|
|
}
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
saved_herrno = res->res_h_errno;
|
2000-06-20 16:33:33 +00:00
|
|
|
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.
|
|
|
|
*/
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
if ((!dots && (res->options & RES_DEFNAMES)) ||
|
|
|
|
(dots && !trailing_dot && (res->options & RES_DNSRCH))) {
|
2000-06-20 16:33:33 +00:00
|
|
|
int done = 0;
|
|
|
|
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
for (domain = (const char * const *)res->dnsrch;
|
2000-06-20 16:33:33 +00:00
|
|
|
*domain && !done;
|
|
|
|
domain++) {
|
2006-02-24 16:53:42 +00:00
|
|
|
searched = 1;
|
|
|
|
|
|
|
|
if (domain[0][0] == '\0' ||
|
|
|
|
(domain[0][0] == '.' && domain[0][1] == '\0'))
|
|
|
|
root_on_list++;
|
|
|
|
|
|
|
|
if (root_on_list && tried_as_is)
|
|
|
|
continue;
|
2000-06-20 16:33:33 +00:00
|
|
|
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
ret = res_querydomainN(name, *domain, target, res);
|
2000-06-20 16:33:33 +00:00
|
|
|
if (ret > 0)
|
|
|
|
return (ret);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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) {
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, TRY_AGAIN);
|
2000-06-20 16:33:33 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
switch (res->res_h_errno) {
|
2000-06-20 16:33:33 +00:00
|
|
|
case NO_DATA:
|
|
|
|
got_nodata++;
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
case HOST_NOT_FOUND:
|
|
|
|
/* keep trying */
|
|
|
|
break;
|
|
|
|
case TRY_AGAIN:
|
2006-03-24 13:30:10 +00:00
|
|
|
got_servfail++;
|
2000-06-20 16:33:33 +00:00
|
|
|
if (hp->rcode == SERVFAIL) {
|
|
|
|
/* try next search element, if any */
|
|
|
|
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.
|
|
|
|
*/
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
if (!(res->options & RES_DNSRCH))
|
2000-06-20 16:33:33 +00:00
|
|
|
done++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
switch (res->res_h_errno) {
|
2006-03-01 15:53:49 +00:00
|
|
|
case NO_DATA:
|
|
|
|
case HOST_NOT_FOUND:
|
|
|
|
break;
|
2006-03-24 13:30:10 +00:00
|
|
|
case TRY_AGAIN:
|
|
|
|
if (hp->rcode == SERVFAIL)
|
|
|
|
break;
|
|
|
|
/* FALLTHROUGH */
|
2006-03-01 15:53:49 +00:00
|
|
|
default:
|
|
|
|
goto giveup;
|
|
|
|
}
|
|
|
|
|
2000-06-20 16:33:33 +00:00
|
|
|
/*
|
2006-02-24 16:53:42 +00:00
|
|
|
* If the query has not already been tried as is then try it
|
|
|
|
* unless RES_NOTLDQUERY is set and there were no dots.
|
2000-06-20 16:33:33 +00:00
|
|
|
*/
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
if ((dots || !searched || !(res->options & RES_NOTLDQUERY)) &&
|
2006-02-24 16:53:42 +00:00
|
|
|
!(tried_as_is || root_on_list)) {
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
ret = res_querydomainN(name, NULL, target, res);
|
2000-06-20 16:33:33 +00:00
|
|
|
if (ret > 0)
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2006-03-01 15:53:49 +00:00
|
|
|
giveup:
|
2000-06-20 16:33:33 +00:00
|
|
|
if (saved_herrno != -1)
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, saved_herrno);
|
2000-06-20 16:33:33 +00:00
|
|
|
else if (got_nodata)
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, NO_DATA);
|
2000-06-20 16:33:33 +00:00
|
|
|
else if (got_servfail)
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, TRY_AGAIN);
|
2000-06-20 16:33:33 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Perform a call on res_query on the concatenation of name and domain,
|
|
|
|
* removing a trailing dot from name if domain is NULL.
|
|
|
|
*/
|
|
|
|
static int
|
2006-03-25 11:46:37 +00:00
|
|
|
res_querydomainN(const char *name, const char *domain,
|
|
|
|
struct res_target *target, res_state res)
|
2000-06-20 16:33:33 +00:00
|
|
|
{
|
|
|
|
char nbuf[MAXDNAME];
|
|
|
|
const char *longname = nbuf;
|
|
|
|
size_t n, d;
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
if (res->options & RES_DEBUG)
|
2000-06-20 16:33:33 +00:00
|
|
|
printf(";; res_querydomain(%s, %s)\n",
|
|
|
|
name, domain?domain:"<Nil>");
|
|
|
|
#endif
|
|
|
|
if (domain == NULL) {
|
|
|
|
/*
|
|
|
|
* Check for trailing '.';
|
|
|
|
* copy without '.' if present.
|
|
|
|
*/
|
|
|
|
n = strlen(name);
|
|
|
|
if (n >= MAXDNAME) {
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, NO_RECOVERY);
|
2000-06-20 16:33:33 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
if (n > 0 && name[--n] == '.') {
|
|
|
|
strncpy(nbuf, name, n);
|
|
|
|
nbuf[n] = '\0';
|
|
|
|
} else
|
|
|
|
longname = name;
|
|
|
|
} else {
|
|
|
|
n = strlen(name);
|
|
|
|
d = strlen(domain);
|
|
|
|
if (n + d + 1 >= MAXDNAME) {
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
RES_SET_H_ERRNO(res, NO_RECOVERY);
|
2000-06-20 16:33:33 +00:00
|
|
|
return (-1);
|
|
|
|
}
|
2002-10-25 16:24:28 +00:00
|
|
|
snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
|
2000-06-20 16:33:33 +00:00
|
|
|
}
|
Update the resolver in libc to BIND9's one.
Since, res_sendsigned(3) and the friends use MD5 functions, it is
hard to include them without having MD5 functions in libc. So,
res_sendsigned(3) is not merged into libc.
Since, res_update(3) in BIND9 is not binary compatible with our
res_update(3), res_update(3) is leaved as is, except some
necessary modifications.
The res_update(3) and the friends are not essential part of the
resolver. They are not defined in resolv.h but defined in
res_update.h separately in BIND9. Further, they are not called from
our tree. So, I hide them from our resolv.h, but leave them only
for binary backward compatibility (perhaps, no one calls them).
Since, struct __res_state_ext is not exposed in BIND9, I hide it
from our resolv.h. And, global variable _res_ext is removed. It
breaks binary backward compatibility. But, since it is not used from
outside of our libc, I think it is safe.
Reviewed by: arch@ (no objection)
2006-03-21 16:11:11 +00:00
|
|
|
return (res_queryN(longname, target, res));
|
2000-06-20 16:33:33 +00:00
|
|
|
}
|