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

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

Remove separate IPv4-only nsaddr_list from res_state

The res_state struct held two separate lists of nameserver addresses,
presumably for binary compatibility with userspace poking directly at
libc internal data structures.

This change removes the IPv4 only statp->nsaddr_list and keeps the
deeply-nested statp->_u._ext.ext->nsaddrs, which is a sockaddr_union.

While cleaning up res_init, I had a wtf moment when I noticed that
HAS_INET6_STRUCTS is never defined. So, we don't actually support v6
nameservers??? The truth is: we don't really use res_setservers()
other than at initialization time, when it's a no-op, and
res_getservers() was actually dead code. So they can both rest in peace.

Test: m, flashall, atest
Change-Id: Iba0d5aa73f531b5ed925eb4178e5d5883c12a23d
parent 3479d3b0
Loading
Loading
Loading
Loading
+1 −10
Original line number Diff line number Diff line
@@ -1583,16 +1583,7 @@ void _resolv_populate_res_for_net(res_state statp) {
            }

            if ((size_t) ai->ai_addrlen <= sizeof(statp->_u._ext.ext->nsaddrs[0])) {
                if (statp->_u._ext.ext != NULL) {
                memcpy(&statp->_u._ext.ext->nsaddrs[nserv], ai->ai_addr, ai->ai_addrlen);
                    statp->nsaddr_list[nserv].sin_family = AF_UNSPEC;
                } else {
                    if ((size_t) ai->ai_addrlen <= sizeof(statp->nsaddr_list[0])) {
                        memcpy(&statp->nsaddr_list[nserv], ai->ai_addr, ai->ai_addrlen);
                    } else {
                        statp->nsaddr_list[nserv].sin_family = AF_UNSPEC;
                    }
                }
            } else {
                LOG(INFO) << __func__ << ": found too long addrlen";
            }
+12 −103
Original line number Diff line number Diff line
@@ -94,22 +94,12 @@
#include "resolv_private.h"

// Set up Resolver state default settings.
// Note that res_ninit() is called with an initialized res_state,
// the memories it allocated must be freed after the task is done.
// Or memory leak will happen.
int res_ninit(res_state statp) {
    int nserv = 0;  // number of nameserver records
    sockaddr_union u[2];

// Note: this is called with statp zero-initialized
void res_init(res_state statp) {
    statp->netid = NETID_UNSET;
    statp->id = arc4random_uniform(65536);
    statp->_mark = MARK_UNSET;

    memset(u, 0, sizeof(u));
    u[nserv].sin.sin_addr.s_addr = INADDR_ANY;
    u[nserv].sin.sin_family = AF_INET;
    u[nserv].sin.sin_port = htons(NAMESERVER_PORT);
    nserv++;
    statp->nscount = 0;
    statp->ndots = 1;
    statp->_vcsock = -1;
@@ -119,17 +109,20 @@ int res_ninit(res_state statp) {
    statp->netcontext_flags = 0;
    if (statp->_u._ext.ext != NULL) {
        memset(statp->_u._ext.ext, 0, sizeof(*statp->_u._ext.ext));
        statp->_u._ext.ext->nsaddrs[0].sin = statp->nsaddr;
    }
    res_setservers(statp, u, nserv);

    if (nserv > 0) {
        statp->nscount = nserv;
    }
    return (0);
    // The following dummy initialization is probably useless because
    // it's overwritten later by _resolv_populate_res_for_net().
    // TODO: check if it's safe to remove.
    const sockaddr_union u{
            .sin.sin_addr.s_addr = INADDR_ANY,
            .sin.sin_family = AF_INET,
            .sin.sin_port = htons(NAMESERVER_PORT),
    };
    memcpy(&statp->_u._ext.ext->nsaddrs[0], &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()
@@ -159,90 +152,6 @@ void res_ndestroy(res_state statp) {
    statp->_u._ext.ext = NULL;
}

void res_setservers(res_state statp, const sockaddr_union* set, int cnt) {
    int i, nserv;
    size_t size;

    /* close open servers */
    res_nclose(statp);

    /* cause rtt times to be forgotten */
    statp->_u._ext.nscount = 0;

    nserv = 0;
    for (i = 0; i < cnt && nserv < MAXNS; i++) {
        switch (set->sin.sin_family) {
            case AF_INET:
                size = sizeof(set->sin);
                if (statp->_u._ext.ext)
                    memcpy(&statp->_u._ext.ext->nsaddrs[nserv], &set->sin, size);
                if (size <= sizeof(statp->nsaddr_list[nserv]))
                    memcpy(&statp->nsaddr_list[nserv], &set->sin, size);
                else
                    statp->nsaddr_list[nserv].sin_family = 0;
                nserv++;
                break;

#ifdef HAS_INET6_STRUCTS
            case AF_INET6:
                size = sizeof(set->sin6);
                if (statp->_u._ext.ext)
                    memcpy(&statp->_u._ext.ext->nsaddrs[nserv], &set->sin6, size);
                if (size <= sizeof(statp->nsaddr_list[nserv]))
                    memcpy(&statp->nsaddr_list[nserv], &set->sin6, size);
                else
                    statp->nsaddr_list[nserv].sin_family = 0;
                nserv++;
                break;
#endif

            default:
                break;
        }
        set++;
    }
    statp->nscount = nserv;
}

int res_getservers(res_state statp, sockaddr_union* set, int cnt) {
    int i;
    size_t size;
    uint16_t family;

    for (i = 0; i < statp->nscount && i < cnt; i++) {
        if (statp->_u._ext.ext)
            family = statp->_u._ext.ext->nsaddrs[i].sin.sin_family;
        else
            family = statp->nsaddr_list[i].sin_family;

        switch (family) {
            case AF_INET:
                size = sizeof(set->sin);
                if (statp->_u._ext.ext)
                    memcpy(&set->sin, &statp->_u._ext.ext->nsaddrs[i], size);
                else
                    memcpy(&set->sin, &statp->nsaddr_list[i], size);
                break;

#ifdef HAS_INET6_STRUCTS
            case AF_INET6:
                size = sizeof(set->sin6);
                if (statp->_u._ext.ext)
                    memcpy(&set->sin6, &statp->_u._ext.ext->nsaddrs[i], size);
                else
                    memcpy(&set->sin6, &statp->nsaddr_list[i], size);
                break;
#endif

            default:
                set->sin.sin_family = 0;
                break;
        }
        set++;
    }
    return (statp->nscount);
}

void res_setnetcontext(res_state statp, const struct android_net_context* netcontext,
                       android::net::NetworkDnsEventReported* _Nonnull event) {
    if (statp != nullptr) {

res_init.h

0 → 100644
+19 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

struct __res_state;
void res_init(__res_state* statp);
+1 −27
Original line number Diff line number Diff line
@@ -470,13 +470,6 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int
            needclose++;
        } else {
            for (int ns = 0; ns < statp->nscount; ns++) {
                if (statp->nsaddr_list[ns].sin_family &&
                    !sock_eq((struct sockaddr*) (void*) &statp->nsaddr_list[ns],
                             (struct sockaddr*) (void*) &statp->_u._ext.ext->nsaddrs[ns])) {
                    needclose++;
                    break;
                }

                if (statp->_u._ext.nssocks[ns] == -1) continue;
                peerlen = sizeof(peer);
                if (getpeername(statp->_u._ext.nssocks[ns], (struct sockaddr*) (void*) &peer,
@@ -503,8 +496,6 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int
        for (int ns = 0; ns < statp->nscount; ns++) {
            statp->_u._ext.nstimes[ns] = RES_MAXTIME;
            statp->_u._ext.nssocks[ns] = -1;
            if (!statp->nsaddr_list[ns].sin_family) continue;
            statp->_u._ext.ext->nsaddrs[ns].sin = statp->nsaddr_list[ns];
        }
        statp->_u._ext.nscount = statp->nscount;
    }
@@ -692,25 +683,8 @@ static int get_salen(const struct sockaddr* sa) {
        return (0); /* unknown, die on connect */
}

/*
 * pick appropriate nsaddr_list for use.  see res_init() for initialization.
 */
static struct sockaddr* get_nsaddr(res_state statp, size_t n) {
    if (!statp->nsaddr_list[n].sin_family && statp->_u._ext.ext) {
        /*
         * - statp->_u._ext.ext->nsaddrs[n] holds an address that is larger
         *   than struct sockaddr, and
         * - user code did not update statp->nsaddr_list[n].
         */
    return (struct sockaddr*)(void*)&statp->_u._ext.ext->nsaddrs[n];
    } else {
        /*
         * - user code updated statp->nsaddr_list[n], or
         * - statp->nsaddr_list[n] has the same content as
         *   statp->_u._ext.ext->nsaddrs[n].
         */
        return (struct sockaddr*) (void*) &statp->nsaddr_list[n];
    }
}

static struct timespec get_timeout(res_state statp, const res_params* params, const int ns) {
+2 −8
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@

#include <android-base/logging.h>

#include "res_init.h"
#include "resolv_cache.h"
#include "resolv_private.h"

@@ -99,14 +100,7 @@ static _res_thread* res_thread_get(void) {
    pthread_setspecific(_res_key, rt);

    LOG(VERBOSE) << __func__ << ": tid=" << gettid() << ", rt=" << rt;
    if (res_ninit(rt->_nres) < 0) {
        /* This should not happen */
        LOG(VERBOSE) << __func__ << ": tid=" << gettid() << " rt=" << rt
                     << ", res_ninit() returned < 0";
        res_thread_free(rt);
        pthread_setspecific(_res_key, NULL);
        return NULL;
    }
    res_init(rt->_nres);
    return rt;
}

Loading