/** check if DNAME applies to a name */
static int
pkt_strict_sub(ldns_buffer* pkt, uint8_t* sname, uint8_t* dr)
{
    uint8_t buf1[LDNS_MAX_DOMAINLEN+1];
    uint8_t buf2[LDNS_MAX_DOMAINLEN+1];
    /* decompress names */
    dname_pkt_copy(pkt, buf1, sname);
    dname_pkt_copy(pkt, buf2, dr);
    return dname_strict_subdomain_c(buf1, buf2);
}
/** remove rrset, update loop variables */
static void
remove_rrset(const char* str, ldns_buffer* pkt, struct msg_parse* msg,
             struct rrset_parse* prev, struct rrset_parse** rrset)
{
    if(verbosity >= VERB_QUERY
            && (*rrset)->dname_len <= LDNS_MAX_DOMAINLEN) {
        uint8_t buf[LDNS_MAX_DOMAINLEN+1];
        dname_pkt_copy(pkt, buf, (*rrset)->dname);
        log_nametypeclass(VERB_QUERY, str, buf,
                          (*rrset)->type, ntohs((*rrset)->rrset_class));
    }
    if(prev)
        prev->rrset_all_next = (*rrset)->rrset_all_next;
    else	msg->rrset_first = (*rrset)->rrset_all_next;
    if(msg->rrset_last == *rrset)
        msg->rrset_last = prev;
    msg->rrset_count --;
    switch((*rrset)->section) {
    case LDNS_SECTION_ANSWER:
        msg->an_rrsets--;
        break;
    case LDNS_SECTION_AUTHORITY:
        msg->ns_rrsets--;
        break;
    case LDNS_SECTION_ADDITIONAL:
        msg->ar_rrsets--;
        break;
    default:
        log_assert(0);
    }
    msgparse_bucket_remove(msg, *rrset);
    *rrset = (*rrset)->rrset_all_next;
}
/** check subdomain with decompression, compressed is parent */
static int
sub_of_pkt(ldns_buffer* pkt, uint8_t* zone, uint8_t* comprname)
{
    uint8_t buf[LDNS_MAX_DOMAINLEN+1];
    dname_pkt_copy(pkt, buf, comprname);
    return dname_subdomain_c(zone, buf);
}
Exemple #4
0
int
parse_copy_decompress_rrset(sldns_buffer* pkt, struct msg_parse* msg,
	struct rrset_parse *pset, struct regional* region, 
	struct ub_packed_rrset_key* pk)
{
	struct packed_rrset_data* data;
	pk->rk.flags = pset->flags;
	pk->rk.dname_len = pset->dname_len;
	if(region)
		pk->rk.dname = (uint8_t*)regional_alloc(
			region, pset->dname_len);
	else	pk->rk.dname = 
			(uint8_t*)malloc(pset->dname_len);
	if(!pk->rk.dname)
		return 0;
	/** copy & decompress dname */
	dname_pkt_copy(pkt, pk->rk.dname, pset->dname);
	/** copy over type and class */
	pk->rk.type = htons(pset->type);
	pk->rk.rrset_class = pset->rrset_class;
	/** read data part. */
	if(!parse_create_rrset(pkt, pset, &data, region))
		return 0;
	pk->entry.data = (void*)data;
	pk->entry.key = (void*)pk;
	pk->entry.hash = pset->hash;
	data->trust = get_rrset_trust(msg, pset);
	return 1;
}
Exemple #5
0
/** check subdomain with decompression */
static int
pkt_sub(sldns_buffer* pkt, uint8_t* comprname, uint8_t* zone)
{
	uint8_t buf[LDNS_MAX_DOMAINLEN+1];
	dname_pkt_copy(pkt, buf, comprname);
	return dname_subdomain_c(buf, zone);
}
/** synthesize a CNAME rrset */
static struct rrset_parse*
synth_cname_rrset(uint8_t** sname, size_t* snamelen, uint8_t* alias,
                  size_t aliaslen, struct regional* region, struct msg_parse* msg,
                  struct rrset_parse* rrset, struct rrset_parse* prev,
                  struct rrset_parse* nx, ldns_buffer* pkt)
{
    struct rrset_parse* cn = (struct rrset_parse*)regional_alloc(region,
                             sizeof(struct rrset_parse));
    if(!cn)
        return NULL;
    memset(cn, 0, sizeof(*cn));
    cn->rr_first = (struct rr_parse*)regional_alloc(region,
                   sizeof(struct rr_parse));
    if(!cn->rr_first)
        return NULL;
    cn->rr_last = cn->rr_first;
    /* CNAME from sname to alias */
    cn->dname = (uint8_t*)regional_alloc(region, *snamelen);
    if(!cn->dname)
        return NULL;
    dname_pkt_copy(pkt, cn->dname, *sname);
    cn->dname_len = *snamelen;
    cn->type = LDNS_RR_TYPE_CNAME;
    cn->section = rrset->section;
    cn->rrset_class = rrset->rrset_class;
    cn->rr_count = 1;
    cn->size = sizeof(uint16_t) + aliaslen;
    cn->hash=pkt_hash_rrset(pkt, cn->dname, cn->type, cn->rrset_class, 0);
    /* allocate TTL + rdatalen + uncompressed dname */
    memset(cn->rr_first, 0, sizeof(struct rr_parse));
    cn->rr_first->outside_packet = 1;
    cn->rr_first->ttl_data = (uint8_t*)regional_alloc(region,
                             sizeof(uint32_t)+sizeof(uint16_t)+aliaslen);
    if(!cn->rr_first->ttl_data)
        return NULL;
    ldns_write_uint32(cn->rr_first->ttl_data, 0); /* TTL = 0 */
    ldns_write_uint16(cn->rr_first->ttl_data+4, aliaslen);
    memmove(cn->rr_first->ttl_data+6, alias, aliaslen);
    cn->rr_first->size = sizeof(uint16_t)+aliaslen;

    /* link it in */
    cn->rrset_all_next = nx;
    if(prev)
        prev->rrset_all_next = cn;
    else	msg->rrset_first = cn;
    if(nx == NULL)
        msg->rrset_last = cn;
    msg->rrset_count ++;
    msg->an_rrsets++;
    /* it is not inserted in the msg hashtable. */

    *sname = cn->rr_first->ttl_data + sizeof(uint32_t)+sizeof(uint16_t);
    *snamelen = aliaslen;
    return cn;
}
/** Synthesize CNAME from DNAME, false if too long */
static int
synth_cname(uint8_t* qname, size_t qnamelen, struct rrset_parse* dname_rrset,
            uint8_t* alias, size_t* aliaslen, ldns_buffer* pkt)
{
    /* we already know that sname is a strict subdomain of DNAME owner */
    uint8_t* dtarg = NULL;
    size_t dtarglen;
    if(!parse_get_cname_target(dname_rrset, &dtarg, &dtarglen))
        return 0;
    log_assert(qnamelen > dname_rrset->dname_len);
    /* DNAME from com. to net. with qname example.com. -> example.net. */
    /* so: \3com\0 to \3net\0 and qname \7example\3com\0 */
    *aliaslen = qnamelen + dtarglen - dname_rrset->dname_len;
    if(*aliaslen > LDNS_MAX_DOMAINLEN)
        return 0; /* should have been RCODE YXDOMAIN */
    /* decompress dnames into buffer, we know it fits */
    dname_pkt_copy(pkt, alias, qname);
    dname_pkt_copy(pkt, alias+(qnamelen-dname_rrset->dname_len), dtarg);
    return 1;
}
Exemple #8
0
/** allocate qinfo, return 0 on error */
static int
parse_create_qinfo(sldns_buffer* pkt, struct msg_parse* msg, 
	struct query_info* qinf, struct regional* region)
{
	if(msg->qname) {
		if(region)
			qinf->qname = (uint8_t*)regional_alloc(region, 
				msg->qname_len);
		else	qinf->qname = (uint8_t*)malloc(msg->qname_len);
		if(!qinf->qname) return 0;
		dname_pkt_copy(pkt, qinf->qname, msg->qname);
	} else	qinf->qname = 0;
	qinf->qname_len = msg->qname_len;
	qinf->qtype = msg->qtype;
	qinf->qclass = msg->qclass;
	return 1;
}
Exemple #9
0
/** do the rdata copy */
static int
rdata_copy(sldns_buffer* pkt, struct packed_rrset_data* data, uint8_t* to, 
	struct rr_parse* rr, time_t* rr_ttl, uint16_t type,
	sldns_pkt_section section)
{
	uint16_t pkt_len;
	const sldns_rr_descriptor* desc;

	*rr_ttl = sldns_read_uint32(rr->ttl_data);
	/* RFC 2181 Section 8. if msb of ttl is set treat as if zero. */
	if(*rr_ttl & 0x80000000U)
		*rr_ttl = 0;
	if(type == LDNS_RR_TYPE_SOA && section == LDNS_SECTION_AUTHORITY) {
		/* negative response. see if TTL of SOA record larger than the
		 * minimum-ttl in the rdata of the SOA record */
		if(*rr_ttl > soa_find_minttl(rr))
			*rr_ttl = soa_find_minttl(rr);
		if(*rr_ttl > MAX_NEG_TTL)
			*rr_ttl = MAX_NEG_TTL;
	}
	if(*rr_ttl < MIN_TTL)
		*rr_ttl = MIN_TTL;
	if(*rr_ttl < data->ttl)
		data->ttl = *rr_ttl;

	if(rr->outside_packet) {
		/* uncompressed already, only needs copy */
		memmove(to, rr->ttl_data+sizeof(uint32_t), rr->size);
		return 1;
	}

	sldns_buffer_set_position(pkt, (size_t)
		(rr->ttl_data - sldns_buffer_begin(pkt) + sizeof(uint32_t)));
	/* insert decompressed size into rdata len stored in memory */
	/* -2 because rdatalen bytes are not included. */
	pkt_len = htons(rr->size - 2);
	memmove(to, &pkt_len, sizeof(uint16_t));
	to += 2;
	/* read packet rdata len */
	pkt_len = sldns_buffer_read_u16(pkt);
	if(sldns_buffer_remaining(pkt) < pkt_len)
		return 0;
	desc = sldns_rr_descript(type);
	if(pkt_len > 0 && desc && desc->_dname_count > 0) {
		int count = (int)desc->_dname_count;
		int rdf = 0;
		size_t len;
		size_t oldpos;
		/* decompress dnames. */
		while(pkt_len > 0 && count) {
			switch(desc->_wireformat[rdf]) {
			case LDNS_RDF_TYPE_DNAME:
				oldpos = sldns_buffer_position(pkt);
				dname_pkt_copy(pkt, to, 
					sldns_buffer_current(pkt));
				to += pkt_dname_len(pkt);
				pkt_len -= sldns_buffer_position(pkt)-oldpos;
				count--;
				len = 0;
				break;
			case LDNS_RDF_TYPE_STR:
				len = sldns_buffer_current(pkt)[0] + 1;
				break;
			default:
				len = get_rdf_size(desc->_wireformat[rdf]);
				break;
			}
			if(len) {
				memmove(to, sldns_buffer_current(pkt), len);
				to += len;
				sldns_buffer_skip(pkt, (ssize_t)len);
				log_assert(len <= pkt_len);
				pkt_len -= len;
			}
			rdf++;
		}
	}
	/* copy remaining rdata */
	if(pkt_len >  0)
		memmove(to, sldns_buffer_current(pkt), pkt_len);
	
	return 1;
}