Exemplo n.º 1
0
static void
idnsGrokReply(const char *buf, size_t sz)
{
    int n;
    int valid;
    rfc1035_rr *answers = NULL;
    unsigned short rid = 0xFFFF;
    idns_query *q;
    n = rfc1035AnswersUnpack(buf,
	sz,
	&answers,
	&rid);
    debug(78, 3) ("idnsGrokReply: ID %#hx, %d answers\n", rid, n);
    if (rid == 0xFFFF) {
	debug(78, 1) ("idnsGrokReply: Unknown error\n");
	/* XXX leak answers? */
	return;
    }
    q = idnsFindQuery(rid);
    if (q == NULL) {
	debug(78, 3) ("idnsGrokReply: Late response\n");
	rfc1035RRDestroy(answers, n);
	return;
    }
    dlinkDelete(&q->lru, &lru_list);
    idnsRcodeCount(n, q->attempt);
    if (n < 0) {
	debug(78, 3) ("idnsGrokReply: error %d\n", rfc1035_errno);
	if (-2 == n && ++q->attempt < MAX_ATTEMPT) {
	    /*
	     * RCODE 2 is "Server failure - The name server was
	     * unable to process this query due to a problem with
	     * the name server."
	     */
	    assert(NULL == answers);
	    q->start_t = current_time;
	    q->id = rfc1035RetryQuery(q->buf);
	    idnsSendQuery(q);
	    return;
	}
    }
    valid = cbdataValid(q->callback_data);
    cbdataUnlock(q->callback_data);
    if (valid)
	q->callback(q->callback_data, answers, n);
    rfc1035RRDestroy(answers, n);
    memFree(q, MEM_IDNS_QUERY);
}
Exemplo n.º 2
0
static unsigned short
idnsQueryID(void)
{
    unsigned short id = squid_random() & 0xFFFF;
    unsigned short first_id = id;

    while (idnsFindQuery(id)) {
	id++;

	if (id == first_id) {
	    debug(78, 1) ("idnsQueryID: Warning, too many pending DNS requests\n");
	    break;
	}
    }

    return id;
}
Exemplo n.º 3
0
static void
idnsGrokReply(const char *buf, size_t sz)
{
    int n;
    rfc1035_message *message = NULL;
    idns_query *q;
    n = rfc1035MessageUnpack(buf,
	sz,
	&message);
    if (message == NULL) {
	debug(78, 2) ("idnsGrokReply: Malformed DNS response\n");
	return;
    }
    debug(78, 3) ("idnsGrokReply: ID %#hx, %d answers\n", message->id, n);

    q = idnsFindQuery(message->id);

    if (q == NULL) {
	debug(78, 3) ("idnsGrokReply: Late response\n");
	rfc1035MessageDestroy(message);
	return;
    }
    if (rfc1035QueryCompare(&q->query, message->query) != 0) {
	debug(78, 3) ("idnsGrokReply: Query mismatch (%s != %s)\n", q->query.name, message->query->name);
	rfc1035MessageDestroy(message);
	return;
    }
    dlinkDelete(&q->lru, &lru_list);
    if (message->tc && q->tcp_socket == -1) {
	debug(78, 2) ("idnsGrokReply: Response for %s truncated. Retrying using TCP\n", message->query->name);
	rfc1035MessageDestroy(message);
	idnsRetryTcp(q);
	return;
    }
    idnsRcodeCount(n, q->attempt);
    q->error = NULL;
    if (n < 0) {
	debug(78, 3) ("idnsGrokReply: error %s (%d)\n", rfc1035_error_message, rfc1035_errno);
	q->error = rfc1035_error_message;
	q->rcode = -n;
	if (q->rcode == 2 && ++q->attempt < MAX_ATTEMPT) {
	    /*
	     * RCODE 2 is "Server failure - The name server was
	     * unable to process this query due to a problem with
	     * the name server."
	     */
	    rfc1035MessageDestroy(message);
	    q->start_t = current_time;
	    q->id = idnsQueryID();
	    rfc1035SetQueryID(q->buf, q->id);
	    idnsSendQuery(q);
	    return;
	}
	if (q->rcode == 3 && q->do_searchpath && q->attempt < MAX_ATTEMPT) {
	    strcpy(q->name, q->orig);
	    if (q->domain < npc) {
		strcat(q->name, ".");
		strcat(q->name, searchpath[q->domain].domain);
		debug(78, 3) ("idnsGrokReply: searchpath used for %s\n",
		    q->name);
		q->domain++;
	    } else {
		q->attempt++;
	    }
	    rfc1035MessageDestroy(message);
	    if (q->hash.key) {
		hash_remove_link(idns_lookup_hash, &q->hash);
		q->hash.key = NULL;
	    }
	    q->start_t = current_time;
	    q->id = idnsQueryID();
	    rfc1035SetQueryID(q->buf, q->id);
	    q->sz = rfc1035BuildAQuery(q->name, q->buf, sizeof(q->buf), q->id,
		&q->query);

	    idnsCacheQuery(q);
	    idnsSendQuery(q);
	    return;
	}
    }
    idnsCallback(q, message->answer, n, q->error);
    rfc1035MessageDestroy(message);

    idnsTcpCleanup(q);
    cbdataFree(q);
}