コード例 #1
0
ldns_status
ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
{
	uint16_t i;
	uint16_t rdl_pos = 0;
	
	if (ldns_rr_owner(rr)) {
		(void) ldns_dname2buffer_wire(buffer, ldns_rr_owner(rr));
	}
	
	if (ldns_buffer_reserve(buffer, 4)) {
		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
	}

	if (section != LDNS_SECTION_QUESTION) {
		if (ldns_buffer_reserve(buffer, 6)) {
			ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
			/* remember pos for later */
			rdl_pos = ldns_buffer_position(buffer);
			ldns_buffer_write_u16(buffer, 0);
		}	

		for (i = 0; i < ldns_rr_rd_count(rr); i++) {
			(void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
		}
		
		if (rdl_pos != 0) {
			ldns_buffer_write_u16_at(buffer, rdl_pos,
			                         ldns_buffer_position(buffer)
		        	                   - rdl_pos - 2);
		}
	}
	return ldns_buffer_status(buffer);
}
コード例 #2
0
/** compress domain names in rdata, return RETVAL_* */
static int
compress_rdata(ldns_buffer* pkt, uint8_t* rdata, size_t todolen, 
	struct regional* region, struct compress_tree_node** tree, 
	const ldns_rr_descriptor* desc)
{
	int labs, r, rdf = 0;
	size_t dname_len, len, pos = ldns_buffer_position(pkt);
	uint8_t count = desc->_dname_count;

	ldns_buffer_skip(pkt, 2); /* rdata len fill in later */
	/* space for rdatalen checked for already */
	rdata += 2;
	todolen -= 2;
	while(todolen > 0 && count) {
		switch(desc->_wireformat[rdf]) {
		case LDNS_RDF_TYPE_DNAME:
			labs = dname_count_size_labels(rdata, &dname_len);
			if((r=compress_any_dname(rdata, pkt, labs, region, 
				tree)) != RETVAL_OK)
				return r;
			rdata += dname_len;
			todolen -= dname_len;
			count--;
			len = 0;
			break;
		case LDNS_RDF_TYPE_STR:
			len = *rdata + 1;
			break;
		default:
			len = get_rdf_size(desc->_wireformat[rdf]);
		}
		if(len) {
			/* copy over */
			if(ldns_buffer_remaining(pkt) < len)
				return RETVAL_TRUNC;
			ldns_buffer_write(pkt, rdata, len);
			todolen -= len;
			rdata += len;
		}
		rdf++;
	}
	/* copy remainder */
	if(todolen > 0) {
		if(ldns_buffer_remaining(pkt) < todolen)
			return RETVAL_TRUNC;
		ldns_buffer_write(pkt, rdata, todolen);
	}

	/* set rdata len */
	ldns_buffer_write_u16_at(pkt, pos, ldns_buffer_position(pkt)-pos-2);
	return RETVAL_OK;
}
コード例 #3
0
/** analyze domain name in packet, possibly compressed */
static void analyze_dname(ldns_buffer* pkt)
{
	size_t oldpos = ldns_buffer_position(pkt);
	size_t len;
	printf("[pos %d] dname: ", (int)oldpos);
	dname_print(stdout, pkt, ldns_buffer_current(pkt));
	len = pkt_dname_len(pkt);
	printf(" len=%d", (int)len);
	if(ldns_buffer_position(pkt)-oldpos != len)
		printf(" comprlen=%d\n", 
			(int)(ldns_buffer_position(pkt)-oldpos));
	else	printf("\n");
}
コード例 #4
0
/** store msg section in wireformat buffer, return RETVAL_* */
static int
insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
	ldns_buffer* pkt, size_t rrsets_before, uint32_t timenow, 
	struct regional* region, struct compress_tree_node** tree,
	ldns_pkt_section s, uint16_t qtype, int dnssec, size_t rr_offset)
{
	int r;
	size_t i, setstart;
	*num_rrs = 0;
	if(s != LDNS_SECTION_ADDITIONAL) {
		if(s == LDNS_SECTION_ANSWER && qtype == LDNS_RR_TYPE_ANY)
			dnssec = 1; /* include all types in ANY answer */
	  	for(i=0; i<num_rrsets; i++) {
			setstart = ldns_buffer_position(pkt);
			if((r=packed_rrset_encode(rep->rrsets[rrsets_before+i], 
				pkt, num_rrs, timenow, region, 1, 1, tree,
				s, qtype, dnssec, rr_offset))
				!= RETVAL_OK) {
				/* Bad, but if due to size must set TC bit */
				/* trim off the rrset neatly. */
				ldns_buffer_set_position(pkt, setstart);
				return r;
			}
		}
	} else {
	  	for(i=0; i<num_rrsets; i++) {
			setstart = ldns_buffer_position(pkt);
			if((r=packed_rrset_encode(rep->rrsets[rrsets_before+i], 
				pkt, num_rrs, timenow, region, 1, 0, tree,
				s, qtype, dnssec, rr_offset))
				!= RETVAL_OK) {
				ldns_buffer_set_position(pkt, setstart);
				return r;
			}
		}
		if(dnssec)
	  	  for(i=0; i<num_rrsets; i++) {
			setstart = ldns_buffer_position(pkt);
			if((r=packed_rrset_encode(rep->rrsets[rrsets_before+i], 
				pkt, num_rrs, timenow, region, 0, 1, tree,
				s, qtype, dnssec, rr_offset))
				!= RETVAL_OK) {
				ldns_buffer_set_position(pkt, setstart);
				return r;
			}
		  }
	}
	return RETVAL_OK;
}
コード例 #5
0
ファイル: dnssec_sign.c プロジェクト: kaloyan13/passivedns
ldns_rdf *
ldns_sign_public_evp(ldns_buffer *to_sign,
				 EVP_PKEY *key,
				 const EVP_MD *digest_type)
{
	unsigned int siglen;
	ldns_rdf *sigdata_rdf;
	ldns_buffer *b64sig;
	EVP_MD_CTX ctx;
	const EVP_MD *md_type;
	int r;

	siglen = 0;
	b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
	if (!b64sig) {
		return NULL;
	}

	/* initializes a signing context */
	md_type = digest_type;
	if(!md_type) {
		/* unknown message difest */
		ldns_buffer_free(b64sig);
		return NULL;
	}

	EVP_MD_CTX_init(&ctx);
	r = EVP_SignInit(&ctx, md_type);
	if(r == 1) {
		r = EVP_SignUpdate(&ctx, (unsigned char*)
					    ldns_buffer_begin(to_sign), 
					    ldns_buffer_position(to_sign));
	} else {
		ldns_buffer_free(b64sig);
		return NULL;
	}
	if(r == 1) {
		r = EVP_SignFinal(&ctx, (unsigned char*)
					   ldns_buffer_begin(b64sig), &siglen, key);
	} else {
		ldns_buffer_free(b64sig);
		return NULL;
	}
	if(r != 1) {
		ldns_buffer_free(b64sig);
		return NULL;
	}

	/* unfortunately, OpenSSL output is differenct from DNS DSA format */
	if (EVP_PKEY_type(key->type) == EVP_PKEY_DSA) {
		sigdata_rdf = ldns_convert_dsa_rrsig_asn12rdf(b64sig, siglen);
	} else {
		/* ok output for other types is the same */
		sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen,
									 ldns_buffer_begin(b64sig));
	}
	ldns_buffer_free(b64sig);
	EVP_MD_CTX_cleanup(&ctx);
	return sigdata_rdf;
}
コード例 #6
0
ファイル: dnssec_sign.c プロジェクト: kaloyan13/passivedns
ldns_rdf *
ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key)
{
	unsigned char *md5_hash;
	unsigned int siglen;
	ldns_rdf *sigdata_rdf;
	ldns_buffer *b64sig;

	b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
	if (!b64sig) {
		return NULL;
	}
	
	md5_hash = MD5((unsigned char*)ldns_buffer_begin(to_sign),
				ldns_buffer_position(to_sign), NULL);
	if (!md5_hash) {
		ldns_buffer_free(b64sig);
		return NULL;
	}

	RSA_sign(NID_md5, md5_hash, MD5_DIGEST_LENGTH,
		    (unsigned char*)ldns_buffer_begin(b64sig),
		    &siglen, key);

	sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, 
								 ldns_buffer_begin(b64sig));
	ldns_buffer_free(b64sig);
	return sigdata_rdf;
}
コード例 #7
0
ファイル: dnssec_sign.c プロジェクト: mbuij/ldns-cga-tsig
ldns_rdf *
ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key)
{
	unsigned char *sha1_hash;
	unsigned int siglen;
	ldns_rdf *sigdata_rdf;
	ldns_buffer *b64sig;
	int result;

	siglen = 0;
	b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
	if (!b64sig) {
		return NULL;
	}

	sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign),
				  ldns_buffer_position(to_sign), NULL);
	if (!sha1_hash) {
		ldns_buffer_free(b64sig);
		return NULL;
	}

	result = RSA_sign(NID_sha1, sha1_hash, SHA_DIGEST_LENGTH,
				   (unsigned char*)ldns_buffer_begin(b64sig),
				   &siglen, key);
	if (result != 1) {
		ldns_buffer_free(b64sig);
		return NULL;
	}

	sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, 
								 ldns_buffer_begin(b64sig));
	ldns_buffer_free(b64sig); /* can't free this buffer ?? */
	return sigdata_rdf;
}
コード例 #8
0
ファイル: dnssec_sign.c プロジェクト: mbuij/ldns-cga-tsig
/**
 * Sign data with DSA
 *
 * \param[in] to_sign The ldns_buffer containing raw data that is
 *                    to be signed
 * \param[in] key The DSA key structure to sign with
 * \return ldns_rdf for the RRSIG ldns_rr
 */
ldns_rdf *
ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key)
{
	unsigned char *sha1_hash;
	ldns_rdf *sigdata_rdf;
	ldns_buffer *b64sig;

	DSA_SIG *sig;
	uint8_t *data;
	size_t pad;

	b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
	if (!b64sig) {
		return NULL;
	}

	sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign),
				  ldns_buffer_position(to_sign), NULL);
	if (!sha1_hash) {
		ldns_buffer_free(b64sig);
		return NULL;
	}

	sig = DSA_do_sign(sha1_hash, SHA_DIGEST_LENGTH, key);
        if(!sig) {
		ldns_buffer_free(b64sig);
		return NULL;
        }

	data = LDNS_XMALLOC(uint8_t, 1 + 2 * SHA_DIGEST_LENGTH);
        if(!data) {
		ldns_buffer_free(b64sig);
                DSA_SIG_free(sig);
		return NULL;
        }

	data[0] = 1;
	pad = 20 - (size_t) BN_num_bytes(sig->r);
	if (pad > 0) {
		memset(data + 1, 0, pad);
	}
	BN_bn2bin(sig->r, (unsigned char *) (data + 1) + pad);

	pad = 20 - (size_t) BN_num_bytes(sig->s);
	if (pad > 0) {
		memset(data + 1 + SHA_DIGEST_LENGTH, 0, pad);
	}
	BN_bn2bin(sig->s, (unsigned char *) (data + 1 + SHA_DIGEST_LENGTH + pad));

	sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
								 1 + 2 * SHA_DIGEST_LENGTH,
								 data);

	ldns_buffer_free(b64sig);
	LDNS_FREE(data);
        DSA_SIG_free(sig);

	return sigdata_rdf;
}
コード例 #9
0
ファイル: net.c プロジェクト: 0xffffffRabbit/NextBSD-1
/* don't wait for an answer */
ssize_t
ldns_udp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, 
		socklen_t tolen)
{
	ssize_t bytes;

	bytes = sendto(sockfd, (void*)ldns_buffer_begin(qbin),
			ldns_buffer_position(qbin), 0, (struct sockaddr *)to, tolen);

	if (bytes == -1 || (size_t)bytes != ldns_buffer_position(qbin)) {
		return 0;
	}
	if ((size_t) bytes != ldns_buffer_position(qbin)) {
		return 0;
	}
	return bytes;
}
コード例 #10
0
ファイル: parse.c プロジェクト: alexandermerritt/dragonfly
void
ldns_bskipc(ldns_buffer *buffer, char c)
{
        while (c == (char) ldns_buffer_read_u8_at(buffer, ldns_buffer_position(buffer))) {
                if (ldns_buffer_available_at(buffer,
					buffer->_position + sizeof(char), sizeof(char))) {
                        buffer->_position += sizeof(char);
                } else {
                        return;
                }
        }
}
コード例 #11
0
ファイル: lua.c プロジェクト: benlaurie/ldns
static int
l_buf_info(lua_State *L)
{
	ldns_buffer *b = (ldns_buffer *)lua_touserdata(L, 1);
	if (!b) {
		return 0;
	}
	printf("capacity %d; position %d; limit %d\n",
			ldns_buffer_capacity(b),
			ldns_buffer_position(b),
			ldns_buffer_limit(b));
	return 0;
}
コード例 #12
0
/** analyze rdata in packet */
static void analyze_rdata(ldns_buffer*pkt, const ldns_rr_descriptor* desc, 
	uint16_t rdlen)
{
	int rdf = 0;
	int count = (int)desc->_dname_count;
	size_t len, oldpos;
	while(rdlen > 0 && count) {
		switch(desc->_wireformat[rdf]) {
		case LDNS_RDF_TYPE_DNAME:
			oldpos = ldns_buffer_position(pkt);
			analyze_dname(pkt);
			rdlen -= ldns_buffer_position(pkt)-oldpos;
			count --;
			len = 0;
			break;
		case LDNS_RDF_TYPE_STR:
			len = ldns_buffer_current(pkt)[0] + 1;
			break;
		default:
			len = get_rdf_size(desc->_wireformat[rdf]);
		}
		if(len) {
			printf(" wf[%d]", (int)len);
			ldns_buffer_skip(pkt, (ssize_t)len);
			rdlen -= len;
		}
		rdf++;
	}
	if(rdlen) {
		size_t i;
		printf(" remain[%d]\n", (int)rdlen);
		for(i=0; i<rdlen; i++)
			printf(" %2.2X", (unsigned)ldns_buffer_current(pkt)[i]);
		printf("\n");
	}
	else	printf("\n");
	ldns_buffer_skip(pkt, (ssize_t)rdlen);
}
コード例 #13
0
ファイル: net.c プロジェクト: 0xffffffRabbit/NextBSD-1
ssize_t
ldns_tcp_send_query(ldns_buffer *qbin, int sockfd, 
                    const struct sockaddr_storage *to, socklen_t tolen)
{
	uint8_t *sendbuf;
	ssize_t bytes;

	/* add length of packet */
	sendbuf = LDNS_XMALLOC(uint8_t, ldns_buffer_position(qbin) + 2);
	if(!sendbuf) return 0;
	ldns_write_uint16(sendbuf, ldns_buffer_position(qbin));
	memcpy(sendbuf + 2, ldns_buffer_begin(qbin), ldns_buffer_position(qbin));

	bytes = sendto(sockfd, (void*)sendbuf,
			ldns_buffer_position(qbin) + 2, 0, (struct sockaddr *)to, tolen);

        LDNS_FREE(sendbuf);

	if (bytes == -1 || (size_t) bytes != ldns_buffer_position(qbin) + 2 ) {
		return 0;
	}
	return bytes;
}
コード例 #14
0
ファイル: dname.c プロジェクト: ChaosJohn/freebsd
size_t
pkt_dname_len(ldns_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(ldns_buffer_remaining(pkt) < 1)
			return 0;
		labellen = ldns_buffer_read_u8(pkt);
		if(LABEL_IS_PTR(labellen)) {
			/* compression ptr */
			uint16_t ptr;
			if(ldns_buffer_remaining(pkt) < 1)
				return 0;
			ptr = PTR_OFFSET(labellen, ldns_buffer_read_u8(pkt));
			if(ptrcount++ > MAX_COMPRESS_PTRS)
				return 0; /* loop! */
			if(ldns_buffer_limit(pkt) <= ptr)
				return 0; /* out of bounds! */
			if(!endpos)
				endpos = ldns_buffer_position(pkt);
			ldns_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(ldns_buffer_remaining(pkt) < labellen)
				return 0;
			ldns_buffer_skip(pkt, (ssize_t)labellen);
		}
	}
	if(endpos)
		ldns_buffer_set_position(pkt, endpos);

	return len;
}
コード例 #15
0
/** compress any domain name to the packet, return RETVAL_* */
static int
compress_any_dname(uint8_t* dname, ldns_buffer* pkt, int labs, 
	struct regional* region, struct compress_tree_node** tree)
{
	struct compress_tree_node* p;
	struct compress_tree_node** insertpt = NULL;
	size_t pos = ldns_buffer_position(pkt);
	if((p = compress_tree_lookup(tree, dname, labs, &insertpt))) {
		if(!write_compressed_dname(pkt, dname, labs, p))
			return RETVAL_TRUNC;
	} else {
		if(!dname_buffer_write(pkt, dname))
			return RETVAL_TRUNC;
	}
	if(!compress_tree_store(dname, labs, pos, region, p, insertpt))
		return RETVAL_OUTMEM;
	return RETVAL_OK;
}
コード例 #16
0
/** store query section in wireformat buffer, return RETVAL */
static int
insert_query(struct query_info* qinfo, struct compress_tree_node** tree, 
	ldns_buffer* buffer, struct regional* region)
{
	if(ldns_buffer_remaining(buffer) < 
		qinfo->qname_len+sizeof(uint16_t)*2)
		return RETVAL_TRUNC; /* buffer too small */
	/* the query is the first name inserted into the tree */
	if(!compress_tree_store(qinfo->qname, 
		dname_count_labels(qinfo->qname), 
		ldns_buffer_position(buffer), region, NULL, tree))
		return RETVAL_OUTMEM;
	if(ldns_buffer_current(buffer) == qinfo->qname)
		ldns_buffer_skip(buffer, (ssize_t)qinfo->qname_len);
	else	ldns_buffer_write(buffer, qinfo->qname, qinfo->qname_len);
	ldns_buffer_write_u16(buffer, qinfo->qtype);
	ldns_buffer_write_u16(buffer, qinfo->qclass);
	return RETVAL_OK;
}
コード例 #17
0
int 
query_info_parse(struct query_info* m, ldns_buffer* query)
{
	uint8_t* q = ldns_buffer_begin(query);
	/* minimum size: header + \0 + qtype + qclass */
	if(ldns_buffer_limit(query) < LDNS_HEADER_SIZE + 5)
		return 0;
	if(LDNS_OPCODE_WIRE(q) != LDNS_PACKET_QUERY || 
		LDNS_QDCOUNT(q) != 1 || ldns_buffer_position(query) != 0)
		return 0;
	ldns_buffer_skip(query, LDNS_HEADER_SIZE);
	m->qname = ldns_buffer_current(query);
	if((m->qname_len = query_dname_len(query)) == 0)
		return 0; /* parse error */
	if(ldns_buffer_remaining(query) < 4)
		return 0; /* need qtype, qclass */
	m->qtype = ldns_buffer_read_u16(query);
	m->qclass = ldns_buffer_read_u16(query);
	return 1;
}
コード例 #18
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, ldns_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 = ldns_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 = ldns_buffer_position(pkt);
    ldns_buffer_set_position(pkt, (size_t)(*nm - ldns_buffer_begin(pkt)));
    *nmlen = pkt_dname_len(pkt);
    ldns_buffer_set_position(pkt, oldpos);
    if(*nmlen == 0)
        return 0;
    return 1;
}
コード例 #19
0
/** 
 * read contents of trusted-keys{ ... ; clauses and insert keys into storage.
 * @param anchors: where to store keys
 * @param buf: buffer to use
 * @param line: line number in file
 * @param in: file to read from.
 * @return 0 on error.
 */
static int
process_bind_contents(struct val_anchors* anchors, ldns_buffer* buf, 
	int* line, FILE* in)
{
	/* loop over contents, collate strings before ; */
	/* contents is (numbered): 0   1    2  3 4   5  6 7 8    */
	/*                           name. 257 3 5 base64 base64 */
	/* quoted value:           0 "111"  0  0 0   0  0 0 0    */
	/* comments value:         1 "000"  1  1  1 "0  0 0 0"  1 */
	int contnum = 0;
	int quoted = 0;
	int comments = 1;
	int rdlen;
	char* str = 0;
	ldns_buffer_clear(buf);
	while((rdlen=readkeyword_bindfile(in, buf, line, comments))) {
		if(rdlen == 1 && ldns_buffer_position(buf) == 1
			&& isspace((int)*ldns_buffer_begin(buf))) {
			/* starting whitespace is removed */
			ldns_buffer_clear(buf);
			continue;
		} else if(rdlen == 1 && ldns_buffer_current(buf)[-1] == '"') {
			/* remove " from the string */
			if(contnum == 0) {
				quoted = 1;
				comments = 0;
			}
			ldns_buffer_skip(buf, -1);
			if(contnum > 0 && quoted) {
				if(ldns_buffer_remaining(buf) < 8+1) {
					log_err("line %d, too long", *line);
					return 0;
				}
				ldns_buffer_write(buf, " DNSKEY ", 8);
				quoted = 0;
				comments = 1;
			} else if(contnum > 0)
				comments = !comments;
			continue;
		} else if(rdlen == 1 && ldns_buffer_current(buf)[-1] == ';') {

			if(contnum < 5) {
				ldns_buffer_write_u8(buf, 0);
				log_err("line %d, bad key", *line);
				return 0;
			}
			ldns_buffer_skip(buf, -1);
			ldns_buffer_write_u8(buf, 0);
			str = strdup((char*)ldns_buffer_begin(buf));
			if(!str) {
				log_err("line %d, allocation failure", *line);
				return 0;
			}
			if(!anchor_store_str(anchors, buf, str)) {
				log_err("line %d, bad key", *line);
				free(str);
				return 0;
			}
			free(str);
			ldns_buffer_clear(buf);
			contnum = 0;
			quoted = 0;
			comments = 1;
			continue;
		} else if(rdlen == 1 && ldns_buffer_current(buf)[-1] == '}') {
			if(contnum > 0) {
				ldns_buffer_write_u8(buf, 0);
				log_err("line %d, bad key before }", *line);
				return 0;
			}
			return 1;
		} else if(rdlen == 1 && 
			isspace((int)ldns_buffer_current(buf)[-1])) {
			/* leave whitespace here */
		} else {
			/* not space or whatnot, so actual content */
			contnum ++;
			if(contnum == 1 && !quoted) {
				if(ldns_buffer_remaining(buf) < 8+1) {
					log_err("line %d, too long", *line);
					return 0;
				}	
				ldns_buffer_write(buf, " DNSKEY ", 8);
			}
		}
	}

	log_err("line %d, EOF before }", *line);
	return 0;
}
コード例 #20
0
/** 
 * Read a keyword skipping bind comments; spaces, specials, restkeywords. 
 * The file is split into the following tokens:
 *	* special characters, on their own, rdlen=1, { } doublequote ;
 *	* whitespace becomes a single ' ' or tab. Newlines become spaces.
 *	* other words ('keywords')
 *	* comments are skipped if desired
 *		/ / C++ style comment to end of line
 *		# to end of line
 *		/ * C style comment * /
 * @param in: file to read from.
 * @param buf: buffer, what is read is stored after current buffer position.
 *	Space is left in the buffer to write a terminating 0.
 * @param line: line number is increased per line, for error reports.
 * @param comments: if 0, comments are not possible and become text.
 *	if 1, comments are skipped entirely.
 *	In BIND files, this is when reading quoted strings, for example
 *	" base 64 text with / / in there "
 * @return the number of character written to the buffer. 
 *	0 on end of file.
 */
static int
readkeyword_bindfile(FILE* in, ldns_buffer* buf, int* line, int comments)
{
	int c;
	int numdone = 0;
	while((c = getc(in)) != EOF ) {
		if(comments && c == '#') {	/*   # blabla   */
			skip_to_eol(in);
			(*line)++;
			continue;
		} else if(comments && c=='/' && numdone>0 && /* /_/ bla*/
			ldns_buffer_read_u8_at(buf, 
			ldns_buffer_position(buf)-1) == '/') {
			ldns_buffer_skip(buf, -1);
			numdone--;
			skip_to_eol(in);
			(*line)++;
			continue;
		} else if(comments && c=='*' && numdone>0 && /* /_* bla *_/ */
			ldns_buffer_read_u8_at(buf, 
			ldns_buffer_position(buf)-1) == '/') {
			ldns_buffer_skip(buf, -1);
			numdone--;
			/* skip to end of comment */
			while(c != EOF && (c=getc(in)) != EOF ) {
				if(c == '*') {
					if((c=getc(in)) == '/')
						break;
				}
				if(c == '\n')
					(*line)++;
			}
			continue;
		}
		/* not a comment, complete the keyword */
		if(numdone > 0) {
			/* check same type */
			if(isspace(c)) {
				ungetc(c, in);
				return numdone;
			}
			if(is_bind_special(c)) {
				ungetc(c, in);
				return numdone;
			}
		}
		if(c == '\n') {
			c = ' ';
			(*line)++;
		}
		/* space for 1 char + 0 string terminator */
		if(ldns_buffer_remaining(buf) < 2) {
			fatal_exit("trusted-keys, %d, string too long", *line);
		}
		ldns_buffer_write_u8(buf, (uint8_t)c);
		numdone++;
		if(isspace(c)) {
			/* collate whitespace into ' ' */
			while((c = getc(in)) != EOF ) {
				if(c == '\n')
					(*line)++;
				if(!isspace(c)) {
					ungetc(c, in);
					break;
				}
			}
			return numdone;
		}
		if(is_bind_special(c))
			return numdone;
	}
	return numdone;
}
コード例 #21
0
static ldns_status
ldns_tsig_mac_new(ldns_rdf **tsig_mac, uint8_t *pkt_wire, size_t pkt_wire_size,
		const char *key_data, ldns_rdf *key_name_rdf, ldns_rdf *fudge_rdf,
		ldns_rdf *algorithm_rdf, ldns_rdf *time_signed_rdf, ldns_rdf *error_rdf,
		ldns_rdf *other_data_rdf, ldns_rdf *orig_mac_rdf, int tsig_timers_only)
{
	ldns_status status;
	char *wireformat;
	int wiresize;
	unsigned char *mac_bytes = NULL;
	unsigned char *key_bytes = NULL;
	int key_size;
	const EVP_MD *digester;
	char *algorithm_name = NULL;
	unsigned int md_len = EVP_MAX_MD_SIZE;
	ldns_rdf *result = NULL;
	ldns_buffer *data_buffer = NULL;
	ldns_rdf *canonical_key_name_rdf = NULL;
	ldns_rdf *canonical_algorithm_rdf = NULL;
	
	if (key_name_rdf == NULL || algorithm_rdf == NULL) {
		return LDNS_STATUS_NULL;
	}
	canonical_key_name_rdf  = ldns_rdf_clone(key_name_rdf);
	if (canonical_key_name_rdf == NULL) {
		return LDNS_STATUS_MEM_ERR;
	}
	canonical_algorithm_rdf = ldns_rdf_clone(algorithm_rdf);
	if (canonical_algorithm_rdf == NULL) {
		ldns_rdf_deep_free(canonical_key_name_rdf);
		return LDNS_STATUS_MEM_ERR;
	}
	/*
	 * prepare the digestable information
	 */
	data_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
	if (!data_buffer) {
		status = LDNS_STATUS_MEM_ERR;
		goto clean;
	}
	/* if orig_mac is not NULL, add it too */
	if (orig_mac_rdf) {
		(void) ldns_rdf2buffer_wire(data_buffer, orig_mac_rdf);
 	}
	ldns_buffer_write(data_buffer, pkt_wire, pkt_wire_size);
	if (!tsig_timers_only) {
		ldns_dname2canonical(canonical_key_name_rdf);
		(void)ldns_rdf2buffer_wire(data_buffer, 
				canonical_key_name_rdf);
		ldns_buffer_write_u16(data_buffer, LDNS_RR_CLASS_ANY);
		ldns_buffer_write_u32(data_buffer, 0);
		ldns_dname2canonical(canonical_algorithm_rdf);
		(void)ldns_rdf2buffer_wire(data_buffer, 
				canonical_algorithm_rdf);
	}
	(void)ldns_rdf2buffer_wire(data_buffer, time_signed_rdf);
	(void)ldns_rdf2buffer_wire(data_buffer, fudge_rdf);
	if (!tsig_timers_only) {
		(void)ldns_rdf2buffer_wire(data_buffer, error_rdf);
		(void)ldns_rdf2buffer_wire(data_buffer, other_data_rdf);
	}

	wireformat = (char *) data_buffer->_data;
	wiresize = (int) ldns_buffer_position(data_buffer);

	algorithm_name = ldns_rdf2str(algorithm_rdf);
	if(!algorithm_name) {
		status = LDNS_STATUS_MEM_ERR;
		goto clean;
	}

	/* prepare the key */
	key_bytes = LDNS_XMALLOC(unsigned char,
			ldns_b64_pton_calculate_size(strlen(key_data)));
	if(!key_bytes) {
		status = LDNS_STATUS_MEM_ERR;
		goto clean;
	}
	key_size = ldns_b64_pton(key_data, key_bytes,
	ldns_b64_pton_calculate_size(strlen(key_data)));
	if (key_size < 0) {
		status = LDNS_STATUS_INVALID_B64;
		goto clean;
	}
	/* hmac it */
	/* 2 spare bytes for the length */
	mac_bytes = LDNS_XMALLOC(unsigned char, md_len+2);
	if(!mac_bytes) {
		status = LDNS_STATUS_MEM_ERR;
		goto clean;
	}
	memset(mac_bytes, 0, md_len+2);

	digester = ldns_digest_function(algorithm_name);

	if (digester) {
		(void) HMAC(digester, key_bytes, key_size, (void *)wireformat,
		            (size_t) wiresize, mac_bytes + 2, &md_len);

		ldns_write_uint16(mac_bytes, md_len);
		result = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16_DATA, md_len + 2,
				mac_bytes);
	} else {
		status = LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
		goto clean;
	}
	*tsig_mac = result;
	status = LDNS_STATUS_OK;
  clean:
	LDNS_FREE(mac_bytes);
	LDNS_FREE(key_bytes);
	LDNS_FREE(algorithm_name);
	ldns_buffer_free(data_buffer);
	ldns_rdf_deep_free(canonical_algorithm_rdf);
	ldns_rdf_deep_free(canonical_key_name_rdf);
	return status;
}
コード例 #22
0
static CborError cbor_ldns_rr_list(CborEncoder *encoder, ldns_rr_list *list, size_t count, int *should_flush) {
    CborError cbor_err = CborNoError;
    size_t n;
    ldns_buffer *dname;
    char *dname_str;

    if (!encoder) {
        return CborErrorInternalError;
    }
    if (!list) {
        return CborErrorInternalError;
    }
    if (!count) {
        return CborErrorInternalError;
    }
    if (!should_flush) {
        return CborErrorInternalError;
    }

    for (n = 0; cbor_err == CborNoError && n < count; n++) {
        CborEncoder cbor_rr;
        uint8_t *rdata_bytes;
        ldns_buffer *rdata;
        ldns_rr *rr = ldns_rr_list_rr(list, n);
        size_t rd_count;

        if (!rr) {
            return CborErrorInternalError;
        }
        rd_count = ldns_rr_rd_count(rr);

        if (!(dname = ldns_buffer_new(512))) {
            return CborErrorOutOfMemory;
        }
        if (ldns_rdf2buffer_str_dname(dname, ldns_rr_owner(rr)) != LDNS_STATUS_OK) {
            ldns_buffer_free(dname);
            return CborErrorInternalError;
        }
        ldns_buffer_write_u8(dname, 0);
        if (!(dname_str = ldns_buffer_export(dname))) {
            ldns_buffer_free(dname);
            return CborErrorOutOfMemory;
        }

        if (cbor_err == CborNoError) cbor_err = append_cbor_map(encoder, &cbor_rr, CborIndefiniteLength, should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "NAME", should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, dname_str, should_flush);
        free(dname_str);
        ldns_buffer_free(dname);
        if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "CLASS", should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor_rr, ldns_rr_get_class(rr), should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "TYPE", should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor_rr, ldns_rr_get_type(rr), should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "TTL", should_flush);
        if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor_rr, ldns_rr_ttl(rr), should_flush);

        if (rd_count == 1) {
            if (!(rdata = ldns_buffer_new(64*1024))) {
                return CborErrorOutOfMemory;
            }
            if (ldns_rdf2buffer_wire(rdata, ldns_rr_rdf(rr, 0)) != LDNS_STATUS_OK) {
                ldns_buffer_free(rdata);
                return CborErrorInternalError;
            }
            if (!(rdata_bytes = ldns_buffer_export(rdata))) {
                ldns_buffer_free(rdata);
                return CborErrorOutOfMemory;
            }

            if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "RDLENGTH", should_flush);
            if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor_rr, ldns_buffer_position(rdata), should_flush);
            if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "RDATA", should_flush);
            if (cbor_err == CborNoError) cbor_err = append_cbor_bytes(&cbor_rr, rdata_bytes, ldns_buffer_position(rdata), should_flush);
            free(rdata_bytes);
            ldns_buffer_free(rdata);
        }
        else if (rd_count > 1) {
            size_t n2;
            CborEncoder rr_set;

            if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor_rr, "rrSet", should_flush);
            if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor_rr, &rr_set, CborIndefiniteLength, should_flush);
            for (n2 = 0; n2 < rd_count; n2++) {
                if (!(rdata = ldns_buffer_new(64*1024))) {
                    return CborErrorOutOfMemory;
                }
                if (ldns_rdf2buffer_wire(rdata, ldns_rr_rdf(rr, n2)) != LDNS_STATUS_OK) {
                    ldns_buffer_free(rdata);
                    return CborErrorInternalError;
                }
                if (!(rdata_bytes = ldns_buffer_export(rdata))) {
                    ldns_buffer_free(rdata);
                    return CborErrorOutOfMemory;
                }

                if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&rr_set, "RDLENGTH", should_flush);
                if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&rr_set, ldns_buffer_position(rdata), should_flush);
                if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&rr_set, "RDATA", should_flush);
                if (cbor_err == CborNoError) cbor_err = append_cbor_bytes(&rr_set, rdata_bytes, ldns_buffer_position(rdata), should_flush);
                free(rdata_bytes);
                ldns_buffer_free(rdata);
            }
            if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor_rr, &rr_set, should_flush);
        }

        if (cbor_err == CborNoError) cbor_err = close_cbor_container(encoder, &cbor_rr, should_flush);
    }

    return cbor_err;
}
コード例 #23
0
ファイル: host2wire.c プロジェクト: LANJr4D/iEnum
ldns_status
ldns_rr2buffer_wire_canonical(ldns_buffer *buffer,
						const ldns_rr *rr,
						int section)
{
	uint16_t i;
	uint16_t rdl_pos = 0;
	bool pre_rfc3597 = false;
	switch (ldns_rr_get_type(rr)) {
	case LDNS_RR_TYPE_NS:
	case LDNS_RR_TYPE_MD:
	case LDNS_RR_TYPE_MF:
	case LDNS_RR_TYPE_CNAME:
	case LDNS_RR_TYPE_SOA:
	case LDNS_RR_TYPE_MB:
	case LDNS_RR_TYPE_MG:
	case LDNS_RR_TYPE_MR:
	case LDNS_RR_TYPE_PTR:
	case LDNS_RR_TYPE_HINFO:
	case LDNS_RR_TYPE_MINFO:
	case LDNS_RR_TYPE_MX:
	case LDNS_RR_TYPE_RP:
	case LDNS_RR_TYPE_AFSDB:
	case LDNS_RR_TYPE_RT:
	case LDNS_RR_TYPE_SIG:
	case LDNS_RR_TYPE_PX:
	case LDNS_RR_TYPE_NXT:
	case LDNS_RR_TYPE_NAPTR:
	case LDNS_RR_TYPE_KX:
	case LDNS_RR_TYPE_SRV:
	case LDNS_RR_TYPE_DNAME:
	case LDNS_RR_TYPE_A6:
		pre_rfc3597 = true;
		break;
	default:
		break;
	}
	
	if (ldns_rr_owner(rr)) {
		(void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_owner(rr));
	}
	
	if (ldns_buffer_reserve(buffer, 4)) {
		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
	}

	if (section != LDNS_SECTION_QUESTION) {
		if (ldns_buffer_reserve(buffer, 6)) {
			ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
			/* remember pos for later */
			rdl_pos = ldns_buffer_position(buffer);
			ldns_buffer_write_u16(buffer, 0);
		}	

		for (i = 0; i < ldns_rr_rd_count(rr); i++) {
			if (pre_rfc3597) {
				(void) ldns_rdf2buffer_wire_canonical(buffer,
											   ldns_rr_rdf(rr, i));
			} else {
				(void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
			}
		}
		
		if (rdl_pos != 0) {
			ldns_buffer_write_u16_at(buffer, rdl_pos,
			                         ldns_buffer_position(buffer)
		        	                   - rdl_pos - 2);
		}
	}
	return ldns_buffer_status(buffer);
}
コード例 #24
0
/** do the rdata copy */
static int
rdata_copy(ldns_buffer* pkt, struct packed_rrset_data* data, uint8_t* to, 
	struct rr_parse* rr, uint32_t* rr_ttl, uint16_t type)
{
	uint16_t pkt_len;
	const ldns_rr_descriptor* desc;

	*rr_ttl = ldns_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(*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;
	}

	ldns_buffer_set_position(pkt, (size_t)
		(rr->ttl_data - ldns_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 = ldns_buffer_read_u16(pkt);
	if(ldns_buffer_remaining(pkt) < pkt_len)
		return 0;
	desc = ldns_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 = ldns_buffer_position(pkt);
				dname_pkt_copy(pkt, to, 
					ldns_buffer_current(pkt));
				to += pkt_dname_len(pkt);
				pkt_len -= ldns_buffer_position(pkt)-oldpos;
				count--;
				len = 0;
				break;
			case LDNS_RDF_TYPE_STR:
				len = ldns_buffer_current(pkt)[0] + 1;
				break;
			default:
				len = get_rdf_size(desc->_wireformat[rdf]);
				break;
			}
			if(len) {
				memmove(to, ldns_buffer_current(pkt), len);
				to += len;
				ldns_buffer_skip(pkt, (ssize_t)len);
				log_assert(len <= pkt_len);
				pkt_len -= len;
			}
			rdf++;
		}
	}
	/* copy remaining rdata */
	if(pkt_len >  0)
		memmove(to, ldns_buffer_current(pkt), pkt_len);
	
	return 1;
}
コード例 #25
0
/** store rrset in buffer in wireformat, return RETVAL_* */
static int
packed_rrset_encode(struct ub_packed_rrset_key* key, ldns_buffer* pkt, 
	uint16_t* num_rrs, uint32_t timenow, struct regional* region,
	int do_data, int do_sig, struct compress_tree_node** tree,
	ldns_pkt_section s, uint16_t qtype, int dnssec, size_t rr_offset)
{
	size_t i, j, owner_pos;
	int r, owner_labs;
	uint16_t owner_ptr = 0;
	struct packed_rrset_data* data = (struct packed_rrset_data*)
		key->entry.data;
	
	/* does this RR type belong in the answer? */
	if(!rrset_belongs_in_reply(s, ntohs(key->rk.type), qtype, dnssec))
		return RETVAL_OK;

	owner_labs = dname_count_labels(key->rk.dname);
	owner_pos = ldns_buffer_position(pkt);

	if(do_data) {
		const ldns_rr_descriptor* c = type_rdata_compressable(key);
		for(i=0; i<data->count; i++) {
			/* rrset roundrobin */
			j = (i + rr_offset) % data->count;
			if((r=compress_owner(key, pkt, region, tree, 
				owner_pos, &owner_ptr, owner_labs))
				!= RETVAL_OK)
				return r;
			ldns_buffer_write(pkt, &key->rk.type, 2);
			ldns_buffer_write(pkt, &key->rk.rrset_class, 2);
			if(data->rr_ttl[j] < timenow)
				ldns_buffer_write_u32(pkt, 0);
			else 	ldns_buffer_write_u32(pkt, 
					data->rr_ttl[j]-timenow);
			if(c) {
				if((r=compress_rdata(pkt, data->rr_data[j],
					data->rr_len[j], region, tree, c))
					!= RETVAL_OK)
					return r;
			} else {
				if(ldns_buffer_remaining(pkt) < data->rr_len[j])
					return RETVAL_TRUNC;
				ldns_buffer_write(pkt, data->rr_data[j],
					data->rr_len[j]);
			}
		}
	}
	/* insert rrsigs */
	if(do_sig && dnssec) {
		size_t total = data->count+data->rrsig_count;
		for(i=data->count; i<total; i++) {
			if(owner_ptr && owner_labs != 1) {
				if(ldns_buffer_remaining(pkt) <
					2+4+4+data->rr_len[i]) 
					return RETVAL_TRUNC;
				ldns_buffer_write(pkt, &owner_ptr, 2);
			} else {
				if((r=compress_any_dname(key->rk.dname, 
					pkt, owner_labs, region, tree))
					!= RETVAL_OK)
					return r;
				if(ldns_buffer_remaining(pkt) < 
					4+4+data->rr_len[i])
					return RETVAL_TRUNC;
			}
			ldns_buffer_write_u16(pkt, LDNS_RR_TYPE_RRSIG);
			ldns_buffer_write(pkt, &key->rk.rrset_class, 2);
			if(data->rr_ttl[i] < timenow)
				ldns_buffer_write_u32(pkt, 0);
			else 	ldns_buffer_write_u32(pkt, 
					data->rr_ttl[i]-timenow);
			/* rrsig rdata cannot be compressed, perform 100+ byte
			 * memcopy. */
			ldns_buffer_write(pkt, data->rr_data[i],
				data->rr_len[i]);
		}
	}
	/* change rrnum only after we are sure it fits */
	if(do_data)
		*num_rrs += data->count;
	if(do_sig && dnssec)
		*num_rrs += data->rrsig_count;

	return RETVAL_OK;
}
コード例 #26
0
ファイル: ldns-testpkts.c プロジェクト: RS-liuyang/rsdns
/** convert hex buffer to binary buffer */
static ldns_buffer *
data_buffer2wire(ldns_buffer *data_buffer)
{
	ldns_buffer *wire_buffer = NULL;
	int c;
	
	/* stat hack
	 * 0 = normal
	 * 1 = comment (skip to end of line)
	 * 2 = unprintable character found, read binary data directly
	 */
	size_t data_buf_pos = 0;
	int state = 0;
	uint8_t *hexbuf;
	int hexbufpos = 0;
	size_t wirelen;
	uint8_t *data_wire = (uint8_t *) ldns_buffer_export(data_buffer);
	uint8_t *wire = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN);
	
	hexbuf = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN);
	for (data_buf_pos = 0; data_buf_pos < ldns_buffer_position(data_buffer); data_buf_pos++) {
		c = (int) data_wire[data_buf_pos];
		
		if (state < 2 && !isascii(c)) {
			/*verbose("non ascii character found in file: (%d) switching to raw mode\n", c);*/
			state = 2;
		}
		switch (state) {
			case 0:
				if (	(c >= '0' && c <= '9') ||
					(c >= 'a' && c <= 'f') ||
					(c >= 'A' && c <= 'F') )
				{
					hexbuf[hexbufpos] = (uint8_t) c;
					hexbufpos++;
				} else if (c == ';') {
					state = 1;
				} else if (c == ' ' || c == '\t' || c == '\n') {
					/* skip whitespace */
				} 
				break;
			case 1:
				if (c == '\n' || c == EOF) {
					state = 0;
				}
				break;
			case 2:
				hexbuf[hexbufpos] = (uint8_t) c;
				hexbufpos++;
				break;
			default:
				error("unknown state while reading");
				LDNS_FREE(hexbuf);
				return 0;
				break;
		}
	}

	if (hexbufpos >= LDNS_MAX_PACKETLEN) {
		/*verbose("packet size reached\n");*/
	}
	
	/* lenient mode: length must be multiple of 2 */
	if (hexbufpos % 2 != 0) {
		hexbuf[hexbufpos] = (uint8_t) '0';
		hexbufpos++;
	}

	if (state < 2) {
		wirelen = hexstr2bin((char *) hexbuf, hexbufpos, wire, 0, LDNS_MAX_PACKETLEN);
		wire_buffer = ldns_buffer_new(wirelen);
		ldns_buffer_new_frm_data(wire_buffer, wire, wirelen);
	} else {
		error("Incomplete hex data, not at byte boundary\n");
	}
	LDNS_FREE(wire);
	LDNS_FREE(hexbuf);
	return wire_buffer;
}