genericopenlibs/openenvcore/libc/src/net/getaddrinfo.c
changeset 0 e4d67989cc36
child 54 4332f0f7be53
child 63 a117ad66e027
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 /*	$KAME: getaddrinfo.c,v 1.15 2000/07/09 04:37:24 itojun Exp $	*/
       
     2  
       
     3 /*
       
     4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
       
     5  * All rights reserved.
       
     6  *
       
     7  * Redistribution and use in source and binary forms, with or without
       
     8  * modification, are permitted provided that the following conditions
       
     9  * are met:
       
    10  * 1. Redistributions of source code must retain the above copyright
       
    11  *    notice, this list of conditions and the following disclaimer.
       
    12  * 2. Redistributions in binary form must reproduce the above copyright
       
    13  *    notice, this list of conditions and the following disclaimer in the
       
    14  *    documentation and/or other materials provided with the distribution.
       
    15  * 3. Neither the name of the project nor the names of its contributors
       
    16  *    may be used to endorse or promote products derived from this software
       
    17  *    without specific prior written permission.
       
    18  *
       
    19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
       
    20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
       
    22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
       
    23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
       
    24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
       
    25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
       
    26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
       
    27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
       
    28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
       
    29  * SUCH DAMAGE.
       
    30  *
       
    31  * Portions Copyright (c) 2006-2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. 
       
    32  */
       
    33 
       
    34 /*
       
    35  * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
       
    36  *
       
    37  * Issues to be discussed:
       
    38  * - Thread safe-ness must be checked.
       
    39  * - Return values.  There are nonstandard return values defined and used
       
    40  *   in the source code.  This is because RFC2553 is silent about which error
       
    41  *   code must be returned for which situation.
       
    42  * - freeaddrinfo(NULL).  RFC2553 is silent about it.  XNET 5.2 says it is
       
    43  *   invalid.  current code - SEGV on freeaddrinfo(NULL)
       
    44  *
       
    45  * Note:
       
    46  * - The code filters out AFs that are not supported by the kernel,
       
    47  *   when globbing NULL hostname (to loopback, or wildcard).  Is it the right
       
    48  *   thing to do?  What is the relationship with post-RFC2553 AI_ADDRCONFIG
       
    49  *   in ai_flags?
       
    50  * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
       
    51  *   (1) what should we do against numeric hostname (2) what should we do
       
    52  *   against NULL hostname (3) what is AI_ADDRCONFIG itself.  AF not ready?
       
    53  *   non-loopback address configured?  global address configured?
       
    54  *
       
    55  * OS specific notes for netbsd/openbsd/freebsd4/bsdi4:
       
    56  * - To avoid search order issue, we have a big amount of code duplicate
       
    57  *   from gethnamaddr.c and some other places.  The issues that there's no
       
    58  *   lower layer function to lookup "IPv4 or IPv6" record.  Calling
       
    59  *   gethostbyname2 from getaddrinfo will end up in wrong search order, as
       
    60  *   presented above.
       
    61  *
       
    62  * OS specific notes for freebsd4:
       
    63  * - FreeBSD supported $GAI.  The code does not.
       
    64  * - FreeBSD allowed classful IPv4 numeric (127.1), the code does not.
       
    65  */
       
    66 
       
    67 #include <sys/cdefs.h>
       
    68 __FBSDID("$FreeBSD: src/lib/libc/net/getaddrinfo.c,v 1.69.2.1 2005/07/22 20:17:30 ume Exp $");
       
    69 
       
    70 #include <unistd.h>
       
    71 #include <sys/socket.h>
       
    72 #include <net/if.h>
       
    73 #include "namespace.h"
       
    74 #include <sys/types.h>
       
    75 #include <sys/param.h>
       
    76 #include <netinet/in.h>
       
    77 #include <sys/queue.h>
       
    78 #ifdef INET6
       
    79 #ifndef __SYMBIAN32__
       
    80 #include <net/if_var.h>
       
    81 #include <sys/sysctl.h>
       
    82 #endif //__SYMBIAN32__
       
    83 #include <sys/ioctl.h>
       
    84 #include <netinet6/in6_var.h>	/* XXX */
       
    85 #endif
       
    86 #include <arpa/inet.h>
       
    87 #include <arpa/nameser.h>
       
    88 #ifndef __SYMBIAN32__
       
    89 #include <rpc/rpc.h>
       
    90 #include <rpcsvc/yp_prot.h>
       
    91 #include <rpcsvc/ypclnt.h>
       
    92 #endif //__SYMBIAN32__
       
    93 #include <netdb.h>
       
    94 #include <resolv.h>
       
    95 #include <string.h>
       
    96 #include <stdlib.h>
       
    97 #include <stddef.h>
       
    98 #include <ctype.h>
       
    99 #include <stdio.h>
       
   100 #include <errno.h>
       
   101 
       
   102 #include "res_config.h"
       
   103 
       
   104 #ifdef DEBUG
       
   105 #include "sys/syslog.h"
       
   106 #endif
       
   107 
       
   108 #include <stdarg.h>
       
   109 #include <nsswitch.h>
       
   110 #include "un-namespace.h"
       
   111 #include "libc_private.h"
       
   112 
       
   113 #ifdef __SYMBIAN32__
       
   114 #if defined(__KAME__)
       
   115 #undef __KAME__
       
   116 #endif
       
   117 #endif
       
   118 
       
   119 #if defined(__KAME__) && defined(INET6)
       
   120 # define FAITH
       
   121 #endif
       
   122 
       
   123 #define SUCCESS 0
       
   124 #define ANY 0
       
   125 #define YES 1
       
   126 #define NO  0
       
   127 
       
   128 static const char in_addrany[] = { 0, 0, 0, 0 };
       
   129 static const char in_loopback[] = { 127, 0, 0, 1 };
       
   130 #ifdef INET6
       
   131 static const char in6_addrany[] = {
       
   132 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
       
   133 };
       
   134 static const char in6_loopback[] = {
       
   135 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
       
   136 };
       
   137 #endif
       
   138 
       
   139 struct policyqueue {
       
   140 	TAILQ_ENTRY(policyqueue) pc_entry;
       
   141 #ifdef INET6
       
   142 	struct in6_addrpolicy pc_policy;
       
   143 #endif
       
   144 };
       
   145 TAILQ_HEAD(policyhead, policyqueue);
       
   146 
       
   147 static const struct afd {
       
   148 	int a_af;
       
   149 	int a_addrlen;
       
   150 	socklen_t a_socklen;
       
   151 	int a_off;
       
   152 	const char *a_addrany;
       
   153 	const char *a_loopback;
       
   154 	int a_scoped;
       
   155 } afdl [] = {
       
   156 #ifdef INET6
       
   157 #define	N_INET6 0
       
   158 	{PF_INET6, sizeof(struct in6_addr),
       
   159 	 sizeof(struct sockaddr_in6),
       
   160 	 offsetof(struct sockaddr_in6, sin6_addr),
       
   161 	 in6_addrany, in6_loopback, 1},
       
   162 #define	N_INET 1
       
   163 #else
       
   164 #define	N_INET 0
       
   165 #endif
       
   166 	{PF_INET, sizeof(struct in_addr),
       
   167 	 sizeof(struct sockaddr_in),
       
   168 	 offsetof(struct sockaddr_in, sin_addr),
       
   169 	 in_addrany, in_loopback, 0},
       
   170 	{0, 0, 0, 0, NULL, NULL, 0},
       
   171 };
       
   172 
       
   173 struct explore {
       
   174 	int e_af;
       
   175 	int e_socktype;
       
   176 	int e_protocol;
       
   177 	const char *e_protostr;
       
   178 	int e_wild;
       
   179 #define WILD_AF(ex)		((ex)->e_wild & 0x01)
       
   180 #define WILD_SOCKTYPE(ex)	((ex)->e_wild & 0x02)
       
   181 #define WILD_PROTOCOL(ex)	((ex)->e_wild & 0x04)
       
   182 };
       
   183 
       
   184 static const struct explore explore[] = {
       
   185 #if 0
       
   186 	{ PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
       
   187 #endif
       
   188 #ifdef INET6
       
   189 	{ PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
       
   190 	{ PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
       
   191 	{ PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
       
   192 #endif
       
   193 	{ PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
       
   194 	{ PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
       
   195 	{ PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
       
   196 	{ PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
       
   197 	{ PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
       
   198 	{ PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 },
       
   199 	{ -1, 0, 0, NULL, 0 },
       
   200 };
       
   201 
       
   202 #ifdef INET6
       
   203 #define PTON_MAX	16
       
   204 #else
       
   205 #define PTON_MAX	4
       
   206 #endif
       
   207 
       
   208 #define AIO_SRCFLAG_DEPRECATED	0x1
       
   209 
       
   210 struct ai_order {
       
   211 	union {
       
   212 		struct sockaddr_storage aiou_ss;
       
   213 		struct sockaddr aiou_sa;
       
   214 	} aio_src_un;
       
   215 #define aio_srcsa aio_src_un.aiou_sa
       
   216 	u_int32_t aio_srcflag;
       
   217 	int aio_srcscope;
       
   218 	int aio_dstscope;
       
   219 	struct policyqueue *aio_srcpolicy;
       
   220 	struct policyqueue *aio_dstpolicy;
       
   221 	struct addrinfo *aio_ai;
       
   222 	int aio_matchlen;
       
   223 };
       
   224 
       
   225 #ifndef __SYMBIAN32__
       
   226 static const ns_src default_dns_files[] = {
       
   227 	{ NSSRC_FILES, 	NS_SUCCESS },
       
   228 	{ NSSRC_DNS, 	NS_SUCCESS },
       
   229 	{ 0 }
       
   230 };
       
   231 #endif//__SYMBIAN32__
       
   232 
       
   233 struct res_target {
       
   234 	struct res_target *next;
       
   235 	const char *name;	/* domain name */
       
   236 	int qclass, qtype;	/* class and type of query */
       
   237 	u_char *answer;		/* buffer to put answer */
       
   238 	int anslen;		/* size of answer buffer */
       
   239 	int n;			/* result length */
       
   240 };
       
   241 
       
   242 #define MAXPACKET	(64*1024)
       
   243 
       
   244 typedef union {
       
   245 	HEADER hdr;
       
   246 	u_char buf[MAXPACKET];
       
   247 } querybuf;
       
   248 
       
   249 static int str2number(const char *);
       
   250 static int explore_null(const struct addrinfo *,
       
   251 	const char *, struct addrinfo **);
       
   252 static int explore_numeric(const struct addrinfo *, const char *,
       
   253 	const char *, struct addrinfo **, const char *);
       
   254 static int explore_numeric_scope(const struct addrinfo *, const char *,
       
   255 	const char *, struct addrinfo **);
       
   256 static int get_canonname(const struct addrinfo *,
       
   257 	struct addrinfo *, const char *);
       
   258 static struct addrinfo *get_ai(const struct addrinfo *,
       
   259 	const struct afd *, const char *);
       
   260 static int get_portmatch(const struct addrinfo *, const char *);
       
   261 static int get_port(struct addrinfo *, const char *, int);
       
   262 static const struct afd *find_afd(int);
       
   263 static int addrconfig(struct addrinfo *);
       
   264 static void set_source(struct ai_order *, struct policyhead *);
       
   265 static int comp_dst(const void *, const void *);
       
   266 #ifdef INET6
       
   267 static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *);
       
   268 #endif
       
   269 static int gai_addr2scopetype(struct sockaddr *);
       
   270 #ifndef __SYMBIAN32__
       
   271 static int explore_fqdn(const struct addrinfo *, const char *,
       
   272 	const char *, struct addrinfo **);
       
   273 #endif //__SYMBIAN32__
       
   274 static int reorder(struct addrinfo *);
       
   275 static int get_addrselectpolicy(struct policyhead *);
       
   276 static void free_addrselectpolicy(struct policyhead *);
       
   277 static struct policyqueue *match_addrselectpolicy(struct sockaddr *,
       
   278 	struct policyhead *);
       
   279 static int matchlen(struct sockaddr *, struct sockaddr *);
       
   280 
       
   281 #ifndef __SYMBIAN32__
       
   282 static struct addrinfo *getanswer(const querybuf *, int, const char *, int,
       
   283 	const struct addrinfo *);
       
   284 #endif //__SYMBIAN32__
       
   285 	
       
   286 #if defined(RESOLVSORT)
       
   287 static int addr4sort(struct addrinfo *);
       
   288 #endif
       
   289 #ifndef __SYMBIAN32__
       
   290 static int _dns_getaddrinfo(void *, void *, va_list);
       
   291 static void _sethtent(FILE **);
       
   292 static void _endhtent(FILE **);
       
   293 #endif /* __SYMBIAN32__ */
       
   294 #ifndef __SYMBIAN32__
       
   295 static struct addrinfo *_gethtent(FILE **, const char *,
       
   296 	const struct addrinfo *);
       
   297 static int _files_getaddrinfo(void *, void *, va_list);
       
   298 #endif // __SYMBIAN32__	
       
   299 #ifdef YP
       
   300 static struct addrinfo *_yphostent(char *, const struct addrinfo *);
       
   301 static int _yp_getaddrinfo(void *, void *, va_list);
       
   302 #endif
       
   303 
       
   304 #ifndef __SYMBIAN32__
       
   305 static int res_queryN(const char *, struct res_target *);
       
   306 static int res_searchN(const char *, struct res_target *);
       
   307 static int res_querydomainN(const char *, const char *,
       
   308 	struct res_target *);
       
   309 #endif //__SYMBIAN32__
       
   310 #ifdef __SYMBIAN32__
       
   311 extern int getaddrinfo_private(const char*, const struct addrinfo*, struct addrinfo**);
       
   312 extern void freeaddrinfo_private(struct addrinfo*);
       
   313 static long int explore_hostname( struct addrinfo *, const char *,
       
   314 	const char *, struct addrinfo **, const struct addrinfo *);
       
   315 #endif
       
   316 /* XXX macros that make external reference is BAD. */
       
   317 
       
   318 #define GET_AI(ai, afd, addr) \
       
   319 do { \
       
   320 	/* external reference: pai, error, and label free */ \
       
   321 	(ai) = get_ai(pai, (afd), (addr)); \
       
   322 	if ((ai) == NULL) { \
       
   323 		error = EAI_MEMORY; \
       
   324 		goto free; \
       
   325 	} \
       
   326 } while (/*CONSTCOND*/0)
       
   327 
       
   328 #define GET_PORT(ai, serv) \
       
   329 do { \
       
   330 	/* external reference: error and label free */ \
       
   331 	error = get_port((ai), (serv), 0); \
       
   332 	if (error != 0) \
       
   333 		goto free; \
       
   334 } while (/*CONSTCOND*/0)
       
   335 
       
   336 #define GET_CANONNAME(ai, str) \
       
   337 do { \
       
   338 	/* external reference: pai, error and label free */ \
       
   339 	error = get_canonname(pai, (ai), (str)); \
       
   340 	if (error != 0) \
       
   341 		goto free; \
       
   342 } while (/*CONSTCOND*/0)
       
   343 
       
   344 #define ERR(err) \
       
   345 do { \
       
   346 	/* external reference: error, and label bad */ \
       
   347 	error = (err); \
       
   348 	goto bad; \
       
   349 	/*NOTREACHED*/ \
       
   350 } while (/*CONSTCOND*/0)
       
   351 
       
   352 #define MATCH_FAMILY(x, y, w) \
       
   353 	((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
       
   354 #define MATCH(x, y, w) \
       
   355 	((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
       
   356 
       
   357 EXPORT_C void
       
   358 freeaddrinfo(ai)
       
   359 	struct addrinfo *ai;
       
   360 {
       
   361 	struct addrinfo *next;
       
   362 	
       
   363 	if(ai == NULL) 
       
   364 	{
       
   365 		return ;
       
   366 	}
       
   367 	
       
   368 	
       
   369 	do {
       
   370 		next = ai->ai_next;
       
   371 		if (ai->ai_canonname)
       
   372 			free(ai->ai_canonname);
       
   373 		/* no need to free(ai->ai_addr) */
       
   374 		free(ai);
       
   375 		ai = next;
       
   376 	} while (ai);
       
   377 }
       
   378 
       
   379 static int
       
   380 str2number(p)
       
   381 	const char *p;
       
   382 {
       
   383 	char *ep;
       
   384 	unsigned long v;
       
   385 
       
   386 	if (*p == '\0')
       
   387 		return -1;
       
   388 	ep = NULL;
       
   389 	errno = 0;
       
   390 	v = strtoul(p, &ep, 10);
       
   391 	if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX)
       
   392 		return v;
       
   393 	else
       
   394 		return -1;
       
   395 }
       
   396 
       
   397 EXPORT_C int
       
   398 getaddrinfo(hostname, servname, hints, res)
       
   399 	const char *hostname, *servname;
       
   400 	const struct addrinfo *hints;
       
   401 	struct addrinfo **res;
       
   402 {
       
   403 	struct addrinfo sentinel;
       
   404 	struct addrinfo *cur;
       
   405 	int error = 0;
       
   406 	struct addrinfo ai;
       
   407 	struct addrinfo ai0;
       
   408 	struct addrinfo *pai;
       
   409 	const struct explore *ex;
       
   410     int numeric = 0;
       
   411 	memset(&sentinel, 0, sizeof(sentinel));
       
   412 	cur = &sentinel;
       
   413 	pai = &ai;
       
   414 	pai->ai_flags = 0;
       
   415 	pai->ai_family = PF_UNSPEC;
       
   416 	pai->ai_socktype = ANY;
       
   417 	pai->ai_protocol = ANY;
       
   418 	pai->ai_addrlen = 0;
       
   419 	pai->ai_canonname = NULL;
       
   420 	pai->ai_addr = NULL;
       
   421 	pai->ai_next = NULL;
       
   422 	if (hostname == NULL && servname == NULL)
       
   423 		return EAI_NONAME;
       
   424 	if (hints) {
       
   425 		/* error check for hints */
       
   426 		if (hints->ai_addrlen || hints->ai_canonname ||
       
   427 		    hints->ai_addr || hints->ai_next)
       
   428 			ERR(EAI_BADHINTS); /* xxx */
       
   429 		if (hints->ai_flags & ~AI_MASK)
       
   430 			ERR(EAI_BADFLAGS);
       
   431 		switch (hints->ai_family) {
       
   432 		case PF_UNSPEC:
       
   433 		case PF_INET:
       
   434 #ifdef INET6
       
   435 		case PF_INET6:
       
   436 #endif
       
   437 			break;
       
   438 		default:
       
   439 			ERR(EAI_FAMILY);
       
   440 		}
       
   441 		memcpy(pai, hints, sizeof(*pai));
       
   442 
       
   443 		/*
       
   444 		 * if both socktype/protocol are specified, check if they
       
   445 		 * are meaningful combination.
       
   446 		 */
       
   447 		if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
       
   448 			for (ex = explore; ex->e_af >= 0; ex++) {
       
   449 				if (pai->ai_family != ex->e_af)
       
   450 					continue;
       
   451 				if (ex->e_socktype == ANY)
       
   452 					continue;
       
   453 				if (ex->e_protocol == ANY)
       
   454 					continue;
       
   455 				if (pai->ai_socktype == ex->e_socktype &&
       
   456 				    pai->ai_protocol != ex->e_protocol) {
       
   457 					ERR(EAI_BADHINTS);
       
   458 				}
       
   459 			}
       
   460 		}
       
   461 	}
       
   462 
       
   463 	/*
       
   464 	 * post-2553: AI_ALL and AI_V4MAPPED are effective only against
       
   465 	 * AF_INET6 query.  They need to be ignored if specified in other
       
   466 	 * occassions.
       
   467 	 */
       
   468 	switch (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) {
       
   469 	case AI_V4MAPPED:
       
   470 	case AI_ALL | AI_V4MAPPED:
       
   471 		if (pai->ai_family != AF_INET6)
       
   472 			pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED);
       
   473 		break;
       
   474 #ifndef __SYMBIAN32__
       
   475 	case AI_ALL:
       
   476 #if 1
       
   477 		/* illegal */
       
   478 		ERR(EAI_BADFLAGS);
       
   479 #else
       
   480 		pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED);
       
   481 #endif
       
   482 		break;
       
   483 #endif /*__SYMBIAN32__*/
       
   484 	}
       
   485 
       
   486 	/*
       
   487 	 * check for special cases.  (1) numeric servname is disallowed if
       
   488 	 * socktype/protocol are left unspecified. (2) servname is disallowed
       
   489 	 * for raw and other inet{,6} sockets.
       
   490 	 */
       
   491 	if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
       
   492 #ifdef PF_INET6
       
   493 	    || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
       
   494 #endif
       
   495 	    ) {
       
   496 		ai0 = *pai;	/* backup *pai */
       
   497 
       
   498 		if (pai->ai_family == PF_UNSPEC) {
       
   499 #ifdef PF_INET6
       
   500 #ifdef __SYMBIAN32__
       
   501 // XXX: Fix this
       
   502 			pai->ai_family = PF_INET;
       
   503 #else			
       
   504 			pai->ai_family = PF_INET6;
       
   505 #endif // __SYMBIAN32__
       
   506 #else
       
   507 			pai->ai_family = PF_INET;
       
   508 #endif
       
   509 		}
       
   510 		error = get_portmatch(pai, servname);
       
   511 		if (error)
       
   512 			ERR(error);
       
   513 
       
   514 		*pai = ai0;
       
   515 	}
       
   516 
       
   517 	ai0 = *pai;
       
   518 
       
   519 	/* NULL hostname, or numeric hostname */
       
   520 	for (ex = explore; ex->e_af >= 0; ex++) {
       
   521 		*pai = ai0;
       
   522 
       
   523 		/* PF_UNSPEC entries are prepared for DNS queries only */
       
   524 		if (ex->e_af == PF_UNSPEC)
       
   525 			continue;
       
   526 
       
   527 		if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
       
   528 			continue;
       
   529 		if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
       
   530 			continue;
       
   531 		if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
       
   532 			continue;
       
   533 
       
   534 		if (pai->ai_family == PF_UNSPEC)
       
   535 			pai->ai_family = ex->e_af;
       
   536 		if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
       
   537 			pai->ai_socktype = ex->e_socktype;
       
   538 		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
       
   539 			pai->ai_protocol = ex->e_protocol;
       
   540 
       
   541 		if (hostname == NULL)
       
   542 			error = explore_null(pai, servname, &cur->ai_next);
       
   543 		else
       
   544 			error = explore_numeric_scope(pai, hostname, servname,
       
   545 			    &cur->ai_next);
       
   546 
       
   547 		if (error)
       
   548 			goto free;
       
   549 
       
   550 		while (cur && cur->ai_next)
       
   551 			cur = cur->ai_next;
       
   552 	}
       
   553 
       
   554 	/*
       
   555 	 * XXX
       
   556 	 * If numreic representation of AF1 can be interpreted as FQDN
       
   557 	 * representation of AF2, we need to think again about the code below.
       
   558 	 */
       
   559 	if (sentinel.ai_next) {
       
   560 		numeric = 1;
       
   561 		goto good;
       
   562 	}
       
   563 
       
   564 	if (hostname == NULL)
       
   565 		ERR(EAI_NONAME);	/* used to be EAI_NODATA */
       
   566 	if (pai->ai_flags & AI_NUMERICHOST)
       
   567 		ERR(EAI_NONAME);
       
   568 
       
   569 	if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && !addrconfig(&ai0))
       
   570 		ERR(EAI_FAIL);
       
   571 
       
   572 	/*
       
   573 	 * hostname as alphabetical name.
       
   574 	 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
       
   575 	 * outer loop by AFs.
       
   576 	 */
       
   577 	for (ex = explore; ex->e_af >= 0; ex++) {
       
   578 		*pai = ai0;
       
   579        
       
   580 		/* require exact match for family field */
       
   581 		if (pai->ai_family != ex->e_af)
       
   582 			continue;
       
   583 
       
   584 		if (!MATCH(pai->ai_socktype, ex->e_socktype,
       
   585 				WILD_SOCKTYPE(ex))) {
       
   586 			continue;
       
   587 		}
       
   588 		if (!MATCH(pai->ai_protocol, ex->e_protocol,
       
   589 				WILD_PROTOCOL(ex))) {
       
   590 			continue;
       
   591 
       
   592 		}
       
   593 
       
   594 #ifdef __SYMBIAN32__
       
   595         if (pai->ai_family == PF_UNSPEC)
       
   596 			pai->ai_family = ex->e_af;
       
   597 #endif
       
   598 		if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
       
   599 			pai->ai_socktype = ex->e_socktype;
       
   600 		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
       
   601 			pai->ai_protocol = ex->e_protocol;
       
   602 
       
   603 #ifndef __SYMBIAN32__
       
   604 		error = explore_fqdn(pai, hostname, servname,
       
   605 			&cur->ai_next);
       
   606 #else
       
   607             
       
   608         error = explore_hostname(pai, hostname, servname,
       
   609         		&cur->ai_next, hints);
       
   610         if(error == -1 || error == EAI_MEMORY)
       
   611         	goto bad;
       
   612         else
       
   613             error = 0;
       
   614          
       
   615 
       
   616 #endif//__SYMBIAN32__
       
   617 		while (cur && cur->ai_next)
       
   618 		cur = cur->ai_next;
       
   619 	}
       
   620 	/* XXX inhibit errors if we have the result */
       
   621 	if (sentinel.ai_next)
       
   622 		error = 0;
       
   623 
       
   624 good:
       
   625 	/*
       
   626 	 * ensure we return either:
       
   627 	 * - error == 0, non-NULL *res
       
   628 	 * - error != 0, NULL *res
       
   629 	 */
       
   630 	if (error == 0) {
       
   631 		if (sentinel.ai_next) {
       
   632 			/*
       
   633 			 * If the returned entry is for an active connection,
       
   634 			 * and the given name is not numeric, reorder the
       
   635 			 * list, so that the application would try the list
       
   636 			 * in the most efficient order.
       
   637 			 */
       
   638 			if (hints == NULL || !(hints->ai_flags & AI_PASSIVE)) {
       
   639 				if (!numeric)
       
   640 					(void)reorder(&sentinel);
       
   641 			}
       
   642 			*res = sentinel.ai_next;
       
   643 			return SUCCESS;
       
   644 		} else
       
   645 			error = EAI_FAIL;
       
   646 	}
       
   647 free:
       
   648 bad:
       
   649 	if (sentinel.ai_next)
       
   650 		freeaddrinfo(sentinel.ai_next);
       
   651 	*res = NULL;
       
   652 	return error;
       
   653 }
       
   654 
       
   655 static int
       
   656 reorder(sentinel)
       
   657 	struct addrinfo *sentinel;
       
   658 {
       
   659 	struct addrinfo *ai, **aip;
       
   660 	struct ai_order *aio;
       
   661 	int i, n;
       
   662 	struct policyhead policyhead;
       
   663 
       
   664 	/* count the number of addrinfo elements for sorting. */
       
   665 	for (n = 0, ai = sentinel->ai_next; ai != NULL; ai = ai->ai_next, n++)
       
   666 		;
       
   667 
       
   668 	/*
       
   669 	 * If the number is small enough, we can skip the reordering process.
       
   670 	 */
       
   671 	if (n <= 1)
       
   672 		return(n);
       
   673 
       
   674 	/* allocate a temporary array for sort and initialization of it. */
       
   675 	if ((aio = malloc(sizeof(*aio) * n)) == NULL)
       
   676 		return(n);	/* give up reordering */
       
   677 	memset(aio, 0, sizeof(*aio) * n);
       
   678 
       
   679 	/* retrieve address selection policy from the kernel */
       
   680 	TAILQ_INIT(&policyhead);
       
   681 	if (!get_addrselectpolicy(&policyhead)) {
       
   682 		/* no policy is installed into kernel, we don't sort. */
       
   683 		free(aio);
       
   684 		return (n);
       
   685 	}
       
   686 
       
   687 	for (i = 0, ai = sentinel->ai_next; i < n; ai = ai->ai_next, i++) {
       
   688 		aio[i].aio_ai = ai;
       
   689 		aio[i].aio_dstscope = gai_addr2scopetype(ai->ai_addr);
       
   690 		aio[i].aio_dstpolicy = match_addrselectpolicy(ai->ai_addr,
       
   691 							      &policyhead);
       
   692 		set_source(&aio[i], &policyhead);
       
   693 	}
       
   694 
       
   695 	/* perform sorting. */
       
   696 	qsort(aio, n, sizeof(*aio), comp_dst);
       
   697 
       
   698 	/* reorder the addrinfo chain. */
       
   699 	for (i = 0, aip = &sentinel->ai_next; i < n; i++) {
       
   700 		*aip = aio[i].aio_ai;
       
   701 		aip = &aio[i].aio_ai->ai_next;
       
   702 	}
       
   703 	*aip = NULL;
       
   704 
       
   705 	/* cleanup and return */
       
   706 	free(aio);
       
   707 	free_addrselectpolicy(&policyhead);
       
   708 	return(n);
       
   709 }
       
   710 
       
   711 static int
       
   712 get_addrselectpolicy(head)
       
   713 	struct policyhead *head;
       
   714 {
       
   715 #ifdef __SYMBIAN32__
       
   716 
       
   717 	head = head; /*to fix warning 'variable/argument not used in function' */
       
   718 #endif //__SYMBIAN32__
       
   719 
       
   720 #ifndef __SYMBIAN32__
       
   721 #ifdef INET6
       
   722 	int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_ADDRCTLPOLICY };
       
   723 	size_t l;
       
   724 	char *buf;
       
   725 	struct in6_addrpolicy *pol, *ep;
       
   726 
       
   727 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0)
       
   728 		return (0);
       
   729 	if ((buf = malloc(l)) == NULL)
       
   730 		return (0);
       
   731 	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) {
       
   732 		free(buf);
       
   733 		return (0);
       
   734 	}
       
   735 
       
   736 	ep = (struct in6_addrpolicy *)(buf + l);
       
   737 	for (pol = (struct in6_addrpolicy *)buf; pol + 1 <= ep; pol++) {
       
   738 		struct policyqueue *new;
       
   739 
       
   740 		if ((new = malloc(sizeof(*new))) == NULL) {
       
   741 			free_addrselectpolicy(head); /* make the list empty */
       
   742 			break;
       
   743 		}
       
   744 		new->pc_policy = *pol;
       
   745 		TAILQ_INSERT_TAIL(head, new, pc_entry);
       
   746 	}
       
   747 
       
   748 	free(buf);
       
   749 	return (1);
       
   750 #else
       
   751 	return (0);
       
   752 #endif
       
   753 #else
       
   754 	return (0);
       
   755 #endif /* __SYMBIAN32__ */
       
   756 }
       
   757 
       
   758 static void
       
   759 free_addrselectpolicy(head)
       
   760 	struct policyhead *head;
       
   761 {
       
   762 	struct policyqueue *ent, *nent;
       
   763 
       
   764 	for (ent = TAILQ_FIRST(head); ent; ent = nent) {
       
   765 		nent = TAILQ_NEXT(ent, pc_entry);
       
   766 		TAILQ_REMOVE(head, ent, pc_entry);
       
   767 		free(ent);
       
   768 	}
       
   769 }
       
   770 
       
   771 static struct policyqueue *
       
   772 match_addrselectpolicy(addr, head)
       
   773 	struct sockaddr *addr;
       
   774 	struct policyhead *head;
       
   775 {
       
   776 #ifdef INET6
       
   777 	struct policyqueue *ent, *bestent = NULL;
       
   778 	struct in6_addrpolicy *pol;
       
   779 	int matchlen, bestmatchlen = -1;
       
   780 	u_char *mp, *ep, *k, *p, m;
       
   781 	struct sockaddr_in6 key;
       
   782 
       
   783 	switch(addr->sa_family) {
       
   784 	case AF_INET6:
       
   785 		key = *(struct sockaddr_in6 *)addr;
       
   786 		break;
       
   787 	case AF_INET:
       
   788 		/* convert the address into IPv4-mapped IPv6 address. */
       
   789 		memset(&key, 0, sizeof(key));
       
   790 		key.sin6_family = AF_INET6;
       
   791 		key.sin6_len = sizeof(key);
       
   792 		key.sin6_addr.s6_addr[10] = 0xff;
       
   793 		key.sin6_addr.s6_addr[11] = 0xff;
       
   794 		memcpy(&key.sin6_addr.s6_addr[12],
       
   795 		       &((struct sockaddr_in *)addr)->sin_addr, 4);
       
   796 		break;
       
   797 	default:
       
   798 		return(NULL);
       
   799 	}
       
   800 
       
   801 	for (ent = TAILQ_FIRST(head); ent; ent = TAILQ_NEXT(ent, pc_entry)) {
       
   802 		pol = &ent->pc_policy;
       
   803 		matchlen = 0;
       
   804 
       
   805 		mp = (u_char *)&pol->addrmask.sin6_addr;
       
   806 		ep = mp + 16;	/* XXX: scope field? */
       
   807 		k = (u_char *)&key.sin6_addr;
       
   808 		p = (u_char *)&pol->addr.sin6_addr;
       
   809 		for (; mp < ep && *mp; mp++, k++, p++) {
       
   810 			m = *mp;
       
   811 			if ((*k & m) != *p)
       
   812 				goto next; /* not match */
       
   813 			if (m == 0xff) /* short cut for a typical case */
       
   814 				matchlen += 8;
       
   815 			else {
       
   816 				while (m >= 0x80) {
       
   817 					matchlen++;
       
   818 					m <<= 1;
       
   819 				}
       
   820 			}
       
   821 		}
       
   822 
       
   823 		/* matched.  check if this is better than the current best. */
       
   824 		if (matchlen > bestmatchlen) {
       
   825 			bestent = ent;
       
   826 			bestmatchlen = matchlen;
       
   827 		}
       
   828 
       
   829 	  next:
       
   830 		continue;
       
   831 	}
       
   832 
       
   833 	return(bestent);
       
   834 #else
       
   835 	return(NULL);
       
   836 #endif
       
   837 
       
   838 }
       
   839 
       
   840 static void
       
   841 set_source(aio, ph)
       
   842 	struct ai_order *aio;
       
   843 	struct policyhead *ph;
       
   844 {
       
   845 	struct addrinfo ai = *aio->aio_ai;
       
   846 	struct sockaddr_storage ss;
       
   847 	socklen_t srclen;
       
   848 	int s;
       
   849 
       
   850 	/* set unspec ("no source is available"), just in case */
       
   851 	aio->aio_srcsa.sa_family = AF_UNSPEC;
       
   852 	aio->aio_srcscope = -1;
       
   853 
       
   854 	switch(ai.ai_family) {
       
   855 	case AF_INET:
       
   856 #ifdef INET6
       
   857 	case AF_INET6:
       
   858 #endif
       
   859 		break;
       
   860 	default:		/* ignore unsupported AFs explicitly */
       
   861 		return;
       
   862 	}
       
   863 
       
   864 	/* XXX: make a dummy addrinfo to call connect() */
       
   865 	ai.ai_socktype = SOCK_DGRAM;
       
   866 	ai.ai_protocol = IPPROTO_UDP; /* is UDP too specific? */
       
   867 	ai.ai_next = NULL;
       
   868 	memset(&ss, 0, sizeof(ss));
       
   869 	memcpy(&ss, ai.ai_addr, ai.ai_addrlen);
       
   870 	ai.ai_addr = (struct sockaddr *)&ss;
       
   871 	get_port(&ai, "1", 0);
       
   872 
       
   873 	/* open a socket to get the source address for the given dst */
       
   874 #ifndef __SYMBIAN32__
       
   875 	if ((s = _socket(ai.ai_family, ai.ai_socktype, ai.ai_protocol)) < 0)
       
   876 		return;		/* give up */
       
   877 	if (_connect(s, ai.ai_addr, ai.ai_addrlen) < 0)
       
   878 		goto cleanup;
       
   879 	srclen = ai.ai_addrlen;
       
   880 	if (_getsockname(s, &aio->aio_srcsa, &srclen) < 0) {
       
   881 		aio->aio_srcsa.sa_family = AF_UNSPEC;
       
   882 #else
       
   883        if ((s = socket(ai.ai_family, ai.ai_socktype, ai.ai_protocol)) < 0)
       
   884 		return;		/* give up */
       
   885 	if (connect(s, ai.ai_addr, ai.ai_addrlen) < 0)
       
   886 		goto cleanup;
       
   887 	srclen = ai.ai_addrlen;
       
   888 	if (getsockname(s, &aio->aio_srcsa, &srclen) < 0) {
       
   889 		aio->aio_srcsa.sa_family = AF_UNSPEC;
       
   890 #endif 
       
   891 		goto cleanup;
       
   892 	}
       
   893 	aio->aio_srcscope = gai_addr2scopetype(&aio->aio_srcsa);
       
   894 	aio->aio_srcpolicy = match_addrselectpolicy(&aio->aio_srcsa, ph);
       
   895 	aio->aio_matchlen = matchlen(&aio->aio_srcsa, aio->aio_ai->ai_addr);
       
   896 #ifndef __SYMBIAN32__
       
   897 /*
       
   898  * XXX:
       
   899  * This path is not traversed
       
   900  * get_addrselectpolicy() returns 0 and reorder() does 
       
   901  * not call this routine yet.	
       
   902  */
       
   903 #ifdef INET6
       
   904 	if (ai.ai_family == AF_INET6) {
       
   905 		struct in6_ifreq ifr6;
       
   906 		u_int32_t flags6;
       
   907 
       
   908 		/* XXX: interface name should not be hardcoded */
       
   909 		strncpy(ifr6.ifr_name, "lo0", sizeof(ifr6.ifr_name));
       
   910 		memset(&ifr6, 0, sizeof(ifr6));
       
   911 		memcpy(&ifr6.ifr_addr, ai.ai_addr, ai.ai_addrlen);
       
   912 #ifdef __SYMBIAN32__
       
   913 		if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == 0) {
       
   914 #else		
       
   915 		if (_ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == 0) {
       
   916 #endif //__SYMBIAN32__		
       
   917 			flags6 = ifr6.ifr_ifru.ifru_flags6;
       
   918 			if ((flags6 & IN6_IFF_DEPRECATED))
       
   919 				aio->aio_srcflag |= AIO_SRCFLAG_DEPRECATED;
       
   920 		}
       
   921 	}
       
   922 #endif
       
   923 #endif
       
   924 
       
   925   cleanup:
       
   926 #ifndef __SYMBIAN32__
       
   927 	_close(s);
       
   928 #else
       
   929 	close(s);
       
   930 #endif /* __SYMBIAN32__ */
       
   931 	return;
       
   932 }
       
   933 
       
   934 static int
       
   935 matchlen(src, dst)
       
   936 	struct sockaddr *src, *dst;
       
   937 {
       
   938 	int match = 0;
       
   939 	u_char *s, *d;
       
   940 	u_char *lim, r;
       
   941 	int addrlen;
       
   942 
       
   943 	switch (src->sa_family) {
       
   944 #ifdef INET6
       
   945 	case AF_INET6:
       
   946 		s = (u_char *)&((struct sockaddr_in6 *)src)->sin6_addr;
       
   947 		d = (u_char *)&((struct sockaddr_in6 *)dst)->sin6_addr;
       
   948 		addrlen = sizeof(struct in6_addr);
       
   949 		lim = s + addrlen;
       
   950 		break;
       
   951 #endif
       
   952 	case AF_INET:
       
   953 		s = (u_char *)&((struct sockaddr_in *)src)->sin_addr;
       
   954 		d = (u_char *)&((struct sockaddr_in *)dst)->sin_addr;
       
   955 		addrlen = sizeof(struct in_addr);
       
   956 		lim = s + addrlen;
       
   957 		break;
       
   958 	default:
       
   959 		return(0);
       
   960 	}
       
   961 
       
   962 	while (s < lim)
       
   963 		if ((r = (*d++ ^ *s++)) != 0) {
       
   964 			while (r < addrlen * 8) {
       
   965 				match++;
       
   966 				r <<= 1;
       
   967 			}
       
   968 			break;
       
   969 		} else
       
   970 			match += 8;
       
   971 	return(match);
       
   972 }
       
   973 
       
   974 static int
       
   975 comp_dst(arg1, arg2)
       
   976 	const void *arg1, *arg2;
       
   977 {
       
   978 	const struct ai_order *dst1 = arg1, *dst2 = arg2;
       
   979 
       
   980 	/*
       
   981 	 * Rule 1: Avoid unusable destinations.
       
   982 	 * XXX: we currently do not consider if an appropriate route exists.
       
   983 	 */
       
   984 	if (dst1->aio_srcsa.sa_family != AF_UNSPEC &&
       
   985 	    dst2->aio_srcsa.sa_family == AF_UNSPEC) {
       
   986 		return(-1);
       
   987 	}
       
   988 	if (dst1->aio_srcsa.sa_family == AF_UNSPEC &&
       
   989 	    dst2->aio_srcsa.sa_family != AF_UNSPEC) {
       
   990 		return(1);
       
   991 	}
       
   992 
       
   993 	/* Rule 2: Prefer matching scope. */
       
   994 	if (dst1->aio_dstscope == dst1->aio_srcscope &&
       
   995 	    dst2->aio_dstscope != dst2->aio_srcscope) {
       
   996 		return(-1);
       
   997 	}
       
   998 	if (dst1->aio_dstscope != dst1->aio_srcscope &&
       
   999 	    dst2->aio_dstscope == dst2->aio_srcscope) {
       
  1000 		return(1);
       
  1001 	}
       
  1002 
       
  1003 	/* Rule 3: Avoid deprecated addresses. */
       
  1004 	if (dst1->aio_srcsa.sa_family != AF_UNSPEC &&
       
  1005 	    dst2->aio_srcsa.sa_family != AF_UNSPEC) {
       
  1006 		if (!(dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) &&
       
  1007 		    (dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) {
       
  1008 			return(-1);
       
  1009 		}
       
  1010 		if ((dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) &&
       
  1011 		    !(dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) {
       
  1012 			return(1);
       
  1013 		}
       
  1014 	}
       
  1015 
       
  1016 	/* Rule 4: Prefer home addresses. */
       
  1017 	/* XXX: not implemented yet */
       
  1018 
       
  1019 	/* Rule 5: Prefer matching label. */
       
  1020 #ifdef INET6
       
  1021 	if (dst1->aio_srcpolicy && dst1->aio_dstpolicy &&
       
  1022 	    dst1->aio_srcpolicy->pc_policy.label ==
       
  1023 	    dst1->aio_dstpolicy->pc_policy.label &&
       
  1024 	    (dst2->aio_srcpolicy == NULL || dst2->aio_dstpolicy == NULL ||
       
  1025 	     dst2->aio_srcpolicy->pc_policy.label !=
       
  1026 	     dst2->aio_dstpolicy->pc_policy.label)) {
       
  1027 		return(-1);
       
  1028 	}
       
  1029 	if (dst2->aio_srcpolicy && dst2->aio_dstpolicy &&
       
  1030 	    dst2->aio_srcpolicy->pc_policy.label ==
       
  1031 	    dst2->aio_dstpolicy->pc_policy.label &&
       
  1032 	    (dst1->aio_srcpolicy == NULL || dst1->aio_dstpolicy == NULL ||
       
  1033 	     dst1->aio_srcpolicy->pc_policy.label !=
       
  1034 	     dst1->aio_dstpolicy->pc_policy.label)) {
       
  1035 		return(1);
       
  1036 	}
       
  1037 #endif
       
  1038 
       
  1039 	/* Rule 6: Prefer higher precedence. */
       
  1040 #ifdef INET6
       
  1041 	if (dst1->aio_dstpolicy &&
       
  1042 	    (dst2->aio_dstpolicy == NULL ||
       
  1043 	     dst1->aio_dstpolicy->pc_policy.preced >
       
  1044 	     dst2->aio_dstpolicy->pc_policy.preced)) {
       
  1045 		return(-1);
       
  1046 	}
       
  1047 	if (dst2->aio_dstpolicy &&
       
  1048 	    (dst1->aio_dstpolicy == NULL ||
       
  1049 	     dst2->aio_dstpolicy->pc_policy.preced >
       
  1050 	     dst1->aio_dstpolicy->pc_policy.preced)) {
       
  1051 		return(1);
       
  1052 	}
       
  1053 #endif
       
  1054 
       
  1055 	/* Rule 7: Prefer native transport. */
       
  1056 	/* XXX: not implemented yet */
       
  1057 
       
  1058 	/* Rule 8: Prefer smaller scope. */
       
  1059 	if (dst1->aio_dstscope >= 0 &&
       
  1060 	    dst1->aio_dstscope < dst2->aio_dstscope) {
       
  1061 		return(-1);
       
  1062 	}
       
  1063 	if (dst2->aio_dstscope >= 0 &&
       
  1064 	    dst2->aio_dstscope < dst1->aio_dstscope) {
       
  1065 		return(1);
       
  1066 	}
       
  1067 
       
  1068 	/*
       
  1069 	 * Rule 9: Use longest matching prefix.
       
  1070 	 * We compare the match length in a same AF only.
       
  1071 	 */
       
  1072 	if (dst1->aio_ai->ai_addr->sa_family ==
       
  1073 	    dst2->aio_ai->ai_addr->sa_family) {
       
  1074 		if (dst1->aio_matchlen > dst2->aio_matchlen) {
       
  1075 			return(-1);
       
  1076 		}
       
  1077 		if (dst1->aio_matchlen < dst2->aio_matchlen) {
       
  1078 			return(1);
       
  1079 		}
       
  1080 	}
       
  1081 
       
  1082 	/* Rule 10: Otherwise, leave the order unchanged. */
       
  1083 	return(-1);
       
  1084 }
       
  1085 
       
  1086 /*
       
  1087  * Copy from scope.c.
       
  1088  * XXX: we should standardize the functions and link them as standard
       
  1089  * library.
       
  1090  */
       
  1091 static int
       
  1092 gai_addr2scopetype(sa)
       
  1093 	struct sockaddr *sa;
       
  1094 {
       
  1095 #ifdef INET6
       
  1096 	struct sockaddr_in6 *sa6;
       
  1097 #endif
       
  1098 	struct sockaddr_in *sa4;
       
  1099 
       
  1100 	switch(sa->sa_family) {
       
  1101 #ifdef INET6
       
  1102 	case AF_INET6:
       
  1103 		sa6 = (struct sockaddr_in6 *)sa;
       
  1104 		if (IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr)) {
       
  1105 			/* just use the scope field of the multicast address */
       
  1106 			return(sa6->sin6_addr.s6_addr[2] & 0x0f);
       
  1107 		}
       
  1108 		/*
       
  1109 		 * Unicast addresses: map scope type to corresponding scope
       
  1110 		 * value defined for multcast addresses.
       
  1111 		 * XXX: hardcoded scope type values are bad...
       
  1112 		 */
       
  1113 		if (IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr))
       
  1114 			return(1); /* node local scope */
       
  1115 		if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr))
       
  1116 			return(2); /* link-local scope */
       
  1117 		if (IN6_IS_ADDR_SITELOCAL(&sa6->sin6_addr))
       
  1118 			return(5); /* site-local scope */
       
  1119 		return(14);	/* global scope */
       
  1120 		break;
       
  1121 #endif
       
  1122 	case AF_INET:
       
  1123 		/*
       
  1124 		 * IPv4 pseudo scoping according to RFC 3484.
       
  1125 		 */
       
  1126 		sa4 = (struct sockaddr_in *)sa;
       
  1127 		/* IPv4 autoconfiguration addresses have link-local scope. */
       
  1128 		if (((u_char *)&sa4->sin_addr)[0] == 169 &&
       
  1129 		    ((u_char *)&sa4->sin_addr)[1] == 254)
       
  1130 			return(2);
       
  1131 		/* Private addresses have site-local scope. */
       
  1132 		if (((u_char *)&sa4->sin_addr)[0] == 10 ||
       
  1133 		    (((u_char *)&sa4->sin_addr)[0] == 172 &&
       
  1134 		     (((u_char *)&sa4->sin_addr)[1] & 0xf0) == 16) ||
       
  1135 		    (((u_char *)&sa4->sin_addr)[0] == 192 &&
       
  1136 		     ((u_char *)&sa4->sin_addr)[1] == 168))
       
  1137 			return(14);	/* XXX: It should be 5 unless NAT */
       
  1138 		/* Loopback addresses have link-local scope. */
       
  1139 		if (((u_char *)&sa4->sin_addr)[0] == 127)
       
  1140 			return(2);
       
  1141 		return(14);
       
  1142 		break;
       
  1143 	default:
       
  1144 		errno = EAFNOSUPPORT; /* is this a good error? */
       
  1145 		return(-1);
       
  1146 	}
       
  1147 }
       
  1148 
       
  1149 /*
       
  1150  * hostname == NULL.
       
  1151  * passive socket -> anyaddr (0.0.0.0 or ::)
       
  1152  * non-passive socket -> localhost (127.0.0.1 or ::1)
       
  1153  */
       
  1154 static int
       
  1155 explore_null(pai, servname, res)
       
  1156 	const struct addrinfo *pai;
       
  1157 	const char *servname;
       
  1158 	struct addrinfo **res;
       
  1159 {
       
  1160 	int s;
       
  1161 	const struct afd *afd;
       
  1162 	struct addrinfo *cur;
       
  1163 	struct addrinfo sentinel;
       
  1164 	int error;
       
  1165 
       
  1166 	*res = NULL;
       
  1167 	sentinel.ai_next = NULL;
       
  1168 	cur = &sentinel;
       
  1169 
       
  1170 	/*
       
  1171 	 * filter out AFs that are not supported by the kernel
       
  1172 	 * XXX errno?
       
  1173 	 */
       
  1174 #ifndef __SYMBIAN32__
       
  1175 	s = _socket(pai->ai_family, SOCK_DGRAM, 0);
       
  1176 #else
       
  1177        s=socket(pai->ai_family, SOCK_DGRAM, IPPROTO_UDP);
       
  1178 #endif /* __SYMBIAN32__ */
       
  1179 	if (s < 0) {
       
  1180 		if (errno != EMFILE)
       
  1181 			return 0;
       
  1182 	} else
       
  1183 #ifndef __SYMBIAN32__
       
  1184 	_close(s);
       
  1185 #else
       
  1186 	close(s);
       
  1187 #endif /*__SYMBIAN32__*/
       
  1188 	/*
       
  1189 	 * if the servname does not match socktype/protocol, ignore it.
       
  1190 	 */
       
  1191 	if (get_portmatch(pai, servname) != 0)
       
  1192 		return 0;
       
  1193 
       
  1194 	afd = find_afd(pai->ai_family);
       
  1195 	if (afd == NULL)
       
  1196 		return 0;
       
  1197 
       
  1198 	if (pai->ai_flags & AI_PASSIVE) {
       
  1199 		GET_AI(cur->ai_next, afd, afd->a_addrany);
       
  1200 		/* xxx meaningless?
       
  1201 		 * GET_CANONNAME(cur->ai_next, "anyaddr");
       
  1202 		 */
       
  1203 		GET_PORT(cur->ai_next, servname);
       
  1204 	} else {
       
  1205 		GET_AI(cur->ai_next, afd, afd->a_loopback);
       
  1206 		/* xxx meaningless?
       
  1207 		 * GET_CANONNAME(cur->ai_next, "localhost");
       
  1208 		 */
       
  1209 		GET_PORT(cur->ai_next, servname);
       
  1210 	}
       
  1211 	cur = cur->ai_next;
       
  1212 
       
  1213 	*res = sentinel.ai_next;
       
  1214 	return 0;
       
  1215 
       
  1216 free:
       
  1217 	if (sentinel.ai_next)
       
  1218 		freeaddrinfo(sentinel.ai_next);
       
  1219 	return error;
       
  1220 }
       
  1221 
       
  1222 /*
       
  1223  * numeric hostname
       
  1224  */
       
  1225 static int
       
  1226 explore_numeric(pai, hostname, servname, res, canonname)
       
  1227 	const struct addrinfo *pai;
       
  1228 	const char *hostname;
       
  1229 	const char *servname;
       
  1230 	struct addrinfo **res;
       
  1231 	const char *canonname;
       
  1232 {
       
  1233 	const struct afd *afd;
       
  1234 	struct addrinfo *cur;
       
  1235 	struct addrinfo sentinel;
       
  1236 	int error;
       
  1237 	char pton[PTON_MAX];
       
  1238 
       
  1239 	*res = NULL;
       
  1240 	sentinel.ai_next = NULL;
       
  1241 	cur = &sentinel;
       
  1242 
       
  1243 	/*
       
  1244 	 * if the servname does not match socktype/protocol, ignore it.
       
  1245 	 */
       
  1246 	if (get_portmatch(pai, servname) != 0)
       
  1247 		return 0;
       
  1248 
       
  1249 	afd = find_afd(pai->ai_family);
       
  1250 	if (afd == NULL)
       
  1251 		return 0;
       
  1252 
       
  1253 	switch (afd->a_af) {
       
  1254 #if 1 /*X/Open spec*/
       
  1255 	case AF_INET:
       
  1256 		if (inet_aton(hostname, (struct in_addr *)pton) == 1) {
       
  1257 			if (pai->ai_family == afd->a_af ||
       
  1258 			    pai->ai_family == PF_UNSPEC /*?*/) {
       
  1259 				GET_AI(cur->ai_next, afd, pton);
       
  1260 				GET_PORT(cur->ai_next, servname);
       
  1261 				if ((pai->ai_flags & AI_CANONNAME)) {
       
  1262 					/*
       
  1263 					 * Set the numeric address itself as
       
  1264 					 * the canonical name, based on a
       
  1265 					 * clarification in rfc3493.
       
  1266 					 */
       
  1267 					GET_CANONNAME(cur->ai_next, canonname);
       
  1268 				}
       
  1269 				while (cur && cur->ai_next)
       
  1270 					cur = cur->ai_next;
       
  1271 			} else
       
  1272 				ERR(EAI_FAMILY);	/*xxx*/
       
  1273 		}
       
  1274 		break;
       
  1275 #endif
       
  1276 	default:
       
  1277 		if (inet_pton(afd->a_af, hostname, pton) == 1) {
       
  1278 			if (pai->ai_family == afd->a_af ||
       
  1279 			    pai->ai_family == PF_UNSPEC /*?*/) {
       
  1280 				GET_AI(cur->ai_next, afd, pton);
       
  1281 				GET_PORT(cur->ai_next, servname);
       
  1282 				if ((pai->ai_flags & AI_CANONNAME)) {
       
  1283 					/*
       
  1284 					 * Set the numeric address itself as
       
  1285 					 * the canonical name, based on a
       
  1286 					 * clarification in rfc3493.
       
  1287 					 */
       
  1288 					GET_CANONNAME(cur->ai_next, canonname);
       
  1289 				}
       
  1290 				while (cur && cur->ai_next)
       
  1291 					cur = cur->ai_next;
       
  1292 			} else
       
  1293 				ERR(EAI_FAMILY);	/* XXX */
       
  1294 		}
       
  1295 		break;
       
  1296 	}
       
  1297 
       
  1298 	*res = sentinel.ai_next;
       
  1299 	return 0;
       
  1300 
       
  1301 free:
       
  1302 bad:
       
  1303 	if (sentinel.ai_next)
       
  1304 		freeaddrinfo(sentinel.ai_next);
       
  1305 	return error;
       
  1306 }
       
  1307 
       
  1308 /*
       
  1309  * numeric hostname with scope
       
  1310  */
       
  1311 static int
       
  1312 explore_numeric_scope(pai, hostname, servname, res)
       
  1313 	const struct addrinfo *pai;
       
  1314 	const char *hostname;
       
  1315 	const char *servname;
       
  1316 	struct addrinfo **res;
       
  1317 {
       
  1318 #if !defined(SCOPE_DELIMITER) || !defined(INET6)
       
  1319 	return explore_numeric(pai, hostname, servname, res, hostname);
       
  1320 #else
       
  1321 	const struct afd *afd;
       
  1322 	struct addrinfo *cur;
       
  1323 	int error;
       
  1324 	char *cp, *hostname2 = NULL, *scope, *addr;
       
  1325 	struct sockaddr_in6 *sin6;
       
  1326 
       
  1327 	/*
       
  1328 	 * if the servname does not match socktype/protocol, ignore it.
       
  1329 	 */
       
  1330 	if (get_portmatch(pai, servname) != 0)
       
  1331 		return 0;
       
  1332 
       
  1333 	afd = find_afd(pai->ai_family);
       
  1334 	if (afd == NULL)
       
  1335 		return 0;
       
  1336 
       
  1337 	if (!afd->a_scoped)
       
  1338 		return explore_numeric(pai, hostname, servname, res, hostname);
       
  1339 
       
  1340 	cp = strchr(hostname, SCOPE_DELIMITER);
       
  1341 	if (cp == NULL)
       
  1342 		return explore_numeric(pai, hostname, servname, res, hostname);
       
  1343 
       
  1344 	/*
       
  1345 	 * Handle special case of <scoped_address><delimiter><scope id>
       
  1346 	 */
       
  1347 	hostname2 = strdup(hostname);
       
  1348 	if (hostname2 == NULL)
       
  1349 		return EAI_MEMORY;
       
  1350 	/* terminate at the delimiter */
       
  1351 	hostname2[cp - hostname] = '\0';
       
  1352 	addr = hostname2;
       
  1353 	scope = cp + 1;
       
  1354 
       
  1355 	error = explore_numeric(pai, addr, servname, res, hostname);
       
  1356 	if (error == 0) {
       
  1357 		u_int32_t scopeid;
       
  1358 
       
  1359 		for (cur = *res; cur; cur = cur->ai_next) {
       
  1360 			if (cur->ai_family != AF_INET6)
       
  1361 				continue;
       
  1362 			sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
       
  1363 			if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
       
  1364 				free(hostname2);
       
  1365 				return(EAI_NONAME); /* XXX: is return OK? */
       
  1366 			}
       
  1367 			sin6->sin6_scope_id = scopeid;
       
  1368 		}
       
  1369 	}
       
  1370 
       
  1371 	free(hostname2);
       
  1372 
       
  1373 	return error;
       
  1374 #endif
       
  1375 }
       
  1376 
       
  1377 static int
       
  1378 get_canonname(pai, ai, str)
       
  1379 	const struct addrinfo *pai;
       
  1380 	struct addrinfo *ai;
       
  1381 	const char *str;
       
  1382 {
       
  1383 	if ((pai->ai_flags & AI_CANONNAME) != 0) {
       
  1384 		ai->ai_canonname = strdup(str);
       
  1385 		if (ai->ai_canonname == NULL)
       
  1386 			return EAI_MEMORY;
       
  1387 	}
       
  1388 	return 0;
       
  1389 }
       
  1390 
       
  1391 static struct addrinfo *
       
  1392 get_ai(pai, afd, addr)
       
  1393 	const struct addrinfo *pai;
       
  1394 	const struct afd *afd;
       
  1395 	const char *addr;
       
  1396 {
       
  1397 	char *p;
       
  1398 	struct addrinfo *ai;
       
  1399 #ifdef FAITH
       
  1400 	struct in6_addr faith_prefix;
       
  1401 	char *fp_str;
       
  1402 	int translate = 0;
       
  1403 #endif
       
  1404 
       
  1405 #ifdef FAITH
       
  1406 	/*
       
  1407 	 * Transfrom an IPv4 addr into a special IPv6 addr format for
       
  1408 	 * IPv6->IPv4 translation gateway. (only TCP is supported now)
       
  1409 	 *
       
  1410 	 * +-----------------------------------+------------+
       
  1411 	 * | faith prefix part (12 bytes)      | embedded   |
       
  1412 	 * |                                   | IPv4 addr part (4 bytes)
       
  1413 	 * +-----------------------------------+------------+
       
  1414 	 *
       
  1415 	 * faith prefix part is specified as ascii IPv6 addr format
       
  1416 	 * in environmental variable GAI.
       
  1417 	 * For FAITH to work correctly, routing to faith prefix must be
       
  1418 	 * setup toward a machine where a FAITH daemon operates.
       
  1419 	 * Also, the machine must enable some mechanizm
       
  1420 	 * (e.g. faith interface hack) to divert those packet with
       
  1421 	 * faith prefixed destination addr to user-land FAITH daemon.
       
  1422 	 */
       
  1423 	fp_str = getenv("GAI");
       
  1424 	if (fp_str && inet_pton(AF_INET6, fp_str, &faith_prefix) == 1 &&
       
  1425 	    afd->a_af == AF_INET && pai->ai_socktype == SOCK_STREAM) {
       
  1426 		u_int32_t v4a;
       
  1427 		u_int8_t v4a_top;
       
  1428 
       
  1429 		memcpy(&v4a, addr, sizeof v4a);
       
  1430 		v4a_top = v4a >> IN_CLASSA_NSHIFT;
       
  1431 		if (!IN_MULTICAST(v4a) && !IN_EXPERIMENTAL(v4a) &&
       
  1432 		    v4a_top != 0 && v4a != IN_LOOPBACKNET) {
       
  1433 			afd = &afdl[N_INET6];
       
  1434 			memcpy(&faith_prefix.s6_addr[12], addr,
       
  1435 			       sizeof(struct in_addr));
       
  1436 			translate = 1;
       
  1437 		}
       
  1438 	}
       
  1439 #endif
       
  1440 
       
  1441 	ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
       
  1442 		+ (afd->a_socklen));
       
  1443 	if (ai == NULL)
       
  1444 		return NULL;
       
  1445 
       
  1446 	memcpy(ai, pai, sizeof(struct addrinfo));
       
  1447 	ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
       
  1448 	memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
       
  1449 #ifndef __SYMBIAN32__
       
  1450 	ai->ai_addr->sa_len = afd->a_socklen;
       
  1451 #endif /* __SYMBIAN32__ */
       
  1452 	ai->ai_addrlen = afd->a_socklen;
       
  1453 #ifndef __SYMBIAN32__
       
  1454 	ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
       
  1455 #endif
       
  1456 	p = (char *)(void *)(ai->ai_addr);
       
  1457 #ifdef FAITH
       
  1458 	if (translate == 1)
       
  1459 		memcpy(p + afd->a_off, &faith_prefix, (size_t)afd->a_addrlen);
       
  1460 	else
       
  1461 #endif
       
  1462 	memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
       
  1463 	return ai;
       
  1464 }
       
  1465 
       
  1466 static int
       
  1467 get_portmatch(ai, servname)
       
  1468 	const struct addrinfo *ai;
       
  1469 	const char *servname;
       
  1470 {
       
  1471 
       
  1472 	/* get_port does not touch first argument when matchonly == 1. */
       
  1473 	/* LINTED const cast */
       
  1474 	return get_port((struct addrinfo *)ai, servname, 1);
       
  1475 }
       
  1476 
       
  1477 static int
       
  1478 get_port(ai, servname, matchonly)
       
  1479 	struct addrinfo *ai;
       
  1480 	const char *servname;
       
  1481 	int matchonly;
       
  1482 {
       
  1483 	const char *proto;
       
  1484 	struct servent *sp;
       
  1485 	int port;
       
  1486 	int allownumeric;
       
  1487 
       
  1488 	if (servname == NULL)
       
  1489 		return 0;
       
  1490 	switch (ai->ai_family) {
       
  1491 	case AF_INET:
       
  1492 #ifdef AF_INET6
       
  1493 	case AF_INET6:
       
  1494 #endif
       
  1495 		break;
       
  1496 	default:
       
  1497 		return 0;
       
  1498 	}
       
  1499 
       
  1500 	switch (ai->ai_socktype) {
       
  1501 	case SOCK_RAW:
       
  1502 		return EAI_SERVICE;
       
  1503 	case SOCK_DGRAM:
       
  1504 	case SOCK_STREAM:
       
  1505 		allownumeric = 1;
       
  1506 		break;
       
  1507 	case ANY:
       
  1508 		allownumeric = 0;
       
  1509 		break;
       
  1510 	default:
       
  1511 		return EAI_SOCKTYPE;
       
  1512 	}
       
  1513 
       
  1514 	port = str2number(servname);
       
  1515 	if (port >= 0) {
       
  1516 		if (!allownumeric)
       
  1517 			return EAI_SERVICE;
       
  1518 		if (port < 0 || port > 65535)
       
  1519 			return EAI_SERVICE;
       
  1520 		port = htons(port);
       
  1521 	} else {
       
  1522 		if (ai->ai_flags & AI_NUMERICSERV)
       
  1523 			return EAI_NONAME;
       
  1524 		switch (ai->ai_socktype) {
       
  1525 		case SOCK_DGRAM:
       
  1526 			proto = "udp";
       
  1527 			break;
       
  1528 		case SOCK_STREAM:
       
  1529 			proto = "tcp";
       
  1530 			break;
       
  1531 		default:
       
  1532 			proto = NULL;
       
  1533 			break;
       
  1534 		}
       
  1535 
       
  1536 		if ((sp = getservbyname(servname, proto)) == NULL)
       
  1537 			return EAI_SERVICE;
       
  1538 		port = sp->s_port;
       
  1539 	}
       
  1540 
       
  1541 	if (!matchonly) {
       
  1542 		switch (ai->ai_family) {
       
  1543 		case AF_INET:
       
  1544 			((struct sockaddr_in *)(void *)
       
  1545 			    ai->ai_addr)->sin_port = port;
       
  1546 			break;
       
  1547 #ifdef INET6
       
  1548 		case AF_INET6:
       
  1549 			((struct sockaddr_in6 *)(void *)
       
  1550 			    ai->ai_addr)->sin6_port = port;
       
  1551 			break;
       
  1552 #endif
       
  1553 		}
       
  1554 	}
       
  1555 
       
  1556 	return 0;
       
  1557 }
       
  1558 
       
  1559 static const struct afd *
       
  1560 find_afd(af)
       
  1561 	int af;
       
  1562 {
       
  1563 	const struct afd *afd;
       
  1564 
       
  1565 	if (af == PF_UNSPEC)
       
  1566 		return NULL;
       
  1567 	for (afd = afdl; afd->a_af; afd++) {
       
  1568 		if (afd->a_af == af)
       
  1569 			return afd;
       
  1570 	}
       
  1571 	return NULL;
       
  1572 }
       
  1573 
       
  1574 /*
       
  1575  * post-2553: AI_ADDRCONFIG check.  if we use getipnodeby* as backend, backend
       
  1576  * will take care of it.
       
  1577  * the semantics of AI_ADDRCONFIG is not defined well.  we are not sure
       
  1578  * if the code is right or not.
       
  1579  *
       
  1580  * XXX PF_UNSPEC -> PF_INET6 + PF_INET mapping needs to be in sync with
       
  1581  * _dns_getaddrinfo.
       
  1582  */
       
  1583 static int
       
  1584 addrconfig(pai)
       
  1585 	struct addrinfo *pai;
       
  1586 {
       
  1587 	int s, af;
       
  1588 
       
  1589 	/*
       
  1590 	 * TODO:
       
  1591 	 * Note that implementation dependent test for address
       
  1592 	 * configuration should be done everytime called
       
  1593 	 * (or apropriate interval),
       
  1594 	 * because addresses will be dynamically assigned or deleted.
       
  1595 	 */
       
  1596 	af = pai->ai_family;
       
  1597 	if (af == AF_UNSPEC) {
       
  1598 #ifndef __SYMBIAN32__
       
  1599 		if ((s = _socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
       
  1600 			af = AF_INET;
       
  1601 		else {
       
  1602 			_close(s);
       
  1603 			if ((s = _socket(AF_INET, SOCK_DGRAM, 0)) < 0)
       
  1604 				af = AF_INET6;
       
  1605 			else
       
  1606 				_close(s);
       
  1607 		}
       
  1608 #else
       
  1609 		if ((s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0)
       
  1610 			af = AF_INET;
       
  1611 		else {
       
  1612 			close(s);
       
  1613 			if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
       
  1614 				af = AF_INET6;
       
  1615 			else
       
  1616 				close(s);
       
  1617 		}
       
  1618 #endif /*__SYMBIAN32__*/
       
  1619 	}
       
  1620 	if (af != AF_UNSPEC) {
       
  1621 #ifndef __SYMBIAN32__
       
  1622 		if ((s = _socket(af, SOCK_DGRAM, 0)) < 0)
       
  1623 			return 0;
       
  1624 		_close(s);
       
  1625 #else
       
  1626 		if ((s = socket(af, SOCK_DGRAM, IPPROTO_UDP)) < 0)
       
  1627 			return 0;
       
  1628 		close(s);
       
  1629 #endif /*__SYMBIAN32__*/
       
  1630 	}
       
  1631 	pai->ai_family = af;
       
  1632 	return 1;
       
  1633 }
       
  1634 
       
  1635 #ifdef INET6
       
  1636 /* convert a string to a scope identifier. XXX: IPv6 specific */
       
  1637 static int
       
  1638 ip6_str2scopeid(scope, sin6, scopeid)
       
  1639 	char *scope;
       
  1640 	struct sockaddr_in6 *sin6;
       
  1641 	u_int32_t *scopeid;
       
  1642 {
       
  1643 	u_long lscopeid;
       
  1644 	struct in6_addr *a6;
       
  1645 	char *ep;
       
  1646 
       
  1647 	a6 = &sin6->sin6_addr;
       
  1648 
       
  1649 	/* empty scopeid portion is invalid */
       
  1650 	if (*scope == '\0')
       
  1651 		return -1;
       
  1652 
       
  1653 	if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) {
       
  1654 		/*
       
  1655 		 * We currently assume a one-to-one mapping between links
       
  1656 		 * and interfaces, so we simply use interface indices for
       
  1657 		 * like-local scopes.
       
  1658 		 */
       
  1659 		*scopeid = if_nametoindex(scope);
       
  1660 		if (*scopeid == 0)
       
  1661 			goto trynumeric;
       
  1662 		return 0;
       
  1663 	}
       
  1664 
       
  1665 	/* still unclear about literal, allow numeric only - placeholder */
       
  1666 	if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
       
  1667 		goto trynumeric;
       
  1668 	if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
       
  1669 		goto trynumeric;
       
  1670 	else
       
  1671 		goto trynumeric;	/* global */
       
  1672 
       
  1673 	/* try to convert to a numeric id as a last resort */
       
  1674   trynumeric:
       
  1675 	errno = 0;
       
  1676 	lscopeid = strtoul(scope, &ep, 10);
       
  1677 	*scopeid = (u_int32_t)(lscopeid & 0xffffffffUL);
       
  1678 	if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid)
       
  1679 		return 0;
       
  1680 	else
       
  1681 		return -1;
       
  1682 }
       
  1683 #endif
       
  1684 
       
  1685 /*
       
  1686  * FQDN hostname, DNS lookup
       
  1687  */
       
  1688 #ifndef __SYMBIAN32__
       
  1689 static int
       
  1690 explore_fqdn(pai, hostname, servname, res)
       
  1691 	const struct addrinfo *pai;
       
  1692 	const char *hostname;
       
  1693 	const char *servname;
       
  1694 	struct addrinfo **res;
       
  1695 {
       
  1696 	struct addrinfo *result;
       
  1697 	struct addrinfo *cur;
       
  1698 	int error = 0;
       
  1699 	static const ns_dtab dtab[] = {
       
  1700 		NS_FILES_CB(_files_getaddrinfo, NULL)
       
  1701 		{ NSSRC_DNS, _dns_getaddrinfo, NULL },	/* force -DHESIOD */
       
  1702 		NS_NIS_CB(_yp_getaddrinfo, NULL)
       
  1703 		{ 0 }
       
  1704 	};
       
  1705 
       
  1706 	result = NULL;
       
  1707 
       
  1708 	/*
       
  1709 	 * if the servname does not match socktype/protocol, ignore it.
       
  1710 	 */
       
  1711 	if (get_portmatch(pai, servname) != 0)
       
  1712 		return 0;
       
  1713 
       
  1714 	switch (_nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",
       
  1715 			default_dns_files, hostname, pai)) {
       
  1716 	case NS_TRYAGAIN:
       
  1717 		error = EAI_AGAIN;
       
  1718 		goto free;
       
  1719 	case NS_UNAVAIL:
       
  1720 		error = EAI_FAIL;
       
  1721 		goto free;
       
  1722 	case NS_NOTFOUND:
       
  1723 		error = EAI_NONAME;
       
  1724 		goto free;
       
  1725 	case NS_SUCCESS:
       
  1726 		error = 0;
       
  1727 		for (cur = result; cur; cur = cur->ai_next) {
       
  1728 			GET_PORT(cur, servname);
       
  1729 			/* canonname should be filled already */
       
  1730 		}
       
  1731 		break;
       
  1732 	}
       
  1733 
       
  1734 	*res = result;
       
  1735 
       
  1736 	return 0;
       
  1737 
       
  1738 free:
       
  1739 	if (result)
       
  1740 		freeaddrinfo(result);
       
  1741 	return error;
       
  1742 }
       
  1743 #endif
       
  1744 #ifdef DEBUG
       
  1745 static const char AskedForGot[] =
       
  1746 	"gethostby*.getanswer: asked for \"%s\", got \"%s\"";
       
  1747 #endif
       
  1748 
       
  1749 #ifndef __SYMBIAN32__
       
  1750 static struct addrinfo *
       
  1751 getanswer(answer, anslen, qname, qtype, pai)
       
  1752 	const querybuf *answer;
       
  1753 	int anslen;
       
  1754 	const char *qname;
       
  1755 	int qtype;
       
  1756 	const struct addrinfo *pai;
       
  1757 {
       
  1758 	struct addrinfo sentinel, *cur;
       
  1759 	struct addrinfo ai;
       
  1760 	const struct afd *afd;
       
  1761 	char *canonname;
       
  1762 	const HEADER *hp;
       
  1763 	const u_char *cp;
       
  1764 	int n;
       
  1765 	const u_char *eom;
       
  1766 	char *bp, *ep;
       
  1767 	int type, class, ancount, qdcount;
       
  1768 	int haveanswer, had_error;
       
  1769 	char tbuf[MAXDNAME];
       
  1770 	int (*name_ok)(const char *);
       
  1771 	char hostbuf[8*1024];
       
  1772 
       
  1773 	memset(&sentinel, 0, sizeof(sentinel));
       
  1774 	cur = &sentinel;
       
  1775 
       
  1776 	canonname = NULL;
       
  1777 	eom = answer->buf + anslen;
       
  1778 	switch (qtype) {
       
  1779 	case T_A:
       
  1780 	case T_AAAA:
       
  1781 	case T_ANY:	/*use T_ANY only for T_A/T_AAAA lookup*/
       
  1782 		name_ok = res_hnok;
       
  1783 		break;
       
  1784 	default:
       
  1785 		return (NULL);	/* XXX should be abort(); */
       
  1786 	}
       
  1787 	/*
       
  1788 	 * find first satisfactory answer
       
  1789 	 */
       
  1790 	hp = &answer->hdr;
       
  1791 	ancount = ntohs(hp->ancount);
       
  1792 	qdcount = ntohs(hp->qdcount);
       
  1793 	bp = hostbuf;
       
  1794 	ep = hostbuf + sizeof hostbuf;
       
  1795 	cp = answer->buf + HFIXEDSZ;
       
  1796 	if (qdcount != 1) {
       
  1797 		h_errno = NO_RECOVERY;
       
  1798 		return (NULL);
       
  1799 	}
       
  1800 	n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
       
  1801 	if ((n < 0) || !(*name_ok)(bp)) {
       
  1802 		h_errno = NO_RECOVERY;
       
  1803 		return (NULL);
       
  1804 	}
       
  1805 	cp += n + QFIXEDSZ;
       
  1806 	if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
       
  1807 		/* res_send() has already verified that the query name is the
       
  1808 		 * same as the one we sent; this just gets the expanded name
       
  1809 		 * (i.e., with the succeeding search-domain tacked on).
       
  1810 		 */
       
  1811 		n = strlen(bp) + 1;		/* for the \0 */
       
  1812 		if (n >= MAXHOSTNAMELEN) {
       
  1813 			h_errno = NO_RECOVERY;
       
  1814 			return (NULL);
       
  1815 		}
       
  1816 		canonname = bp;
       
  1817 		bp += n;
       
  1818 		/* The qname can be abbreviated, but h_name is now absolute. */
       
  1819 		qname = canonname;
       
  1820 	}
       
  1821 	haveanswer = 0;
       
  1822 	had_error = 0;
       
  1823 	while (ancount-- > 0 && cp < eom && !had_error) {
       
  1824 		n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
       
  1825 		if ((n < 0) || !(*name_ok)(bp)) {
       
  1826 			had_error++;
       
  1827 			continue;
       
  1828 		}
       
  1829 		cp += n;			/* name */
       
  1830 		type = _getshort(cp);
       
  1831  		cp += INT16SZ;			/* type */
       
  1832 		class = _getshort(cp);
       
  1833  		cp += INT16SZ + INT32SZ;	/* class, TTL */
       
  1834 		n = _getshort(cp);
       
  1835 		cp += INT16SZ;			/* len */
       
  1836 		if (class != C_IN) {
       
  1837 			/* XXX - debug? syslog? */
       
  1838 			cp += n;
       
  1839 			continue;		/* XXX - had_error++ ? */
       
  1840 		}
       
  1841 		if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
       
  1842 		    type == T_CNAME) {
       
  1843 			n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
       
  1844 			if ((n < 0) || !(*name_ok)(tbuf)) {
       
  1845 				had_error++;
       
  1846 				continue;
       
  1847 			}
       
  1848 			cp += n;
       
  1849 			/* Get canonical name. */
       
  1850 			n = strlen(tbuf) + 1;	/* for the \0 */
       
  1851 			if (n > ep - bp || n >= MAXHOSTNAMELEN) {
       
  1852 				had_error++;
       
  1853 				continue;
       
  1854 			}
       
  1855 			strlcpy(bp, tbuf, ep - bp);
       
  1856 			canonname = bp;
       
  1857 			bp += n;
       
  1858 			continue;
       
  1859 		}
       
  1860 		if (qtype == T_ANY) {
       
  1861 			if (!(type == T_A || type == T_AAAA)) {
       
  1862 				cp += n;
       
  1863 				continue;
       
  1864 			}
       
  1865 		} else if (type != qtype) {
       
  1866 #ifdef DEBUG
       
  1867 			if (type != T_KEY && type != T_SIG)
       
  1868 #ifndef __SYMBIAN32__
       
  1869 			syslog(LOG_NOTICE|LOG_AUTH,
       
  1870 	       "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
       
  1871 				       qname, p_class(C_IN), p_type(qtype),
       
  1872 				       p_type(type));
       
  1873 #endif/* __SYMBIAN32__ */
       
  1874 #endif/* DEBUG */
       
  1875 			cp += n;
       
  1876 			continue;		/* XXX - had_error++ ? */
       
  1877 		}
       
  1878 		switch (type) {
       
  1879 		case T_A:
       
  1880 		case T_AAAA:
       
  1881 			if (strcasecmp(canonname, bp) != 0) {
       
  1882 #ifdef DEBUG
       
  1883 #ifndef __SYMBIAN32__
       
  1884 				syslog(LOG_NOTICE|LOG_AUTH, 
       
  1885 				AskedForGot,canonname, bp);
       
  1886 #endif/* __SYMBIAN32__ */
       
  1887 #endif/* DEBUG */
       
  1888 				cp += n;
       
  1889 				continue;	/* XXX - had_error++ ? */
       
  1890 			}
       
  1891 			if (type == T_A && n != INADDRSZ) {
       
  1892 				cp += n;
       
  1893 				continue;
       
  1894 			}
       
  1895 			if (type == T_AAAA && n != IN6ADDRSZ) {
       
  1896 				cp += n;
       
  1897 				continue;
       
  1898 			}
       
  1899 #ifdef FILTER_V4MAPPED
       
  1900 			if (type == T_AAAA) {
       
  1901 				struct in6_addr in6;
       
  1902 				memcpy(&in6, cp, sizeof(in6));
       
  1903 				if (IN6_IS_ADDR_V4MAPPED(&in6)) {
       
  1904 					cp += n;
       
  1905 					continue;
       
  1906 				}
       
  1907 			}
       
  1908 #endif
       
  1909 			if (!haveanswer) {
       
  1910 				int nn;
       
  1911 
       
  1912 				canonname = bp;
       
  1913 				nn = strlen(bp) + 1;	/* for the \0 */
       
  1914 				bp += nn;
       
  1915 			}
       
  1916 
       
  1917 			/* don't overwrite pai */
       
  1918 			ai = *pai;
       
  1919 			ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
       
  1920 			afd = find_afd(ai.ai_family);
       
  1921 			if (afd == NULL) {
       
  1922 				cp += n;
       
  1923 				continue;
       
  1924 			}
       
  1925 			cur->ai_next = get_ai(&ai, afd, (const char *)cp);
       
  1926 			if (cur->ai_next == NULL)
       
  1927 				had_error++;
       
  1928 			while (cur && cur->ai_next)
       
  1929 				cur = cur->ai_next;
       
  1930 			cp += n;
       
  1931 			break;
       
  1932 		default:
       
  1933 			abort();
       
  1934 		}
       
  1935 		if (!had_error)
       
  1936 			haveanswer++;
       
  1937 	}
       
  1938 	if (haveanswer) {
       
  1939 #if defined(RESOLVSORT)
       
  1940 		/*
       
  1941 		 * We support only IPv4 address for backward
       
  1942 		 * compatibility against gethostbyname(3).
       
  1943 		 */
       
  1944 		if (_res.nsort && qtype == T_A) {
       
  1945 			if (addr4sort(&sentinel) < 0) {
       
  1946 				freeaddrinfo(sentinel.ai_next);
       
  1947 				h_errno = NO_RECOVERY;
       
  1948 				return NULL;
       
  1949 			}
       
  1950 		}
       
  1951 #endif /*RESOLVSORT*/
       
  1952 		if (!canonname)
       
  1953 			(void)get_canonname(pai, sentinel.ai_next, qname);
       
  1954 		else
       
  1955 			(void)get_canonname(pai, sentinel.ai_next, canonname);
       
  1956 		h_errno = NETDB_SUCCESS;
       
  1957 		return sentinel.ai_next;
       
  1958 	}
       
  1959 
       
  1960 	h_errno = NO_RECOVERY;
       
  1961 	return NULL;
       
  1962 }
       
  1963 #endif /* __SYMBIAN32__ */
       
  1964 
       
  1965 
       
  1966 #ifdef RESOLVSORT
       
  1967 #ifndef __SYMBIAN32__
       
  1968 
       
  1969 struct addr_ptr {
       
  1970 	struct addrinfo *ai;
       
  1971 	int aval;
       
  1972 };
       
  1973 
       
  1974 static int
       
  1975 addr4sort(struct addrinfo *sentinel)
       
  1976 {
       
  1977 	struct addrinfo *ai;
       
  1978 	struct addr_ptr *addrs, addr;
       
  1979 	struct sockaddr_in *sin;
       
  1980 	int naddrs, i, j;
       
  1981 	int needsort = 0;
       
  1982 
       
  1983 	if (!sentinel)
       
  1984 		return -1;
       
  1985 	naddrs = 0;
       
  1986 	for (ai = sentinel->ai_next; ai; ai = ai->ai_next)
       
  1987 		naddrs++;
       
  1988 	if (naddrs < 2)
       
  1989 		return 0;		/* We don't need sorting. */
       
  1990 	if ((addrs = malloc(sizeof(struct addr_ptr) * naddrs)) == NULL)
       
  1991 		return -1;
       
  1992 	i = 0;
       
  1993 	for (ai = sentinel->ai_next; ai; ai = ai->ai_next) {
       
  1994 		sin = (struct sockaddr_in *)ai->ai_addr;
       
  1995 		for (j = 0; (unsigned)j < _res.nsort; j++) {
       
  1996 			if (_res.sort_list[j].addr.s_addr == 
       
  1997 			    (sin->sin_addr.s_addr & _res.sort_list[j].mask))
       
  1998 				break;
       
  1999 		}
       
  2000 		addrs[i].ai = ai;
       
  2001 		addrs[i].aval = j;
       
  2002 		if (needsort == 0 && i > 0 && j < addrs[i - 1].aval)
       
  2003 			needsort = i;
       
  2004 		i++;
       
  2005 	}
       
  2006 	if (!needsort) {
       
  2007 		free(addrs);
       
  2008 		return 0;
       
  2009 	}
       
  2010 
       
  2011 	while (needsort < naddrs) {
       
  2012 	    for (j = needsort - 1; j >= 0; j--) {
       
  2013 		if (addrs[j].aval > addrs[j+1].aval) {
       
  2014 		    addr = addrs[j];
       
  2015 		    addrs[j] = addrs[j + 1];
       
  2016 		    addrs[j + 1] = addr;
       
  2017 		} else
       
  2018 		    break;
       
  2019 	    }
       
  2020 	    needsort++;
       
  2021 	}
       
  2022 
       
  2023 	ai = sentinel;
       
  2024 	for (i = 0; i < naddrs; ++i) {
       
  2025 		ai->ai_next = addrs[i].ai;
       
  2026 		ai = ai->ai_next;
       
  2027 	}
       
  2028 	ai->ai_next = NULL;
       
  2029 	free(addrs);
       
  2030 	return 0;
       
  2031 }
       
  2032 #endif /*RESOLVSORT*/
       
  2033 #endif /*__SYMBIAN32__*/
       
  2034 
       
  2035 /*ARGSUSED*/
       
  2036 
       
  2037 #ifndef __SYMBIAN32__
       
  2038 static int
       
  2039 _dns_getaddrinfo(rv, cb_data, ap)
       
  2040 	void	*rv;
       
  2041 	void	*cb_data;
       
  2042 	va_list	 ap;
       
  2043 {
       
  2044 	struct addrinfo *ai;
       
  2045 	querybuf *buf, *buf2;
       
  2046 	const char *hostname;
       
  2047 	const struct addrinfo *pai;
       
  2048 	struct addrinfo sentinel, *cur;
       
  2049 	struct res_target q, q2;
       
  2050 
       
  2051 	hostname = va_arg(ap, char *);
       
  2052 	pai = va_arg(ap, const struct addrinfo *);
       
  2053 
       
  2054 	memset(&q, 0, sizeof(q2));
       
  2055 	memset(&q2, 0, sizeof(q2));
       
  2056 	memset(&sentinel, 0, sizeof(sentinel));
       
  2057 	cur = &sentinel;
       
  2058 
       
  2059 	buf = malloc(sizeof(*buf));
       
  2060 	if (!buf) {
       
  2061 		h_errno = NETDB_INTERNAL;
       
  2062 		return NS_NOTFOUND;
       
  2063 	}
       
  2064 	buf2 = malloc(sizeof(*buf2));
       
  2065 	if (!buf2) {
       
  2066 		free(buf);
       
  2067 		h_errno = NETDB_INTERNAL;
       
  2068 		return NS_NOTFOUND;
       
  2069 	}
       
  2070 
       
  2071 	switch (pai->ai_family) {
       
  2072 	case AF_UNSPEC:
       
  2073 		q.name = hostname;
       
  2074 		q.qclass = C_IN;
       
  2075 		q.qtype = T_A;
       
  2076 		q.answer = buf->buf;
       
  2077 		q.anslen = sizeof(buf->buf);
       
  2078 		q.next = &q2;
       
  2079 		q2.name = hostname;
       
  2080 		q2.qclass = C_IN;
       
  2081 		q2.qtype = T_AAAA;
       
  2082 		q2.answer = buf2->buf;
       
  2083 		q2.anslen = sizeof(buf2->buf);
       
  2084 		break;
       
  2085 	case AF_INET:
       
  2086 		q.name = hostname;
       
  2087 		q.qclass = C_IN;
       
  2088 		q.qtype = T_A;
       
  2089 		q.answer = buf->buf;
       
  2090 		q.anslen = sizeof(buf->buf);
       
  2091 		break;
       
  2092 	case AF_INET6:
       
  2093 		q.name = hostname;
       
  2094 		q.qclass = C_IN;
       
  2095 		q.qtype = T_AAAA;
       
  2096 		q.answer = buf->buf;
       
  2097 		q.anslen = sizeof(buf->buf);
       
  2098 		break;
       
  2099 	default:
       
  2100 		free(buf);
       
  2101 		free(buf2);
       
  2102 		return NS_UNAVAIL;
       
  2103 	}
       
  2104 	if (res_searchN(hostname, &q) < 0) {
       
  2105 		free(buf);
       
  2106 		free(buf2);
       
  2107 		return NS_NOTFOUND;
       
  2108 	}
       
  2109 	/* prefer IPv6 */
       
  2110 	if (q.next) {
       
  2111 		ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai);
       
  2112 		if (ai) {
       
  2113 			cur->ai_next = ai;
       
  2114 			while (cur && cur->ai_next)
       
  2115 				cur = cur->ai_next;
       
  2116 		}
       
  2117 	}
       
  2118 	ai = getanswer(buf, q.n, q.name, q.qtype, pai);
       
  2119 	if (ai)
       
  2120 		cur->ai_next = ai;
       
  2121 	free(buf);
       
  2122 	free(buf2);
       
  2123 	if (sentinel.ai_next == NULL)
       
  2124 		switch (h_errno) {
       
  2125 		case HOST_NOT_FOUND:
       
  2126 			return NS_NOTFOUND;
       
  2127 		case TRY_AGAIN:
       
  2128 			return NS_TRYAGAIN;
       
  2129 		default:
       
  2130 			return NS_UNAVAIL;
       
  2131 		}
       
  2132 	*((struct addrinfo **)rv) = sentinel.ai_next;
       
  2133 	return NS_SUCCESS;
       
  2134 }
       
  2135 
       
  2136 #endif /* __SYMBIAN32__ */
       
  2137 
       
  2138 #ifndef __SYMBIAN32__
       
  2139 static void
       
  2140 _sethtent(FILE **hostf)
       
  2141 {
       
  2142 	if (!*hostf) {	}
       
  2143 	
       
  2144 #ifndef __SYMBIAN32__
       
  2145 		*hostf = fopen(_PATH_HOSTS, "r");
       
  2146 #endif	
       
  2147 	else
       
  2148 		rewind(*hostf);
       
  2149 }
       
  2150 
       
  2151 static void
       
  2152 _endhtent(FILE **hostf)
       
  2153 {
       
  2154 	if (*hostf) {
       
  2155 		(void) fclose(*hostf);
       
  2156 		*hostf = NULL;
       
  2157 	}
       
  2158 }
       
  2159 #endif /* __SYMBIAN32__ */
       
  2160 
       
  2161 #ifndef __SYMBIAN32__
       
  2162 
       
  2163 static struct addrinfo *
       
  2164 _gethtent(FILE **hostf, const char *name, const struct addrinfo *pai)
       
  2165 {
       
  2166 	char *p;
       
  2167 	char *cp, *tname, *cname;
       
  2168 	struct addrinfo hints, *res0, *res;
       
  2169 	int error;
       
  2170 	const char *addr;
       
  2171 	char hostbuf[8*1024];
       
  2172 #ifndef __SYMBIAN32__
       
  2173 	if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "r")))
       
  2174 #endif//__SYMBIAN32__	
       
  2175 		return (NULL);
       
  2176 again:
       
  2177 	if (!(p = fgets(hostbuf, sizeof hostbuf, *hostf)))
       
  2178 		return (NULL);
       
  2179 	if (*p == '#')
       
  2180 		goto again;
       
  2181 	// to strip both carriage return and line feed character 
       
  2182 	cp = strpbrk(p, "#\r\n");
       
  2183 	
       
  2184 	if (cp != NULL)
       
  2185 		*cp = '\0';
       
  2186 	if (!(cp = strpbrk(p, " \t")))
       
  2187 		goto again;
       
  2188 	*cp++ = '\0';
       
  2189 	addr = p;
       
  2190 	cname = NULL;
       
  2191 	/* if this is not something we're looking for, skip it. */
       
  2192 	while (cp && *cp) {
       
  2193 		if (*cp == ' ' || *cp == '\t') {
       
  2194 			cp++;
       
  2195 			continue;
       
  2196 		}
       
  2197 		tname = cp;
       
  2198 		if (cname == NULL)
       
  2199 			cname = cp;
       
  2200 		if ((cp = strpbrk(cp, " \t")) != NULL)
       
  2201 			*cp++ = '\0';
       
  2202 		if (strcasecmp(name, tname) == 0)
       
  2203 			goto found;
       
  2204 	}
       
  2205 	goto again;
       
  2206 
       
  2207 found:
       
  2208 	/* we should not glob socktype/protocol here */
       
  2209 	memset(&hints, 0, sizeof(hints));
       
  2210 	hints.ai_family = pai->ai_family;
       
  2211 	hints.ai_socktype = SOCK_DGRAM;
       
  2212 	hints.ai_protocol = 0;
       
  2213 	hints.ai_flags = AI_NUMERICHOST;
       
  2214 	error = getaddrinfo(addr, "0", &hints, &res0);
       
  2215 	if (error)
       
  2216 		goto again;
       
  2217 #ifdef FILTER_V4MAPPED
       
  2218 	/* XXX should check all items in the chain */
       
  2219 	if (res0->ai_family == AF_INET6 &&
       
  2220 	    IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)res0->ai_addr)->sin6_addr)) {
       
  2221 		freeaddrinfo(res0);
       
  2222 		goto again;
       
  2223 	}
       
  2224 #endif
       
  2225 	for (res = res0; res; res = res->ai_next) {
       
  2226 		/* cover it up */
       
  2227 		res->ai_flags = pai->ai_flags;
       
  2228 		res->ai_socktype = pai->ai_socktype;
       
  2229 		res->ai_protocol = pai->ai_protocol;
       
  2230 
       
  2231 		if (pai->ai_flags & AI_CANONNAME) {
       
  2232 			if (get_canonname(pai, res, cname) != 0) {
       
  2233 				freeaddrinfo(res0);
       
  2234 				goto again;
       
  2235 			}
       
  2236 		}
       
  2237 	}
       
  2238 	return res0;
       
  2239 }
       
  2240 
       
  2241 #endif //__SYMBIAN32__
       
  2242 /*ARGSUSED*/
       
  2243 #ifndef __SYMBIAN32__
       
  2244 
       
  2245 static int
       
  2246 _files_getaddrinfo(rv, cb_data, ap)
       
  2247 	void	*rv;
       
  2248 	void	*cb_data;
       
  2249 	va_list	 ap;
       
  2250 {
       
  2251 	const char *name;
       
  2252 	const struct addrinfo *pai;
       
  2253 	struct addrinfo sentinel, *cur;
       
  2254 	struct addrinfo *p;
       
  2255 	FILE *hostf = NULL;
       
  2256 	name = va_arg(ap, char *);
       
  2257 	pai = va_arg(ap, struct addrinfo *);
       
  2258 
       
  2259 	memset(&sentinel, 0, sizeof(sentinel));
       
  2260 	cur = &sentinel;
       
  2261 
       
  2262 	_sethtent(&hostf);
       
  2263 	while ((p = _gethtent(&hostf, name, pai)) != NULL) {
       
  2264 		cur->ai_next = p;
       
  2265 		while (cur && cur->ai_next)
       
  2266 			cur = cur->ai_next;
       
  2267 	}
       
  2268 	_endhtent(&hostf);
       
  2269 
       
  2270 	*((struct addrinfo **)rv) = sentinel.ai_next;
       
  2271 	if (sentinel.ai_next == NULL)
       
  2272 		return NS_NOTFOUND;
       
  2273 	return NS_SUCCESS;
       
  2274 }
       
  2275 #endif // __SYMBIAN32__
       
  2276 
       
  2277 #ifdef YP
       
  2278 /*ARGSUSED*/
       
  2279 static struct addrinfo *
       
  2280 _yphostent(line, pai)
       
  2281 	char *line;
       
  2282 	const struct addrinfo *pai;
       
  2283 {
       
  2284 	struct addrinfo sentinel, *cur;
       
  2285 	struct addrinfo hints, *res, *res0;
       
  2286 	int error;
       
  2287 	char *p = line;
       
  2288 	const char *addr, *canonname;
       
  2289 	char *nextline;
       
  2290 	char *cp;
       
  2291 
       
  2292 	addr = canonname = NULL;
       
  2293 
       
  2294 	memset(&sentinel, 0, sizeof(sentinel));
       
  2295 	cur = &sentinel;
       
  2296 
       
  2297 nextline:
       
  2298 	/* terminate line */
       
  2299 	cp = strchr(p, '\n');
       
  2300 	if (cp) {
       
  2301 		*cp++ = '\0';
       
  2302 		nextline = cp;
       
  2303 	} else
       
  2304 		nextline = NULL;
       
  2305 
       
  2306 	cp = strpbrk(p, " \t");
       
  2307 	if (cp == NULL) {
       
  2308 		if (canonname == NULL)
       
  2309 			return (NULL);
       
  2310 		else
       
  2311 			goto done;
       
  2312 	}
       
  2313 	*cp++ = '\0';
       
  2314 
       
  2315 	addr = p;
       
  2316 
       
  2317 	while (cp && *cp) {
       
  2318 		if (*cp == ' ' || *cp == '\t') {
       
  2319 			cp++;
       
  2320 			continue;
       
  2321 		}
       
  2322 		if (!canonname)
       
  2323 			canonname = cp;
       
  2324 		if ((cp = strpbrk(cp, " \t")) != NULL)
       
  2325 			*cp++ = '\0';
       
  2326 	}
       
  2327 
       
  2328 	hints = *pai;
       
  2329 	hints.ai_flags = AI_NUMERICHOST;
       
  2330 	error = getaddrinfo(addr, NULL, &hints, &res0);
       
  2331 	if (error == 0) {
       
  2332 		for (res = res0; res; res = res->ai_next) {
       
  2333 			/* cover it up */
       
  2334 			res->ai_flags = pai->ai_flags;
       
  2335 
       
  2336 			if (pai->ai_flags & AI_CANONNAME)
       
  2337 				(void)get_canonname(pai, res, canonname);
       
  2338 		}
       
  2339 	} else
       
  2340 		res0 = NULL;
       
  2341 	if (res0) {
       
  2342 		cur->ai_next = res0;
       
  2343 		while (cur && cur->ai_next)
       
  2344 			cur = cur->ai_next;
       
  2345 	}
       
  2346 
       
  2347 	if (nextline) {
       
  2348 		p = nextline;
       
  2349 		goto nextline;
       
  2350 	}
       
  2351 
       
  2352 done:
       
  2353 	return sentinel.ai_next;
       
  2354 }
       
  2355 
       
  2356 /*ARGSUSED*/
       
  2357 static int
       
  2358 _yp_getaddrinfo(rv, cb_data, ap)
       
  2359 	void	*rv;
       
  2360 	void	*cb_data;
       
  2361 	va_list	 ap;
       
  2362 {
       
  2363 	struct addrinfo sentinel, *cur;
       
  2364 	struct addrinfo *ai = NULL;
       
  2365 	char *ypbuf;
       
  2366 	int ypbuflen, r;
       
  2367 	const char *name;
       
  2368 	const struct addrinfo *pai;
       
  2369 	char *ypdomain;
       
  2370 
       
  2371 	if (_yp_check(&ypdomain) == 0)
       
  2372 		return NS_UNAVAIL;
       
  2373 
       
  2374 	name = va_arg(ap, char *);
       
  2375 	pai = va_arg(ap, const struct addrinfo *);
       
  2376 
       
  2377 	memset(&sentinel, 0, sizeof(sentinel));
       
  2378 	cur = &sentinel;
       
  2379 
       
  2380 	/* hosts.byname is only for IPv4 (Solaris8) */
       
  2381 	if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) {
       
  2382 		r = yp_match(ypdomain, "hosts.byname", name,
       
  2383 			(int)strlen(name), &ypbuf, &ypbuflen);
       
  2384 		if (r == 0) {
       
  2385 			struct addrinfo ai4;
       
  2386 
       
  2387 			ai4 = *pai;
       
  2388 			ai4.ai_family = AF_INET;
       
  2389 			ai = _yphostent(ypbuf, &ai4);
       
  2390 			if (ai) {
       
  2391 				cur->ai_next = ai;
       
  2392 				while (cur && cur->ai_next)
       
  2393 					cur = cur->ai_next;
       
  2394 			}
       
  2395 			free(ypbuf);
       
  2396 		}
       
  2397 	}
       
  2398 
       
  2399 	/* ipnodes.byname can hold both IPv4/v6 */
       
  2400 	r = yp_match(ypdomain, "ipnodes.byname", name,
       
  2401 		(int)strlen(name), &ypbuf, &ypbuflen);
       
  2402 	if (r == 0) {
       
  2403 		ai = _yphostent(ypbuf, pai);
       
  2404 		if (ai)
       
  2405 			cur->ai_next = ai;
       
  2406 		free(ypbuf);
       
  2407 	}
       
  2408 
       
  2409 	if (sentinel.ai_next == NULL) {
       
  2410 		h_errno = HOST_NOT_FOUND;
       
  2411 		return NS_NOTFOUND;
       
  2412 	}
       
  2413 	*((struct addrinfo **)rv) = sentinel.ai_next;
       
  2414 	return NS_SUCCESS;
       
  2415 }
       
  2416 #endif
       
  2417 
       
  2418 /* resolver logic */
       
  2419 
       
  2420 extern const char *_res_hostalias(const char *, char *, size_t);
       
  2421 
       
  2422 /*
       
  2423  * Formulate a normal query, send, and await answer.
       
  2424  * Returned answer is placed in supplied buffer "answer".
       
  2425  * Perform preliminary check of answer, returning success only
       
  2426  * if no error is indicated and the answer count is nonzero.
       
  2427  * Return the size of the response on success, -1 on error.
       
  2428  * Error number is left in h_errno.
       
  2429  *
       
  2430  * Caller must parse answer and determine whether it answers the question.
       
  2431  */
       
  2432 #ifndef __SYMBIAN32__
       
  2433 static int
       
  2434 res_queryN(name, target)
       
  2435 	const char *name;	/* domain name */
       
  2436 	struct res_target *target;
       
  2437 {
       
  2438 	u_char *buf;
       
  2439 	HEADER *hp;
       
  2440 	int n;
       
  2441 	struct res_target *t;
       
  2442 	int rcode;
       
  2443 	int ancount;
       
  2444 
       
  2445 	rcode = NOERROR;
       
  2446 	ancount = 0;
       
  2447 
       
  2448 	buf = malloc(MAXPACKET);
       
  2449 	if (!buf) {
       
  2450 		h_errno = NETDB_INTERNAL;
       
  2451 		return -1;
       
  2452 	}
       
  2453 
       
  2454 	for (t = target; t; t = t->next) {
       
  2455 		int class, type;
       
  2456 		u_char *answer;
       
  2457 		int anslen;
       
  2458 
       
  2459 		hp = (HEADER *)(void *)t->answer;
       
  2460 		hp->rcode = NOERROR;	/* default */
       
  2461 
       
  2462 		/* make it easier... */
       
  2463 		class = t->qclass;
       
  2464 		type = t->qtype;
       
  2465 		answer = t->answer;
       
  2466 		anslen = t->anslen;
       
  2467 #ifdef DEBUG
       
  2468 		if (_res.options & RES_DEBUG)
       
  2469 			printf(";; res_query(%s, %d, %d)\n", name, class, type);
       
  2470 #endif
       
  2471 
       
  2472 		n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
       
  2473 		    buf, MAXPACKET);
       
  2474 		if (n > 0 && (_res.options & RES_USE_EDNS0) != 0)
       
  2475 			n = res_opt(n, buf, MAXPACKET, anslen);
       
  2476 		if (n <= 0) {
       
  2477 #ifdef DEBUG
       
  2478 			if (_res.options & RES_DEBUG)
       
  2479 				printf(";; res_query: mkquery failed\n");
       
  2480 #endif
       
  2481 			free(buf);
       
  2482 			h_errno = NO_RECOVERY;
       
  2483 			return (n);
       
  2484 		}
       
  2485 		n = res_send(buf, n, answer, anslen);
       
  2486 #if 0
       
  2487 		if (n < 0) {
       
  2488 #ifdef DEBUG
       
  2489 			if (_res.options & RES_DEBUG)
       
  2490 				printf(";; res_query: send error\n");
       
  2491 #endif
       
  2492 			free(buf);
       
  2493 			h_errno = TRY_AGAIN;
       
  2494 			return (n);
       
  2495 		}
       
  2496 #endif
       
  2497 
       
  2498 		if (n < 0 || n > anslen)
       
  2499 			hp->rcode = FORMERR; /* XXX not very informative */
       
  2500 		if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
       
  2501 			rcode = hp->rcode;	/* record most recent error */
       
  2502 #ifdef DEBUG
       
  2503 			if (_res.options & RES_DEBUG)
       
  2504 				printf(";; rcode = %u, ancount=%u\n", hp->rcode,
       
  2505 				    ntohs(hp->ancount));
       
  2506 #endif
       
  2507 			continue;
       
  2508 		}
       
  2509 
       
  2510 		ancount += ntohs(hp->ancount);
       
  2511 
       
  2512 		t->n = n;
       
  2513 	}
       
  2514 
       
  2515 	free(buf);
       
  2516 
       
  2517 	if (ancount == 0) {
       
  2518 		switch (rcode) {
       
  2519 		case NXDOMAIN:
       
  2520 			h_errno = HOST_NOT_FOUND;
       
  2521 			break;
       
  2522 		case SERVFAIL:
       
  2523 			h_errno = TRY_AGAIN;
       
  2524 			break;
       
  2525 		case NOERROR:
       
  2526 			h_errno = NO_DATA;
       
  2527 			break;
       
  2528 		case FORMERR:
       
  2529 		case NOTIMP:
       
  2530 		case REFUSED:
       
  2531 		default:
       
  2532 			h_errno = NO_RECOVERY;
       
  2533 			break;
       
  2534 		}
       
  2535 		return (-1);
       
  2536 	}
       
  2537 	return (ancount);
       
  2538 }
       
  2539 
       
  2540 #endif
       
  2541 
       
  2542 /*
       
  2543  * Formulate a normal query, send, and retrieve answer in supplied buffer.
       
  2544  * Return the size of the response on success, -1 on error.
       
  2545  * If enabled, implement search rules until answer or unrecoverable failure
       
  2546  * is detected.  Error code, if any, is left in h_errno.
       
  2547  */
       
  2548 #ifndef __SYMBIAN32__
       
  2549 static int
       
  2550 res_searchN(name, target)
       
  2551 	const char *name;	/* domain name */
       
  2552 	struct res_target *target;
       
  2553 {
       
  2554 	const char *cp, * const *domain;
       
  2555 	HEADER *hp = (HEADER *)(void *)target->answer;	/*XXX*/
       
  2556 	u_int dots;
       
  2557 	int trailing_dot, ret, saved_herrno;
       
  2558 	int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
       
  2559 	char abuf[MAXDNAME];
       
  2560 
       
  2561 	if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
       
  2562 		h_errno = NETDB_INTERNAL;
       
  2563 		return (-1);
       
  2564 	}
       
  2565 
       
  2566 	errno = 0;
       
  2567 	h_errno = HOST_NOT_FOUND;	/* default, if we never query */
       
  2568 	dots = 0;
       
  2569 	for (cp = name; *cp; cp++)
       
  2570 		dots += (*cp == '.');
       
  2571 	trailing_dot = 0;
       
  2572 	if (cp > name && *--cp == '.')
       
  2573 		trailing_dot++;
       
  2574 
       
  2575 	/*
       
  2576 	 * if there aren't any dots, it could be a user-level alias
       
  2577 	 */
       
  2578 	if (!dots && (cp = _res_hostalias(name, abuf, sizeof(abuf))) != NULL)
       
  2579 		return (res_queryN(cp, target));
       
  2580 
       
  2581 	/*
       
  2582 	 * If there are dots in the name already, let's just give it a try
       
  2583 	 * 'as is'.  The threshold can be set with the "ndots" option.
       
  2584 	 */
       
  2585 	saved_herrno = -1;
       
  2586 	if (dots >= _res.ndots) {
       
  2587 		ret = res_querydomainN(name, NULL, target);
       
  2588 		if (ret > 0)
       
  2589 			return (ret);
       
  2590 		saved_herrno = h_errno;
       
  2591 		tried_as_is++;
       
  2592 	}
       
  2593 
       
  2594 	/*
       
  2595 	 * We do at least one level of search if
       
  2596 	 *	- there is no dot and RES_DEFNAME is set, or
       
  2597 	 *	- there is at least one dot, there is no trailing dot,
       
  2598 	 *	  and RES_DNSRCH is set.
       
  2599 	 */
       
  2600 	if ((!dots && (_res.options & RES_DEFNAMES)) ||
       
  2601 	    (dots && !trailing_dot && (_res.options & RES_DNSRCH))) {
       
  2602 		int done = 0;
       
  2603 
       
  2604 		for (domain = (const char * const *)_res.dnsrch;
       
  2605 		   *domain && !done;
       
  2606 		   domain++) {
       
  2607 
       
  2608 			ret = res_querydomainN(name, *domain, target);
       
  2609 			if (ret > 0)
       
  2610 				return (ret);
       
  2611 
       
  2612 			/*
       
  2613 			 * If no server present, give up.
       
  2614 			 * If name isn't found in this domain,
       
  2615 			 * keep trying higher domains in the search list
       
  2616 			 * (if that's enabled).
       
  2617 			 * On a NO_DATA error, keep trying, otherwise
       
  2618 			 * a wildcard entry of another type could keep us
       
  2619 			 * from finding this entry higher in the domain.
       
  2620 			 * If we get some other error (negative answer or
       
  2621 			 * server failure), then stop searching up,
       
  2622 			 * but try the input name below in case it's
       
  2623 			 * fully-qualified.
       
  2624 			 */
       
  2625 			if (errno == ECONNREFUSED) {
       
  2626 				h_errno = TRY_AGAIN;
       
  2627 				return (-1);
       
  2628 			}
       
  2629 
       
  2630 			switch (h_errno) {
       
  2631 			case NO_DATA:
       
  2632 				got_nodata++;
       
  2633 				/* FALLTHROUGH */
       
  2634 			case HOST_NOT_FOUND:
       
  2635 				/* keep trying */
       
  2636 				break;
       
  2637 			case TRY_AGAIN:
       
  2638 				if (hp->rcode == SERVFAIL) {
       
  2639 					/* try next search element, if any */
       
  2640 					got_servfail++;
       
  2641 					break;
       
  2642 				}
       
  2643 				/* FALLTHROUGH */
       
  2644 			default:
       
  2645 				/* anything else implies that we're done */
       
  2646 				done++;
       
  2647 			}
       
  2648 			/*
       
  2649 			 * if we got here for some reason other than DNSRCH,
       
  2650 			 * we only wanted one iteration of the loop, so stop.
       
  2651 			 */
       
  2652 			if (!(_res.options & RES_DNSRCH))
       
  2653 			        done++;
       
  2654 		}
       
  2655 	}
       
  2656 
       
  2657 	/*
       
  2658 	 * if we have not already tried the name "as is", do that now.
       
  2659 	 * note that we do this regardless of how many dots were in the
       
  2660 	 * name or whether it ends with a dot.
       
  2661 	 */
       
  2662 	if (!tried_as_is && (dots || !(_res.options & RES_NOTLDQUERY))) {
       
  2663 		ret = res_querydomainN(name, NULL, target);
       
  2664 		if (ret > 0)
       
  2665 			return (ret);
       
  2666 	}
       
  2667 
       
  2668 	/*
       
  2669 	 * if we got here, we didn't satisfy the search.
       
  2670 	 * if we did an initial full query, return that query's h_errno
       
  2671 	 * (note that we wouldn't be here if that query had succeeded).
       
  2672 	 * else if we ever got a nodata, send that back as the reason.
       
  2673 	 * else send back meaningless h_errno, that being the one from
       
  2674 	 * the last DNSRCH we did.
       
  2675 	 */
       
  2676 	if (saved_herrno != -1)
       
  2677 		h_errno = saved_herrno;
       
  2678 	else if (got_nodata)
       
  2679 		h_errno = NO_DATA;
       
  2680 	else if (got_servfail)
       
  2681 		h_errno = TRY_AGAIN;
       
  2682 	return (-1);
       
  2683 }
       
  2684 #endif
       
  2685 /*
       
  2686  * Perform a call on res_query on the concatenation of name and domain,
       
  2687  * removing a trailing dot from name if domain is NULL.
       
  2688  */
       
  2689  
       
  2690 #ifndef __SYMBIAN32__
       
  2691 static int
       
  2692 res_querydomainN(name, domain, target)
       
  2693 	const char *name, *domain;
       
  2694 	struct res_target *target;
       
  2695 {
       
  2696 	char nbuf[MAXDNAME];
       
  2697 	const char *longname = nbuf;
       
  2698 	size_t n, d;
       
  2699 
       
  2700 #ifdef DEBUG
       
  2701 	if (_res.options & RES_DEBUG)
       
  2702 		printf(";; res_querydomain(%s, %s)\n",
       
  2703 			name, domain?domain:"<Nil>");
       
  2704 #endif
       
  2705 	if (domain == NULL) {
       
  2706 		/*
       
  2707 		 * Check for trailing '.';
       
  2708 		 * copy without '.' if present.
       
  2709 		 */
       
  2710 		n = strlen(name);
       
  2711 		if (n >= MAXDNAME) {
       
  2712 			h_errno = NO_RECOVERY;
       
  2713 			return (-1);
       
  2714 		}
       
  2715 		if (n > 0 && name[--n] == '.') {
       
  2716 			strncpy(nbuf, name, n);
       
  2717 			nbuf[n] = '\0';
       
  2718 		} else
       
  2719 			longname = name;
       
  2720 	} else {
       
  2721 		n = strlen(name);
       
  2722 		d = strlen(domain);
       
  2723 		if (n + d + 1 >= MAXDNAME) {
       
  2724 			h_errno = NO_RECOVERY;
       
  2725 			return (-1);
       
  2726 		}
       
  2727 		snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
       
  2728 	}
       
  2729 	return (res_queryN(longname, target));
       
  2730 }
       
  2731 #endif /*__SYMBIAN32__*/
       
  2732 
       
  2733 #ifdef __SYMBIAN32__
       
  2734 static long int
       
  2735 explore_hostname(pai, hostname, servname, res, hints)
       
  2736 	struct addrinfo *pai;
       
  2737 	const char *hostname;
       
  2738 	const char *servname;
       
  2739 	struct addrinfo **res;
       
  2740 	const struct addrinfo *hints;
       
  2741 {
       
  2742 	const struct afd *afd;
       
  2743 	struct addrinfo *cur;
       
  2744 	struct addrinfo sentinel;
       
  2745 	int error;
       
  2746     int family_flag=0;
       
  2747 	*res = NULL;
       
  2748 	
       
  2749 	sentinel.ai_next = NULL;
       
  2750 	cur = &sentinel;
       
  2751  
       
  2752 	/*
       
  2753 	 * if the servname does not match socktype/protocol, ignore it.
       
  2754 	 */
       
  2755  
       
  2756  	if (get_portmatch(pai, servname) != 0)
       
  2757 	 	return 0;
       
  2758         if (pai->ai_family == PF_UNSPEC) {
       
  2759 #ifdef PF_INET6
       
  2760 #ifdef __SYMBIAN32__		
       
  2761 // XXX: Fix this
       
  2762 			pai->ai_family = PF_INET;
       
  2763 #else			
       
  2764 			pai->ai_family = PF_INET6;
       
  2765 #endif // __SYMBIAN32__	
       
  2766 #else
       
  2767 			pai->ai_family = PF_INET;
       
  2768 #endif
       
  2769             family_flag=1;
       
  2770         }
       
  2771      
       
  2772 	afd = find_afd(pai->ai_family);
       
  2773     if( afd==NULL && family_flag )
       
  2774        	{
       
  2775        	if(pai->ai_family==PF_INET6)
       
  2776        		{
       
  2777        		pai->ai_family=PF_INET;
       
  2778        		}
       
  2779        	else
       
  2780        		{
       
  2781        		pai->ai_family=PF_INET6;
       
  2782        		}
       
  2783        	afd=find_afd(pai->ai_family);
       
  2784        	}
       
  2785 
       
  2786     if (afd == NULL)
       
  2787         {
       
  2788         return 0;
       
  2789         }
       
  2790        
       
  2791 	if ( pai->ai_family == PF_UNSPEC ||pai->ai_family == afd->a_af)
       
  2792 		{
       
  2793 		struct addrinfo *resNative;
       
  2794 		struct addrinfo *currNative;
       
  2795 		int haveV4Mapped = 0;
       
  2796 		/* Get the list of addresses using the native api */
       
  2797 		int ret = getaddrinfo_private(hostname, pai, &resNative);
       
  2798 		if(ret != 0)
       
  2799 			ERR(ret);
       
  2800 		
       
  2801 		/* copy the addresses to the local list */
       
  2802 		currNative = resNative;
       
  2803 	      while(currNative)
       
  2804 	            {
       
  2805 	            if(currNative->ai_family == PF_INET && (hints->ai_family == PF_INET || hints->ai_family == PF_UNSPEC))
       
  2806 	                {
       
  2807 	                if(currNative->ai_flags & AI_V4MAPPED)
       
  2808 	                    {
       
  2809 	                    haveV4Mapped = 1;
       
  2810 	                    }
       
  2811 	                else
       
  2812 	                    {
       
  2813 	                    struct sockaddr_in* sAddrTmp = (struct sockaddr_in*) (currNative->ai_addr);
       
  2814 	                    GET_AI(cur->ai_next, afd, (char*)&(sAddrTmp->sin_addr));
       
  2815 	                    cur->ai_next->ai_addr->sa_family = cur->ai_next->ai_family  = PF_INET;
       
  2816 	                    GET_PORT(cur->ai_next, servname);
       
  2817 	                    
       
  2818 	                    if((pai->ai_flags & AI_CANONNAME)) 
       
  2819 	                        GET_CANONNAME(cur->ai_next, currNative->ai_canonname);
       
  2820 	                    
       
  2821 	                    cur = cur->ai_next;
       
  2822 	                    }
       
  2823 	                }
       
  2824 	            
       
  2825 	            if(currNative->ai_family == PF_INET6 && (hints->ai_family == PF_INET6 || hints->ai_family == PF_UNSPEC))
       
  2826 	                {
       
  2827 	                struct sockaddr_in6* sAddrTmp = (struct sockaddr_in6*) (currNative->ai_addr);
       
  2828 	                GET_AI(cur->ai_next, afd, (char*)&(sAddrTmp->sin6_addr));
       
  2829 	                cur->ai_next->ai_addr->sa_family = cur->ai_next->ai_family = PF_INET6;
       
  2830 	                GET_PORT(cur->ai_next, servname);
       
  2831 	                 
       
  2832 	                if((pai->ai_flags & AI_CANONNAME)) 
       
  2833 	                    GET_CANONNAME(cur->ai_next, currNative->ai_canonname);
       
  2834 	                
       
  2835 	                cur = cur->ai_next;
       
  2836 	                }
       
  2837 	            
       
  2838 	            currNative = currNative->ai_next;   
       
  2839 	            }
       
  2840 
       
  2841 	        if(hints->ai_family == PF_INET && !sentinel.ai_next && haveV4Mapped)
       
  2842 	            {
       
  2843 	            currNative = resNative;
       
  2844 	            while(currNative)
       
  2845 	                {
       
  2846 	                //This is the set of Mapped Addresses.
       
  2847 	                if(currNative->ai_flags & AI_V4MAPPED)
       
  2848 	                    {
       
  2849 	                    struct sockaddr_in* sAddrTmp = (struct sockaddr_in*) (currNative->ai_addr);
       
  2850 	                    currNative->ai_flags &= ~AI_V4MAPPED;
       
  2851 	                    GET_AI(cur->ai_next, afd, (char*)&(sAddrTmp->sin_addr));
       
  2852 	                    cur->ai_next->ai_addr->sa_family = cur->ai_next->ai_family  = PF_INET;
       
  2853 	                    GET_PORT(cur->ai_next, servname);
       
  2854 	                    
       
  2855 	                    if((pai->ai_flags & AI_CANONNAME)) 
       
  2856 	                        GET_CANONNAME(cur->ai_next, currNative->ai_canonname);      
       
  2857 	                    cur = cur->ai_next;
       
  2858 	                    }
       
  2859 	                
       
  2860 	                currNative = currNative->ai_next;   
       
  2861 	                }
       
  2862 	            }
       
  2863 		/* free the address list returned by native api */
       
  2864 		freeaddrinfo_private(resNative);
       
  2865 		}
       
  2866 	else
       
  2867 		ERR(EAI_FAMILY);
       
  2868 
       
  2869 	*res = sentinel.ai_next;
       
  2870 	return 0;
       
  2871 
       
  2872 free:
       
  2873 bad:
       
  2874 	if (sentinel.ai_next)
       
  2875 		freeaddrinfo(sentinel.ai_next);
       
  2876 	return error;
       
  2877 }
       
  2878 
       
  2879 #endif//__SYMBIAN32__