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

Commit c50c43d1 authored by Bernie Innocenti's avatar Bernie Innocenti
Browse files

Use unique_ptr in dns_getaddrinfo()

This simplifies memory management a bit. In fact, we don't even bother
checking for memory allocation failures because 'new' aborts instead of
returning null to the caller.

Test: atest resolv_integration_test
Change-Id: I6456922f4ca6d04d67fedc8873b0c32becf1d3dc
parent 3952ccca
Loading
Loading
Loading
Loading
+16 −39
Original line number Diff line number Diff line
@@ -233,7 +233,7 @@ static int str2number(const char* p) {
 * on the local system". However, bionic doesn't currently support getifaddrs,
 * so checking for connectivity is the next best thing.
 */
static int _have_ipv6(unsigned mark, uid_t uid) {
static int have_ipv6(unsigned mark, uid_t uid) {
    static const struct sockaddr_in6 sin6_test = {
            .sin6_family = AF_INET6,
            .sin6_addr.s6_addr = {// 2000::
@@ -242,7 +242,7 @@ static int _have_ipv6(unsigned mark, uid_t uid) {
    return _find_src_addr(&addr.sa, NULL, mark, uid) == 1;
}

static int _have_ipv4(unsigned mark, uid_t uid) {
static int have_ipv4(unsigned mark, uid_t uid) {
    static const struct sockaddr_in sin_test = {
            .sin_family = AF_INET,
            .sin_addr.s_addr = __constant_htonl(0x08080808L)  // 8.8.8.8
@@ -425,7 +425,7 @@ int android_getaddrinfofornetcontext(const char* hostname, const char* servname,

    if (error) {
        freeaddrinfo(sentinel.ai_next);
        *res = NULL;
        *res = nullptr;
    } else {
        *res = sentinel.ai_next;
    }
@@ -1375,24 +1375,11 @@ error:

static int dns_getaddrinfo(const char* name, const addrinfo* pai,
                           const android_net_context* netcontext, addrinfo** rv) {
    struct addrinfo *ai, *cur;
    struct addrinfo sentinel = {};
    struct res_target q, q2;
    res_state res;

    memset(&q, 0, sizeof(q));
    memset(&q2, 0, sizeof(q2));
    cur = &sentinel;
    res_target q = {};
    res_target q2 = {};

    querybuf* buf = (querybuf*) malloc(sizeof(*buf));
    if (buf == NULL) {
        return EAI_MEMORY;
    }
    querybuf* buf2 = (querybuf*) malloc(sizeof(*buf2));
    if (buf2 == NULL) {
        free(buf);
        return EAI_MEMORY;
    }
    auto buf = std::make_unique<querybuf>();
    auto buf2 = std::make_unique<querybuf>();

    switch (pai->ai_family) {
        case AF_UNSPEC: {
@@ -1403,8 +1390,8 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai,
            q.anslen = sizeof(buf->buf);
            int query_ipv6 = 1, query_ipv4 = 1;
            if (pai->ai_flags & AI_ADDRCONFIG) {
                query_ipv6 = _have_ipv6(netcontext->app_mark, netcontext->uid);
                query_ipv4 = _have_ipv4(netcontext->app_mark, netcontext->uid);
                query_ipv6 = have_ipv6(netcontext->app_mark, netcontext->uid);
                query_ipv4 = have_ipv4(netcontext->app_mark, netcontext->uid);
            }
            if (query_ipv6) {
                q.qtype = T_AAAA;
@@ -1419,8 +1406,6 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai,
            } else if (query_ipv4) {
                q.qtype = T_A;
            } else {
                free(buf);
                free(buf2);
                return EAI_NODATA;
            }
            break;
@@ -1440,17 +1425,11 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai,
            q.anslen = sizeof(buf->buf);
            break;
        default:
            free(buf);
            free(buf2);
            return EAI_FAMILY;
    }

    res = res_get_state();
    if (res == NULL) {
        free(buf);
        free(buf2);
        return EAI_MEMORY;
    }
    res_state res = res_get_state();
    if (!res) return EAI_MEMORY;

    /* this just sets our netid val in the thread private data so we don't have to
     * modify the api's all the way down to res_send.c's res_nsend.  We could
@@ -1461,22 +1440,21 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai,

    int herrno = NETDB_INTERNAL;
    if (res_searchN(name, &q, res, &herrno) < 0) {
        free(buf);
        free(buf2);
        // Pass herrno to catch more detailed errors rather than EAI_NODATA.
        return herrnoToAiErrno(herrno);
    }
    ai = getanswer(buf, q.n, q.name, q.qtype, pai, &herrno);

    addrinfo sentinel = {};
    addrinfo* cur = &sentinel;
    addrinfo* ai = getanswer(buf.get(), q.n, q.name, q.qtype, pai, &herrno);
    if (ai) {
        cur->ai_next = ai;
        while (cur && cur->ai_next) cur = cur->ai_next;
    }
    if (q.next) {
        ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai, &herrno);
        ai = getanswer(buf2.get(), q2.n, q2.name, q2.qtype, pai, &herrno);
        if (ai) cur->ai_next = ai;
    }
    free(buf);
    free(buf2);
    if (sentinel.ai_next == NULL) {
        return herrnoToAiErrno(herrno);
    }
@@ -1531,7 +1509,6 @@ again:
        if (!cname) cname = cp;
        tname = cp;
        if ((cp = strpbrk(cp, " \t")) != NULL) *cp++ = '\0';
        //		fprintf(stderr, "\ttname = '%s'", tname);
        if (strcasecmp(name, tname) == 0) goto found;
    }
    goto again;