Ejemplo n.º 1
0
uint8_t *
ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout)
{
	uint8_t *wire;
	uint16_t wire_size;
	ssize_t bytes = 0, rc = 0;

	wire = LDNS_XMALLOC(uint8_t, 2);
	if (!wire) {
		*size = 0;
		return NULL;
	}
	
	while (bytes < 2) {
		if(!ldns_sock_wait(sockfd, timeout, 0)) {
			*size = 0;
			LDNS_FREE(wire);
			return NULL;
		}
		rc = recv(sockfd, (void*) (wire + bytes), 
				(size_t) (2 - bytes), 0);
		if (rc == -1 || rc == 0) {
			*size = 0;
			LDNS_FREE(wire);
			return NULL;
		}
                bytes += rc;
	}

	wire_size = ldns_read_uint16(wire);
	
	LDNS_FREE(wire);
	wire = LDNS_XMALLOC(uint8_t, wire_size);
	if (!wire) {
		*size = 0;
		return NULL;
	}
	bytes = 0;

	while (bytes < (ssize_t) wire_size) {
		if(!ldns_sock_wait(sockfd, timeout, 0)) {
			*size = 0;
			LDNS_FREE(wire);
			return NULL;
		}
		rc = recv(sockfd, (void*) (wire + bytes), 
				(size_t) (wire_size - bytes), 0);
		if (rc == -1 || rc == 0) {
			LDNS_FREE(wire);
			*size = 0;
			return NULL;
		}
                bytes += rc;
	}
	
	*size = (size_t) bytes;
	return wire;
}
Ejemplo n.º 2
0
ldns_status
ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size)
{
	ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
	uint8_t *result = NULL;
	ldns_status status;
	*result_size = 0;
	*dest = NULL;
	
	status = ldns_pkt2buffer_wire(buffer, packet);
	if (status == LDNS_STATUS_OK) {
		*result_size =  ldns_buffer_position(buffer);
		result = (uint8_t *) ldns_buffer_export(buffer);
	} else {
		return status;
	}
	
	if (result) {
		*dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer));
		memcpy(*dest, result, ldns_buffer_position(buffer));
	}
	
	ldns_buffer_free(buffer);
	return status;
}
Ejemplo n.º 3
0
ldns_status
ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size)
{
	ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
	uint8_t *result = NULL;
	ldns_status status;
	*result_size = 0;
	*dest = NULL;
	if(!buffer) return LDNS_STATUS_MEM_ERR;
	
	status = ldns_rr2buffer_wire(buffer, rr, section);
	if (status == LDNS_STATUS_OK) {
		*result_size =  ldns_buffer_position(buffer);
		result = (uint8_t *) ldns_buffer_export(buffer);
	} else {
		ldns_buffer_free(buffer);
		return status;
	}
	
	if (result) {
		*dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer));
		if(!*dest) {
			ldns_buffer_free(buffer);
			return LDNS_STATUS_MEM_ERR;
		}
		memcpy(*dest, result, ldns_buffer_position(buffer));
	}
	
	ldns_buffer_free(buffer);
	return status;
}
Ejemplo n.º 4
0
uint8_t *
ldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *from,
		socklen_t *fromlen)
{
	uint8_t *wire, *wireout;
	ssize_t wire_size;

	wire = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN);
	if (!wire) {
		*size = 0;
		return NULL;
	}

	wire_size = recvfrom(sockfd, (void*)wire, LDNS_MAX_PACKETLEN, 0, 
			(struct sockaddr *)from, fromlen);

	/* recvfrom can also return 0 */
	if (wire_size == -1 || wire_size == 0) {
		*size = 0;
		LDNS_FREE(wire);
		return NULL;
	}

	*size = (size_t)wire_size;
	wireout = LDNS_XREALLOC(wire, uint8_t, (size_t)wire_size);
	if(!wireout) LDNS_FREE(wire);

	return wireout;
}
Ejemplo n.º 5
0
/**
 * 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;
}
Ejemplo n.º 6
0
void
ldns_buffer_new_frm_data(ldns_buffer *buffer, void *data, size_t size)
{
	assert(data != NULL);

	buffer->_position = 0; 
	buffer->_limit = buffer->_capacity = size;
	buffer->_fixed = 0;
	buffer->_data = LDNS_XMALLOC(uint8_t, size);
	if(!buffer->_data) {
		buffer->_status = LDNS_STATUS_MEM_ERR;
		return;
	}
	memcpy(buffer->_data, data, size);
	buffer->_status = LDNS_STATUS_OK;
	
	ldns_buffer_invariant(buffer);
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
ldns_buffer *
ldns_buffer_new(size_t capacity)
{
	ldns_buffer *buffer = LDNS_MALLOC(ldns_buffer);

	if (!buffer) {
		return NULL;
	}
	
	buffer->_data = (uint8_t *) LDNS_XMALLOC(uint8_t, capacity);
	if (!buffer->_data) {
		LDNS_FREE(buffer);
		return NULL;
	}
	
	buffer->_position = 0;
	buffer->_limit = buffer->_capacity = capacity;
	buffer->_fixed = 0;
	buffer->_status = LDNS_STATUS_OK;
	
	ldns_buffer_invariant(buffer);
	
	return buffer;
}
Ejemplo n.º 9
0
/*
 *  Makes an exact copy of the wire, but with the tsig rr removed
 */
static uint8_t *
ldns_tsig_prepare_pkt_wire(uint8_t *wire, size_t wire_len, size_t *result_len)
{
	uint8_t *wire2 = NULL;
	uint16_t qd_count;
	uint16_t an_count;
	uint16_t ns_count;
	uint16_t ar_count;
	ldns_rr *rr;

	size_t pos;
	uint16_t i;

	ldns_status status;

	if(wire_len < LDNS_HEADER_SIZE) {
		return NULL;
	}
	/* fake parse the wire */
	qd_count = LDNS_QDCOUNT(wire);
	an_count = LDNS_ANCOUNT(wire);
	ns_count = LDNS_NSCOUNT(wire);
	ar_count = LDNS_ARCOUNT(wire);

	if (ar_count > 0) {
		ar_count--;
	} else {
		return NULL;
	}

	pos = LDNS_HEADER_SIZE;

	for (i = 0; i < qd_count; i++) {
		status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_QUESTION);
		if (status != LDNS_STATUS_OK) {
			return NULL;
		}
		ldns_rr_free(rr);
	}

	for (i = 0; i < an_count; i++) {
		status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_ANSWER);
		if (status != LDNS_STATUS_OK) {
			return NULL;
		}
		ldns_rr_free(rr);
	}

	for (i = 0; i < ns_count; i++) {
		status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_AUTHORITY);
		if (status != LDNS_STATUS_OK) {
			return NULL;
		}
		ldns_rr_free(rr);
	}

	for (i = 0; i < ar_count; i++) {
		status = ldns_wire2rr(&rr, wire, wire_len, &pos,
				LDNS_SECTION_ADDITIONAL);
		if (status != LDNS_STATUS_OK) {
			return NULL;
		}
		ldns_rr_free(rr);
	}

	*result_len = pos;
	wire2 = LDNS_XMALLOC(uint8_t, *result_len);
	if(!wire2) {
		return NULL;
	}
	memcpy(wire2, wire, *result_len);

	ldns_write_uint16(wire2 + LDNS_ARCOUNT_OFF, ar_count);

	return wire2;
}
Ejemplo n.º 10
0
ldns_status
ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_data,
	uint16_t fudge, const char *algorithm_name, ldns_rdf *query_mac, int tsig_timers_only)
{
	ldns_rr *tsig_rr;
	ldns_rdf *key_name_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, key_name);
	ldns_rdf *fudge_rdf = NULL;
	ldns_rdf *orig_id_rdf = NULL;
	ldns_rdf *algorithm_rdf;
	ldns_rdf *error_rdf = NULL;
	ldns_rdf *mac_rdf = NULL;
	ldns_rdf *other_data_rdf = NULL;

	ldns_status status = LDNS_STATUS_OK;

	uint8_t *pkt_wire = NULL;
	size_t pkt_wire_len;

	struct timeval tv_time_signed;
	uint8_t *time_signed = NULL;
	ldns_rdf *time_signed_rdf = NULL;

	algorithm_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, algorithm_name);
	if(!key_name_rdf || !algorithm_rdf) {
		status = LDNS_STATUS_MEM_ERR;
		goto clean;
	}

	/* eww don't have create tsigtime rdf yet :( */
	/* bleh :p */
	if (gettimeofday(&tv_time_signed, NULL) == 0) {
		time_signed = LDNS_XMALLOC(uint8_t, 6);
		if(!time_signed) {
			status = LDNS_STATUS_MEM_ERR;
			goto clean;
		}
		ldns_write_uint64_as_uint48(time_signed,
				(uint64_t)tv_time_signed.tv_sec);
	} else {
		status = LDNS_STATUS_INTERNAL_ERR;
		goto clean;
	}

	time_signed_rdf = ldns_rdf_new(LDNS_RDF_TYPE_TSIGTIME, 6, time_signed);
	if(!time_signed_rdf) {
		LDNS_FREE(time_signed);
		status = LDNS_STATUS_MEM_ERR;
		goto clean;
	}

	fudge_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, fudge);

	orig_id_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, ldns_pkt_id(pkt));

	error_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 0);

	other_data_rdf = ldns_native2rdf_int16_data(0, NULL);

	if(!fudge_rdf || !orig_id_rdf || !error_rdf || !other_data_rdf) {
		status = LDNS_STATUS_MEM_ERR;
		goto clean;
	}

	if (ldns_pkt2wire(&pkt_wire, pkt, &pkt_wire_len) != LDNS_STATUS_OK) {
		status = LDNS_STATUS_ERR;
		goto clean;
	}

	status = ldns_tsig_mac_new(&mac_rdf, pkt_wire, pkt_wire_len,
			key_data, key_name_rdf, fudge_rdf, algorithm_rdf,
			time_signed_rdf, error_rdf, other_data_rdf, query_mac, tsig_timers_only);

	if (!mac_rdf) {
		goto clean;
	}

	LDNS_FREE(pkt_wire);

	/* Create the TSIG RR */
	tsig_rr = ldns_rr_new();
	if(!tsig_rr) {
		status = LDNS_STATUS_MEM_ERR;
		goto clean;
	}
	ldns_rr_set_owner(tsig_rr, key_name_rdf);
	ldns_rr_set_class(tsig_rr, LDNS_RR_CLASS_ANY);
	ldns_rr_set_type(tsig_rr, LDNS_RR_TYPE_TSIG);
	ldns_rr_set_ttl(tsig_rr, 0);

	ldns_rr_push_rdf(tsig_rr, algorithm_rdf);
	ldns_rr_push_rdf(tsig_rr, time_signed_rdf);
	ldns_rr_push_rdf(tsig_rr, fudge_rdf);
	ldns_rr_push_rdf(tsig_rr, mac_rdf);
	ldns_rr_push_rdf(tsig_rr, orig_id_rdf);
	ldns_rr_push_rdf(tsig_rr, error_rdf);
	ldns_rr_push_rdf(tsig_rr, other_data_rdf);

	ldns_pkt_set_tsig(pkt, tsig_rr);

	return status;

  clean:
	LDNS_FREE(pkt_wire);
	ldns_rdf_free(key_name_rdf);
	ldns_rdf_free(algorithm_rdf);
	ldns_rdf_free(time_signed_rdf);
	ldns_rdf_free(fudge_rdf);
	ldns_rdf_free(orig_id_rdf);
	ldns_rdf_free(error_rdf);
	ldns_rdf_free(other_data_rdf);
	return status;
}
Ejemplo n.º 11
0
int
main(int argc, char *argv[])
{
	ldns_rdf *dname, *hashed_dname;
	uint8_t nsec3_algorithm = 1;
	size_t nsec3_iterations_cmd = 1;
	uint16_t nsec3_iterations = 1;
	uint8_t nsec3_salt_length = 0;
	uint8_t *nsec3_salt = NULL;
	
	char *prog = strdup(argv[0]);

	int c;
	while ((c = getopt(argc, argv, "a:s:t:")) != -1) {
		switch (c) {
		case 'a':
			nsec3_algorithm = (uint8_t) atoi(optarg);
			break;
		case 's':
			if (strlen(optarg) % 2 != 0) {
				fprintf(stderr, "Salt value is not valid hex data, not a multiple of 2 characters\n");
				exit(EXIT_FAILURE);
			}
			if (strlen(optarg) > 512) {
				fprintf(stderr, "Salt too long\n");
				exit(EXIT_FAILURE);
			}
			nsec3_salt_length = (uint8_t) (strlen(optarg) / 2);
			nsec3_salt = LDNS_XMALLOC(uint8_t, nsec3_salt_length);
			for (c = 0; c < (int) strlen(optarg); c += 2) {
				if (isxdigit((int) optarg[c]) && isxdigit((int) optarg[c+1])) {
					nsec3_salt[c/2] = (uint8_t) ldns_hexdigit_to_int(optarg[c]) * 16 +
						ldns_hexdigit_to_int(optarg[c+1]);
				} else {
					fprintf(stderr, "Salt value is not valid hex data.\n");
					exit(EXIT_FAILURE);
				}
			}

			break;
		case 't':
			nsec3_iterations_cmd = (size_t) atol(optarg);
			if (nsec3_iterations_cmd > LDNS_NSEC3_MAX_ITERATIONS) {
				fprintf(stderr, "Iterations count can not exceed %u, quitting\n", LDNS_NSEC3_MAX_ITERATIONS);
				exit(EXIT_FAILURE);
			}
			nsec3_iterations = (uint16_t) nsec3_iterations_cmd;
			break;
		default:
			usage(stderr, prog);
			exit(EXIT_SUCCESS);
		}
	}
	
	argc -= optind;
	argv += optind;

	if (argc < 1) {
		printf("Error: not enough arguments\n");
		usage(stdout, prog);
		exit(EXIT_FAILURE);
	} else {
		dname = ldns_dname_new_frm_str(argv[0]);
		if (!dname) {
			fprintf(stderr,
			        "Error: unable to parse domain name\n");
			return EXIT_FAILURE;
		}
		hashed_dname = ldns_nsec3_hash_name(dname,
		                                    nsec3_algorithm,
		                                    nsec3_iterations,
		                                    nsec3_salt_length,
		                                    nsec3_salt);
		if (!hashed_dname) {
			fprintf(stderr,
			        "Error creating NSEC3 hash\n");
			return EXIT_FAILURE;
		}
		ldns_rdf_print(stdout, hashed_dname);
		printf("\n");
		ldns_rdf_deep_free(dname);
		ldns_rdf_deep_free(hashed_dname);
	}

	if (nsec3_salt) {
		free(nsec3_salt);
	}

	free(prog);
	
	return EXIT_SUCCESS;
}
Ejemplo n.º 12
0
/*
 * Parses data buffer to a query, finds the correct answer 
 * and calls the given function for every packet to send.
 */
void
handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries, int* count,
	enum transport_type transport, void (*sendfunc)(uint8_t*, size_t, void*),
	void* userdata, FILE* verbose_out)
{
	ldns_status status;
	ldns_pkt *query_pkt = NULL;
	ldns_pkt *answer_pkt = NULL;
	struct reply_packet *p;
	ldns_rr *query_rr = NULL;
	uint8_t *outbuf = NULL;
	size_t answer_size = 0;
	struct entry* entry = NULL;
	ldns_rdf *stop_command = ldns_dname_new_frm_str("server.stop.");

	status = ldns_wire2pkt(&query_pkt, inbuf, (size_t)inlen);
	if (status != LDNS_STATUS_OK) {
		verbose(1, "Got bad packet: %s\n", ldns_get_errorstr_by_id(status));
		ldns_rdf_free(stop_command);
		return;
	}
	
	query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0);
	verbose(1, "query %d: id %d: %s %d bytes: ", ++(*count), (int)ldns_pkt_id(query_pkt), 
		(transport==transport_tcp)?"TCP":"UDP", (int)inlen);
	if(verbose_out) ldns_rr_print(verbose_out, query_rr);
	if(verbose_out) ldns_pkt_print(verbose_out, query_pkt);

	if (ldns_rr_get_type(query_rr) == LDNS_RR_TYPE_TXT &&
	    ldns_rr_get_class(query_rr) == LDNS_RR_CLASS_CH &&
	    ldns_dname_compare(ldns_rr_owner(query_rr), stop_command) == 0) {
		exit(0);
        }
	
	/* fill up answer packet */
	entry = find_match(entries, query_pkt, transport);
	if(!entry || !entry->reply_list) {
		verbose(1, "no answer packet for this query, no reply.\n");
		ldns_pkt_free(query_pkt);
		ldns_rdf_free(stop_command);
		return;
	}
	for(p = entry->reply_list; p; p = p->next)
	{
		verbose(3, "Answer pkt:\n");
		if (p->reply_from_hex) {
			/* try to parse the hex packet, if it can be
			 * parsed, we can use adjust rules. if not,
			 * send packet literally */
			status = ldns_buffer2pkt_wire(&answer_pkt, p->reply_from_hex);
			if (status == LDNS_STATUS_OK) {
				adjust_packet(entry, answer_pkt, query_pkt);
				if(verbose_out) ldns_pkt_print(verbose_out, answer_pkt);
				status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size);
				verbose(2, "Answer packet size: %u bytes.\n", (unsigned int)answer_size);
				if (status != LDNS_STATUS_OK) {
					verbose(1, "Error creating answer: %s\n", ldns_get_errorstr_by_id(status));
					ldns_pkt_free(query_pkt);
					ldns_rdf_free(stop_command);
					return;
				}
				ldns_pkt_free(answer_pkt);
				answer_pkt = NULL;
			} else {
				verbose(3, "Could not parse hex data (%s), sending hex data directly.\n", ldns_get_errorstr_by_id(status));
				/* still try to adjust ID */
				answer_size = ldns_buffer_capacity(p->reply_from_hex);
				outbuf = LDNS_XMALLOC(uint8_t, answer_size);
				memcpy(outbuf, ldns_buffer_export(p->reply_from_hex), answer_size);
				if(entry->copy_id) {
					ldns_write_uint16(outbuf, 
						ldns_pkt_id(query_pkt));
				}
			}
		} else {
			answer_pkt = ldns_pkt_clone(p->reply);
			adjust_packet(entry, answer_pkt, query_pkt);
			if(verbose_out) ldns_pkt_print(verbose_out, answer_pkt);
			status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size);
			verbose(1, "Answer packet size: %u bytes.\n", (unsigned int)answer_size);
			if (status != LDNS_STATUS_OK) {
				verbose(1, "Error creating answer: %s\n", ldns_get_errorstr_by_id(status));
				ldns_pkt_free(query_pkt);
				ldns_rdf_free(stop_command);
				return;
			}
			ldns_pkt_free(answer_pkt);
			answer_pkt = NULL;
		}
		if(p->packet_sleep) {
			verbose(3, "sleeping for next packet %d secs\n", 
				p->packet_sleep);
#ifdef HAVE_SLEEP
			sleep(p->packet_sleep);
#else
			Sleep(p->packet_sleep * 1000);
#endif
			verbose(3, "wakeup for next packet "
				"(slept %d secs)\n", p->packet_sleep);
		}
		sendfunc(outbuf, answer_size, userdata);
		LDNS_FREE(outbuf);
		outbuf = NULL;
		answer_size = 0;
	}
	ldns_pkt_free(query_pkt);
	ldns_rdf_free(stop_command);
}
Ejemplo n.º 13
0
/** 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;
}