am 2d94ee29: Merge "Revert "Revert "Hide _tolower_tab_ and _toupper_tab_ on LP64."""
[android-sdk/platform-bionic.git] / libc / dns / resolv / res_send.c
1 /*      $NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $    */
3 /*
4  * Copyright 2008  Android Open Source Project (source port randomization)
5  * Copyright (c) 1985, 1989, 1993
6  *    The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
37 /*
38  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
39  *
40  * Permission to use, copy, modify, and distribute this software for any
41  * purpose with or without fee is hereby granted, provided that the above
42  * copyright notice and this permission notice appear in all copies, and that
43  * the name of Digital Equipment Corporation not be used in advertising or
44  * publicity pertaining to distribution of the document or software without
45  * specific, written prior permission.
46  *
47  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
48  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
49  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
50  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
51  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
52  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
53  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
54  * SOFTWARE.
55  */
57 /*
58  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
59  * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
60  *
61  * Permission to use, copy, modify, and distribute this software for any
62  * purpose with or without fee is hereby granted, provided that the above
63  * copyright notice and this permission notice appear in all copies.
64  *
65  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
66  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
67  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
68  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
69  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
70  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
71  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
72  */
74 #include <sys/cdefs.h>
75 #if defined(LIBC_SCCS) && !defined(lint)
76 #ifdef notdef
77 static const char sccsid[] = "@(#)res_send.c    8.1 (Berkeley) 6/4/93";
78 static const char rcsid[] = "Id: res_send.c,v 1.5.2.2.4.5 2004/08/10 02:19:56 marka Exp";
79 #else
80 __RCSID("$NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $");
81 #endif
82 #endif /* LIBC_SCCS and not lint */
84 /* set to 1 to use our small/simple/limited DNS cache */
85 #define  USE_RESOLV_CACHE  1
87 /*
88  * Send query to name server and wait for reply.
89  */
91 #include <sys/types.h>
92 #include <sys/param.h>
93 #include <sys/time.h>
94 #include <sys/socket.h>
95 #include <sys/uio.h>
97 #include <netinet/in.h>
98 #include <arpa/nameser.h>
99 #include <arpa/inet.h>
101 #include <errno.h>
102 #include <fcntl.h>
103 #include <netdb.h>
104 #ifdef ANDROID_CHANGES
105 #include "resolv_netid.h"
106 #include "resolv_private.h"
107 #else
108 #include <resolv.h>
109 #endif
110 #include <signal.h>
111 #include <stdio.h>
112 #include <stdlib.h>
113 #include <string.h>
114 #include <time.h>
115 #include <unistd.h>
117 #include <isc/eventlib.h>
119 #if USE_RESOLV_CACHE
120 #  include <resolv_cache.h>
121 #endif
123 #include "private/libc_logging.h"
125 #ifndef DE_CONST
126 #define DE_CONST(c,v)   v = ((c) ? \
127     strchr((const void *)(c), *(const char *)(const void *)(c)) : NULL)
128 #endif
130 /* Options.  Leave them on. */
131 #ifndef DEBUG
132 #define DEBUG
133 #endif
134 #include "res_debug.h"
135 #include "res_private.h"
137 #define EXT(res) ((res)->_u._ext)
138 #define DBG 0
140 static const int highestFD = FD_SETSIZE - 1;
142 /* Forward. */
144 static int              get_salen __P((const struct sockaddr *));
145 static struct sockaddr * get_nsaddr __P((res_state, size_t));
146 static int              send_vc(res_state, const u_char *, int,
147                                 u_char *, int, int *, int);
148 static int              send_dg(res_state, const u_char *, int,
149                                 u_char *, int, int *, int,
150                                 int *, int *);
151 static void             Aerror(const res_state, FILE *, const char *, int,
152                                const struct sockaddr *, int);
153 static void             Perror(const res_state, FILE *, const char *, int);
154 static int              sock_eq(struct sockaddr *, struct sockaddr *);
155 #ifdef NEED_PSELECT
156 static int              pselect(int, void *, void *, void *,
157                                 struct timespec *,
158                                 const sigset_t *);
159 #endif
160 void res_pquery(const res_state, const u_char *, int, FILE *);
161 static int connect_with_timeout(int sock, const struct sockaddr *nsap,
162                         socklen_t salen, int sec);
163 static int retrying_select(const int sock, fd_set *readset, fd_set *writeset,
164                         const struct timespec *finish);
166 /* BIONIC-BEGIN: implement source port randomization */
167 typedef union {
168     struct sockaddr      sa;
169     struct sockaddr_in   sin;
170     struct sockaddr_in6  sin6;
171 } _sockaddr_union;
173 static int
174 random_bind( int  s, int  family )
176     _sockaddr_union  u;
177     int              j;
178     socklen_t        slen;
180     /* clear all, this also sets the IP4/6 address to 'any' */
181     memset( &u, 0, sizeof u );
183     switch (family) {
184         case AF_INET:
185             u.sin.sin_family = family;
186             slen             = sizeof u.sin;
187             break;
188         case AF_INET6:
189             u.sin6.sin6_family = family;
190             slen               = sizeof u.sin6;
191             break;
192         default:
193             errno = EPROTO;
194             return -1;
195     }
197     /* first try to bind to a random source port a few times */
198     for (j = 0; j < 10; j++) {
199         /* find a random port between 1025 .. 65534 */
200         int  port = 1025 + (res_randomid() % (65535-1025));
201         if (family == AF_INET)
202             u.sin.sin_port = htons(port);
203         else
204             u.sin6.sin6_port = htons(port);
206         if ( !bind( s, &u.sa, slen ) )
207             return 0;
208     }
210     /* nothing after 10 tries, our network table is probably busy */
211     /* let the system decide which port is best */
212     if (family == AF_INET)
213         u.sin.sin_port = 0;
214     else
215         u.sin6.sin6_port = 0;
217     return bind( s, &u.sa, slen );
219 /* BIONIC-END */
221 static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
223 /* Public. */
225 /* int
226  * res_isourserver(ina)
227  *      looks up "ina" in _res.ns_addr_list[]
228  * returns:
229  *      0  : not found
230  *      >0 : found
231  * author:
232  *      paul vixie, 29may94
233  */
234 __LIBC_HIDDEN__ int
235 res_ourserver_p(const res_state statp, const struct sockaddr *sa) {
236         const struct sockaddr_in *inp, *srv;
237         const struct sockaddr_in6 *in6p, *srv6;
238         int ns;
240         switch (sa->sa_family) {
241         case AF_INET:
242                 inp = (const struct sockaddr_in *)(const void *)sa;
243                 for (ns = 0;  ns < statp->nscount;  ns++) {
244                         srv = (struct sockaddr_in *)(void *)get_nsaddr(statp, (size_t)ns);
245                         if (srv->sin_family == inp->sin_family &&
246                             srv->sin_port == inp->sin_port &&
247                             (srv->sin_addr.s_addr == INADDR_ANY ||
248                              srv->sin_addr.s_addr == inp->sin_addr.s_addr))
249                                 return (1);
250                 }
251                 break;
252         case AF_INET6:
253                 if (EXT(statp).ext == NULL)
254                         break;
255                 in6p = (const struct sockaddr_in6 *)(const void *)sa;
256                 for (ns = 0;  ns < statp->nscount;  ns++) {
257                         srv6 = (struct sockaddr_in6 *)(void *)get_nsaddr(statp, (size_t)ns);
258                         if (srv6->sin6_family == in6p->sin6_family &&
259                             srv6->sin6_port == in6p->sin6_port &&
260 #ifdef HAVE_SIN6_SCOPE_ID
261                             (srv6->sin6_scope_id == 0 ||
262                              srv6->sin6_scope_id == in6p->sin6_scope_id) &&
263 #endif
264                             (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
265                              IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr)))
266                                 return (1);
267                 }
268                 break;
269         default:
270                 break;
271         }
272         return (0);
275 /* int
276  * res_nameinquery(name, type, class, buf, eom)
277  *      look for (name,type,class) in the query section of packet (buf,eom)
278  * requires:
279  *      buf + HFIXEDSZ <= eom
280  * returns:
281  *      -1 : format error
282  *      0  : not found
283  *      >0 : found
284  * author:
285  *      paul vixie, 29may94
286  */
287 int
288 res_nameinquery(const char *name, int type, int class,
289                 const u_char *buf, const u_char *eom)
291         const u_char *cp = buf + HFIXEDSZ;
292         int qdcount = ntohs(((const HEADER*)(const void *)buf)->qdcount);
294         while (qdcount-- > 0) {
295                 char tname[MAXDNAME+1];
296                 int n, ttype, tclass;
298                 n = dn_expand(buf, eom, cp, tname, sizeof tname);
299                 if (n < 0)
300                         return (-1);
301                 cp += n;
302                 if (cp + 2 * INT16SZ > eom)
303                         return (-1);
304                 ttype = ns_get16(cp); cp += INT16SZ;
305                 tclass = ns_get16(cp); cp += INT16SZ;
306                 if (ttype == type && tclass == class &&
307                     ns_samename(tname, name) == 1)
308                         return (1);
309         }
310         return (0);
313 /* int
314  * res_queriesmatch(buf1, eom1, buf2, eom2)
315  *      is there a 1:1 mapping of (name,type,class)
316  *      in (buf1,eom1) and (buf2,eom2)?
317  * returns:
318  *      -1 : format error
319  *      0  : not a 1:1 mapping
320  *      >0 : is a 1:1 mapping
321  * author:
322  *      paul vixie, 29may94
323  */
324 int
325 res_queriesmatch(const u_char *buf1, const u_char *eom1,
326                  const u_char *buf2, const u_char *eom2)
328         const u_char *cp = buf1 + HFIXEDSZ;
329         int qdcount = ntohs(((const HEADER*)(const void *)buf1)->qdcount);
331         if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
332                 return (-1);
334         /*
335          * Only header section present in replies to
336          * dynamic update packets.
337          */
338         if ((((const HEADER *)(const void *)buf1)->opcode == ns_o_update) &&
339             (((const HEADER *)(const void *)buf2)->opcode == ns_o_update))
340                 return (1);
342         if (qdcount != ntohs(((const HEADER*)(const void *)buf2)->qdcount))
343                 return (0);
344         while (qdcount-- > 0) {
345                 char tname[MAXDNAME+1];
346                 int n, ttype, tclass;
348                 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
349                 if (n < 0)
350                         return (-1);
351                 cp += n;
352                 if (cp + 2 * INT16SZ > eom1)
353                         return (-1);
354                 ttype = ns_get16(cp);   cp += INT16SZ;
355                 tclass = ns_get16(cp); cp += INT16SZ;
356                 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
357                         return (0);
358         }
359         return (1);
363 int
364 res_nsend(res_state statp,
365           const u_char *buf, int buflen, u_char *ans, int anssiz)
367         int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
368         char abuf[NI_MAXHOST];
369 #if USE_RESOLV_CACHE
370         struct resolv_cache*  cache;
371         ResolvCacheStatus     cache_status = RESOLV_CACHE_UNSUPPORTED;
372 #endif
374 #if !USE_RESOLV_CACHE
375         if (statp->nscount == 0) {
376                 errno = ESRCH;
377                 return (-1);
378         }
379 #endif
381         if (anssiz < HFIXEDSZ) {
382                 errno = EINVAL;
383                 return (-1);
384         }
385         DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
386                 (stdout, ";; res_send()\n"), buf, buflen);
387         v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
388         gotsomewhere = 0;
389         terrno = ETIMEDOUT;
391 #if USE_RESOLV_CACHE
392         // get the cache associated with the network
393         cache = __get_res_cache(statp->netid);
394         if (cache != NULL) {
395                 int  anslen = 0;
396                 cache_status = _resolv_cache_lookup(
397                                 cache, buf, buflen,
398                                 ans, anssiz, &anslen);
400                 if (cache_status == RESOLV_CACHE_FOUND) {
401                         return anslen;
402                 } else {
403                         // had a cache miss for a known network, so populate the thread private
404                         // data so the normal resolve path can do its thing
405                         _resolv_populate_res_for_net(statp);
406                 }
407         }
409         if (statp->nscount == 0) {
410                 errno = ESRCH;
411                 return (-1);
412         }
413 #endif
415         /*
416          * If the ns_addr_list in the resolver context has changed, then
417          * invalidate our cached copy and the associated timing data.
418          */
419         if (EXT(statp).nscount != 0) {
420                 int needclose = 0;
421                 struct sockaddr_storage peer;
422                 socklen_t peerlen;
424                 if (EXT(statp).nscount != statp->nscount)
425                         needclose++;
426                 else
427                         for (ns = 0; ns < statp->nscount; ns++) {
428                                 if (statp->nsaddr_list[ns].sin_family &&
429                                     !sock_eq((struct sockaddr *)(void *)&statp->nsaddr_list[ns],
430                                              (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[ns])) {
431                                         needclose++;
432                                         break;
433                                 }
435                                 if (EXT(statp).nssocks[ns] == -1)
436                                         continue;
437                                 peerlen = sizeof(peer);
438                                 if (getpeername(EXT(statp).nssocks[ns],
439                                     (struct sockaddr *)(void *)&peer, &peerlen) < 0) {
440                                         needclose++;
441                                         break;
442                                 }
443                                 if (!sock_eq((struct sockaddr *)(void *)&peer,
444                                     get_nsaddr(statp, (size_t)ns))) {
445                                         needclose++;
446                                         break;
447                                 }
448                         }
449                 if (needclose) {
450                         res_nclose(statp);
451                         EXT(statp).nscount = 0;
452                 }
453         }
455         /*
456          * Maybe initialize our private copy of the ns_addr_list.
457          */
458         if (EXT(statp).nscount == 0) {
459                 for (ns = 0; ns < statp->nscount; ns++) {
460                         EXT(statp).nstimes[ns] = RES_MAXTIME;
461                         EXT(statp).nssocks[ns] = -1;
462                         if (!statp->nsaddr_list[ns].sin_family)
463                                 continue;
464                         EXT(statp).ext->nsaddrs[ns].sin =
465                                  statp->nsaddr_list[ns];
466                 }
467                 EXT(statp).nscount = statp->nscount;
468         }
470         /*
471          * Some resolvers want to even out the load on their nameservers.
472          * Note that RES_BLAST overrides RES_ROTATE.
473          */
474         if ((statp->options & RES_ROTATE) != 0U &&
475             (statp->options & RES_BLAST) == 0U) {
476                 union res_sockaddr_union inu;
477                 struct sockaddr_in ina;
478                 int lastns = statp->nscount - 1;
479                 int fd;
480                 u_int16_t nstime;
482                 if (EXT(statp).ext != NULL)
483                         inu = EXT(statp).ext->nsaddrs[0];
484                 ina = statp->nsaddr_list[0];
485                 fd = EXT(statp).nssocks[0];
486                 nstime = EXT(statp).nstimes[0];
487                 for (ns = 0; ns < lastns; ns++) {
488                         if (EXT(statp).ext != NULL)
489                                 EXT(statp).ext->nsaddrs[ns] =
490                                         EXT(statp).ext->nsaddrs[ns + 1];
491                         statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
492                         EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
493                         EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1];
494                 }
495                 if (EXT(statp).ext != NULL)
496                         EXT(statp).ext->nsaddrs[lastns] = inu;
497                 statp->nsaddr_list[lastns] = ina;
498                 EXT(statp).nssocks[lastns] = fd;
499                 EXT(statp).nstimes[lastns] = nstime;
500         }
502         /*
503          * Send request, RETRY times, or until successful.
504          */
505         for (try = 0; try < statp->retry; try++) {
506             for (ns = 0; ns < statp->nscount; ns++) {
507                 struct sockaddr *nsap;
508                 int nsaplen;
509                 nsap = get_nsaddr(statp, (size_t)ns);
510                 nsaplen = get_salen(nsap);
511                 statp->_flags &= ~RES_F_LASTMASK;
512                 statp->_flags |= (ns << RES_F_LASTSHIFT);
513  same_ns:
514                 if (statp->qhook) {
515                         int done = 0, loops = 0;
517                         do {
518                                 res_sendhookact act;
520                                 act = (*statp->qhook)(&nsap, &buf, &buflen,
521                                                       ans, anssiz, &resplen);
522                                 switch (act) {
523                                 case res_goahead:
524                                         done = 1;
525                                         break;
526                                 case res_nextns:
527                                         res_nclose(statp);
528                                         goto next_ns;
529                                 case res_done:
530                                         return (resplen);
531                                 case res_modified:
532                                         /* give the hook another try */
533                                         if (++loops < 42) /*doug adams*/
534                                                 break;
535                                         /*FALLTHROUGH*/
536                                 case res_error:
537                                         /*FALLTHROUGH*/
538                                 default:
539                                         goto fail;
540                                 }
541                         } while (!done);
542                 }
544                 Dprint(((statp->options & RES_DEBUG) &&
545                         getnameinfo(nsap, (socklen_t)nsaplen, abuf, sizeof(abuf),
546                                 NULL, 0, niflags) == 0),
547                                 (stdout, ";; Querying server (# %d) address = %s\n",
548                                 ns + 1, abuf));
551                 if (v_circuit) {
552                         /* Use VC; at most one attempt per server. */
553                         try = statp->retry;
555                         n = send_vc(statp, buf, buflen, ans, anssiz, &terrno,
556                                     ns);
558                         if (DBG) {
559                                 __libc_format_log(ANDROID_LOG_DEBUG, "libc",
560                                         "used send_vc %d\n", n);
561                         }
563                         if (n < 0)
564                                 goto fail;
565                         if (n == 0)
566                                 goto next_ns;
567                         resplen = n;
568                 } else {
569                         /* Use datagrams. */
570                         if (DBG) {
571                                 __libc_format_log(ANDROID_LOG_DEBUG, "libc", "using send_dg\n");
572                         }
574                         n = send_dg(statp, buf, buflen, ans, anssiz, &terrno,
575                                     ns, &v_circuit, &gotsomewhere);
576                         if (DBG) {
577                                 __libc_format_log(ANDROID_LOG_DEBUG, "libc", "used send_dg %d\n",n);
578                         }
580                         if (n < 0)
581                                 goto fail;
582                         if (n == 0)
583                                 goto next_ns;
584                         if (DBG) {
585                                 __libc_format_log(ANDROID_LOG_DEBUG, "libc", "time=%ld\n",
586                                                   time(NULL));
587                         }
588                         if (v_circuit)
589                                 goto same_ns;
590                         resplen = n;
591                 }
593                 Dprint((statp->options & RES_DEBUG) ||
594                        ((statp->pfcode & RES_PRF_REPLY) &&
595                         (statp->pfcode & RES_PRF_HEAD1)),
596                        (stdout, ";; got answer:\n"));
598                 DprintQ((statp->options & RES_DEBUG) ||
599                         (statp->pfcode & RES_PRF_REPLY),
600                         (stdout, "%s", ""),
601                         ans, (resplen > anssiz) ? anssiz : resplen);
603 #if USE_RESOLV_CACHE
604                 if (cache_status == RESOLV_CACHE_NOTFOUND) {
605                     _resolv_cache_add(cache, buf, buflen,
606                                       ans, resplen);
607                 }
608 #endif
609                 /*
610                  * If we have temporarily opened a virtual circuit,
611                  * or if we haven't been asked to keep a socket open,
612                  * close the socket.
613                  */
614                 if ((v_circuit && (statp->options & RES_USEVC) == 0U) ||
615                     (statp->options & RES_STAYOPEN) == 0U) {
616                         res_nclose(statp);
617                 }
618                 if (statp->rhook) {
619                         int done = 0, loops = 0;
621                         do {
622                                 res_sendhookact act;
624                                 act = (*statp->rhook)(nsap, buf, buflen,
625                                                       ans, anssiz, &resplen);
626                                 switch (act) {
627                                 case res_goahead:
628                                 case res_done:
629                                         done = 1;
630                                         break;
631                                 case res_nextns:
632                                         res_nclose(statp);
633                                         goto next_ns;
634                                 case res_modified:
635                                         /* give the hook another try */
636                                         if (++loops < 42) /*doug adams*/
637                                                 break;
638                                         /*FALLTHROUGH*/
639                                 case res_error:
640                                         /*FALLTHROUGH*/
641                                 default:
642                                         goto fail;
643                                 }
644                         } while (!done);
646                 }
647                 return (resplen);
648  next_ns: ;
649            } /*foreach ns*/
650         } /*foreach retry*/
651         res_nclose(statp);
652         if (!v_circuit) {
653                 if (!gotsomewhere)
654                         errno = ECONNREFUSED;   /* no nameservers found */
655                 else
656                         errno = ETIMEDOUT;      /* no answer obtained */
657         } else
658                 errno = terrno;
660 #if USE_RESOLV_CACHE
661         _resolv_cache_query_failed(cache, buf, buflen);
662 #endif
664         return (-1);
665  fail:
666 #if USE_RESOLV_CACHE
667         _resolv_cache_query_failed(cache, buf, buflen);
668 #endif
669         res_nclose(statp);
670         return (-1);
673 /* Private */
675 static int
676 get_salen(sa)
677         const struct sockaddr *sa;
680 #ifdef HAVE_SA_LEN
681         /* There are people do not set sa_len.  Be forgiving to them. */
682         if (sa->sa_len)
683                 return (sa->sa_len);
684 #endif
686         if (sa->sa_family == AF_INET)
687                 return (sizeof(struct sockaddr_in));
688         else if (sa->sa_family == AF_INET6)
689                 return (sizeof(struct sockaddr_in6));
690         else
691                 return (0);     /* unknown, die on connect */
694 /*
695  * pick appropriate nsaddr_list for use.  see res_init() for initialization.
696  */
697 static struct sockaddr *
698 get_nsaddr(statp, n)
699         res_state statp;
700         size_t n;
703         if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) {
704                 /*
705                  * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
706                  *   than struct sockaddr, and
707                  * - user code did not update statp->nsaddr_list[n].
708                  */
709                 return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n];
710         } else {
711                 /*
712                  * - user code updated statp->nsaddr_list[n], or
713                  * - statp->nsaddr_list[n] has the same content as
714                  *   EXT(statp).ext->nsaddrs[n].
715                  */
716                 return (struct sockaddr *)(void *)&statp->nsaddr_list[n];
717         }
720 static int get_timeout(const res_state statp, const int ns)
722         int timeout = (statp->retrans << ns);
723         if (ns > 0) {
724                 timeout /= statp->nscount;
725         }
726         if (timeout <= 0) {
727                 timeout = 1;
728         }
729         if (DBG) {
730                 __libc_format_log(ANDROID_LOG_DEBUG, "libc", "using timeout of %d sec\n", timeout);
731         }
733         return timeout;
736 static int
737 send_vc(res_state statp,
738         const u_char *buf, int buflen, u_char *ans, int anssiz,
739         int *terrno, int ns)
741         const HEADER *hp = (const HEADER *)(const void *)buf;
742         HEADER *anhp = (HEADER *)(void *)ans;
743         struct sockaddr *nsap;
744         int nsaplen;
745         int truncating, connreset, resplen, n;
746         struct iovec iov[2];
747         u_short len;
748         u_char *cp;
749         void *tmp;
751         if (DBG) {
752                 __libc_format_log(ANDROID_LOG_DEBUG, "libc", "using send_vc\n");
753         }
755         nsap = get_nsaddr(statp, (size_t)ns);
756         nsaplen = get_salen(nsap);
758         connreset = 0;
759  same_ns:
760         truncating = 0;
762         /* Are we still talking to whom we want to talk to? */
763         if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
764                 struct sockaddr_storage peer;
765                 socklen_t size = sizeof peer;
766                 unsigned old_mark;
767                 socklen_t mark_size = sizeof(old_mark);
768                 if (getpeername(statp->_vcsock,
769                                 (struct sockaddr *)(void *)&peer, &size) < 0 ||
770                     !sock_eq((struct sockaddr *)(void *)&peer, nsap) ||
771                         getsockopt(statp->_vcsock, SOL_SOCKET, SO_MARK, &old_mark, &mark_size) < 0 ||
772                         old_mark != statp->_mark) {
773                         res_nclose(statp);
774                         statp->_flags &= ~RES_F_VC;
775                 }
776         }
778         if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
779                 if (statp->_vcsock >= 0)
780                         res_nclose(statp);
782                 statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
783                 if (statp->_vcsock > highestFD) {
784                         res_nclose(statp);
785                         errno = ENOTSOCK;
786                 }
787                 if (statp->_vcsock < 0) {
788                         switch (errno) {
789                         case EPROTONOSUPPORT:
790 #ifdef EPFNOSUPPORT
791                         case EPFNOSUPPORT:
792 #endif
793                         case EAFNOSUPPORT:
794                                 Perror(statp, stderr, "socket(vc)", errno);
795                                 return (0);
796                         default:
797                                 *terrno = errno;
798                                 Perror(statp, stderr, "socket(vc)", errno);
799                                 return (-1);
800                         }
801                 }
802                 if (statp->_mark != MARK_UNSET) {
803                         if (setsockopt(statp->_vcsock, SOL_SOCKET,
804                                         SO_MARK, &statp->_mark, sizeof(statp->_mark)) < 0) {
805                                 *terrno = errno;
806                                 Perror(statp, stderr, "setsockopt", errno);
807                                 return -1;
808                         }
809                 }
810                 errno = 0;
811                 if (random_bind(statp->_vcsock,nsap->sa_family) < 0) {
812                         *terrno = errno;
813                         Aerror(statp, stderr, "bind/vc", errno, nsap,
814                             nsaplen);
815                         res_nclose(statp);
816                         return (0);
817                 }
818                 if (connect_with_timeout(statp->_vcsock, nsap, (socklen_t)nsaplen,
819                                 get_timeout(statp, ns)) < 0) {
820                         *terrno = errno;
821                         Aerror(statp, stderr, "connect/vc", errno, nsap,
822                             nsaplen);
823                         res_nclose(statp);
824                         return (0);
825                 }
826                 statp->_flags |= RES_F_VC;
827         }
829         /*
830          * Send length & message
831          */
832         ns_put16((u_short)buflen, (u_char*)(void *)&len);
833         iov[0] = evConsIovec(&len, INT16SZ);
834         DE_CONST(buf, tmp);
835         iov[1] = evConsIovec(tmp, (size_t)buflen);
836         if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
837                 *terrno = errno;
838                 Perror(statp, stderr, "write failed", errno);
839                 res_nclose(statp);
840                 return (0);
841         }
842         /*
843          * Receive length & response
844          */
845  read_len:
846         cp = ans;
847         len = INT16SZ;
848         while ((n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0) {
849                 cp += n;
850                 if ((len -= n) == 0)
851                         break;
852         }
853         if (n <= 0) {
854                 *terrno = errno;
855                 Perror(statp, stderr, "read failed", errno);
856                 res_nclose(statp);
857                 /*
858                  * A long running process might get its TCP
859                  * connection reset if the remote server was
860                  * restarted.  Requery the server instead of
861                  * trying a new one.  When there is only one
862                  * server, this means that a query might work
863                  * instead of failing.  We only allow one reset
864                  * per query to prevent looping.
865                  */
866                 if (*terrno == ECONNRESET && !connreset) {
867                         connreset = 1;
868                         res_nclose(statp);
869                         goto same_ns;
870                 }
871                 res_nclose(statp);
872                 return (0);
873         }
874         resplen = ns_get16(ans);
875         if (resplen > anssiz) {
876                 Dprint(statp->options & RES_DEBUG,
877                        (stdout, ";; response truncated\n")
878                        );
879                 truncating = 1;
880                 len = anssiz;
881         } else
882                 len = resplen;
883         if (len < HFIXEDSZ) {
884                 /*
885                  * Undersized message.
886                  */
887                 Dprint(statp->options & RES_DEBUG,
888                        (stdout, ";; undersized: %d\n", len));
889                 *terrno = EMSGSIZE;
890                 res_nclose(statp);
891                 return (0);
892         }
893         cp = ans;
894         while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0){
895                 cp += n;
896                 len -= n;
897         }
898         if (n <= 0) {
899                 *terrno = errno;
900                 Perror(statp, stderr, "read(vc)", errno);
901                 res_nclose(statp);
902                 return (0);
903         }
904         if (truncating) {
905                 /*
906                  * Flush rest of answer so connection stays in synch.
907                  */
908                 anhp->tc = 1;
909                 len = resplen - anssiz;
910                 while (len != 0) {
911                         char junk[PACKETSZ];
913                         n = read(statp->_vcsock, junk,
914                                  (len > sizeof junk) ? sizeof junk : len);
915                         if (n > 0)
916                                 len -= n;
917                         else
918                                 break;
919                 }
920         }
921         /*
922          * If the calling applicating has bailed out of
923          * a previous call and failed to arrange to have
924          * the circuit closed or the server has got
925          * itself confused, then drop the packet and
926          * wait for the correct one.
927          */
928         if (hp->id != anhp->id) {
929                 DprintQ((statp->options & RES_DEBUG) ||
930                         (statp->pfcode & RES_PRF_REPLY),
931                         (stdout, ";; old answer (unexpected):\n"),
932                         ans, (resplen > anssiz) ? anssiz: resplen);
933                 goto read_len;
934         }
936         /*
937          * All is well, or the error is fatal.  Signal that the
938          * next nameserver ought not be tried.
939          */
940         return (resplen);
943 /* return -1 on error (errno set), 0 on success */
944 static int
945 connect_with_timeout(int sock, const struct sockaddr *nsap, socklen_t salen, int sec)
947         int res, origflags;
948         fd_set rset, wset;
949         struct timespec now, timeout, finish;
951         origflags = fcntl(sock, F_GETFL, 0);
952         fcntl(sock, F_SETFL, origflags | O_NONBLOCK);
954         res = connect(sock, nsap, salen);
955         if (res < 0 && errno != EINPROGRESS) {
956                 res = -1;
957                 goto done;
958         }
959         if (res != 0) {
960                 now = evNowTime();
961                 timeout = evConsTime((long)sec, 0L);
962                 finish = evAddTime(now, timeout);
963                 if (DBG) {
964                         __libc_format_log(ANDROID_LOG_DEBUG, "libc", "  %d send_vc\n", sock);
965                 }
967                 res = retrying_select(sock, &rset, &wset, &finish);
968                 if (res <= 0) {
969                         res = -1;
970                 }
971         }
972 done:
973         fcntl(sock, F_SETFL, origflags);
974         if (DBG) {
975                 __libc_format_log(ANDROID_LOG_DEBUG, "libc",
976                         "  %d connect_with_timeout returning %d\n", sock, res);
977         }
978         return res;
981 static int
982 retrying_select(const int sock, fd_set *readset, fd_set *writeset, const struct timespec *finish)
984         struct timespec now, timeout;
985         int n, error;
986         socklen_t len;
989 retry:
990         if (DBG) {
991                 __libc_format_log(ANDROID_LOG_DEBUG, "libc", "  %d retying_select\n", sock);
992         }
994         now = evNowTime();
995         if (readset) {
996                 FD_ZERO(readset);
997                 FD_SET(sock, readset);
998         }
999         if (writeset) {
1000                 FD_ZERO(writeset);
1001                 FD_SET(sock, writeset);
1002         }
1003         if (evCmpTime(*finish, now) > 0)
1004                 timeout = evSubTime(*finish, now);
1005         else
1006                 timeout = evConsTime(0L, 0L);
1008         n = pselect(sock + 1, readset, writeset, NULL, &timeout, NULL);
1009         if (n == 0) {
1010                 if (DBG) {
1011                         __libc_format_log(ANDROID_LOG_DEBUG, " libc",
1012                                 "  %d retrying_select timeout\n", sock);
1013                 }
1014                 errno = ETIMEDOUT;
1015                 return 0;
1016         }
1017         if (n < 0) {
1018                 if (errno == EINTR)
1019                         goto retry;
1020                 if (DBG) {
1021                         __libc_format_log(ANDROID_LOG_DEBUG, "libc",
1022                                 "  %d retrying_select got error %d\n",sock, n);
1023                 }
1024                 return n;
1025         }
1026         if ((readset && FD_ISSET(sock, readset)) || (writeset && FD_ISSET(sock, writeset))) {
1027                 len = sizeof(error);
1028                 if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error) {
1029                         errno = error;
1030                         if (DBG) {
1031                                 __libc_format_log(ANDROID_LOG_DEBUG, "libc",
1032                                         "  %d retrying_select dot error2 %d\n", sock, errno);
1033                         }
1035                         return -1;
1036                 }
1037         }
1038         if (DBG) {
1039                 __libc_format_log(ANDROID_LOG_DEBUG, "libc",
1040                         "  %d retrying_select returning %d\n",sock, n);
1041         }
1043         return n;
1047 static int
1048 send_dg(res_state statp,
1049         const u_char *buf, int buflen, u_char *ans, int anssiz,
1050         int *terrno, int ns, int *v_circuit, int *gotsomewhere)
1052         const HEADER *hp = (const HEADER *)(const void *)buf;
1053         HEADER *anhp = (HEADER *)(void *)ans;
1054         const struct sockaddr *nsap;
1055         int nsaplen;
1056         struct timespec now, timeout, finish;
1057         fd_set dsmask;
1058         struct sockaddr_storage from;
1059         socklen_t fromlen;
1060         int resplen, seconds, n, s;
1062         nsap = get_nsaddr(statp, (size_t)ns);
1063         nsaplen = get_salen(nsap);
1064         if (EXT(statp).nssocks[ns] == -1) {
1065                 EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1066                 if (EXT(statp).nssocks[ns] > highestFD) {
1067                         res_nclose(statp);
1068                         errno = ENOTSOCK;
1069                 }
1070                 if (EXT(statp).nssocks[ns] < 0) {
1071                         switch (errno) {
1072                         case EPROTONOSUPPORT:
1073 #ifdef EPFNOSUPPORT
1074                         case EPFNOSUPPORT:
1075 #endif
1076                         case EAFNOSUPPORT:
1077                                 Perror(statp, stderr, "socket(dg)", errno);
1078                                 return (0);
1079                         default:
1080                                 *terrno = errno;
1081                                 Perror(statp, stderr, "socket(dg)", errno);
1082                                 return (-1);
1083                         }
1084                 }
1086                 if (statp->_mark != MARK_UNSET) {
1087                         if (setsockopt(EXT(statp).nssocks[ns], SOL_SOCKET,
1088                                         SO_MARK, &(statp->_mark), sizeof(statp->_mark)) < 0) {
1089                                 res_nclose(statp);
1090                                 return -1;
1091                         }
1092                 }
1093 #ifndef CANNOT_CONNECT_DGRAM
1094                 /*
1095                  * On a 4.3BSD+ machine (client and server,
1096                  * actually), sending to a nameserver datagram
1097                  * port with no nameserver will cause an
1098                  * ICMP port unreachable message to be returned.
1099                  * If our datagram socket is "connected" to the
1100                  * server, we get an ECONNREFUSED error on the next
1101                  * socket operation, and select returns if the
1102                  * error message is received.  We can thus detect
1103                  * the absence of a nameserver without timing out.
1104                  */
1105                 if (random_bind(EXT(statp).nssocks[ns], nsap->sa_family) < 0) {
1106                         Aerror(statp, stderr, "bind(dg)", errno, nsap,
1107                             nsaplen);
1108                         res_nclose(statp);
1109                         return (0);
1110                 }
1111                 if (connect(EXT(statp).nssocks[ns], nsap, (socklen_t)nsaplen) < 0) {
1112                         Aerror(statp, stderr, "connect(dg)", errno, nsap,
1113                             nsaplen);
1114                         res_nclose(statp);
1115                         return (0);
1116                 }
1117 #endif /* !CANNOT_CONNECT_DGRAM */
1118                 Dprint(statp->options & RES_DEBUG,
1119                        (stdout, ";; new DG socket\n"))
1121         }
1122         s = EXT(statp).nssocks[ns];
1123 #ifndef CANNOT_CONNECT_DGRAM
1124         if (send(s, (const char*)buf, (size_t)buflen, 0) != buflen) {
1125                 Perror(statp, stderr, "send", errno);
1126                 res_nclose(statp);
1127                 return (0);
1128         }
1129 #else /* !CANNOT_CONNECT_DGRAM */
1130         if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)
1131         {
1132                 Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
1133                 res_nclose(statp);
1134                 return (0);
1135         }
1136 #endif /* !CANNOT_CONNECT_DGRAM */
1138         /*
1139          * Wait for reply.
1140          */
1141         seconds = get_timeout(statp, ns);
1142         now = evNowTime();
1143         timeout = evConsTime((long)seconds, 0L);
1144         finish = evAddTime(now, timeout);
1145 retry:
1146         n = retrying_select(s, &dsmask, NULL, &finish);
1148         if (n == 0) {
1149                 Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
1150                 *gotsomewhere = 1;
1151                 return (0);
1152         }
1153         if (n < 0) {
1154                 Perror(statp, stderr, "select", errno);
1155                 res_nclose(statp);
1156                 return (0);
1157         }
1158         errno = 0;
1159         fromlen = sizeof(from);
1160         resplen = recvfrom(s, (char*)ans, (size_t)anssiz,0,
1161                            (struct sockaddr *)(void *)&from, &fromlen);
1162         if (resplen <= 0) {
1163                 Perror(statp, stderr, "recvfrom", errno);
1164                 res_nclose(statp);
1165                 return (0);
1166         }
1167         *gotsomewhere = 1;
1168         if (resplen < HFIXEDSZ) {
1169                 /*
1170                  * Undersized message.
1171                  */
1172                 Dprint(statp->options & RES_DEBUG,
1173                        (stdout, ";; undersized: %d\n",
1174                         resplen));
1175                 *terrno = EMSGSIZE;
1176                 res_nclose(statp);
1177                 return (0);
1178         }
1179         if (hp->id != anhp->id) {
1180                 /*
1181                  * response from old query, ignore it.
1182                  * XXX - potential security hazard could
1183                  *       be detected here.
1184                  */
1185 #ifdef ANDROID_CHANGES
1186                 __libc_android_log_event_uid(BIONIC_EVENT_RESOLVER_OLD_RESPONSE);
1187 #endif
1188                 DprintQ((statp->options & RES_DEBUG) ||
1189                         (statp->pfcode & RES_PRF_REPLY),
1190                         (stdout, ";; old answer:\n"),
1191                         ans, (resplen > anssiz) ? anssiz : resplen);
1192                 goto retry;
1193         }
1194         if (!(statp->options & RES_INSECURE1) &&
1195             !res_ourserver_p(statp, (struct sockaddr *)(void *)&from)) {
1196                 /*
1197                  * response from wrong server? ignore it.
1198                  * XXX - potential security hazard could
1199                  *       be detected here.
1200                  */
1201 #ifdef ANDROID_CHANGES
1202                 __libc_android_log_event_uid(BIONIC_EVENT_RESOLVER_WRONG_SERVER);
1203 #endif
1204                 DprintQ((statp->options & RES_DEBUG) ||
1205                         (statp->pfcode & RES_PRF_REPLY),
1206                         (stdout, ";; not our server:\n"),
1207                         ans, (resplen > anssiz) ? anssiz : resplen);
1208                 goto retry;
1209         }
1210 #ifdef RES_USE_EDNS0
1211         if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) {
1212                 /*
1213                  * Do not retry if the server do not understand EDNS0.
1214                  * The case has to be captured here, as FORMERR packet do not
1215                  * carry query section, hence res_queriesmatch() returns 0.
1216                  */
1217                 DprintQ(statp->options & RES_DEBUG,
1218                         (stdout, "server rejected query with EDNS0:\n"),
1219                         ans, (resplen > anssiz) ? anssiz : resplen);
1220                 /* record the error */
1221                 statp->_flags |= RES_F_EDNS0ERR;
1222                 res_nclose(statp);
1223                 return (0);
1224         }
1225 #endif
1226         if (!(statp->options & RES_INSECURE2) &&
1227             !res_queriesmatch(buf, buf + buflen,
1228                               ans, ans + anssiz)) {
1229                 /*
1230                  * response contains wrong query? ignore it.
1231                  * XXX - potential security hazard could
1232                  *       be detected here.
1233                  */
1234 #ifdef ANDROID_CHANGES
1235                 __libc_android_log_event_uid(BIONIC_EVENT_RESOLVER_WRONG_QUERY);
1236 #endif
1237                 DprintQ((statp->options & RES_DEBUG) ||
1238                         (statp->pfcode & RES_PRF_REPLY),
1239                         (stdout, ";; wrong query name:\n"),
1240                         ans, (resplen > anssiz) ? anssiz : resplen);
1241                 goto retry;;
1242         }
1243         if (anhp->rcode == SERVFAIL ||
1244             anhp->rcode == NOTIMP ||
1245             anhp->rcode == REFUSED) {
1246                 DprintQ(statp->options & RES_DEBUG,
1247                         (stdout, "server rejected query:\n"),
1248                         ans, (resplen > anssiz) ? anssiz : resplen);
1249                 res_nclose(statp);
1250                 /* don't retry if called from dig */
1251                 if (!statp->pfcode)
1252                         return (0);
1253         }
1254         if (!(statp->options & RES_IGNTC) && anhp->tc) {
1255                 /*
1256                  * To get the rest of answer,
1257                  * use TCP with same server.
1258                  */
1259                 Dprint(statp->options & RES_DEBUG,
1260                        (stdout, ";; truncated answer\n"));
1261                 *v_circuit = 1;
1262                 res_nclose(statp);
1263                 return (1);
1264         }
1265         /*
1266          * All is well, or the error is fatal.  Signal that the
1267          * next nameserver ought not be tried.
1268          */
1269         return (resplen);
1272 static void
1273 Aerror(const res_state statp, FILE *file, const char *string, int error,
1274        const struct sockaddr *address, int alen)
1276         int save = errno;
1277         char hbuf[NI_MAXHOST];
1278         char sbuf[NI_MAXSERV];
1280         alen = alen;
1282         if ((statp->options & RES_DEBUG) != 0U) {
1283                 if (getnameinfo(address, (socklen_t)alen, hbuf, sizeof(hbuf),
1284                     sbuf, sizeof(sbuf), niflags)) {
1285                         strncpy(hbuf, "?", sizeof(hbuf) - 1);
1286                         hbuf[sizeof(hbuf) - 1] = '\0';
1287                         strncpy(sbuf, "?", sizeof(sbuf) - 1);
1288                         sbuf[sizeof(sbuf) - 1] = '\0';
1289                 }
1290                 fprintf(file, "res_send: %s ([%s].%s): %s\n",
1291                         string, hbuf, sbuf, strerror(error));
1292         }
1293         errno = save;
1296 static void
1297 Perror(const res_state statp, FILE *file, const char *string, int error) {
1298         int save = errno;
1300         if ((statp->options & RES_DEBUG) != 0U)
1301                 fprintf(file, "res_send: %s: %s\n",
1302                         string, strerror(error));
1303         errno = save;
1306 static int
1307 sock_eq(struct sockaddr *a, struct sockaddr *b) {
1308         struct sockaddr_in *a4, *b4;
1309         struct sockaddr_in6 *a6, *b6;
1311         if (a->sa_family != b->sa_family)
1312                 return 0;
1313         switch (a->sa_family) {
1314         case AF_INET:
1315                 a4 = (struct sockaddr_in *)(void *)a;
1316                 b4 = (struct sockaddr_in *)(void *)b;
1317                 return a4->sin_port == b4->sin_port &&
1318                     a4->sin_addr.s_addr == b4->sin_addr.s_addr;
1319         case AF_INET6:
1320                 a6 = (struct sockaddr_in6 *)(void *)a;
1321                 b6 = (struct sockaddr_in6 *)(void *)b;
1322                 return a6->sin6_port == b6->sin6_port &&
1323 #ifdef HAVE_SIN6_SCOPE_ID
1324                     a6->sin6_scope_id == b6->sin6_scope_id &&
1325 #endif
1326                     IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);
1327         default:
1328                 return 0;
1329         }
1332 #ifdef NEED_PSELECT
1333 /* XXX needs to move to the porting library. */
1334 static int
1335 pselect(int nfds, void *rfds, void *wfds, void *efds,
1336         struct timespec *tsp, const sigset_t *sigmask)
1338         struct timeval tv, *tvp;
1339         sigset_t sigs;
1340         int n;
1342         if (tsp) {
1343                 tvp = &tv;
1344                 tv = evTimeVal(*tsp);
1345         } else
1346                 tvp = NULL;
1347         if (sigmask)
1348                 sigprocmask(SIG_SETMASK, sigmask, &sigs);
1349         n = select(nfds, rfds, wfds, efds, tvp);
1350         if (sigmask)
1351                 sigprocmask(SIG_SETMASK, &sigs, NULL);
1352         if (tsp)
1353                 *tsp = evTimeSpec(tv);
1354         return (n);
1356 #endif