Beispiel #1
0
static void
idnsCheckQueue(void *unused)
{
	dlink_node *n;
	dlink_node *p = NULL;
	idns_query *q;
	event_queued = 0;
	if (0 == nns)
		/* name servers went away; reconfiguring or shutting down */
		return;
	for (n = lru_list.tail; n; n = p)
	{
		p = n->prev;
		q = n->data;
		/* Anything to process in the queue? */
		if (tvSubDsec(q->queue_t, current_time) < Config.Timeout.idns_retransmit)
			break;
		/* Query timer expired? */
		if (tvSubDsec(q->sent_t, current_time) < Config.Timeout.idns_retransmit * 1 << ((q->nsends - 1) / nns))
		{
			dlinkDelete(&q->lru, &lru_list);
			q->queue_t = current_time;
			dlinkAdd(q, &q->lru, &lru_list);
			continue;
		}
		debug(78, 3) ("idnsCheckQueue: ID %#04x timeout\n",
					  q->id);
		dlinkDelete(&q->lru, &lru_list);
		if (tvSubDsec(q->start_t, current_time) < Config.Timeout.idns_query)
		{
			idnsSendQuery(q);
		}
		else
		{
			debug(78, 2) ("idnsCheckQueue: ID %x: giving up after %d tries and %5.1f seconds\n",
						  (int) q->id, q->nsends,
						  tvSubDsec(q->start_t, current_time));
			if (q->rcode != 0)
				idnsCallback(q, NULL, -q->rcode, q->error);
			else
				idnsCallback(q, NULL, -16, "Timeout");
			idnsTcpCleanup(q);
			cbdataFree(q);
		}
	}
	idnsTickleQueue();
}
Beispiel #2
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);
}