Example #1
0
int rfc1035MessageUnpack(const char *buf, size_t sz, rfc1035_message ** answer)
{
	int off = 0;
	int i;
	int nr = 0;
	rfc1035_message *msg;
	rfc1035_rr *recs;
	rfc1035_query *querys;

	msg = (rfc1035_message*) acl_mycalloc(1, sizeof(*msg));
	if (rfc1035HeaderUnpack(buf + off, sz - off, &off, msg)) {
		RFC1035_UNPACK_DEBUG;
		rfc1035SetErrno(rfc1035_unpack_error);
		acl_myfree(msg);
		return -rfc1035_unpack_error;
	}
	rfc1035_errno = 0;
	rfc1035_error_message = NULL;
	i = (int) msg->qdcount;
	if (i != 1) {
		/* This can not be an answer to our queries.. */
		RFC1035_UNPACK_DEBUG;
		rfc1035SetErrno(rfc1035_unpack_error);
		acl_myfree(msg);
		return -rfc1035_unpack_error;
	}
	querys = msg->query = (rfc1035_query*) acl_mycalloc((int) msg->qdcount, sizeof(*querys));
	for (i = 0; i < (int) msg->qdcount; i++) {
		if (rfc1035QueryUnpack(buf, sz, &off, &querys[i])) {
			RFC1035_UNPACK_DEBUG;
			rfc1035SetErrno(rfc1035_unpack_error);
			rfc1035MessageDestroy(msg);
			return -rfc1035_unpack_error;
		}
	}
	*answer = msg;
	if (msg->rcode) {
		RFC1035_UNPACK_DEBUG;
		rfc1035SetErrno((int) msg->rcode);
		return -((int) msg->rcode);
	}
	if (msg->ancount == 0)
		return 0;
	recs = msg->answer = (rfc1035_rr*) acl_mycalloc((int) msg->ancount, sizeof(*recs));
	for (i = 0; i < (int) msg->ancount; i++) {
		if (off >= (int) sz) {	/* corrupt packet */
			RFC1035_UNPACK_DEBUG;
			break;
		}
		if (rfc1035RRUnpack(buf, sz, &off, &recs[i])) {		/* corrupt RR */
			RFC1035_UNPACK_DEBUG;
			break;
		}
		nr++;
	}
	if (nr == 0) {
		/*
		* we expected to unpack some answers (ancount != 0), but
		* didn't actually get any.
		*/
		rfc1035MessageDestroy(msg);
		*answer = NULL;
		rfc1035SetErrno(rfc1035_unpack_error);
		return -rfc1035_unpack_error;
	}

	if (msg->nscount > 0) {
		//rfc1035NSUnpack(buf, sz, &off);
	}

	if (msg->arcount > 0) {
		//rfc1035ARUnpack(buf, sz, &off);
	}
	return nr;
}
Example #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);
}