예제 #1
0
파일: msgreply.c 프로젝트: Karm/unbound
int reply_info_parse(sldns_buffer* pkt, struct alloc_cache* alloc,
        struct query_info* qinf, struct reply_info** rep, 
	struct regional* region, struct edns_data* edns)
{
	/* use scratch pad region-allocator during parsing. */
	struct msg_parse* msg;
	int ret;
	
	qinf->qname = NULL;
	*rep = NULL;
	if(!(msg = regional_alloc(region, sizeof(*msg)))) {
		return LDNS_RCODE_SERVFAIL;
	}
	memset(msg, 0, sizeof(*msg));
	
	sldns_buffer_set_position(pkt, 0);
	if((ret = parse_packet(pkt, msg, region)) != 0) {
		return ret;
	}
	if((ret = parse_extract_edns(msg, edns)) != 0)
		return ret;

	/* parse OK, allocate return structures */
	/* this also performs dname decompression */
	if(!parse_create_msg(pkt, msg, alloc, qinf, rep, NULL)) {
		query_info_clear(qinf);
		reply_info_parsedelete(*rep, alloc);
		*rep = NULL;
		return LDNS_RCODE_SERVFAIL;
	}
	return 0;
}
예제 #2
0
/* Create response according to the ldns packet content */
int createResponse(struct module_qstate* qstate, sldns_buffer* pkt)
{
    struct msg_parse* prs;
    struct edns_data edns;
    
    /* parse message */
    prs = (struct msg_parse*) regional_alloc(qstate->env->scratch, sizeof(struct msg_parse));
    if (!prs) {
	log_err("storeResponse: out of memory on incoming message");
	return 0;
    }

    memset(prs, 0, sizeof(*prs));
    memset(&edns, 0, sizeof(edns));

    sldns_buffer_set_position(pkt, 0);
    if (parse_packet(pkt, prs, qstate->env->scratch) != LDNS_RCODE_NOERROR) {
	verbose(VERB_ALGO, "storeResponse: parse error on reply packet");
	return 0;
    }
    /* edns is not examined, but removed from message to help cache */
    if(parse_extract_edns(prs, &edns) != LDNS_RCODE_NOERROR)
	return 0;

    /* remove CD-bit, we asked for in case we handle validation ourself */
    prs->flags &= ~BIT_CD;

    /* allocate response dns_msg in region */
    qstate->return_msg = (struct dns_msg*)regional_alloc(qstate->region, sizeof(struct dns_msg));
    if (!qstate->return_msg)
       return 0;

    memset(qstate->return_msg, 0, sizeof(*qstate->return_msg));
    if(!parse_create_msg(pkt, prs, NULL, &(qstate->return_msg)->qinfo, &(qstate->return_msg)->rep, qstate->region)) {
	log_err("storeResponse: malloc failure: allocating incoming dns_msg");
	return 0;
    }
    
    /* Make sure that the RA flag is set (since the presence of 
     * this module means that recursion is available) */
    /* qstate->return_msg->rep->flags |= BIT_RA; */

    /* Clear the AA flag */
    /* FIXME: does this action go here or in some other module? */
    /*qstate->return_msg->rep->flags &= ~BIT_AA; */

    /* make sure QR flag is on */
    /*qstate->return_msg->rep->flags |= BIT_QR; */

    if(verbosity >= VERB_ALGO)
	log_dns_msg("storeResponse: packet:", &qstate->return_msg->qinfo, qstate->return_msg->rep);

    return 1;
}
예제 #3
0
/** convert dns message in buffer to return_msg */
static int
parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
{
	struct msg_parse* prs;
	struct edns_data edns;
	uint64_t timestamp, expiry;
	time_t adjust;
	size_t lim = sldns_buffer_limit(buf);
	if(lim < LDNS_HEADER_SIZE+sizeof(timestamp)+sizeof(expiry))
		return 0; /* too short */

	/* remove timestamp and expiry from end */
	sldns_buffer_read_at(buf, lim-sizeof(expiry), &expiry, sizeof(expiry));
	sldns_buffer_read_at(buf, lim-sizeof(expiry)-sizeof(timestamp),
		&timestamp, sizeof(timestamp));
	expiry = be64toh(expiry);
	timestamp = be64toh(timestamp);

	/* parse DNS packet */
	regional_free_all(qstate->env->scratch);
	prs = (struct msg_parse*)regional_alloc(qstate->env->scratch,
		sizeof(struct msg_parse));
	if(!prs)
		return 0; /* out of memory */
	memset(prs, 0, sizeof(*prs));
	memset(&edns, 0, sizeof(edns));
	sldns_buffer_set_limit(buf, lim - sizeof(expiry)-sizeof(timestamp));
	if(parse_packet(buf, prs, qstate->env->scratch) != LDNS_RCODE_NOERROR) {
		sldns_buffer_set_limit(buf, lim);
		return 0;
	}
	if(parse_extract_edns(prs, &edns, qstate->env->scratch) !=
		LDNS_RCODE_NOERROR) {
		sldns_buffer_set_limit(buf, lim);
		return 0;
	}

	qstate->return_msg = dns_alloc_msg(buf, prs, qstate->region);
	sldns_buffer_set_limit(buf, lim);
	if(!qstate->return_msg)
		return 0;
	
	qstate->return_rcode = LDNS_RCODE_NOERROR;

	/* see how much of the TTL expired, and remove it */
	if(*qstate->env->now <= (time_t)timestamp) {
		verbose(VERB_ALGO, "cachedb msg adjust by zero");
		return 1; /* message from the future (clock skew?) */
	}
	adjust = *qstate->env->now - (time_t)timestamp;
	if(qstate->return_msg->rep->ttl < adjust) {
		verbose(VERB_ALGO, "cachedb msg expired");
		/* If serve-expired is enabled, we still use an expired message
		 * setting the TTL to 0. */
		if(qstate->env->cfg->serve_expired)
			adjust = -1;
		else
			return 0; /* message expired */
	}
	verbose(VERB_ALGO, "cachedb msg adjusted down by %d", (int)adjust);
	adjust_msg_ttl(qstate->return_msg, adjust);

	/* Similar to the unbound worker, if serve-expired is enabled and
	 * the msg would be considered to be expired, mark the state so a
	 * refetch will be scheduled.  The comparison between 'expiry' and
	 * 'now' should be redundant given how these values were calculated,
	 * but we check it just in case as does good_expiry_and_qinfo(). */
	if(qstate->env->cfg->serve_expired &&
		(adjust == -1 || (time_t)expiry < *qstate->env->now)) {
		qstate->need_refetch = 1;
	}

	return 1;
}