Exemple #1
0
static void
rr_iter_find_nxt(priv_getdns_rr_iter *i)
{
	assert(i);
	assert(i->rr_type);

	i->nxt = i->n < GLDNS_QDCOUNT(i->pkt)
	       ? i->rr_type + 4
	       : i->rr_type + 10 > i->pkt_end
	       ? i->pkt_end
	       : i->rr_type + 10 + gldns_read_uint16(i->rr_type + 8) > i->pkt_end
	       ? i->pkt_end
	       : i->rr_type + 10 + gldns_read_uint16(i->rr_type + 8);
}
Exemple #2
0
priv_getdns_rdf_iter *
priv_getdns_rdf_iter_init(priv_getdns_rdf_iter *i, priv_getdns_rr_iter *rr)
{
	const priv_getdns_rr_def *rr_def;

	assert(i);
	assert(rr);

	i->end     = NULL;
	/* rr_iter already done or in question section */
	if (!rr->pos || rr->n < GLDNS_QDCOUNT(rr->pkt))
		goto done;

	i->pkt     = rr->pkt;
	i->pkt_end = rr->pkt_end;
	rr_def     = priv_getdns_rr_def_lookup(gldns_read_uint16(rr->rr_type));
	i->rdd_pos = rr_def->rdata;
	i->rdd_end = rr_def->rdata + rr_def->n_rdata_fields;

	/* No space to read rdata len */
	if (rr->rr_type + 10 >= rr->nxt)
		goto done;

	i->rdd_repeat = NULL;
	i->pos        = rr->rr_type + 10;
	i->end        = rr->nxt;

	/* rdata */
	if (i->rdd_pos != i->rdd_end)
		return rdf_iter_find_nxt(i);
done:
	i->pos = NULL;
	return NULL;
}
Exemple #3
0
static priv_getdns_rdf_iter *
rdf_iter_find_nxt(priv_getdns_rdf_iter *i)
{
	uint8_t *pos;

	assert(i);
	assert(i->pos);
	assert(i->rdd_pos);

	if (!i->rdd_repeat && (i->rdd_pos->type & GETDNS_RDF_REPEAT)) {
		i->rdd_repeat = i->rdd_pos;
		if (i->rdd_pos->type == GETDNS_RDF_REPEAT &&
		    ++i->rdd_pos == i->rdd_end)
			goto done;
	}
	if (i->rdd_pos->type & GETDNS_RDF_FIXEDSZ)
		i->nxt = i->pos + (i->rdd_pos->type & GETDNS_RDF_FIXEDSZ);

	else if ((i->rdd_pos->type & GETDNS_RDF_LEN_VAL) == 0x100)
		i->nxt = i->pos < i->end ? i->pos + *i->pos + 1 : i->end;

	else if ((i->rdd_pos->type & GETDNS_RDF_LEN_VAL) == 0x200)
		i->nxt = i->pos + 1 < i->end
		       ? i->pos + gldns_read_uint16(i->pos) + 2 : i->end;

	else if (i->rdd_pos->type & GETDNS_RDF_DNAME)

		for (pos = i->pos; pos < i->end; pos += *pos + 1) {
			if (!*pos) {
				i->nxt = pos + 1;
				break;
			} else if ((*pos & 0xC0) == 0xC0) {
				i->nxt = pos + 2;
				break;
			} else if (*pos & 0xC0) /* Uknown label type */
				goto done;
		}
	else if ((i->rdd_pos->type & GETDNS_RDF_SPECIAL) && i->rdd_pos->special) {
		if (!(i->nxt = i->rdd_pos->special->rdf_end(
		    i->pkt, i->pkt_end, i->pos)))
			i->nxt = i->end;

	} else /* RDF is for remaining data */
		i->nxt = i->end;

	if ( i->nxt <= i->end &&

	    /* Empty rdata fields are only allowed in case of non-repeating
	     * remaining data. So only the GETDNS_RDF_BINDATA bit is set.
	     */
	    (i->nxt >  i->pos || (i->rdd_pos->type == GETDNS_RDF_BINDATA)))
		return i;
done:
	i->pos = NULL;
	return NULL;
}
static priv_getdns_rdf_iter *
rdf_iter_find_nxt(priv_getdns_rdf_iter *i)
{
	uint8_t *pos;

	assert(i);
	assert(i->pos);
	assert(i->rdd_pos);

	if (!i->rdd_repeat && (i->rdd_pos->type & GETDNS_RDF_REPEAT)) {
		i->rdd_repeat = i->rdd_pos;
		if (i->rdd_pos->type == GETDNS_RDF_REPEAT &&
		    ++i->rdd_pos == i->rdd_end)
			goto done;
	}
	if (i->rdd_pos->type & GETDNS_RDF_FIXEDSZ)
		i->nxt = i->pos + (i->rdd_pos->type & GETDNS_RDF_FIXEDSZ);

	else if ((i->rdd_pos->type & GETDNS_RDF_LEN_VAL) == 0x100)
		i->nxt = i->pos < i->end ? i->pos + *i->pos + 1 : i->end;

	else if ((i->rdd_pos->type & GETDNS_RDF_LEN_VAL) == 0x200)
		i->nxt = i->pos + 1 < i->end
		       ? i->pos + gldns_read_uint16(i->pos) + 2 : i->end;

	else if ((i->rdd_pos->type & GETDNS_RDF_DNAME) == GETDNS_RDF_DNAME)

		for (pos = i->pos; pos < i->end; pos += *pos + 1) {
			if (!*pos) {
				i->nxt = pos + 1;
				break;
			} else if ((*pos & 0xC0) == 0xC0) {
				i->nxt = pos + 2;
				break;
			} else if (*pos & 0xC0) /* Uknown label type */
				goto done;
		}
	else if ((i->rdd_pos->type & GETDNS_RDF_SPECIAL) && i->rdd_pos->special) {
		if (!(i->nxt = i->rdd_pos->special->rdf_end(
		    i->pkt, i->pkt_end, i->pos)))
			i->nxt = i->end;
	} else
		i->nxt = i->end;

	if (i->nxt <= i->end)
		return i;
done:
	i->pos = NULL;
	return NULL;
}
Exemple #5
0
static uint8_t *
dname_if_or_as_decompressed(uint8_t *pkt, uint8_t *pkt_end, uint8_t *pos,
    uint8_t *buf, size_t *len, size_t refs)
{
	uint16_t offset;
	uint8_t *start, *dst;

	assert(pkt);
	assert(pkt_end);
	assert(pos);
	assert(buf);
	assert(len);

	if (refs > GLDNS_MAX_POINTERS)
		goto error;

	if ((*pos & 0xC0) == 0xC0) {
		if (pos + 1 >= pkt_end)
			goto error;
		offset = gldns_read_uint16(pos) & 0x3FFF;
		if (pkt + offset >= pkt_end)
			goto error;
		return dname_if_or_as_decompressed(pkt, pkt_end, pkt + offset,
		    buf, len, refs + 1);
	}
	if (*pos & 0xC0)
		goto error;

	start = pos;
	*len  = 0;
	while (*pos) {
		if ((*pos & 0xC0) == 0xC0)
			break;

		else if (*pos & 0xC0)
			goto error;

		*len += *pos + 1;
		pos += *pos + 1;
	}
	if (!*pos) {
		*len += 1;
		return start;
	}
	dst = buf;
	for (;;) {
		if (pos > start) {
			if (dst + (pos - start) > buf + 255)
				goto error;
			(void) memcpy(dst, start, pos - start);
			dst += (pos - start);
			start = pos;
		}
		if ((*pos & 0xC0) == 0xC0) {
			if (pos + 1 >= pkt_end)
				goto error;
			offset = gldns_read_uint16(pos) & 0x3FFF;
			if (pkt + offset >= pkt_end)
				goto error;

			start = pos = pkt + offset;
			if (++refs > 256)
				goto error;
		}
		if ((*pos & 0xC0) == 0xC0)
			continue;

		else if (*pos & 0xC0)
			goto error;

		else if (!*pos) {
			*len += 1;
			*dst = 0;
			return buf;
		}
		*len += *pos + 1;
		pos += *pos + 1;
	}
error:
	*len = 0;
	return NULL;
}