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

Commit 324f9f8c authored by Bernie Innocenti's avatar Bernie Innocenti
Browse files

Make resolv_gethostbyaddr() re-entrant

The new call signature is closer to gethostbyaddr_r() and no longer
relies on thread-local storage for its buffers. This is the last nail
in the coffin of res_get_static().

Change-Id: I0673dd5a566e53a47a1c7a5b0afc67f5f28d1361
parent 36db7736
Loading
Loading
Loading
Loading
+12 −8
Original line number Original line Diff line number Diff line
@@ -1186,7 +1186,9 @@ DnsProxyListener::GetHostByAddrHandler::~GetHostByAddrHandler() {
    free(mAddress);
    free(mAddress);
}
}


void DnsProxyListener::GetHostByAddrHandler::doDns64ReverseLookup(struct hostent** hpp,
void DnsProxyListener::GetHostByAddrHandler::doDns64ReverseLookup(hostent* hbuf, char* buf,
                                                                  size_t buflen,
                                                                  struct hostent** hpp,
                                                                  NetworkDnsEventReported* event) {
                                                                  NetworkDnsEventReported* event) {
    if (*hpp != nullptr || mAddressFamily != AF_INET6 || !mAddress) {
    if (*hpp != nullptr || mAddressFamily != AF_INET6 || !mAddress) {
        return;
        return;
@@ -1215,14 +1217,14 @@ void DnsProxyListener::GetHostByAddrHandler::doDns64ReverseLookup(struct hostent
    if (queryLimiter.start(uid)) {
    if (queryLimiter.start(uid)) {
        // Remove NAT64 prefix and do reverse DNS query
        // Remove NAT64 prefix and do reverse DNS query
        struct in_addr v4addr = {.s_addr = v6addr.s6_addr32[3]};
        struct in_addr v4addr = {.s_addr = v6addr.s6_addr32[3]};
        android_gethostbyaddrfornetcontext(&v4addr, sizeof(v4addr), AF_INET, &mNetContext, hpp,
        resolv_gethostbyaddr(&v4addr, sizeof(v4addr), AF_INET, hbuf, buf, buflen, &mNetContext, hpp,
                             event);
                             event);
        queryLimiter.finish(uid);
        queryLimiter.finish(uid);
        if (*hpp) {
        if (*hpp) {
            // Replace IPv4 address with original queried IPv6 address in place. The space has
            // Replace IPv4 address with original queried IPv6 address in place. The space has
            // reserved by dns_gethtbyaddr() and netbsd_gethostent_r() in
            // reserved by dns_gethtbyaddr() and netbsd_gethostent_r() in
            // system/netd/resolv/gethnamaddr.cpp.
            // system/netd/resolv/gethnamaddr.cpp.
            // Note that android_gethostbyaddrfornetcontext returns only one entry in result.
            // Note that resolv_gethostbyaddr() returns only one entry in result.
            memcpy((*hpp)->h_addr_list[0], &v6addr, sizeof(v6addr));
            memcpy((*hpp)->h_addr_list[0], &v6addr, sizeof(v6addr));
            (*hpp)->h_addrtype = AF_INET6;
            (*hpp)->h_addrtype = AF_INET6;
            (*hpp)->h_length = sizeof(struct in6_addr);
            (*hpp)->h_length = sizeof(struct in6_addr);
@@ -1237,12 +1239,14 @@ void DnsProxyListener::GetHostByAddrHandler::run() {
    maybeFixupNetContext(&mNetContext);
    maybeFixupNetContext(&mNetContext);
    const uid_t uid = mClient->getUid();
    const uid_t uid = mClient->getUid();
    hostent* hp = nullptr;
    hostent* hp = nullptr;
    hostent hbuf;
    char tmpbuf[MAXPACKET];
    int32_t rv = 0;
    int32_t rv = 0;
    NetworkDnsEventReported event;
    NetworkDnsEventReported event;
    initDnsEvent(&event);
    initDnsEvent(&event);
    if (queryLimiter.start(uid)) {
    if (queryLimiter.start(uid)) {
        rv = android_gethostbyaddrfornetcontext(mAddress, mAddressLen, mAddressFamily, &mNetContext,
        rv = resolv_gethostbyaddr(mAddress, mAddressLen, mAddressFamily, &hbuf, tmpbuf,
                                                &hp, &event);
                                  sizeof tmpbuf, &mNetContext, &hp, &event);
        queryLimiter.finish(uid);
        queryLimiter.finish(uid);
    } else {
    } else {
        rv = EAI_MEMORY;
        rv = EAI_MEMORY;
@@ -1250,12 +1254,12 @@ void DnsProxyListener::GetHostByAddrHandler::run() {
                   << ", max concurrent queries reached";
                   << ", max concurrent queries reached";
    }
    }


    doDns64ReverseLookup(&hp, &event);
    doDns64ReverseLookup(&hbuf, tmpbuf, sizeof tmpbuf, &hp, &event);
    const int32_t latencyUs = saturate_cast<int32_t>(s.timeTakenUs());
    const int32_t latencyUs = saturate_cast<int32_t>(s.timeTakenUs());
    event.set_latency_micros(latencyUs);
    event.set_latency_micros(latencyUs);
    event.set_event_type(EVENT_GETHOSTBYADDR);
    event.set_event_type(EVENT_GETHOSTBYADDR);


    LOG(DEBUG) << "GetHostByAddrHandler::run: result: " << (hp ? "success" : gai_strerror(rv));
    LOG(DEBUG) << "GetHostByAddrHandler::run: result: " << gai_strerror(rv);


    bool success = true;
    bool success = true;
    if (hp) {
    if (hp) {
+2 −1
Original line number Original line Diff line number Diff line
@@ -111,7 +111,8 @@ class DnsProxyListener : public FrameworkListener {
        std::string threadName();
        std::string threadName();


      private:
      private:
        void doDns64ReverseLookup(hostent** hpp, NetworkDnsEventReported* event);
        void doDns64ReverseLookup(hostent* hbuf, char* buf, size_t buflen, hostent** hpp,
                                  NetworkDnsEventReported* event);


        SocketClient* mClient;  // ref counted
        SocketClient* mClient;  // ref counted
        void* mAddress;         // address to lookup; owned
        void* mAddress;         // address to lookup; owned
+4 −40
Original line number Original line Diff line number Diff line
@@ -117,14 +117,6 @@ static int dns_gethtbyaddr(const unsigned char* uaddr, int len, int af,
                           NetworkDnsEventReported* event);
                           NetworkDnsEventReported* event);
static int dns_gethtbyname(const char* name, int af, getnamaddr* info);
static int dns_gethtbyname(const char* name, int af, getnamaddr* info);


static int android_gethostbyaddrfornetcontext_proxy_internal(const void*, socklen_t, int,
                                                             struct hostent*, char*, size_t,
                                                             const struct android_net_context*,
                                                             NetworkDnsEventReported* event);
static int android_gethostbyaddrfornetcontext_proxy(const void* addr, socklen_t len, int af,
                                                    const struct android_net_context* netcontext,
                                                    hostent** hp, NetworkDnsEventReported* event);

#define BOUNDED_INCR(x)      \
#define BOUNDED_INCR(x)      \
    do {                     \
    do {                     \
        BOUNDS_CHECK(cp, x); \
        BOUNDS_CHECK(cp, x); \
@@ -483,10 +475,9 @@ fake:
    return 0;
    return 0;
}
}


static int android_gethostbyaddrfornetcontext_real(const void* addr, socklen_t len, int af,
int resolv_gethostbyaddr(const void* addr, socklen_t len, int af, hostent* hp, char* buf,
                                                   struct hostent* hp, char* buf, size_t buflen,
                         size_t buflen, const struct android_net_context* netcontext,
                                                   const struct android_net_context* netcontext,
                         hostent** result, NetworkDnsEventReported* event) {
                                                   NetworkDnsEventReported* event) {
    const uint8_t* uaddr = (const uint8_t*)addr;
    const uint8_t* uaddr = (const uint8_t*)addr;
    socklen_t size;
    socklen_t size;
    struct getnamaddr info;
    struct getnamaddr info;
@@ -531,16 +522,10 @@ static int android_gethostbyaddrfornetcontext_real(const void* addr, socklen_t l
        int error = dns_gethtbyaddr(uaddr, len, af, netcontext, &info, event);
        int error = dns_gethtbyaddr(uaddr, len, af, netcontext, &info, event);
        if (error != 0) return error;
        if (error != 0) return error;
    }
    }
    *result = hp;
    return 0;
    return 0;
}
}


static int 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, NetworkDnsEventReported* event) {
    return android_gethostbyaddrfornetcontext_real(addr, len, af, hp, hbuf, hbuflen, netcontext,
                                                   event);
}

// TODO: Consider leaving function without returning error code as _gethtent() does because
// TODO: Consider leaving function without returning error code as _gethtent() does because
// the error code of the caller does not currently return to netd.
// the error code of the caller does not currently return to netd.
struct hostent* netbsd_gethostent_r(FILE* hf, struct hostent* hent, char* buf, size_t buflen,
struct hostent* netbsd_gethostent_r(FILE* hf, struct hostent* hent, char* buf, size_t buflen,
@@ -584,9 +569,6 @@ struct hostent* netbsd_gethostent_r(FILE* hf, struct hostent* hent, char* buf, s
            len = NS_IN6ADDRSZ;
            len = NS_IN6ADDRSZ;
        } else {
        } else {
            if (inet_pton(AF_INET, p, &host_addr) <= 0) continue;
            if (inet_pton(AF_INET, p, &host_addr) <= 0) continue;

            res_state res = res_get_state();
            if (res == NULL) goto nospc;
            af = AF_INET;
            af = AF_INET;
            len = NS_INADDRSZ;
            len = NS_INADDRSZ;
        }
        }
@@ -787,24 +769,6 @@ nospc:
    return EAI_MEMORY;
    return EAI_MEMORY;
}
}


int android_gethostbyaddrfornetcontext(const void* addr, socklen_t len, int af,
                                       const struct android_net_context* netcontext, hostent** hp,
                                       NetworkDnsEventReported* event) {
    return android_gethostbyaddrfornetcontext_proxy(addr, len, af, netcontext, hp, event);
}

static int android_gethostbyaddrfornetcontext_proxy(const void* addr, socklen_t len, int af,
                                                    const struct android_net_context* netcontext,
                                                    hostent** hp, NetworkDnsEventReported* event) {
    assert(event != nullptr);

    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), netcontext, event);
    if (error == 0) *hp = &rs->host;
    return error;
}

int herrnoToAiErrno(int he) {
int herrnoToAiErrno(int he) {
    switch (he) {
    switch (he) {
        // extended h_errno
        // extended h_errno
+4 −3
Original line number Original line Diff line number Diff line
@@ -30,8 +30,9 @@
// This is the entry point for the gethostbyname() family of legacy calls.
// This is the entry point for the gethostbyname() family of legacy calls.
int resolv_gethostbyname(const char* name, int af, hostent* hp, char* buf, size_t buflen,
int resolv_gethostbyname(const char* name, int af, hostent* hp, char* buf, size_t buflen,
                         const android_net_context* netcontext, hostent** result,
                         const android_net_context* netcontext, hostent** result,
                         android::net::NetworkDnsEventReported*);
                         android::net::NetworkDnsEventReported* event);


// This is the entry point for the gethostbyaddr() family of legacy calls.
// This is the entry point for the gethostbyaddr() family of legacy calls.
int android_gethostbyaddrfornetcontext(const void*, socklen_t, int, const android_net_context*,
int resolv_gethostbyaddr(const void* addr, socklen_t len, int af, hostent* hp, char* buf,
                                       hostent**, android::net::NetworkDnsEventReported*);
                         size_t buflen, const android_net_context* netcontext, hostent** result,
                         android::net::NetworkDnsEventReported* event);
+1 −1
Original line number Original line Diff line number Diff line
@@ -968,7 +968,7 @@ TEST_F(GetHostByNameForNetContextTest, CnamesInfiniteLoop) {
//           - Invalid length CNAME, or QNAME.
//           - Invalid length CNAME, or QNAME.
//           - Unexpected amount of questions.
//           - Unexpected amount of questions.
//       - CNAME RDATA with the domain name which has null label(s).
//       - CNAME RDATA with the domain name which has null label(s).
// TODO: Add test for android_gethostbyaddrfornetcontext().
// TODO: Add test for resolv_gethostbyaddr().


}  // end of namespace net
}  // end of namespace net
}  // end of namespace android
}  // end of namespace android