Example #1
0
int 
parse_extract_edns(struct msg_parse* msg, struct edns_data* edns)
{
	struct rrset_parse* rrset = msg->rrset_first;
	struct rrset_parse* prev = 0;
	struct rrset_parse* found = 0;
	struct rrset_parse* found_prev = 0;
	/* since the class encodes the UDP size, we cannot use hash table to
	 * find the EDNS OPT record. Scan the packet. */
	while(rrset) {
		if(rrset->type == LDNS_RR_TYPE_OPT) {
			/* only one OPT RR allowed. */
			if(found) return LDNS_RCODE_FORMERR;
			/* found it! */
			found_prev = prev;
			found = rrset;
		}
		prev = rrset;
		rrset = rrset->rrset_all_next;
	}
	if(!found) {
		memset(edns, 0, sizeof(*edns));
		edns->udp_size = 512;
		return 0;
	}
	/* check the found RRset */
	/* most lenient check possible. ignore dname, use last opt */
	if(found->section != LDNS_SECTION_ADDITIONAL)
		return LDNS_RCODE_FORMERR; 
	if(found->rr_count == 0)
		return LDNS_RCODE_FORMERR;
	if(0) { /* strict checking of dname and RRcount */
		if(found->dname_len != 1 || !found->dname 
			|| found->dname[0] != 0) return LDNS_RCODE_FORMERR; 
		if(found->rr_count != 1) return LDNS_RCODE_FORMERR; 
	}
	log_assert(found->rr_first && found->rr_last);

	/* remove from packet */
	if(found_prev)	found_prev->rrset_all_next = found->rrset_all_next;
	else	msg->rrset_first = found->rrset_all_next;
	if(found == msg->rrset_last)
		msg->rrset_last = found_prev;
	msg->arcount --;
	msg->ar_rrsets --;
	msg->rrset_count --;
	
	/* take the data ! */
	edns->edns_present = 1;
	edns->ext_rcode = found->rr_last->ttl_data[0];
	edns->edns_version = found->rr_last->ttl_data[1];
	edns->bits = sldns_read_uint16(&found->rr_last->ttl_data[2]);
	edns->udp_size = ntohs(found->rrset_class);
	/* ignore rdata and rrsigs */
	return 0;
}
Example #2
0
/** find the minimumttl in the rdata of SOA record */
static time_t
soa_find_minttl(struct rr_parse* rr)
{
	uint16_t rlen = sldns_read_uint16(rr->ttl_data+4);
	if(rlen < 20)
		return 0; /* rdata too small for SOA (dname, dname, 5*32bit) */
	/* minimum TTL is the last 32bit value in the rdata of the record */
	/* at position ttl_data + 4(ttl) + 2(rdatalen) + rdatalen - 4(timeval)*/
	return (time_t)sldns_read_uint32(rr->ttl_data+6+rlen-4);
}
Example #3
0
int 
delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region,
        struct ub_packed_rrset_key* ns_rrset, uint8_t lame)
{
	struct packed_rrset_data* nsdata = (struct packed_rrset_data*)
		ns_rrset->entry.data;
	size_t i;
	log_assert(!dp->dp_type_mlc);
	if(nsdata->security == sec_status_bogus)
		dp->bogus = 1;
	for(i=0; i<nsdata->count; i++) {
		if(nsdata->rr_len[i] < 2+1) continue; /* len + root label */
		if(dname_valid(nsdata->rr_data[i]+2, nsdata->rr_len[i]-2) !=
			(size_t)sldns_read_uint16(nsdata->rr_data[i]))
			continue; /* bad format */
		/* add rdata of NS (= wirefmt dname), skip rdatalen bytes */
		if(!delegpt_add_ns(dp, region, nsdata->rr_data[i]+2, lame))
			return 0;
	}
	return 1;
}
Example #4
0
void 
get_cname_target(struct ub_packed_rrset_key* rrset, uint8_t** dname, 
	size_t* dname_len)
{
	struct packed_rrset_data* d;
	size_t len;
	if(ntohs(rrset->rk.type) != LDNS_RR_TYPE_CNAME && 
		ntohs(rrset->rk.type) != LDNS_RR_TYPE_DNAME)
		return;
	d = (struct packed_rrset_data*)rrset->entry.data;
	if(d->count < 1)
		return;
	if(d->rr_len[0] < 3) /* at least rdatalen + 0byte root label */
		return;
	len = sldns_read_uint16(d->rr_data[0]);
	if(len != d->rr_len[0] - sizeof(uint16_t))
		return;
	if(dname_valid(d->rr_data[0]+sizeof(uint16_t), len) != len)
		return;
	*dname = d->rr_data[0]+sizeof(uint16_t);
	*dname_len = len;
}
Example #5
0
/**
 * Check if right hand name in NSEC is within zone
 * @param rrset: the NSEC rrset
 * @param zonename: the zone name.
 * @return true if BAD.
 */
static int sanitize_nsec_is_overreach(struct rrset_parse* rrset, 
	uint8_t* zonename)
{
	struct rr_parse* rr;
	uint8_t* rhs;
	size_t len;
	log_assert(rrset->type == LDNS_RR_TYPE_NSEC);
	for(rr = rrset->rr_first; rr; rr = rr->next) {
		rhs = rr->ttl_data+4+2;
		len = sldns_read_uint16(rr->ttl_data+4);
		if(!dname_valid(rhs, len)) {
			/* malformed domain name in rdata */
			return 1;
		}
		if(!dname_subdomain_c(rhs, zonename)) {
			/* overreaching */
			return 1;
		}
	}
	/* all NSEC RRs OK */
	return 0;
}
Example #6
0
/** get additional name from rrset RR, return false if no name present */
static int
get_additional_name(struct rrset_parse* rrset, struct rr_parse* rr, 
	uint8_t** nm, size_t* nmlen, sldns_buffer* pkt) 
{
	size_t offset = 0;
	size_t len, oldpos;
	switch(rrset->type) {
		case LDNS_RR_TYPE_MB:
		case LDNS_RR_TYPE_MD:
		case LDNS_RR_TYPE_MF:
		case LDNS_RR_TYPE_NS:
			offset = 0;
			break;
		case LDNS_RR_TYPE_MX:
		case LDNS_RR_TYPE_KX:
			offset = 2;
			break;
		case LDNS_RR_TYPE_SRV:
			offset = 6;
			break;
		case LDNS_RR_TYPE_NAPTR:
			/* TODO: NAPTR not supported, glue stripped off */
			return 0;
		default:
			return 0;
	}
	len = sldns_read_uint16(rr->ttl_data+sizeof(uint32_t));
	if(len < offset+1)
		return 0; /* rdata field too small */
	*nm = rr->ttl_data+sizeof(uint32_t)+sizeof(uint16_t)+offset;
	oldpos = sldns_buffer_position(pkt);
	sldns_buffer_set_position(pkt, (size_t)(*nm - sldns_buffer_begin(pkt)));
	*nmlen = pkt_dname_len(pkt);
	sldns_buffer_set_position(pkt, oldpos);
	if(*nmlen == 0)
		return 0;
	return 1;
}