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

Commit de5a43fe authored by Automerger Merge Worker's avatar Automerger Merge Worker
Browse files

Use unique_fd instead of int for sockets am: adb0f5b9

Change-Id: Ibfdb775b0be22e8507b7eab53231cb478d17466c
parents b9688bdc adb0f5b9
Loading
Loading
Loading
Loading
+8 −35
Original line number Original line Diff line number Diff line
@@ -94,23 +94,11 @@


void res_init(ResState* statp, const struct android_net_context* _Nonnull netcontext,
void res_init(ResState* statp, const struct android_net_context* _Nonnull netcontext,
              android::net::NetworkDnsEventReported* _Nonnull event) {
              android::net::NetworkDnsEventReported* _Nonnull event) {
    memset(statp, 0, sizeof *statp);

    statp->netid = netcontext->dns_netid;
    statp->netid = netcontext->dns_netid;
    statp->uid = netcontext->uid;
    statp->uid = netcontext->uid;
    statp->pid = netcontext->pid;
    statp->pid = netcontext->pid;
    statp->nscount = 1;
    statp->id = arc4random_uniform(65536);
    statp->id = arc4random_uniform(65536);
    statp->_mark = netcontext->dns_mark;
    statp->netcontext_flags = netcontext->flags;
    statp->event = event;

    statp->ndots = 1;
    statp->_vcsock = -1;

    for (int ns = 0; ns < MAXNS; ns++) {
        statp->nssocks[ns] = -1;
    }

    // The following dummy initialization is probably useless because
    // The following dummy initialization is probably useless because
    // it's overwritten later by resolv_populate_res_for_net().
    // it's overwritten later by resolv_populate_res_for_net().
    // TODO: check if it's safe to remove.
    // TODO: check if it's safe to remove.
@@ -120,28 +108,13 @@ void res_init(ResState* statp, const struct android_net_context* _Nonnull netcon
            .sin.sin_port = htons(NAMESERVER_PORT),
            .sin.sin_port = htons(NAMESERVER_PORT),
    };
    };
    memcpy(&statp->nsaddrs, &u, sizeof(u));
    memcpy(&statp->nsaddrs, &u, sizeof(u));
    statp->nscount = 1;
}

/*
 * This routine is for closing the socket if a virtual circuit is used and
 * the program wants to close it.  This provides support for endhostent()
 * which expects to close the socket.
 *
 * This routine is not expected to be user visible.
 */
void res_nclose(res_state statp) {
    int ns;


    if (statp->_vcsock >= 0) {
    for (auto& sock : statp->nssocks) {
        (void) close(statp->_vcsock);
        sock.reset();
        statp->_vcsock = -1;
        statp->_flags &= ~RES_F_VC;
    }
    for (ns = 0; ns < MAXNS; ns++) {
        if (statp->nssocks[ns] != -1) {
            close(statp->nssocks[ns]);
            statp->nssocks[ns] = -1;
        }
    }
    }
    statp->ndots = 1;
    statp->_mark = netcontext->dns_mark;
    statp->tcp_nssock.reset();
    statp->event = event;
    statp->netcontext_flags = netcontext->flags;
}
}
+37 −40
Original line number Original line Diff line number Diff line
@@ -555,7 +555,7 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int
            }
            }
            if (resplen < 0) {
            if (resplen < 0) {
                _resolv_cache_query_failed(statp->netid, buf, buflen, flags);
                _resolv_cache_query_failed(statp->netid, buf, buflen, flags);
                res_nclose(statp);
                statp->closeSockets();
                return -terrno;
                return -terrno;
            };
            };


@@ -565,11 +565,11 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int
            if (cache_status == RESOLV_CACHE_NOTFOUND) {
            if (cache_status == RESOLV_CACHE_NOTFOUND) {
                resolv_cache_add(statp->netid, buf, buflen, ans, resplen);
                resolv_cache_add(statp->netid, buf, buflen, ans, resplen);
            }
            }
            res_nclose(statp);
            statp->closeSockets();
            return (resplen);
            return (resplen);
        }  // for each ns
        }  // for each ns
    }  // for each retry
    }  // for each retry
    res_nclose(statp);
    statp->closeSockets();
    terrno = useTcp ? terrno : gotsomewhere ? ETIMEDOUT : ECONNREFUSED;
    terrno = useTcp ? terrno : gotsomewhere ? ETIMEDOUT : ECONNREFUSED;
    // TODO: Remove errno once callers stop using it
    // TODO: Remove errno once callers stop using it
    errno = useTcp ? terrno
    errno = useTcp ? terrno
@@ -631,25 +631,24 @@ same_ns:
    struct timespec now = evNowTime();
    struct timespec now = evNowTime();


    /* Are we still talking to whom we want to talk to? */
    /* Are we still talking to whom we want to talk to? */
    if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
    if (statp->tcp_nssock >= 0 && (statp->_flags & RES_F_VC) != 0) {
        struct sockaddr_storage peer;
        struct sockaddr_storage peer;
        socklen_t size = sizeof peer;
        socklen_t size = sizeof peer;
        unsigned old_mark;
        unsigned old_mark;
        socklen_t mark_size = sizeof(old_mark);
        socklen_t mark_size = sizeof(old_mark);
        if (getpeername(statp->_vcsock, (struct sockaddr*) (void*) &peer, &size) < 0 ||
        if (getpeername(statp->tcp_nssock, (struct sockaddr*)(void*)&peer, &size) < 0 ||
            !sock_eq((struct sockaddr*)(void*)&peer, nsap) ||
            !sock_eq((struct sockaddr*)(void*)&peer, nsap) ||
            getsockopt(statp->_vcsock, SOL_SOCKET, SO_MARK, &old_mark, &mark_size) < 0 ||
            getsockopt(statp->tcp_nssock, SOL_SOCKET, SO_MARK, &old_mark, &mark_size) < 0 ||
            old_mark != statp->_mark) {
            old_mark != statp->_mark) {
            res_nclose(statp);
            statp->closeSockets();
            statp->_flags &= ~RES_F_VC;
        }
        }
    }
    }


    if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
    if (statp->tcp_nssock < 0 || (statp->_flags & RES_F_VC) == 0) {
        if (statp->_vcsock >= 0) res_nclose(statp);
        if (statp->tcp_nssock >= 0) statp->closeSockets();


        statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
        statp->tcp_nssock.reset(socket(nsap->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0));
        if (statp->_vcsock < 0) {
        if (statp->tcp_nssock < 0) {
            switch (errno) {
            switch (errno) {
                case EPROTONOSUPPORT:
                case EPROTONOSUPPORT:
                case EPFNOSUPPORT:
                case EPFNOSUPPORT:
@@ -662,9 +661,9 @@ same_ns:
                    return -1;
                    return -1;
            }
            }
        }
        }
        resolv_tag_socket(statp->_vcsock, statp->uid, statp->pid);
        resolv_tag_socket(statp->tcp_nssock, statp->uid, statp->pid);
        if (statp->_mark != MARK_UNSET) {
        if (statp->_mark != MARK_UNSET) {
            if (setsockopt(statp->_vcsock, SOL_SOCKET, SO_MARK, &statp->_mark,
            if (setsockopt(statp->tcp_nssock, SOL_SOCKET, SO_MARK, &statp->_mark,
                           sizeof(statp->_mark)) < 0) {
                           sizeof(statp->_mark)) < 0) {
                *terrno = errno;
                *terrno = errno;
                PLOG(DEBUG) << __func__ << ": setsockopt: ";
                PLOG(DEBUG) << __func__ << ": setsockopt: ";
@@ -672,17 +671,17 @@ same_ns:
            }
            }
        }
        }
        errno = 0;
        errno = 0;
        if (random_bind(statp->_vcsock, nsap->sa_family) < 0) {
        if (random_bind(statp->tcp_nssock, nsap->sa_family) < 0) {
            *terrno = errno;
            *terrno = errno;
            dump_error("bind/vc", nsap, nsaplen);
            dump_error("bind/vc", nsap, nsaplen);
            res_nclose(statp);
            statp->closeSockets();
            return (0);
            return (0);
        }
        }
        if (connect_with_timeout(statp->_vcsock, nsap, (socklen_t) nsaplen,
        if (connect_with_timeout(statp->tcp_nssock, nsap, (socklen_t)nsaplen,
                                 get_timeout(statp, params, ns)) < 0) {
                                 get_timeout(statp, params, ns)) < 0) {
            *terrno = errno;
            *terrno = errno;
            dump_error("connect/vc", nsap, nsaplen);
            dump_error("connect/vc", nsap, nsaplen);
            res_nclose(statp);
            statp->closeSockets();
            /*
            /*
             * The way connect_with_timeout() is implemented prevents us from reliably
             * The way connect_with_timeout() is implemented prevents us from reliably
             * determining whether this was really a timeout or e.g. ECONNREFUSED. Since
             * determining whether this was really a timeout or e.g. ECONNREFUSED. Since
@@ -705,10 +704,10 @@ same_ns:
            {.iov_base = &len, .iov_len = INT16SZ},
            {.iov_base = &len, .iov_len = INT16SZ},
            {.iov_base = const_cast<uint8_t*>(buf), .iov_len = static_cast<size_t>(buflen)},
            {.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->tcp_nssock, iov, 2) != (INT16SZ + buflen)) {
        *terrno = errno;
        *terrno = errno;
        PLOG(DEBUG) << __func__ << ": write failed: ";
        PLOG(DEBUG) << __func__ << ": write failed: ";
        res_nclose(statp);
        statp->closeSockets();
        return (0);
        return (0);
    }
    }
    /*
    /*
@@ -717,14 +716,14 @@ same_ns:
read_len:
read_len:
    cp = ans;
    cp = ans;
    len = INT16SZ;
    len = INT16SZ;
    while ((n = read(statp->_vcsock, (char*) cp, (size_t) len)) > 0) {
    while ((n = read(statp->tcp_nssock, (char*)cp, (size_t)len)) > 0) {
        cp += n;
        cp += n;
        if ((len -= n) == 0) break;
        if ((len -= n) == 0) break;
    }
    }
    if (n <= 0) {
    if (n <= 0) {
        *terrno = errno;
        *terrno = errno;
        PLOG(DEBUG) << __func__ << ": read failed: ";
        PLOG(DEBUG) << __func__ << ": read failed: ";
        res_nclose(statp);
        statp->closeSockets();
        /*
        /*
         * A long running process might get its TCP
         * A long running process might get its TCP
         * connection reset if the remote server was
         * connection reset if the remote server was
@@ -736,10 +735,8 @@ read_len:
         */
         */
        if (*terrno == ECONNRESET && !connreset) {
        if (*terrno == ECONNRESET && !connreset) {
            connreset = 1;
            connreset = 1;
            res_nclose(statp);
            goto same_ns;
            goto same_ns;
        }
        }
        res_nclose(statp);
        return (0);
        return (0);
    }
    }
    uint16_t resplen = ntohs(*reinterpret_cast<const uint16_t*>(ans));
    uint16_t resplen = ntohs(*reinterpret_cast<const uint16_t*>(ans));
@@ -755,18 +752,18 @@ read_len:
         */
         */
        LOG(DEBUG) << __func__ << ": undersized: " << len;
        LOG(DEBUG) << __func__ << ": undersized: " << len;
        *terrno = EMSGSIZE;
        *terrno = EMSGSIZE;
        res_nclose(statp);
        statp->closeSockets();
        return (0);
        return (0);
    }
    }
    cp = ans;
    cp = ans;
    while (len != 0 && (n = read(statp->_vcsock, (char*) cp, (size_t) len)) > 0) {
    while (len != 0 && (n = read(statp->tcp_nssock, (char*)cp, (size_t)len)) > 0) {
        cp += n;
        cp += n;
        len -= n;
        len -= n;
    }
    }
    if (n <= 0) {
    if (n <= 0) {
        *terrno = errno;
        *terrno = errno;
        PLOG(DEBUG) << __func__ << ": read(vc): ";
        PLOG(DEBUG) << __func__ << ": read(vc): ";
        res_nclose(statp);
        statp->closeSockets();
        return (0);
        return (0);
    }
    }


@@ -779,7 +776,7 @@ read_len:
        while (len != 0) {
        while (len != 0) {
            char junk[PACKETSZ];
            char junk[PACKETSZ];


            n = read(statp->_vcsock, junk, (len > sizeof junk) ? sizeof junk : len);
            n = read(statp->tcp_nssock, junk, (len > sizeof junk) ? sizeof junk : len);
            if (n > 0)
            if (n > 0)
                len -= n;
                len -= n;
            else
            else
@@ -907,7 +904,7 @@ static int send_dg(res_state statp, res_params* params, const uint8_t* buf, int
    const int nsaplen = sockaddrSize(nsap);
    const int nsaplen = sockaddrSize(nsap);


    if (statp->nssocks[ns] == -1) {
    if (statp->nssocks[ns] == -1) {
        statp->nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
        statp->nssocks[ns].reset(socket(nsap->sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0));
        if (statp->nssocks[ns] < 0) {
        if (statp->nssocks[ns] < 0) {
            switch (errno) {
            switch (errno) {
                case EPROTONOSUPPORT:
                case EPROTONOSUPPORT:
@@ -926,7 +923,7 @@ static int send_dg(res_state statp, res_params* params, const uint8_t* buf, int
        if (statp->_mark != MARK_UNSET) {
        if (statp->_mark != MARK_UNSET) {
            if (setsockopt(statp->nssocks[ns], SOL_SOCKET, SO_MARK, &(statp->_mark),
            if (setsockopt(statp->nssocks[ns], SOL_SOCKET, SO_MARK, &(statp->_mark),
                           sizeof(statp->_mark)) < 0) {
                           sizeof(statp->_mark)) < 0) {
                res_nclose(statp);
                statp->closeSockets();
                return -1;
                return -1;
            }
            }
        }
        }
@@ -936,19 +933,19 @@ static int send_dg(res_state statp, res_params* params, const uint8_t* buf, int
        // a nameserver without timing out.
        // a nameserver without timing out.
        if (random_bind(statp->nssocks[ns], nsap->sa_family) < 0) {
        if (random_bind(statp->nssocks[ns], nsap->sa_family) < 0) {
            dump_error("bind(dg)", nsap, nsaplen);
            dump_error("bind(dg)", nsap, nsaplen);
            res_nclose(statp);
            statp->closeSockets();
            return (0);
            return (0);
        }
        }
        if (connect(statp->nssocks[ns], nsap, (socklen_t)nsaplen) < 0) {
        if (connect(statp->nssocks[ns], nsap, (socklen_t)nsaplen) < 0) {
            dump_error("connect(dg)", nsap, nsaplen);
            dump_error("connect(dg)", nsap, nsaplen);
            res_nclose(statp);
            statp->closeSockets();
            return (0);
            return (0);
        }
        }
        LOG(DEBUG) << __func__ << ": new DG socket";
        LOG(DEBUG) << __func__ << ": new DG socket";
    }
    }
    if (send(statp->nssocks[ns], (const char*)buf, (size_t)buflen, 0) != buflen) {
    if (send(statp->nssocks[ns], (const char*)buf, (size_t)buflen, 0) != buflen) {
        PLOG(DEBUG) << __func__ << ": send: ";
        PLOG(DEBUG) << __func__ << ": send: ";
        res_nclose(statp);
        statp->closeSockets();
        return 0;
        return 0;
    }
    }


@@ -966,7 +963,7 @@ static int send_dg(res_state statp, res_params* params, const uint8_t* buf, int
        }
        }
        if (n < 0) {
        if (n < 0) {
            PLOG(DEBUG) << __func__ << ": poll: ";
            PLOG(DEBUG) << __func__ << ": poll: ";
            res_nclose(statp);
            statp->closeSockets();
            return 0;
            return 0;
        }
        }


@@ -977,7 +974,7 @@ static int send_dg(res_state statp, res_params* params, const uint8_t* buf, int
                               (sockaddr*)(void*)&from, &fromlen);
                               (sockaddr*)(void*)&from, &fromlen);
        if (resplen <= 0) {
        if (resplen <= 0) {
            PLOG(DEBUG) << __func__ << ": recvfrom: ";
            PLOG(DEBUG) << __func__ << ": recvfrom: ";
            res_nclose(statp);
            statp->closeSockets();
            return 0;
            return 0;
        }
        }
        *gotsomewhere = 1;
        *gotsomewhere = 1;
@@ -985,7 +982,7 @@ static int send_dg(res_state statp, res_params* params, const uint8_t* buf, int
            // Undersized message.
            // Undersized message.
            LOG(DEBUG) << __func__ << ": undersized: " << resplen;
            LOG(DEBUG) << __func__ << ": undersized: " << resplen;
            *terrno = EMSGSIZE;
            *terrno = EMSGSIZE;
            res_nclose(statp);
            statp->closeSockets();
            return 0;
            return 0;
        }
        }


@@ -1003,7 +1000,7 @@ static int send_dg(res_state statp, res_params* params, const uint8_t* buf, int
            res_pquery(ans, (resplen > anssiz) ? anssiz : resplen);
            res_pquery(ans, (resplen > anssiz) ? anssiz : resplen);
            // record the error
            // record the error
            statp->_flags |= RES_F_EDNS0ERR;
            statp->_flags |= RES_F_EDNS0ERR;
            res_nclose(statp);
            statp->closeSockets();
            return 0;
            return 0;
        }
        }


@@ -1012,7 +1009,7 @@ static int send_dg(res_state statp, res_params* params, const uint8_t* buf, int
        if (anhp->rcode == SERVFAIL || anhp->rcode == NOTIMP || anhp->rcode == REFUSED) {
        if (anhp->rcode == SERVFAIL || anhp->rcode == NOTIMP || anhp->rcode == REFUSED) {
            LOG(DEBUG) << __func__ << ": server rejected query:";
            LOG(DEBUG) << __func__ << ": server rejected query:";
            res_pquery(ans, (resplen > anssiz) ? anssiz : resplen);
            res_pquery(ans, (resplen > anssiz) ? anssiz : resplen);
            res_nclose(statp);
            statp->closeSockets();
            *rcode = anhp->rcode;
            *rcode = anhp->rcode;
            return 0;
            return 0;
        }
        }
@@ -1021,7 +1018,7 @@ static int send_dg(res_state statp, res_params* params, const uint8_t* buf, int
            // use TCP with same server.
            // use TCP with same server.
            LOG(DEBUG) << __func__ << ": truncated answer";
            LOG(DEBUG) << __func__ << ": truncated answer";
            *v_circuit = 1;
            *v_circuit = 1;
            res_nclose(statp);
            statp->closeSockets();
            return 1;
            return 1;
        }
        }
        // All is well, or the error is fatal. Signal that the
        // All is well, or the error is fatal. Signal that the
+27 −17
Original line number Original line Diff line number Diff line
@@ -49,6 +49,7 @@
#pragma once
#pragma once


#include <android-base/logging.h>
#include <android-base/logging.h>
#include <android-base/unique_fd.h>
#include <net/if.h>
#include <net/if.h>
#include <time.h>
#include <time.h>
#include <string>
#include <string>
@@ -73,6 +74,10 @@
#define RES_TIMEOUT 5000 /* min. milliseconds between retries */
#define RES_TIMEOUT 5000 /* min. milliseconds between retries */
#define RES_DFLRETRY 2    /* Default #/tries. */
#define RES_DFLRETRY 2    /* Default #/tries. */


// Flags for res_state->_flags
#define RES_F_VC 0x00000001        // socket is TCP
#define RES_F_EDNS0ERR 0x00000004  // EDNS0 caused errors

// Holds either a sockaddr_in or a sockaddr_in6.
// Holds either a sockaddr_in or a sockaddr_in6.
union sockaddr_union {
union sockaddr_union {
    struct sockaddr sa;
    struct sockaddr sa;
@@ -82,21 +87,31 @@ union sockaddr_union {
constexpr int MAXPACKET = 8 * 1024;
constexpr int MAXPACKET = 8 * 1024;


struct ResState {
struct ResState {
    void closeSockets() {
        tcp_nssock.reset();
        _flags &= ~RES_F_VC;

        for (auto& sock : nssocks) {
            sock.reset();
        }
    }
    // clang-format off
    unsigned netid;                             // NetId: cache key and socket mark
    unsigned netid;                             // NetId: cache key and socket mark
    uid_t uid;                                  // uid of the app that sent the DNS lookup
    uid_t uid;                                  // uid of the app that sent the DNS lookup
    pid_t pid;                                  // pid of the app that sent the DNS lookup
    pid_t pid;                                  // pid of the app that sent the DNS lookup
    int nscount;                                // number of name srvers
    int nscount;                                // number of name srvers
    uint16_t id;                                // current message id
    uint16_t id;                                // current message id
    std::vector<std::string> search_domains;  // domains to search
    std::vector<std::string> search_domains{};  // domains to search
    sockaddr_union nsaddrs[MAXNS];
    sockaddr_union nsaddrs[MAXNS];
    int nssocks[MAXNS];                       // UDP sockets to nameservers
    android::base::unique_fd nssocks[MAXNS];    // UDP sockets to nameservers
    unsigned ndots : 4;                         // threshold for initial abs. query
    unsigned ndots : 4;                         // threshold for initial abs. query
    unsigned _mark;                             // If non-0 SET_MARK to _mark on all request sockets
    unsigned _mark;                             // If non-0 SET_MARK to _mark on all request sockets
    int _vcsock;                              // TCP socket (but why not one per nameserver?)
    android::base::unique_fd tcp_nssock;        // TCP socket (but why not one per nameserver?)
    uint32_t _flags;                          // See RES_F_* defines below
    uint32_t _flags = 0;                        // See RES_F_* defines below
    android::net::NetworkDnsEventReported* event;
    android::net::NetworkDnsEventReported* event;
    uint32_t netcontext_flags;
    uint32_t netcontext_flags;
    int tc_mode;
    int tc_mode = 0;
    // clang-format on
};
};


// TODO: remove these legacy aliases
// TODO: remove these legacy aliases
@@ -121,10 +136,6 @@ void _res_stats_set_sample(res_sample* sample, time_t now, int rcode, int rtt);


/* End of stats related definitions */
/* End of stats related definitions */


// Flags for res_state->_flags
#define RES_F_VC 0x00000001        // socket is TCP
#define RES_F_EDNS0ERR 0x00000004  // EDNS0 caused errors

/*
/*
 * Error code extending h_errno codes defined in bionic/libc/include/netdb.h.
 * Error code extending h_errno codes defined in bionic/libc/include/netdb.h.
 *
 *
@@ -146,7 +157,6 @@ int res_nquerydomain(res_state, const char*, const char*, int, int, uint8_t*, in
int res_nmkquery(int op, const char* qname, int cl, int type, const uint8_t* data, int datalen,
int res_nmkquery(int op, const char* qname, int cl, int type, const uint8_t* data, int datalen,
                 uint8_t* buf, int buflen, int netcontext_flags);
                 uint8_t* buf, int buflen, int netcontext_flags);
int res_nsend(res_state, const uint8_t*, int, uint8_t*, int, int*, uint32_t);
int res_nsend(res_state, const uint8_t*, int, uint8_t*, int, int*, uint32_t);
void res_nclose(res_state);
int res_nopt(res_state, int, uint8_t*, int, int);
int res_nopt(res_state, int, uint8_t*, int, int);


int getaddrinfo_numeric(const char* hostname, const char* servname, addrinfo hints,
int getaddrinfo_numeric(const char* hostname, const char* servname, addrinfo hints,