• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*	$NetBSD: gethnamaddr.c,v 1.91 2014/06/19 15:08:18 christos Exp $	*/
2 
3 /*
4  * ++Copyright++ 1985, 1988, 1993
5  * -
6  * Copyright (c) 1985, 1988, 1993
7  *    The Regents of the University of California.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  * -
33  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
34  *
35  * Permission to use, copy, modify, and distribute this software for any
36  * purpose with or without fee is hereby granted, provided that the above
37  * copyright notice and this permission notice appear in all copies, and that
38  * the name of Digital Equipment Corporation not be used in advertising or
39  * publicity pertaining to distribution of the document or software without
40  * specific, written prior permission.
41  *
42  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
45  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49  * SOFTWARE.
50  * -
51  * --Copyright--
52  */
53 
54 #include "gethnamaddr.h"
55 
56 #include <android-base/logging.h>
57 #include <arpa/inet.h>
58 #include <arpa/nameser.h>
59 #include <assert.h>
60 #include <ctype.h>
61 #include <errno.h>
62 #include <netdb.h>
63 #include <netinet/in.h>
64 #include <stdarg.h>
65 #include <stdbool.h>
66 #include <stdio.h>
67 #include <stdlib.h>
68 #include <string.h>
69 #include <sys/param.h>
70 #include <sys/socket.h>
71 #include <sys/types.h>
72 #include <sys/un.h>
73 #include <unistd.h>
74 #include <functional>
75 #include <vector>
76 
77 #include "hostent.h"
78 #include "netd_resolv/resolv.h"
79 #include "resolv_cache.h"
80 #include "resolv_private.h"
81 
82 // NetBSD uses _DIAGASSERT to null-check arguments and the like,
83 // but it's clear from the number of mistakes in their assertions
84 // that they don't actually test or ship with this.
85 #define _DIAGASSERT(e) /* nothing */
86 
87 // TODO: unify macro ALIGNBYTES and ALIGN for all possible data type alignment of hostent
88 // buffer.
89 #define ALIGNBYTES (sizeof(uintptr_t) - 1)
90 #define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) & ~ALIGNBYTES)
91 
92 #define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || (ok)(nm) != 0)
93 #define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok)
94 #define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok)
95 
96 #define MAXPACKET (8 * 1024)
97 
98 typedef union {
99     HEADER hdr;
100     u_char buf[MAXPACKET];
101 } querybuf;
102 
103 typedef union {
104     int32_t al;
105     char ac;
106 } align;
107 
108 static struct hostent* getanswer(const querybuf*, int, const char*, int, res_state, struct hostent*,
109                                  char*, size_t, int*);
110 static void convert_v4v6_hostent(struct hostent* hp, char** bpp, char* ep,
111                                  std::function<void(struct hostent* hp)> mapping_param,
112                                  std::function<void(char* src, char* dst)> mapping_addr);
113 static void map_v4v6_address(const char*, char*);
114 static void map_v4v6_hostent(struct hostent*, char**, char*);
115 static void pad_v4v6_hostent(struct hostent* hp, char** bpp, char* ep);
116 static void addrsort(char**, int, res_state);
117 
118 static int dns_gethtbyaddr(const unsigned char* uaddr, int len, int af,
119                            const android_net_context* netcontext, getnamaddr* info);
120 static int dns_gethtbyname(const char* name, int af, getnamaddr* info);
121 
122 static int gethostbyname_internal(const char* name, int af, res_state res, hostent* hp, char* hbuf,
123                                   size_t hbuflen, const android_net_context* netcontext);
124 static int gethostbyname_internal_real(const char* name, int af, res_state res, hostent* hp,
125                                        char* buf, size_t buflen);
126 static int android_gethostbyaddrfornetcontext_proxy_internal(const void*, socklen_t, int,
127                                                              struct hostent*, char*, size_t,
128                                                              const struct android_net_context*);
129 static int android_gethostbyaddrfornetcontext_proxy(const void* addr, socklen_t len, int af,
130                                                     const struct android_net_context* netcontext,
131                                                     hostent** hp);
132 
133 #define BOUNDED_INCR(x)      \
134     do {                     \
135         BOUNDS_CHECK(cp, x); \
136         cp += (x);           \
137     } while (0)
138 
139 #define BOUNDS_CHECK(ptr, count)                     \
140     do {                                             \
141         if (eom - (ptr) < (count)) goto no_recovery; \
142     } while (0)
143 
getanswer(const querybuf * answer,int anslen,const char * qname,int qtype,res_state res,struct hostent * hent,char * buf,size_t buflen,int * he)144 static struct hostent* getanswer(const querybuf* answer, int anslen, const char* qname, int qtype,
145                                  res_state res, struct hostent* hent, char* buf, size_t buflen,
146                                  int* he) {
147     const HEADER* hp;
148     const u_char* cp;
149     int n;
150     size_t qlen;
151     const u_char *eom, *erdata;
152     char *bp, **hap, *ep;
153     int ancount, qdcount;
154     int haveanswer, had_error;
155     int toobig = 0;
156     char tbuf[MAXDNAME];
157     char* addr_ptrs[MAXADDRS];
158     const char* tname;
159     int (*name_ok)(const char*);
160     std::vector<char*> aliases;
161 
162     _DIAGASSERT(answer != NULL);
163     _DIAGASSERT(qname != NULL);
164 
165     tname = qname;
166     hent->h_name = NULL;
167     eom = answer->buf + anslen;
168     switch (qtype) {
169         case T_A:
170         case T_AAAA:
171             name_ok = res_hnok;
172             break;
173         case T_PTR:
174             name_ok = res_dnok;
175             break;
176         default:
177             *he = NO_RECOVERY;
178             return NULL; /* XXX should be abort(); */
179     }
180 
181     /*
182      * find first satisfactory answer
183      */
184     hp = &answer->hdr;
185     ancount = ntohs(hp->ancount);
186     qdcount = ntohs(hp->qdcount);
187     bp = buf;
188     ep = buf + buflen;
189     cp = answer->buf;
190     BOUNDED_INCR(HFIXEDSZ);
191     if (qdcount != 1) goto no_recovery;
192 
193     n = dn_expand(answer->buf, eom, cp, bp, (int) (ep - bp));
194     if ((n < 0) || !maybe_ok(res, bp, name_ok)) goto no_recovery;
195 
196     BOUNDED_INCR(n + QFIXEDSZ);
197     if (qtype == T_A || qtype == T_AAAA) {
198         /* res_send() has already verified that the query name is the
199          * same as the one we sent; this just gets the expanded name
200          * (i.e., with the succeeding search-domain tacked on).
201          */
202         n = (int) strlen(bp) + 1; /* for the \0 */
203         if (n >= MAXHOSTNAMELEN) goto no_recovery;
204         hent->h_name = bp;
205         bp += n;
206         /* The qname can be abbreviated, but h_name is now absolute. */
207         qname = hent->h_name;
208     }
209     hent->h_addr_list = hap = addr_ptrs;
210     *hap = NULL;
211     haveanswer = 0;
212     had_error = 0;
213     while (ancount-- > 0 && cp < eom && !had_error) {
214         n = dn_expand(answer->buf, eom, cp, bp, (int) (ep - bp));
215         if ((n < 0) || !maybe_ok(res, bp, name_ok)) {
216             had_error++;
217             continue;
218         }
219         cp += n; /* name */
220         BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
221         int type = ntohs(*reinterpret_cast<const uint16_t*>(cp));
222         cp += INT16SZ; /* type */
223         int cl = ntohs(*reinterpret_cast<const uint16_t*>(cp));
224         cp += INT16SZ + INT32SZ; /* class, TTL */
225         n = ntohs(*reinterpret_cast<const uint16_t*>(cp));
226         cp += INT16SZ; /* len */
227         BOUNDS_CHECK(cp, n);
228         erdata = cp + n;
229         if (cl != C_IN) {
230             /* XXX - debug? syslog? */
231             cp += n;
232             continue; /* XXX - had_error++ ? */
233         }
234         if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
235             n = dn_expand(answer->buf, eom, cp, tbuf, (int) sizeof tbuf);
236             if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) {
237                 had_error++;
238                 continue;
239             }
240             cp += n;
241             if (cp != erdata) goto no_recovery;
242             /* Store alias. */
243             aliases.push_back(bp);
244             n = (int) strlen(bp) + 1; /* for the \0 */
245             if (n >= MAXHOSTNAMELEN) {
246                 had_error++;
247                 continue;
248             }
249             bp += n;
250             /* Get canonical name. */
251             n = (int) strlen(tbuf) + 1; /* for the \0 */
252             if (n > ep - bp || n >= MAXHOSTNAMELEN) {
253                 had_error++;
254                 continue;
255             }
256             strlcpy(bp, tbuf, (size_t)(ep - bp));
257             hent->h_name = bp;
258             bp += n;
259             continue;
260         }
261         if (qtype == T_PTR && type == T_CNAME) {
262             n = dn_expand(answer->buf, eom, cp, tbuf, (int) sizeof tbuf);
263             if (n < 0 || !maybe_dnok(res, tbuf)) {
264                 had_error++;
265                 continue;
266             }
267             cp += n;
268             if (cp != erdata) goto no_recovery;
269             /* Get canonical name. */
270             n = (int) strlen(tbuf) + 1; /* for the \0 */
271             if (n > ep - bp || n >= MAXHOSTNAMELEN) {
272                 had_error++;
273                 continue;
274             }
275             strlcpy(bp, tbuf, (size_t)(ep - bp));
276             tname = bp;
277             bp += n;
278             continue;
279         }
280         if (type != qtype) {
281             if (type != T_KEY && type != T_SIG)
282                 LOG(DEBUG) << __func__ << ": asked for \"" << qname << " " << p_class(C_IN) << " "
283                            << p_type(qtype) << "\", got type \"" << p_type(type) << "\"";
284             cp += n;
285             continue; /* XXX - had_error++ ? */
286         }
287         switch (type) {
288             case T_PTR:
289                 if (strcasecmp(tname, bp) != 0) {
290                     LOG(DEBUG) << __func__ << ": asked for \"" << qname << "\", got \"" << bp
291                                << "\"";
292                     cp += n;
293                     continue; /* XXX - had_error++ ? */
294                 }
295                 n = dn_expand(answer->buf, eom, cp, bp, (int) (ep - bp));
296                 if ((n < 0) || !maybe_hnok(res, bp)) {
297                     had_error++;
298                     break;
299                 }
300                 cp += n;
301                 if (cp != erdata) goto no_recovery;
302                 if (!haveanswer)
303                     hent->h_name = bp;
304                 else
305                     aliases.push_back(bp);
306                 if (n != -1) {
307                     n = (int) strlen(bp) + 1; /* for the \0 */
308                     if (n >= MAXHOSTNAMELEN) {
309                         had_error++;
310                         break;
311                     }
312                     bp += n;
313                 }
314                 break;
315             case T_A:
316             case T_AAAA:
317                 if (strcasecmp(hent->h_name, bp) != 0) {
318                     LOG(DEBUG) << __func__ << ": asked for \"" << hent->h_name << "\", got \"" << bp
319                                << "\"";
320                     cp += n;
321                     continue; /* XXX - had_error++ ? */
322                 }
323                 if (n != hent->h_length) {
324                     cp += n;
325                     continue;
326                 }
327                 if (type == T_AAAA) {
328                     struct in6_addr in6;
329                     memcpy(&in6, cp, NS_IN6ADDRSZ);
330                     if (IN6_IS_ADDR_V4MAPPED(&in6)) {
331                         cp += n;
332                         continue;
333                     }
334                 }
335                 if (!haveanswer) {
336                     int nn;
337 
338                     hent->h_name = bp;
339                     nn = (int) strlen(bp) + 1; /* for the \0 */
340                     bp += nn;
341                 }
342 
343                 bp += sizeof(align) - (size_t)((u_long) bp % sizeof(align));
344 
345                 if (bp + n >= ep) {
346                     LOG(DEBUG) << __func__ << ": size (" << n << ") too big";
347                     had_error++;
348                     continue;
349                 }
350                 if (hap >= &addr_ptrs[MAXADDRS - 1]) {
351                     if (!toobig++) {
352                         LOG(DEBUG) << __func__ << ": Too many addresses (" << MAXADDRS << ")";
353                     }
354                     cp += n;
355                     continue;
356                 }
357                 (void) memcpy(*hap++ = bp, cp, (size_t) n);
358                 bp += n;
359                 cp += n;
360                 if (cp != erdata) goto no_recovery;
361                 break;
362             default:
363                 abort();
364         }
365         if (!had_error) haveanswer++;
366     }
367     if (haveanswer) {
368         *hap = NULL;
369         /*
370          * Note: we sort even if host can take only one address
371          * in its return structures - should give it the "best"
372          * address in that case, not some random one
373          */
374         if (res->nsort && haveanswer > 1 && qtype == T_A) addrsort(addr_ptrs, haveanswer, res);
375         if (!hent->h_name) {
376             n = (int) strlen(qname) + 1; /* for the \0 */
377             if (n > ep - bp || n >= MAXHOSTNAMELEN) goto no_recovery;
378             strlcpy(bp, qname, (size_t)(ep - bp));
379             hent->h_name = bp;
380             bp += n;
381         }
382         if (res->options & RES_USE_INET6) map_v4v6_hostent(hent, &bp, ep);
383         if (hent->h_addrtype == AF_INET) pad_v4v6_hostent(hent, &bp, ep);
384         goto success;
385     }
386 no_recovery:
387     *he = NO_RECOVERY;
388     return NULL;
389 success:
390     bp = (char*) ALIGN(bp);
391     aliases.push_back(nullptr);
392     qlen = aliases.size() * sizeof(*hent->h_aliases);
393     if ((size_t)(ep - bp) < qlen) goto nospc;
394     hent->h_aliases = (char**) bp;
395     memcpy(bp, aliases.data(), qlen);
396 
397     bp += qlen;
398     n = (int) (hap - addr_ptrs);
399     qlen = (n + 1) * sizeof(*hent->h_addr_list);
400     if ((size_t)(ep - bp) < qlen) goto nospc;
401     hent->h_addr_list = (char**) bp;
402     memcpy(bp, addr_ptrs, qlen);
403     *he = NETDB_SUCCESS;
404     return hent;
405 nospc:
406     errno = ENOSPC;
407     *he = NETDB_INTERNAL;
408     return NULL;
409 }
410 
gethostbyname_internal_real(const char * name,int af,res_state res,hostent * hp,char * buf,size_t buflen)411 static int gethostbyname_internal_real(const char* name, int af, res_state res, hostent* hp,
412                                        char* buf, size_t buflen) {
413     getnamaddr info;
414     size_t size;
415 
416     _DIAGASSERT(name != NULL);
417 
418     switch (af) {
419         case AF_INET:
420             size = NS_INADDRSZ;
421             break;
422         case AF_INET6:
423             size = NS_IN6ADDRSZ;
424             break;
425         default:
426             return EAI_FAMILY;
427     }
428     if (buflen < size) goto nospc;
429 
430     hp->h_addrtype = af;
431     hp->h_length = (int) size;
432 
433     /*
434      * disallow names consisting only of digits/dots, unless
435      * they end in a dot.
436      */
437     if (isdigit((u_char) name[0])) {
438         for (const char* cp = name;; ++cp) {
439             if (!*cp) {
440                 if (*--cp == '.') break;
441                 /*
442                  * All-numeric, no dot at the end.
443                  * Fake up a hostent as if we'd actually
444                  * done a lookup.
445                  */
446                 goto fake;
447             }
448             if (!isdigit((u_char) *cp) && *cp != '.') break;
449         }
450     }
451     if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) || name[0] == ':') {
452         for (const char* cp = name;; ++cp) {
453             if (!*cp) {
454                 if (*--cp == '.') break;
455                 /*
456                  * All-IPv6-legal, no dot at the end.
457                  * Fake up a hostent as if we'd actually
458                  * done a lookup.
459                  */
460                 goto fake;
461             }
462             if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.') break;
463         }
464     }
465 
466     info.hp = hp;
467     info.buf = buf;
468     info.buflen = buflen;
469     if (_hf_gethtbyname2(name, af, &info)) {
470         int error = dns_gethtbyname(name, af, &info);
471         if (error != 0) return error;
472     }
473     return 0;
474 nospc:
475     return EAI_MEMORY;
476 fake:
477     HENT_ARRAY(hp->h_addr_list, 1, buf, buflen);
478     HENT_ARRAY(hp->h_aliases, 0, buf, buflen);
479 
480     hp->h_aliases[0] = NULL;
481     if (size > buflen) goto nospc;
482 
483     if (inet_pton(af, name, buf) <= 0) {
484         return EAI_NODATA;
485     }
486     hp->h_addr_list[0] = buf;
487     hp->h_addr_list[1] = NULL;
488     buf += size;
489     buflen -= size;
490     HENT_SCOPY(hp->h_name, name, buf, buflen);
491     if (res->options & RES_USE_INET6) map_v4v6_hostent(hp, &buf, buf + buflen);
492     return 0;
493 }
494 
495 // very similar in proxy-ness to android_getaddrinfo_proxy
gethostbyname_internal(const char * name,int af,res_state res,hostent * hp,char * hbuf,size_t hbuflen,const android_net_context * netcontext)496 static int gethostbyname_internal(const char* name, int af, res_state res, hostent* hp, char* hbuf,
497                                   size_t hbuflen, const android_net_context* netcontext) {
498     res_setnetcontext(res, netcontext);
499     return gethostbyname_internal_real(name, af, res, hp, hbuf, hbuflen);
500 }
501 
android_gethostbyaddrfornetcontext_real(const void * addr,socklen_t len,int af,struct hostent * hp,char * buf,size_t buflen,const struct android_net_context * netcontext)502 static int android_gethostbyaddrfornetcontext_real(const void* addr, socklen_t len, int af,
503                                                    struct hostent* hp, char* buf, size_t buflen,
504                                                    const struct android_net_context* netcontext) {
505     const u_char* uaddr = (const u_char*) addr;
506     socklen_t size;
507     struct getnamaddr info;
508 
509     _DIAGASSERT(addr != NULL);
510 
511     if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
512         (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr*) addr) ||
513          IN6_IS_ADDR_SITELOCAL((const struct in6_addr*) addr))) {
514         return EAI_NODATA;
515     }
516     if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
517         (IN6_IS_ADDR_V4MAPPED((const struct in6_addr*) addr) ||
518          IN6_IS_ADDR_V4COMPAT((const struct in6_addr*) addr))) {
519         /* Unmap. */
520         uaddr += NS_IN6ADDRSZ - NS_INADDRSZ;
521         addr = uaddr;
522         af = AF_INET;
523         len = NS_INADDRSZ;
524     }
525     switch (af) {
526         case AF_INET:
527             size = NS_INADDRSZ;
528             break;
529         case AF_INET6:
530             size = NS_IN6ADDRSZ;
531             break;
532         default:
533             return EAI_FAMILY;
534     }
535     if (size != len) {
536         // TODO: Consider converting to a private extended EAI_* error code.
537         // Currently, the EAI_* value has no corresponding error code for invalid argument socket
538         // length. In order to not rely on errno, convert the original error code pair, EAI_SYSTEM
539         // and EINVAL, to EAI_FAIL.
540         return EAI_FAIL;
541     }
542     info.hp = hp;
543     info.buf = buf;
544     info.buflen = buflen;
545     if (_hf_gethtbyaddr(uaddr, len, af, &info)) {
546         int error = dns_gethtbyaddr(uaddr, len, af, netcontext, &info);
547         if (error != 0) return error;
548     }
549     return 0;
550 }
551 
android_gethostbyaddrfornetcontext_proxy_internal(const void * addr,socklen_t len,int af,struct hostent * hp,char * hbuf,size_t hbuflen,const struct android_net_context * netcontext)552 static int android_gethostbyaddrfornetcontext_proxy_internal(
553         const void* addr, socklen_t len, int af, struct hostent* hp, char* hbuf, size_t hbuflen,
554         const struct android_net_context* netcontext) {
555     return android_gethostbyaddrfornetcontext_real(addr, len, af, hp, hbuf, hbuflen, netcontext);
556 }
557 
558 // TODO: Consider leaving function without returning error code as _gethtent() does because
559 // the error code of the caller does not currently return to netd.
netbsd_gethostent_r(FILE * hf,struct hostent * hent,char * buf,size_t buflen,int * he)560 struct hostent* netbsd_gethostent_r(FILE* hf, struct hostent* hent, char* buf, size_t buflen,
561                                     int* he) {
562     const size_t line_buf_size = sizeof(res_get_static()->hostbuf);
563     char *name;
564     char* cp;
565     int af, len;
566     size_t anum;
567     struct in6_addr host_addr;
568     std::vector<char*> aliases;
569 
570     if (hf == NULL) {
571         *he = NETDB_INTERNAL;
572         errno = EINVAL;
573         return NULL;
574     }
575     char* p = NULL;
576 
577     /* Allocate a new space to read file lines like upstream does.
578      * To keep reentrancy we cannot use res_get_static()->hostbuf here,
579      * as the buffer may be used to store content for a previous hostent
580      * returned by non-reentrant functions like gethostbyname().
581      */
582     if ((p = (char*) malloc(line_buf_size)) == NULL) {
583         goto nospc;
584     }
585     for (;;) {
586         if (!fgets(p, line_buf_size, hf)) {
587             free(p);
588             *he = HOST_NOT_FOUND;
589             return NULL;
590         }
591         if (*p == '#') {
592             continue;
593         }
594         if (!(cp = strpbrk(p, "#\n"))) {
595             continue;
596         }
597         *cp = '\0';
598         if (!(cp = strpbrk(p, " \t"))) continue;
599         *cp++ = '\0';
600         if (inet_pton(AF_INET6, p, &host_addr) > 0) {
601             af = AF_INET6;
602             len = NS_IN6ADDRSZ;
603         } else {
604             if (inet_pton(AF_INET, p, &host_addr) <= 0) continue;
605 
606             res_state res = res_get_state();
607             if (res == NULL) goto nospc;
608             if (res->options & RES_USE_INET6) {
609                 map_v4v6_address(buf, buf);
610                 af = AF_INET6;
611                 len = NS_IN6ADDRSZ;
612             } else {
613                 af = AF_INET;
614                 len = NS_INADDRSZ;
615             }
616         }
617 
618         /* if this is not something we're looking for, skip it. */
619         if (hent->h_addrtype != 0 && hent->h_addrtype != af) continue;
620         if (hent->h_length != 0 && hent->h_length != len) continue;
621 
622         while (*cp == ' ' || *cp == '\t') cp++;
623         if ((cp = strpbrk(name = cp, " \t")) != NULL) *cp++ = '\0';
624         while (cp && *cp) {
625             if (*cp == ' ' || *cp == '\t') {
626                 cp++;
627                 continue;
628             }
629             aliases.push_back(cp);
630             if ((cp = strpbrk(cp, " \t")) != NULL) *cp++ = '\0';
631         }
632         break;
633     }
634     hent->h_length = len;
635     hent->h_addrtype = af;
636     HENT_ARRAY(hent->h_addr_list, 1, buf, buflen);
637     anum = aliases.size();
638     HENT_ARRAY(hent->h_aliases, anum, buf, buflen);
639     HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf, buflen);
640     hent->h_addr_list[1] = NULL;
641 
642     /* Reserve space for mapping IPv4 address to IPv6 address in place */
643     if (hent->h_addrtype == AF_INET) {
644         HENT_COPY(buf, NAT64_PAD, sizeof(NAT64_PAD), buf, buflen);
645     }
646 
647     HENT_SCOPY(hent->h_name, name, buf, buflen);
648     for (size_t i = 0; i < anum; i++) HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen);
649     hent->h_aliases[anum] = NULL;
650     *he = NETDB_SUCCESS;
651     free(p);
652     return hent;
653 nospc:
654     free(p);
655     errno = ENOSPC;
656     *he = NETDB_INTERNAL;
657     return NULL;
658 }
659 
map_v4v6_address(const char * src,char * dst)660 static void map_v4v6_address(const char* src, char* dst) {
661     u_char* p = (u_char*) dst;
662     char tmp[NS_INADDRSZ];
663     int i;
664 
665     _DIAGASSERT(src != NULL);
666     _DIAGASSERT(dst != NULL);
667 
668     /* Stash a temporary copy so our caller can update in place. */
669     memcpy(tmp, src, NS_INADDRSZ);
670     /* Mark this ipv6 addr as a mapped ipv4. */
671     for (i = 0; i < 10; i++) *p++ = 0x00;
672     *p++ = 0xff;
673     *p++ = 0xff;
674     /* Retrieve the saved copy and we're done. */
675     memcpy(p, tmp, NS_INADDRSZ);
676 }
677 
convert_v4v6_hostent(struct hostent * hp,char ** bpp,char * ep,std::function<void (struct hostent * hp)> map_param,std::function<void (char * src,char * dst)> map_addr)678 static void convert_v4v6_hostent(struct hostent* hp, char** bpp, char* ep,
679                                  std::function<void(struct hostent* hp)> map_param,
680                                  std::function<void(char* src, char* dst)> map_addr) {
681     _DIAGASSERT(hp != NULL);
682     _DIAGASSERT(bpp != NULL);
683     _DIAGASSERT(ep != NULL);
684 
685     if (hp->h_addrtype != AF_INET || hp->h_length != NS_INADDRSZ) return;
686     map_param(hp);
687     for (char** ap = hp->h_addr_list; *ap; ap++) {
688         int i = (int) (sizeof(align) - (size_t)((u_long) *bpp % sizeof(align)));
689 
690         if (ep - *bpp < (i + NS_IN6ADDRSZ)) {
691             /* Out of memory.  Truncate address list here.  XXX */
692             *ap = NULL;
693             return;
694         }
695         *bpp += i;
696         map_addr(*ap, *bpp);
697         *ap = *bpp;
698         *bpp += NS_IN6ADDRSZ;
699     }
700 }
701 
map_v4v6_hostent(struct hostent * hp,char ** bpp,char * ep)702 static void map_v4v6_hostent(struct hostent* hp, char** bpp, char* ep) {
703     convert_v4v6_hostent(hp, bpp, ep,
704                          [](struct hostent* hp) {
705                              hp->h_addrtype = AF_INET6;
706                              hp->h_length = NS_IN6ADDRSZ;
707                          },
708                          [](char* src, char* dst) { map_v4v6_address(src, dst); });
709 }
710 
711 /* Reserve space for mapping IPv4 address to IPv6 address in place */
pad_v4v6_hostent(struct hostent * hp,char ** bpp,char * ep)712 static void pad_v4v6_hostent(struct hostent* hp, char** bpp, char* ep) {
713     convert_v4v6_hostent(hp, bpp, ep,
714                          [](struct hostent* hp) {
715                              (void) hp; /* unused */
716                          },
717                          [](char* src, char* dst) {
718                              memcpy(dst, src, NS_INADDRSZ);
719                              memcpy(dst + NS_INADDRSZ, NAT64_PAD, sizeof(NAT64_PAD));
720                          });
721 }
722 
addrsort(char ** ap,int num,res_state res)723 static void addrsort(char** ap, int num, res_state res) {
724     int i, j;
725     char** p;
726     short aval[MAXADDRS];
727     int needsort = 0;
728 
729     _DIAGASSERT(ap != NULL);
730 
731     p = ap;
732     for (i = 0; i < num; i++, p++) {
733         for (j = 0; (unsigned) j < res->nsort; j++)
734             if (res->sort_list[j].addr.s_addr ==
735                 (((struct in_addr*) (void*) (*p))->s_addr & res->sort_list[j].mask))
736                 break;
737         aval[i] = j;
738         if (needsort == 0 && i > 0 && j < aval[i - 1]) needsort = i;
739     }
740     if (!needsort) return;
741 
742     while (needsort < num) {
743         for (j = needsort - 1; j >= 0; j--) {
744             if (aval[j] > aval[j + 1]) {
745                 char* hp;
746 
747                 i = aval[j];
748                 aval[j] = aval[j + 1];
749                 aval[j + 1] = i;
750 
751                 hp = ap[j];
752                 ap[j] = ap[j + 1];
753                 ap[j + 1] = hp;
754             } else
755                 break;
756         }
757         needsort++;
758     }
759 }
760 
dns_gethtbyname(const char * name,int addr_type,getnamaddr * info)761 static int dns_gethtbyname(const char* name, int addr_type, getnamaddr* info) {
762     int n, type;
763     info->hp->h_addrtype = addr_type;
764 
765     switch (info->hp->h_addrtype) {
766         case AF_INET:
767             info->hp->h_length = NS_INADDRSZ;
768             type = T_A;
769             break;
770         case AF_INET6:
771             info->hp->h_length = NS_IN6ADDRSZ;
772             type = T_AAAA;
773             break;
774         default:
775             return EAI_FAMILY;
776     }
777     auto buf = std::make_unique<querybuf>();
778 
779     res_state res = res_get_state();
780     if (!res) return EAI_MEMORY;
781 
782     int he;
783     n = res_nsearch(res, name, C_IN, type, buf->buf, (int)sizeof(buf->buf), &he);
784     if (n < 0) {
785         LOG(DEBUG) << __func__ << ": res_nsearch failed (" << n << ")";
786         // Return h_errno (he) to catch more detailed errors rather than EAI_NODATA.
787         // Note that res_nsearch() doesn't set the pair NETDB_INTERNAL and errno.
788         // See also herrnoToAiErrno().
789         return herrnoToAiErrno(he);
790     }
791     hostent* hp = getanswer(buf.get(), n, name, type, res, info->hp, info->buf, info->buflen, &he);
792     if (hp == NULL) return herrnoToAiErrno(he);
793 
794     return 0;
795 }
796 
dns_gethtbyaddr(const unsigned char * uaddr,int len,int af,const android_net_context * netcontext,getnamaddr * info)797 static int dns_gethtbyaddr(const unsigned char* uaddr, int len, int af,
798                            const android_net_context* netcontext, getnamaddr* info) {
799     char qbuf[MAXDNAME + 1], *qp, *ep;
800     int n;
801     int advance;
802 
803     info->hp->h_length = len;
804     info->hp->h_addrtype = af;
805 
806     switch (info->hp->h_addrtype) {
807         case AF_INET:
808             (void) snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa", (uaddr[3] & 0xff),
809                             (uaddr[2] & 0xff), (uaddr[1] & 0xff), (uaddr[0] & 0xff));
810             break;
811 
812         case AF_INET6:
813             qp = qbuf;
814             ep = qbuf + sizeof(qbuf) - 1;
815             for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) {
816                 advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.", uaddr[n] & 0xf,
817                                    ((unsigned int) uaddr[n] >> 4) & 0xf);
818                 if (advance > 0 && qp + advance < ep)
819                     qp += advance;
820                 else {
821                     // TODO: Consider converting to a private extended EAI_* error code.
822                     // Currently, the EAI_* value has no corresponding error code for an internal
823                     // out of buffer space. In order to not rely on errno, convert the original
824                     // error code EAI_SYSTEM to EAI_MEMORY.
825                     return EAI_MEMORY;
826                 }
827             }
828             if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) {
829                 // TODO: Consider converting to a private extended EAI_* error code.
830                 // Currently, the EAI_* value has no corresponding error code for an internal
831                 // out of buffer space. In order to not rely on errno, convert the original
832                 // error code EAI_SYSTEM to EAI_MEMORY.
833                 return EAI_MEMORY;
834             }
835             break;
836         default:
837             return EAI_FAMILY;
838     }
839 
840     auto buf = std::make_unique<querybuf>();
841 
842     res_state res = res_get_state();
843     if (!res) return EAI_MEMORY;
844 
845     res_setnetcontext(res, netcontext);
846     int he;
847     n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int)sizeof(buf->buf), &he);
848     if (n < 0) {
849         LOG(DEBUG) << __func__ << ": res_nquery failed (" << n << ")";
850         // Note that res_nquery() doesn't set the pair NETDB_INTERNAL and errno.
851         // Return h_errno (he) to catch more detailed errors rather than EAI_NODATA.
852         // See also herrnoToAiErrno().
853         return herrnoToAiErrno(he);
854     }
855     hostent* hp = getanswer(buf.get(), n, qbuf, T_PTR, res, info->hp, info->buf, info->buflen, &he);
856     if (hp == NULL) return herrnoToAiErrno(he);
857 
858     char* bf = (char*) (hp->h_addr_list + 2);
859     size_t blen = (size_t)(bf - info->buf);
860     if (blen + info->hp->h_length > info->buflen) goto nospc;
861     hp->h_addr_list[0] = bf;
862     hp->h_addr_list[1] = NULL;
863     memcpy(bf, uaddr, (size_t) info->hp->h_length);
864     if (info->hp->h_addrtype == AF_INET && (res->options & RES_USE_INET6)) {
865         if (blen + NS_IN6ADDRSZ > info->buflen) goto nospc;
866         map_v4v6_address(bf, bf);
867         hp->h_addrtype = AF_INET6;
868         hp->h_length = NS_IN6ADDRSZ;
869     }
870 
871     /* Reserve enough space for mapping IPv4 address to IPv6 address in place */
872     if (info->hp->h_addrtype == AF_INET) {
873         if (blen + NS_IN6ADDRSZ > info->buflen) goto nospc;
874         // Pad zero to the unused address space
875         memcpy(bf + NS_INADDRSZ, NAT64_PAD, sizeof(NAT64_PAD));
876     }
877 
878     return 0;
879 
880 nospc:
881     return EAI_MEMORY;
882 }
883 
884 /*
885  * Non-reentrant versions.
886  */
887 
android_gethostbynamefornetcontext(const char * name,int af,const struct android_net_context * netcontext,hostent ** hp)888 int android_gethostbynamefornetcontext(const char* name, int af,
889                                        const struct android_net_context* netcontext, hostent** hp) {
890     int error;
891     res_state res = res_get_state();
892     if (res == NULL) return EAI_MEMORY;
893     res_static* rs = res_get_static();  // For thread-safety.
894     error = gethostbyname_internal(name, af, res, &rs->host, rs->hostbuf, sizeof(rs->hostbuf),
895                                    netcontext);
896     if (error == 0) {
897         *hp = &rs->host;
898     }
899     return error;
900 }
901 
android_gethostbyaddrfornetcontext(const void * addr,socklen_t len,int af,const struct android_net_context * netcontext,hostent ** hp)902 int android_gethostbyaddrfornetcontext(const void* addr, socklen_t len, int af,
903                                        const struct android_net_context* netcontext, hostent** hp) {
904     return android_gethostbyaddrfornetcontext_proxy(addr, len, af, netcontext, hp);
905 }
906 
android_gethostbyaddrfornetcontext_proxy(const void * addr,socklen_t len,int af,const struct android_net_context * netcontext,hostent ** hp)907 static int android_gethostbyaddrfornetcontext_proxy(const void* addr, socklen_t len, int af,
908                                                     const struct android_net_context* netcontext,
909                                                     hostent** hp) {
910     struct res_static* rs = res_get_static();  // For thread-safety.
911     int error = android_gethostbyaddrfornetcontext_proxy_internal(
912             addr, len, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), netcontext);
913     if (error == 0) *hp = &rs->host;
914     return error;
915 }
916 
herrnoToAiErrno(int he)917 int herrnoToAiErrno(int he) {
918     switch (he) {
919         // extended h_errno
920         case NETD_RESOLV_H_ERRNO_EXT_TIMEOUT:
921             return NETD_RESOLV_TIMEOUT;
922         // legacy h_errno
923         case NETDB_SUCCESS:
924             return 0;
925         case HOST_NOT_FOUND:  // TODO: Perhaps convert HOST_NOT_FOUND to EAI_NONAME instead
926         case NO_DATA:         // NO_ADDRESS
927             return EAI_NODATA;
928         case TRY_AGAIN:
929             return EAI_AGAIN;
930         case NETDB_INTERNAL:
931             // TODO: Remove ENOSPC and call abort() immediately whenever any allocation fails.
932             if (errno == ENOSPC) return EAI_MEMORY;
933             // Theoretically, this should not happen. Leave this here just in case.
934             // Currently, getanswer() of {gethnamaddr, getaddrinfo}.cpp, res_nsearch() and
935             // res_searchN() use this function to convert error code. Only getanswer()
936             // of gethnamaddr.cpp may return the error code pair, herrno NETDB_INTERNAL and
937             // errno ENOSPC, which has already converted to EAI_MEMORY. The remaining functions
938             // don't set the pair herrno and errno.
939             return EAI_SYSTEM;  // see errno for detail
940         case NO_RECOVERY:
941         default:
942             return EAI_FAIL;  // TODO: Perhaps convert default to EAI_MAX (unknown error) instead
943     }
944 }
945