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

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

send_dg() refactor am: bff43fc2

Change-Id: I3ab4a126e9d91b91c900943a50c44be61cd23b5b
parents 366ec41a bff43fc2
Loading
Loading
Loading
Loading
+103 −117
Original line number Original line Diff line number Diff line
@@ -875,22 +875,37 @@ retry:
    return n;
    return n;
}
}


bool ignoreInvalidAnswer(res_state statp, const sockaddr_storage& from, const uint8_t* buf,
                         int buflen, uint8_t* ans, int anssiz) {
    const HEADER* hp = (const HEADER*)(const void*)buf;
    HEADER* anhp = (HEADER*)(void*)ans;
    if (hp->id != anhp->id) {
        // response from old query, ignore it.
        LOG(DEBUG) << __func__ << ": old answer:";
        return true;
    }
    if (!res_ourserver_p(statp, (sockaddr*)(void*)&from)) {
        // response from wrong server? ignore it.
        LOG(DEBUG) << __func__ << ": not our server:";
        return true;
    }
    if (!res_queriesmatch(buf, buf + buflen, ans, ans + anssiz)) {
        // response contains wrong query? ignore it.
        LOG(DEBUG) << __func__ << ": wrong query name:";
        return true;
    }
    return false;
}

static int send_dg(res_state statp, res_params* params, const uint8_t* buf, int buflen,
static int send_dg(res_state statp, res_params* params, const uint8_t* buf, int buflen,
                   uint8_t* ans, int anssiz, int* terrno, int ns, int* v_circuit, int* gotsomewhere,
                   uint8_t* ans, int anssiz, int* terrno, int ns, int* v_circuit, int* gotsomewhere,
                   time_t* at, int* rcode, int* delay) {
                   time_t* at, int* rcode, int* delay) {
    *at = time(NULL);
    *at = time(nullptr);
    *delay = 0;
    *delay = 0;
    const HEADER* hp = (const HEADER*) (const void*) buf;
    HEADER* anhp = (HEADER*) (void*) ans;
    const struct sockaddr* nsap;
    int nsaplen;
    struct timespec now, timeout, finish, done;
    struct sockaddr_storage from;
    socklen_t fromlen;
    int resplen, n, s;


    nsap = get_nsaddr(statp, (size_t) ns);
    const sockaddr* nsap = get_nsaddr(statp, (size_t)ns);
    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] = socket(nsap->sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
        if (statp->nssocks[ns] < 0) {
        if (statp->nssocks[ns] < 0) {
@@ -931,20 +946,18 @@ static int send_dg(res_state statp, res_params* params, const uint8_t* buf, int
        }
        }
        LOG(DEBUG) << __func__ << ": new DG socket";
        LOG(DEBUG) << __func__ << ": new DG socket";
    }
    }
    s = statp->nssocks[ns];
    if (send(statp->nssocks[ns], (const char*)buf, (size_t)buflen, 0) != buflen) {
    if (send(s, (const char*) buf, (size_t) buflen, 0) != buflen) {
        PLOG(DEBUG) << __func__ << ": send: ";
        PLOG(DEBUG) << __func__ << ": send: ";
        res_nclose(statp);
        res_nclose(statp);
        return 0;
        return 0;
    }
    }


    timespec timeout = get_timeout(statp, params, ns);
    timespec now = evNowTime();
    timespec finish = evAddTime(now, timeout);
    for (;;) {
        // Wait for reply.
        // Wait for reply.
    timeout = get_timeout(statp, params, ns);
        int n = retrying_poll(statp->nssocks[ns], POLLIN, &finish);
    now = evNowTime();
    finish = evAddTime(now, timeout);
retry:
    n = retrying_poll(s, POLLIN, &finish);

        if (n == 0) {
        if (n == 0) {
            *rcode = RCODE_TIMEOUT;
            *rcode = RCODE_TIMEOUT;
            LOG(DEBUG) << __func__ << ": timeout";
            LOG(DEBUG) << __func__ << ": timeout";
@@ -956,10 +969,12 @@ retry:
            res_nclose(statp);
            res_nclose(statp);
            return 0;
            return 0;
        }
        }

        errno = 0;
        errno = 0;
    fromlen = sizeof(from);
        sockaddr_storage from;
    resplen = recvfrom(s, (char*) ans, (size_t) anssiz, 0, (struct sockaddr*) (void*) &from,
        socklen_t fromlen = sizeof(from);
                       &fromlen);
        int resplen = recvfrom(statp->nssocks[ns], (char*)ans, (size_t)anssiz, 0,
                               (sockaddr*)(void*)&from, &fromlen);
        if (resplen <= 0) {
        if (resplen <= 0) {
            PLOG(DEBUG) << __func__ << ": recvfrom: ";
            PLOG(DEBUG) << __func__ << ": recvfrom: ";
            res_nclose(statp);
            res_nclose(statp);
@@ -967,58 +982,32 @@ retry:
        }
        }
        *gotsomewhere = 1;
        *gotsomewhere = 1;
        if (resplen < HFIXEDSZ) {
        if (resplen < HFIXEDSZ) {
        /*
            // Undersized message.
         * Undersized message.
         */
            LOG(DEBUG) << __func__ << ": undersized: " << resplen;
            LOG(DEBUG) << __func__ << ": undersized: " << resplen;
            *terrno = EMSGSIZE;
            *terrno = EMSGSIZE;
            res_nclose(statp);
            res_nclose(statp);
            return 0;
            return 0;
        }
        }
    if (hp->id != anhp->id) {

        /*
        if (ignoreInvalidAnswer(statp, from, buf, buflen, ans, anssiz)) {
         * response from old query, ignore it.
         * XXX - potential security hazard could
         *	 be detected here.
         */
        LOG(DEBUG) << __func__ << ": old answer:";
        res_pquery(ans, (resplen > anssiz) ? anssiz : resplen);
        goto retry;
    }
    if (!res_ourserver_p(statp, (struct sockaddr*)(void*)&from)) {
        /*
         * response from wrong server? ignore it.
         * XXX - potential security hazard could
         *	 be detected here.
         */
        LOG(DEBUG) << __func__ << ": not our server:";
            res_pquery(ans, (resplen > anssiz) ? anssiz : resplen);
            res_pquery(ans, (resplen > anssiz) ? anssiz : resplen);
        goto retry;
            continue;
        }
        }

        HEADER* anhp = (HEADER*)(void*)ans;
        if (anhp->rcode == FORMERR && (statp->netcontext_flags & NET_CONTEXT_FLAG_USE_EDNS)) {
        if (anhp->rcode == FORMERR && (statp->netcontext_flags & NET_CONTEXT_FLAG_USE_EDNS)) {
        /*
            //  Do not retry if the server do not understand EDNS0.
         * Do not retry if the server do not understand EDNS0.
            //  The case has to be captured here, as FORMERR packet do not
         * The case has to be captured here, as FORMERR packet do not
            //  carry query section, hence res_queriesmatch() returns 0.
         * carry query section, hence res_queriesmatch() returns 0.
         */
            LOG(DEBUG) << __func__ << ": server rejected query with EDNS0:";
            LOG(DEBUG) << __func__ << ": server rejected query with EDNS0:";
            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);
            res_nclose(statp);
            return 0;
            return 0;
        }
        }
    if (!res_queriesmatch(buf, buf + buflen, ans, ans + anssiz)) {

        /*
        timespec done = evNowTime();
         * response contains wrong query? ignore it.
         * XXX - potential security hazard could
         *	 be detected here.
         */
        LOG(DEBUG) << __func__ << ": wrong query name:";
        res_pquery(ans, (resplen > anssiz) ? anssiz : resplen);
        goto retry;
    }
    done = evNowTime();
        *delay = _res_stats_calculate_rtt(&done, &now);
        *delay = _res_stats_calculate_rtt(&done, &now);
        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:";
@@ -1028,24 +1017,21 @@ retry:
            return 0;
            return 0;
        }
        }
        if (anhp->tc) {
        if (anhp->tc) {
        /*
            // To get the rest of answer,
         * To get the rest of answer,
            // 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);
            res_nclose(statp);
            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
        // next nameserver ought not be tried.
     * next nameserver ought not be tried.
     */
        if (resplen > 0) {
        if (resplen > 0) {
            *rcode = anhp->rcode;
            *rcode = anhp->rcode;
        }
        }
        return resplen;
        return resplen;
    }
    }
}


static void dump_error(const char* str, const struct sockaddr* address, int alen) {
static void dump_error(const char* str, const struct sockaddr* address, int alen) {
    char hbuf[NI_MAXHOST];
    char hbuf[NI_MAXHOST];