Exemplo n.º 1
0
int 
parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns)
{
	log_assert(LDNS_QDCOUNT(sldns_buffer_begin(pkt)) == 1);
	log_assert(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) == 0);
	log_assert(LDNS_NSCOUNT(sldns_buffer_begin(pkt)) == 0);
	/* check edns section is present */
	if(LDNS_ARCOUNT(sldns_buffer_begin(pkt)) > 1) {
		return LDNS_RCODE_FORMERR;
	}
	if(LDNS_ARCOUNT(sldns_buffer_begin(pkt)) == 0) {
		memset(edns, 0, sizeof(*edns));
		edns->udp_size = 512;
		return 0;
	}
	/* domain name must be the root of length 1. */
	if(pkt_dname_len(pkt) != 1)
		return LDNS_RCODE_FORMERR;
	if(sldns_buffer_remaining(pkt) < 10) /* type, class, ttl, rdatalen */
		return LDNS_RCODE_FORMERR;
	if(sldns_buffer_read_u16(pkt) != LDNS_RR_TYPE_OPT)
		return LDNS_RCODE_FORMERR;
	edns->edns_present = 1;
	edns->udp_size = sldns_buffer_read_u16(pkt); /* class is udp size */
	edns->ext_rcode = sldns_buffer_read_u8(pkt); /* ttl used for bits */
	edns->edns_version = sldns_buffer_read_u8(pkt);
	edns->bits = sldns_buffer_read_u16(pkt);
	/* ignore rdata and rrsigs */
	return 0;
}
Exemplo n.º 2
0
size_t
pkt_dname_len(sldns_buffer* pkt)
{
    size_t len = 0;
    int ptrcount = 0;
    uint8_t labellen;
    size_t endpos = 0;

    /* read dname and determine length */
    /* check compression pointers, loops, out of bounds */
    while(1) {
        /* read next label */
        if(sldns_buffer_remaining(pkt) < 1)
            return 0;
        labellen = sldns_buffer_read_u8(pkt);
        if(LABEL_IS_PTR(labellen)) {
            /* compression ptr */
            uint16_t ptr;
            if(sldns_buffer_remaining(pkt) < 1)
                return 0;
            ptr = PTR_OFFSET(labellen, sldns_buffer_read_u8(pkt));
            if(ptrcount++ > MAX_COMPRESS_PTRS)
                return 0; /* loop! */
            if(sldns_buffer_limit(pkt) <= ptr)
                return 0; /* out of bounds! */
            if(!endpos)
                endpos = sldns_buffer_position(pkt);
            sldns_buffer_set_position(pkt, ptr);
        } else {
            /* label contents */
            if(labellen > 0x3f)
                return 0; /* label too long */
            len += 1 + labellen;
            if(len > LDNS_MAX_DOMAINLEN)
                return 0;
            if(labellen == 0) {
                /* end of dname */
                break;
            }
            if(sldns_buffer_remaining(pkt) < labellen)
                return 0;
            sldns_buffer_skip(pkt, (ssize_t)labellen);
        }
    }
    if(endpos)
        sldns_buffer_set_position(pkt, endpos);

    return len;
}
Exemplo n.º 3
0
/** See if next rrset is nsec at zone apex */
static int
nsec_at_apex(sldns_buffer* pkt)
{
	/* we are at ttl position in packet. */
	size_t pos = sldns_buffer_position(pkt);
	uint16_t rdatalen;
	if(sldns_buffer_remaining(pkt) < 7) /* ttl+len+root */
		return 0; /* eek! */
	sldns_buffer_skip(pkt, 4); /* ttl */;
	rdatalen = sldns_buffer_read_u16(pkt);
	if(sldns_buffer_remaining(pkt) < rdatalen) {
		sldns_buffer_set_position(pkt, pos);
		return 0; /* parse error happens later */
	}
	/* must validate the nsec next domain name format */
	if(pkt_dname_len(pkt) == 0) {
		sldns_buffer_set_position(pkt, pos);
		return 0; /* parse error */
	}

	/* see if SOA bit is set. */
	if(sldns_buffer_position(pkt) < pos+4+rdatalen) {
		/* nsec type bitmap contains items */
		uint8_t win, blen, bits;
		/* need: windownum, bitmap len, firstbyte */
		if(sldns_buffer_position(pkt)+3 > pos+4+rdatalen) {
			sldns_buffer_set_position(pkt, pos);
			return 0; /* malformed nsec */
		}
		win = sldns_buffer_read_u8(pkt);
		blen = sldns_buffer_read_u8(pkt);
		bits = sldns_buffer_read_u8(pkt);
		/* 0window always first window. bitlen >=1 or parse
		   error really. bit 0x2 is SOA. */
		if(win == 0 && blen >= 1 && (bits & 0x02)) {
			sldns_buffer_set_position(pkt, pos);
			return 1;
		}
	}

	sldns_buffer_set_position(pkt, pos);
	return 0;
}
Exemplo n.º 4
0
/* determine length of a dname in buffer, no compression pointers allowed */
size_t
query_dname_len(sldns_buffer* query)
{
    size_t len = 0;
    size_t labellen;
    while(1) {
        if(sldns_buffer_remaining(query) < 1)
            return 0; /* parse error, need label len */
        labellen = sldns_buffer_read_u8(query);
        if(labellen&0xc0)
            return 0; /* no compression allowed in queries */
        len += labellen + 1;
        if(len > LDNS_MAX_DOMAINLEN)
            return 0; /* too long */
        if(labellen == 0)
            return len;
        if(sldns_buffer_remaining(query) < labellen)
            return 0; /* parse error, need content */
        sldns_buffer_skip(query, (ssize_t)labellen);
    }
}