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

Commit c98fd802 authored by Luke Huang's avatar Luke Huang
Browse files

Unify MAXPACKET and refactor buffer allocation of getaddrinfo

We have many copies of MAXPACKET
Use vector instead of old struct

Test: atest
Change-Id: I406a52855814646814d19dfdc083cd27e1aa6813
parent effead99
Loading
Loading
Loading
Loading
+0 −4
Original line number Original line Diff line number Diff line
@@ -74,10 +74,6 @@ namespace {
// Limits the number of outstanding DNS queries by client UID.
// Limits the number of outstanding DNS queries by client UID.
constexpr int MAX_QUERIES_PER_UID = 256;
constexpr int MAX_QUERIES_PER_UID = 256;


// Max packet size for answer, sync with getaddrinfo.c
// TODO: switch to dynamically allocated buffers with std::vector
constexpr int MAXPACKET = 8 * 1024;

android::netdutils::OperationLimiter<uid_t> queryLimiter(MAX_QUERIES_PER_UID);
android::netdutils::OperationLimiter<uid_t> queryLimiter(MAX_QUERIES_PER_UID);


void logArguments(int argc, char** argv) {
void logArguments(int argc, char** argv) {
+20 −44
Original line number Original line Diff line number Diff line
@@ -108,20 +108,13 @@ const Explore explore_options[] = {
};
};


#define PTON_MAX 16
#define PTON_MAX 16
#define MAXPACKET (8 * 1024)

typedef union {
    HEADER hdr;
    uint8_t buf[MAXPACKET];
} querybuf;


struct res_target {
struct res_target {
    struct res_target* next;
    struct res_target* next;
    const char* name;  /* domain name */
    const char* name;                                                  // domain name
    int qclass, qtype; /* class and type of query */
    int qclass, qtype;                                                 // class and type of query
    uint8_t* answer;   /* buffer to put answer */
    std::vector<uint8_t> answer = std::vector<uint8_t>(MAXPACKET, 0);  // buffer to put answer
    int anslen;        /* size of answer buffer */
    int n = 0;                                                         // result length
    int n;             /* result length */
};
};


static int str2number(const char*);
static int str2number(const char*);
@@ -139,8 +132,8 @@ static int get_port(const struct addrinfo*, const char*, int);
static const struct afd* find_afd(int);
static const struct afd* find_afd(int);
static int ip6_str2scopeid(const char*, struct sockaddr_in6*, uint32_t*);
static int ip6_str2scopeid(const char*, struct sockaddr_in6*, uint32_t*);


static struct addrinfo* getanswer(const querybuf*, int, const char*, int, const struct addrinfo*,
static struct addrinfo* getanswer(const std::vector<uint8_t>&, int, const char*, int,
                                  int* herrno);
                                  const struct addrinfo*, int* herrno);
static int dns_getaddrinfo(const char* name, const addrinfo* pai,
static int dns_getaddrinfo(const char* name, const addrinfo* pai,
                           const android_net_context* netcontext, addrinfo** rv,
                           const android_net_context* netcontext, addrinfo** rv,
                           NetworkDnsEventReported* event);
                           NetworkDnsEventReported* event);
@@ -838,8 +831,8 @@ static int ip6_str2scopeid(const char* scope, struct sockaddr_in6* sin6, uint32_
        }                            \
        }                            \
    } while (0)
    } while (0)


static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char* qname, int qtype,
static struct addrinfo* getanswer(const std::vector<uint8_t>& answer, int anslen, const char* qname,
                                  const struct addrinfo* pai, int* herrno) {
                                  int qtype, const struct addrinfo* pai, int* herrno) {
    struct addrinfo sentinel = {};
    struct addrinfo sentinel = {};
    struct addrinfo *cur;
    struct addrinfo *cur;
    struct addrinfo ai;
    struct addrinfo ai;
@@ -856,14 +849,13 @@ static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char
    int (*name_ok)(const char*);
    int (*name_ok)(const char*);
    char hostbuf[8 * 1024];
    char hostbuf[8 * 1024];


    assert(answer != NULL);
    assert(qname != NULL);
    assert(qname != NULL);
    assert(pai != NULL);
    assert(pai != NULL);


    cur = &sentinel;
    cur = &sentinel;


    canonname = NULL;
    canonname = NULL;
    eom = answer->buf + anslen;
    eom = answer.data() + anslen;
    switch (qtype) {
    switch (qtype) {
        case T_A:
        case T_A:
        case T_AAAA:
        case T_AAAA:
@@ -876,18 +868,18 @@ static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char
    /*
    /*
     * find first satisfactory answer
     * find first satisfactory answer
     */
     */
    hp = &answer->hdr;
    hp = reinterpret_cast<const HEADER*>(answer.data());
    ancount = ntohs(hp->ancount);
    ancount = ntohs(hp->ancount);
    qdcount = ntohs(hp->qdcount);
    qdcount = ntohs(hp->qdcount);
    bp = hostbuf;
    bp = hostbuf;
    ep = hostbuf + sizeof hostbuf;
    ep = hostbuf + sizeof hostbuf;
    cp = answer->buf;
    cp = answer.data();
    BOUNDED_INCR(HFIXEDSZ);
    BOUNDED_INCR(HFIXEDSZ);
    if (qdcount != 1) {
    if (qdcount != 1) {
        *herrno = NO_RECOVERY;
        *herrno = NO_RECOVERY;
        return (NULL);
        return (NULL);
    }
    }
    n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
    n = dn_expand(answer.data(), eom, cp, bp, ep - bp);
    if ((n < 0) || !(*name_ok)(bp)) {
    if ((n < 0) || !(*name_ok)(bp)) {
        *herrno = NO_RECOVERY;
        *herrno = NO_RECOVERY;
        return (NULL);
        return (NULL);
@@ -911,7 +903,7 @@ static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char
    haveanswer = 0;
    haveanswer = 0;
    had_error = 0;
    had_error = 0;
    while (ancount-- > 0 && cp < eom && !had_error) {
    while (ancount-- > 0 && cp < eom && !had_error) {
        n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
        n = dn_expand(answer.data(), eom, cp, bp, ep - bp);
        if ((n < 0) || !(*name_ok)(bp)) {
        if ((n < 0) || !(*name_ok)(bp)) {
            had_error++;
            had_error++;
            continue;
            continue;
@@ -931,7 +923,7 @@ static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char
            continue; /* XXX - had_error++ ? */
            continue; /* XXX - had_error++ ? */
        }
        }
        if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && type == T_CNAME) {
        if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && type == T_CNAME) {
            n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
            n = dn_expand(answer.data(), eom, cp, tbuf, sizeof tbuf);
            if ((n < 0) || !(*name_ok)(tbuf)) {
            if ((n < 0) || !(*name_ok)(tbuf)) {
                had_error++;
                had_error++;
                continue;
                continue;
@@ -1397,16 +1389,11 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai,
    res_target q = {};
    res_target q = {};
    res_target q2 = {};
    res_target q2 = {};


    auto buf = std::make_unique<querybuf>();
    auto buf2 = std::make_unique<querybuf>();

    switch (pai->ai_family) {
    switch (pai->ai_family) {
        case AF_UNSPEC: {
        case AF_UNSPEC: {
            /* prefer IPv6 */
            /* prefer IPv6 */
            q.name = name;
            q.name = name;
            q.qclass = C_IN;
            q.qclass = C_IN;
            q.answer = buf->buf;
            q.anslen = sizeof(buf->buf);
            int query_ipv6 = 1, query_ipv4 = 1;
            int query_ipv6 = 1, query_ipv4 = 1;
            if (pai->ai_flags & AI_ADDRCONFIG) {
            if (pai->ai_flags & AI_ADDRCONFIG) {
                query_ipv6 = have_ipv6(netcontext->app_mark, netcontext->uid);
                query_ipv6 = have_ipv6(netcontext->app_mark, netcontext->uid);
@@ -1419,8 +1406,6 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai,
                    q2.name = name;
                    q2.name = name;
                    q2.qclass = C_IN;
                    q2.qclass = C_IN;
                    q2.qtype = T_A;
                    q2.qtype = T_A;
                    q2.answer = buf2->buf;
                    q2.anslen = sizeof(buf2->buf);
                }
                }
            } else if (query_ipv4) {
            } else if (query_ipv4) {
                q.qtype = T_A;
                q.qtype = T_A;
@@ -1433,15 +1418,11 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai,
            q.name = name;
            q.name = name;
            q.qclass = C_IN;
            q.qclass = C_IN;
            q.qtype = T_A;
            q.qtype = T_A;
            q.answer = buf->buf;
            q.anslen = sizeof(buf->buf);
            break;
            break;
        case AF_INET6:
        case AF_INET6:
            q.name = name;
            q.name = name;
            q.qclass = C_IN;
            q.qclass = C_IN;
            q.qtype = T_AAAA;
            q.qtype = T_AAAA;
            q.answer = buf->buf;
            q.anslen = sizeof(buf->buf);
            break;
            break;
        default:
        default:
            return EAI_FAMILY;
            return EAI_FAMILY;
@@ -1460,13 +1441,13 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai,


    addrinfo sentinel = {};
    addrinfo sentinel = {};
    addrinfo* cur = &sentinel;
    addrinfo* cur = &sentinel;
    addrinfo* ai = getanswer(buf.get(), q.n, q.name, q.qtype, pai, &he);
    addrinfo* ai = getanswer(q.answer, q.n, q.name, q.qtype, pai, &he);
    if (ai) {
    if (ai) {
        cur->ai_next = ai;
        cur->ai_next = ai;
        while (cur && cur->ai_next) cur = cur->ai_next;
        while (cur && cur->ai_next) cur = cur->ai_next;
    }
    }
    if (q.next) {
    if (q.next) {
        ai = getanswer(buf2.get(), q2.n, q2.name, q2.qtype, pai, &he);
        ai = getanswer(q2.answer, q2.n, q2.name, q2.qtype, pai, &he);
        if (ai) cur->ai_next = ai;
        if (ai) cur->ai_next = ai;
    }
    }
    if (sentinel.ai_next == NULL) {
    if (sentinel.ai_next == NULL) {
@@ -1578,7 +1559,6 @@ static bool files_getaddrinfo(const char* name, const addrinfo* pai, addrinfo**
 */
 */
static int res_queryN(const char* name, res_target* target, res_state res, int* herrno) {
static int res_queryN(const char* name, res_target* target, res_state res, int* herrno) {
    uint8_t buf[MAXPACKET];
    uint8_t buf[MAXPACKET];
    HEADER* hp;
    int n;
    int n;
    struct res_target* t;
    struct res_target* t;
    int rcode;
    int rcode;
@@ -1591,10 +1571,7 @@ static int res_queryN(const char* name, res_target* target, res_state res, int*
    ancount = 0;
    ancount = 0;


    for (t = target; t; t = t->next) {
    for (t = target; t; t = t->next) {
        uint8_t* answer;
        HEADER* hp = (HEADER*)(void*)t->answer.data();
        int anslen;

        hp = (HEADER*) (void*) t->answer;
        bool retried = false;
        bool retried = false;
    again:
    again:
        hp->rcode = NOERROR; /* default */
        hp->rcode = NOERROR; /* default */
@@ -1602,8 +1579,7 @@ static int res_queryN(const char* name, res_target* target, res_state res, int*
        /* make it easier... */
        /* make it easier... */
        int cl = t->qclass;
        int cl = t->qclass;
        int type = t->qtype;
        int type = t->qtype;
        answer = t->answer;
        const int anslen = t->answer.size();
        anslen = t->anslen;


        LOG(DEBUG) << __func__ << ": (" << cl << ", " << type << ")";
        LOG(DEBUG) << __func__ << ": (" << cl << ", " << type << ")";


@@ -1620,7 +1596,7 @@ static int res_queryN(const char* name, res_target* target, res_state res, int*
            return n;
            return n;
        }
        }


        n = res_nsend(res, buf, n, answer, anslen, &rcode, 0);
        n = res_nsend(res, buf, n, t->answer.data(), anslen, &rcode, 0);
        if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
        if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
            // Record rcode from DNS response header only if no timeout.
            // Record rcode from DNS response header only if no timeout.
            // Keep rcode timeout for reporting later if any.
            // Keep rcode timeout for reporting later if any.
@@ -1689,7 +1665,7 @@ static int res_searchN(const char* name, res_target* target, res_state res, int*
    assert(name != NULL);
    assert(name != NULL);
    assert(target != NULL);
    assert(target != NULL);


    hp = (HEADER*) (void*) target->answer; /*XXX*/
    hp = (HEADER*)(void*)target->answer.data();


    errno = 0;
    errno = 0;
    *herrno = HOST_NOT_FOUND; /* default, if we never query */
    *herrno = HOST_NOT_FOUND; /* default, if we never query */
+0 −2
Original line number Original line Diff line number Diff line
@@ -95,8 +95,6 @@ using android::net::NetworkDnsEventReported;
#define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok)
#define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok)
#define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok)
#define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok)


#define MAXPACKET (8 * 1024)

constexpr int MAXADDRS = 35;
constexpr int MAXADDRS = 35;


typedef union {
typedef union {
+0 −6
Original line number Original line Diff line number Diff line
@@ -89,12 +89,6 @@
#include "resolv_cache.h"
#include "resolv_cache.h"
#include "resolv_private.h"
#include "resolv_private.h"


#if PACKETSZ > 1024
#define MAXPACKET PACKETSZ
#else
#define MAXPACKET 1024
#endif

/*
/*
 * Formulate a normal query, send, and await answer.
 * Formulate a normal query, send, and await answer.
 * Returned answer is placed in supplied buffer "answer".
 * Returned answer is placed in supplied buffer "answer".
+10 −16
Original line number Original line Diff line number Diff line
@@ -226,15 +226,6 @@ static struct timespec evNowTime(void) {
    return tsnow;
    return tsnow;
}
}


static struct iovec evConsIovec(void* buf, size_t cnt) {
    struct iovec ret;

    memset(&ret, 0xf5, sizeof ret);
    ret.iov_base = buf;
    ret.iov_len = cnt;
    return ret;
}

// END: Code copied from ISC eventlib
// END: Code copied from ISC eventlib


/* BIONIC-BEGIN: implement source port randomization */
/* BIONIC-BEGIN: implement source port randomization */
@@ -669,7 +660,6 @@ static int send_vc(res_state statp, res_params* params, const uint8_t* buf, int
    struct sockaddr* nsap;
    struct sockaddr* nsap;
    int nsaplen;
    int nsaplen;
    int truncating, connreset, n;
    int truncating, connreset, n;
    struct iovec iov[2];
    uint8_t* cp;
    uint8_t* cp;


    LOG(INFO) << __func__ << ": using send_vc";
    LOG(INFO) << __func__ << ": using send_vc";
@@ -754,8 +744,10 @@ same_ns:
     * Send length & message
     * Send length & message
     */
     */
    uint16_t len = htons(static_cast<uint16_t>(buflen));
    uint16_t len = htons(static_cast<uint16_t>(buflen));
    iov[0] = evConsIovec(&len, INT16SZ);
    const iovec iov[] = {
    iov[1] = evConsIovec((void*) buf, (size_t) buflen);
            {.iov_base = &len, .iov_len = INT16SZ},
            {.iov_base = const_cast<uint8_t*>(buf), .iov_len = static_cast<size_t>(buflen)},
    };
    if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
    if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
        *terrno = errno;
        *terrno = errno;
        PLOG(DEBUG) << __func__ << ": write failed: ";
        PLOG(DEBUG) << __func__ << ": write failed: ";
@@ -863,8 +855,8 @@ read_len:
}
}


/* return -1 on error (errno set), 0 on success */
/* return -1 on error (errno set), 0 on success */
static int connect_with_timeout(int sock, const struct sockaddr* nsap, socklen_t salen,
static int connect_with_timeout(int sock, const sockaddr* nsap, socklen_t salen,
                                const struct timespec timeout) {
                                const timespec timeout) {
    int res, origflags;
    int res, origflags;


    origflags = fcntl(sock, F_GETFL, 0);
    origflags = fcntl(sock, F_GETFL, 0);
@@ -876,8 +868,8 @@ static int connect_with_timeout(int sock, const struct sockaddr* nsap, socklen_t
        goto done;
        goto done;
    }
    }
    if (res != 0) {
    if (res != 0) {
        struct timespec now = evNowTime();
        timespec now = evNowTime();
        struct timespec finish = evAddTime(now, timeout);
        timespec finish = evAddTime(now, timeout);
        LOG(INFO) << __func__ << ": " << sock << " send_vc";
        LOG(INFO) << __func__ << ": " << sock << " send_vc";
        res = retrying_poll(sock, POLLIN | POLLOUT, &finish);
        res = retrying_poll(sock, POLLIN | POLLOUT, &finish);
        if (res <= 0) {
        if (res <= 0) {
@@ -1102,6 +1094,7 @@ static void dump_error(const char* str, const struct sockaddr* address, int alen
    char hbuf[NI_MAXHOST];
    char hbuf[NI_MAXHOST];
    char sbuf[NI_MAXSERV];
    char sbuf[NI_MAXSERV];
    constexpr int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
    constexpr int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
    const int err = errno;


    if (!WOULD_LOG(DEBUG)) return;
    if (!WOULD_LOG(DEBUG)) return;


@@ -1111,6 +1104,7 @@ static void dump_error(const char* str, const struct sockaddr* address, int alen
        strncpy(sbuf, "?", sizeof(sbuf) - 1);
        strncpy(sbuf, "?", sizeof(sbuf) - 1);
        sbuf[sizeof(sbuf) - 1] = '\0';
        sbuf[sizeof(sbuf) - 1] = '\0';
    }
    }
    errno = err;
    PLOG(DEBUG) << __func__ << ": " << str << " ([" << hbuf << "]." << sbuf << "): ";
    PLOG(DEBUG) << __func__ << ": " << str << " ([" << hbuf << "]." << sbuf << "): ";
}
}


Loading