Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6c84a3d0 authored by Hungming Chen's avatar Hungming Chen
Browse files

Remove thread-local variable h_errno in gethostby{name, addr} related APIs

Using a thread-local variable to return an int to the caller is a hack and
adds a lot of complexity. Return error code with an int pointer instead.

Test: built, flashed, booted
      system/netd/tests/runtests.sh pass

Change-Id: Ie9da1a6b18525967f0e8fe3d54b0df18e37d2b0e
parent 598202c4
Loading
Loading
Loading
Loading
+29 −39
Original line number Diff line number Diff line
@@ -140,12 +140,11 @@ static int _dns_gethtbyaddr(const unsigned char* uaddr, int len, int af,
static int _dns_gethtbyname(const char* name, int af, getnamaddr* info);

static int gethostbyname_internal(const char* name, int af, res_state res, hostent* hp, char* hbuf,
                                  size_t hbuflen, int* errorp,
                                  const android_net_context* netcontext);
                                  size_t hbuflen, const android_net_context* netcontext);
static int gethostbyname_internal_real(const char* name, int af, res_state res, hostent* hp,
                                       char* buf, size_t buflen, int* he);
                                       char* buf, size_t buflen);
static int android_gethostbyaddrfornetcontext_proxy_internal(const void*, socklen_t, int,
                                                             struct hostent*, char*, size_t, int*,
                                                             struct hostent*, char*, size_t,
                                                             const struct android_net_context*);
static int android_gethostbyaddrfornetcontext_proxy(const void* addr, socklen_t len, int af,
                                                    const struct android_net_context* netcontext,
@@ -471,9 +470,11 @@ nospc:
}

static int gethostbyname_internal_real(const char* name, int af, res_state res, hostent* hp,
                                       char* buf, size_t buflen, int* he) {
                                       char* buf, size_t buflen) {
    getnamaddr info;
    size_t size;
    // TODO: Remove it once the data member "he" of struct getnamaddr is removed.
    int he = NETDB_INTERNAL;

    _DIAGASSERT(name != NULL);

@@ -485,7 +486,6 @@ static int gethostbyname_internal_real(const char* name, int af, res_state res,
            size = NS_IN6ADDRSZ;
            break;
        default:
            *he = NETDB_INTERNAL;
            errno = EAFNOSUPPORT;
            return EAI_FAMILY;
    }
@@ -527,24 +527,20 @@ static int gethostbyname_internal_real(const char* name, int af, res_state res,
        }
    }

    *he = NETDB_INTERNAL;
    info.hp = hp;
    info.buf = buf;
    info.buflen = buflen;
    info.he = he;
    if (!_hf_gethtbyname2(name, af, &info)) {
    info.he = &he;  // TODO: Remove the data member "he" of struct getnamaddr.
    if (_hf_gethtbyname2(name, af, &info)) {
        int error = _dns_gethtbyname(name, af, &info);
        if (error != 0) {
            return error;
        }
    }
    *he = NETDB_SUCCESS;
    return 0;
nospc:
    *he = NETDB_INTERNAL;
    errno = ENOSPC;
    // Bad arguments
    return EAI_FAIL;
    return EAI_MEMORY;
fake:
    HENT_ARRAY(hp->h_addr_list, 1, buf, buflen);
    HENT_ARRAY(hp->h_aliases, 0, buf, buflen);
@@ -553,7 +549,6 @@ fake:
    if (size > buflen) goto nospc;

    if (inet_pton(af, name, buf) <= 0) {
        *he = HOST_NOT_FOUND;
        return EAI_NODATA;
    }
    hp->h_addr_list[0] = buf;
@@ -562,32 +557,30 @@ fake:
    buflen -= size;
    HENT_SCOPY(hp->h_name, name, buf, buflen);
    if (res->options & RES_USE_INET6) map_v4v6_hostent(hp, &buf, buf + buflen);
    *he = NETDB_SUCCESS;
    return 0;
}

// very similar in proxy-ness to android_getaddrinfo_proxy
static int gethostbyname_internal(const char* name, int af, res_state res, hostent* hp, char* hbuf,
                                  size_t hbuflen, int* errorp,
                                  const android_net_context* netcontext) {
                                  size_t hbuflen, const android_net_context* netcontext) {
    res_setnetcontext(res, netcontext);
    return gethostbyname_internal_real(name, af, res, hp, hbuf, hbuflen, errorp);
    return gethostbyname_internal_real(name, af, res, hp, hbuf, hbuflen);
}

static int android_gethostbyaddrfornetcontext_real(const void* addr, socklen_t len, int af,
                                                   struct hostent* hp, char* buf, size_t buflen,
                                                   int* he,
                                                   const struct android_net_context* netcontext) {
    const u_char* uaddr = (const u_char*) addr;
    socklen_t size;
    struct getnamaddr info;
    // TODO: Remove it once the data member "he" of struct getnamaddr is removed.
    int he = NETDB_INTERNAL;

    _DIAGASSERT(addr != NULL);

    if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
        (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr*) addr) ||
         IN6_IS_ADDR_SITELOCAL((const struct in6_addr*) addr))) {
        *he = HOST_NOT_FOUND;
        return EAI_NODATA;
    }
    if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
@@ -608,35 +601,30 @@ static int android_gethostbyaddrfornetcontext_real(const void* addr, socklen_t l
            break;
        default:
            errno = EAFNOSUPPORT;
            *he = NETDB_INTERNAL;
            return EAI_FAMILY;
    }
    if (size != len) {
        errno = EINVAL;
        *he = NETDB_INTERNAL;
        // TODO: Consider to remap error code without relying on errno.
        return EAI_SYSTEM;
    }
    info.hp = hp;
    info.buf = buf;
    info.buflen = buflen;
    info.he = he;
    *he = NETDB_INTERNAL;
    if (!_hf_gethtbyaddr(uaddr, len, af, &info)) {
    info.he = &he;  // TODO: Remove the data member "he" of struct getnamaddr.
    if (_hf_gethtbyaddr(uaddr, len, af, &info)) {
        int error = _dns_gethtbyaddr(uaddr, len, af, netcontext, &info);
        if (error != 0) {
            return error;
        }
    }
    *he = NETDB_SUCCESS;
    return 0;
}

static int android_gethostbyaddrfornetcontext_proxy_internal(
        const void* addr, socklen_t len, int af, struct hostent* hp, char* hbuf, size_t hbuflen,
        int* he, const struct android_net_context* netcontext) {
    return android_gethostbyaddrfornetcontext_real(addr, len, af, hp, hbuf, hbuflen, he,
                                                   netcontext);
        const struct android_net_context* netcontext) {
    return android_gethostbyaddrfornetcontext_real(addr, len, af, hp, hbuf, hbuflen, netcontext);
}

struct hostent* netbsd_gethostent_r(FILE* hf, struct hostent* hent, char* buf, size_t buflen,
@@ -878,7 +866,8 @@ static int _dns_gethtbyname(const char* name, int addr_type, getnamaddr* info) {
    }

    int ai_error = EAI_NODATA;
    n = res_nsearch(res, name, C_IN, type, buf->buf, (int) sizeof(buf->buf), &ai_error);
    int herrno = NETDB_INTERNAL;
    n = res_nsearch(res, name, C_IN, type, buf->buf, (int) sizeof(buf->buf), &ai_error, &herrno);
    if (n < 0) {
        free(buf);
        debugprintf("res_nsearch failed (%d)\n", res, n);
@@ -887,14 +876,14 @@ static int _dns_gethtbyname(const char* name, int addr_type, getnamaddr* info) {
        // get the nulltpr hp.
        // TODO: Adjust the error closed to res_nsend instead of here after h_errno is removed.
        if (ai_error == 0) {
            return herrnoToAiError(h_errno);
            return herrnoToAiError(herrno);
        }
        return ai_error;
    }
    hp = getanswer(buf, n, name, type, res, info->hp, info->buf, info->buflen, info->he);
    hp = getanswer(buf, n, name, type, res, info->hp, info->buf, info->buflen, &herrno);
    free(buf);
    if (hp == NULL) {
        return herrnoToAiError(h_errno);
        return herrnoToAiError(herrno);
    }
    return 0;
}
@@ -952,7 +941,8 @@ static int _dns_gethtbyaddr(const unsigned char* uaddr, int len, int af,
    }
    res_setnetcontext(res, netcontext);
    int ai_error = 0;
    n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int) sizeof(buf->buf), &ai_error);
    int herrno = NETDB_INTERNAL;
    n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int) sizeof(buf->buf), &ai_error, &herrno);
    if (n < 0) {
        free(buf);
        debugprintf("res_nquery failed (%d)\n", res, n);
@@ -963,12 +953,12 @@ static int _dns_gethtbyaddr(const unsigned char* uaddr, int len, int af,
        // query progress. DNS server may respond a DNS packet without any answer for queried
        // address. In this case, return error code from h_errno NO_DATA rather than rcode NOERROR
        // (ai_error).
        return herrnoToAiError(h_errno);
        return herrnoToAiError(herrno);
    }
    hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf, info->buflen, info->he);
    hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf, info->buflen, &herrno);
    free(buf);
    if (hp == NULL) {
        return herrnoToAiError(h_errno);
        return herrnoToAiError(herrno);
    }

    char* bf = (char*) (hp->h_addr_list + 2);
@@ -1011,7 +1001,7 @@ int android_gethostbynamefornetcontext(const char* name, int af,
    if (res == NULL) return EAI_MEMORY;
    res_static* rs = res_get_static();  // For thread-safety.
    error = gethostbyname_internal(name, af, res, &rs->host, rs->hostbuf, sizeof(rs->hostbuf),
                                   &h_errno, netcontext);
                                   netcontext);
    if (error == 0) {
        *hp = &rs->host;
    }
@@ -1028,7 +1018,7 @@ static int android_gethostbyaddrfornetcontext_proxy(const void* addr, socklen_t
                                                    hostent** hp) {
    struct res_static* rs = res_get_static();  // For thread-safety.
    int error = android_gethostbyaddrfornetcontext_proxy_internal(
            addr, len, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &h_errno, netcontext);
            addr, len, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), netcontext);
    if (error == 0) *hp = &rs->host;
    return error;
}
+2 −2
Original line number Diff line number Diff line
@@ -42,8 +42,8 @@ struct getnamaddr {
};

// /etc/hosts lookup
bool _hf_gethtbyaddr(const unsigned char* uaddr, int len, int af, getnamaddr* info);
hostent* _hf_gethtbyname2(const char* name, int af, getnamaddr* info);
int _hf_gethtbyaddr(const unsigned char* uaddr, int len, int af, getnamaddr* info);
int _hf_gethtbyname2(const char* name, int af, getnamaddr* info);
hostent* netbsd_gethostent_r(FILE*, struct hostent*, char*, size_t, int*);

// Reserved padding for remapping IPv4 address to NAT64 synthesis IPv6 address
+28 −24
Original line number Diff line number Diff line
@@ -103,7 +103,7 @@
 * Perform preliminary check of answer, returning success only
 * if no error is indicated and the answer count is nonzero.
 * Return the size of the response on success, -1 on error.
 * Error number is left in H_ERRNO.
 * Error number is left in *herrno.
 *
 * Caller must parse answer and determine whether it answers the question.
 */
@@ -111,7 +111,8 @@ int res_nquery(res_state statp, const char* name, // domain name
               int cl, int type,                   // class and type of query
               u_char* answer,                     // buffer to put answer
               int anslen,                         // size of answer buffer
               int* ai_error)                      // error will be set based on rcode
               int* ai_error,                      // error will be set based on rcode
               int* herrno)                        // legacy h_errno
{
    u_char buf[MAXPACKET];
    HEADER* hp = (HEADER*) (void*) answer;
@@ -136,7 +137,7 @@ again:
#ifdef DEBUG
        if (statp->options & RES_DEBUG) printf(";; res_query: mkquery failed\n");
#endif
        RES_SET_H_ERRNO(statp, NO_RECOVERY);
        *herrno = NO_RECOVERY;
        return n;
    }
    n = res_nsend(statp, buf, n, answer, anslen, &rcode);
@@ -152,7 +153,7 @@ again:
#ifdef DEBUG
        if (statp->options & RES_DEBUG) printf(";; res_query: send error\n");
#endif
        RES_SET_H_ERRNO(statp, TRY_AGAIN);
        *herrno = TRY_AGAIN;
        return n;
    }

@@ -164,19 +165,19 @@ again:
#endif
        switch (hp->rcode) {
            case NXDOMAIN:
                RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
                *herrno = HOST_NOT_FOUND;
                break;
            case SERVFAIL:
                RES_SET_H_ERRNO(statp, TRY_AGAIN);
                *herrno = TRY_AGAIN;
                break;
            case NOERROR:
                RES_SET_H_ERRNO(statp, NO_DATA);
                *herrno = NO_DATA;
                break;
            case FORMERR:
            case NOTIMP:
            case REFUSED:
            default:
                RES_SET_H_ERRNO(statp, NO_RECOVERY);
                *herrno = NO_RECOVERY;
                break;
        }
        return -1;
@@ -188,13 +189,14 @@ again:
 * Formulate a normal query, send, and retrieve answer in supplied buffer.
 * Return the size of the response on success, -1 on error.
 * If enabled, implement search rules until answer or unrecoverable failure
 * is detected.  Error code, if any, is left in H_ERRNO.
 * is detected.  Error code, if any, is left in *herrno.
 */
int res_nsearch(res_state statp, const char* name, /* domain name */
                int cl, int type,                  /* class and type of query */
                u_char* answer,                    /* buffer to put answer */
                int anslen,                        /* size of answer */
                int* ai_error)                     /* error will be set based on rcode*/
                int* ai_error,                     /* error will be set based on rcode */
                int* herrno)                       /* legacy h_errno */
{
    const char *cp, *const *domain;
    HEADER* hp = (HEADER*) (void*) answer;
@@ -205,7 +207,7 @@ int res_nsearch(res_state statp, const char* name, /* domain name */
    int searched = 0;

    errno = 0;
    RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /* True if we never query. */
    *herrno = HOST_NOT_FOUND; /* True if we never query. */

    dots = 0;
    for (cp = name; *cp != '\0'; cp++) dots += (*cp == '.');
@@ -219,9 +221,9 @@ int res_nsearch(res_state statp, const char* name, /* domain name */
     */
    saved_herrno = -1;
    if (dots >= statp->ndots || trailing_dot) {
        ret = res_nquerydomain(statp, name, NULL, cl, type, answer, anslen, ai_error);
        ret = res_nquerydomain(statp, name, NULL, cl, type, answer, anslen, ai_error, herrno);
        if (ret > 0 || trailing_dot) return ret;
        saved_herrno = statp->res_h_errno;
        saved_herrno = *herrno;
        tried_as_is++;
    }

@@ -250,7 +252,8 @@ int res_nsearch(res_state statp, const char* name, /* domain name */
            if (domain[0][0] == '\0' || (domain[0][0] == '.' && domain[0][1] == '\0'))
                root_on_list++;

            ret = res_nquerydomain(statp, name, *domain, cl, type, answer, anslen, ai_error);
            ret = res_nquerydomain(statp, name, *domain, cl, type, answer, anslen, ai_error,
                                   herrno);
            if (ret > 0) return ret;

            /*
@@ -267,11 +270,11 @@ int res_nsearch(res_state statp, const char* name, /* domain name */
             * fully-qualified.
             */
            if (errno == ECONNREFUSED) {
                RES_SET_H_ERRNO(statp, TRY_AGAIN);
                *herrno = TRY_AGAIN;
                return -1;
            }

            switch (statp->res_h_errno) {
            switch (*herrno) {
                case NO_DATA:
                    got_nodata++;
                    break;
@@ -303,7 +306,7 @@ int res_nsearch(res_state statp, const char* name, /* domain name */
     */
    if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0U) &&
        !(tried_as_is || root_on_list)) {
        ret = res_nquerydomain(statp, name, NULL, cl, type, answer, anslen, ai_error);
        ret = res_nquerydomain(statp, name, NULL, cl, type, answer, anslen, ai_error, herrno);
        if (ret > 0) return ret;
    }

@@ -315,11 +318,11 @@ int res_nsearch(res_state statp, const char* name, /* domain name */
     * the last DNSRCH we did.
     */
    if (saved_herrno != -1)
        RES_SET_H_ERRNO(statp, saved_herrno);
        *herrno = saved_herrno;
    else if (got_nodata)
        RES_SET_H_ERRNO(statp, NO_DATA);
        *herrno = NO_DATA;
    else if (got_servfail)
        RES_SET_H_ERRNO(statp, TRY_AGAIN);
        *herrno = TRY_AGAIN;
    return -1;
}

@@ -331,7 +334,8 @@ int res_nquerydomain(res_state statp, const char* name, const char* domain, int
                     int type,       /* class and type of query */
                     u_char* answer, /* buffer to put answer */
                     int anslen,     /* size of answer */
                     int* ai_error)  /* error will be set based on rcode*/
                     int* ai_error,  /* error will be set based on rcode */
                     int* herrno)    /* legacy h_errno */
{
    char nbuf[MAXDNAME];
    const char* longname = nbuf;
@@ -349,7 +353,7 @@ int res_nquerydomain(res_state statp, const char* name, const char* domain, int
         */
        n = strlen(name);
        if (n >= MAXDNAME) {
            RES_SET_H_ERRNO(statp, NO_RECOVERY);
            *herrno = NO_RECOVERY;
            return -1;
        }
        n--;
@@ -362,10 +366,10 @@ int res_nquerydomain(res_state statp, const char* name, const char* domain, int
        n = strlen(name);
        d = strlen(domain);
        if (n + d + 1 >= MAXDNAME) {
            RES_SET_H_ERRNO(statp, NO_RECOVERY);
            *herrno = NO_RECOVERY;
            return -1;
        }
        snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
    }
    return res_nquery(statp, longname, cl, type, answer, anslen, ai_error);
    return res_nquery(statp, longname, cl, type, answer, anslen, ai_error, herrno);
}
+5 −3
Original line number Diff line number Diff line
@@ -258,9 +258,11 @@ const char* p_section(int, int);
/* Things involving a resolver context. */
int res_ninit(res_state);
void res_pquery(const res_state, const u_char*, int, FILE*);
int res_nquery(res_state, const char*, int, int, u_char*, int, int*);
int res_nsearch(res_state, const char*, int, int, u_char*, int, int*);
int res_nquerydomain(res_state, const char*, const char*, int, int, u_char*, int, int*);
// TODO: Consider that refactor res_nquery, res_nsearch and res_nquerydomain to return one error
// code but two error codes.
int res_nquery(res_state, const char*, int, int, u_char*, int, int*, int*);
int res_nsearch(res_state, const char*, int, int, u_char*, int, int*, int*);
int res_nquerydomain(res_state, const char*, const char*, int, int, u_char*, int, int*, int*);
int res_nmkquery(res_state, int, const char*, int, int, const u_char*, int, const u_char*, u_char*,
                 int);
int res_nsend(res_state, const u_char*, int, u_char*, int, int*);
+13 −11
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ static void endhostent_r(FILE** hf) {
    }
}

hostent* _hf_gethtbyname2(const char* name, int af, getnamaddr* info) {
int _hf_gethtbyname2(const char* name, int af, getnamaddr* info) {
    struct hostent *hp, hent;
    char *buf, *ptr;
    size_t len, num, i;
@@ -73,12 +73,13 @@ hostent* _hf_gethtbyname2(const char* name, int af, getnamaddr* info) {
    if (hf == NULL) {
        errno = EINVAL;
        *info->he = NETDB_INTERNAL;
        return NULL;
        // TODO: Consider to remap error code without relying on errno.
        return EAI_SYSTEM;
    }

    if ((ptr = buf = (char*) malloc(len = info->buflen)) == NULL) {
        *info->he = NETDB_INTERNAL;
        return NULL;
        return EAI_MEMORY;
    }

    hent.h_name = NULL;
@@ -129,7 +130,7 @@ hostent* _hf_gethtbyname2(const char* name, int af, getnamaddr* info) {
    if (num == 0) {
        *info->he = HOST_NOT_FOUND;
        free(buf);
        return NULL;
        return EAI_NODATA;
    }

    hp = info->hp;
@@ -160,15 +161,15 @@ hostent* _hf_gethtbyname2(const char* name, int af, getnamaddr* info) {
    hp->h_aliases[anum] = NULL;

    free(buf);
    return hp;
    return 0;
nospc:
    *info->he = NETDB_INTERNAL;
    free(buf);
    errno = ENOSPC;
    return NULL;
    return EAI_MEMORY;
}

bool _hf_gethtbyaddr(const unsigned char* uaddr, int len, int af, getnamaddr* info) {
int _hf_gethtbyaddr(const unsigned char* uaddr, int len, int af, getnamaddr* info) {
    info->hp->h_length = len;
    info->hp->h_addrtype = af;

@@ -176,7 +177,8 @@ bool _hf_gethtbyaddr(const unsigned char* uaddr, int len, int af, getnamaddr* in
    sethostent_r(&hf);
    if (hf == NULL) {
        *info->he = NETDB_INTERNAL;
        return false;
        // TODO: Consider to remap error code without relying on errno.
        return EAI_SYSTEM;
    }
    struct hostent* hp;
    while ((hp = netbsd_gethostent_r(hf, info->hp, info->buf, info->buflen, info->he)) != NULL)
@@ -184,9 +186,9 @@ bool _hf_gethtbyaddr(const unsigned char* uaddr, int len, int af, getnamaddr* in
    endhostent_r(&hf);

    if (hp == NULL) {
        if (errno == ENOSPC) return false;  // glibc compatibility.
        if (errno == ENOSPC) return EAI_MEMORY;  // glibc compatibility.
        *info->he = HOST_NOT_FOUND;
        return false;
        return EAI_NODATA;
    }
    return true;
    return 0;
}