xref: /freebsd/contrib/ldns/host2wire.c (revision 2787e39aaaaffd1fb07657ffaa2e3561858b3c73)
17b5038d7SDag-Erling Smørgrav /*
27b5038d7SDag-Erling Smørgrav  * host2wire.c
37b5038d7SDag-Erling Smørgrav  *
47b5038d7SDag-Erling Smørgrav  * conversion routines from the host to the wire format.
57b5038d7SDag-Erling Smørgrav  * This will usually just a re-ordering of the
67b5038d7SDag-Erling Smørgrav  * data (as we store it in network format)
77b5038d7SDag-Erling Smørgrav  *
87b5038d7SDag-Erling Smørgrav  * a Net::DNS like library for C
97b5038d7SDag-Erling Smørgrav  *
107b5038d7SDag-Erling Smørgrav  * (c) NLnet Labs, 2004-2006
117b5038d7SDag-Erling Smørgrav  *
127b5038d7SDag-Erling Smørgrav  * See the file LICENSE for the license
137b5038d7SDag-Erling Smørgrav  */
147b5038d7SDag-Erling Smørgrav 
157b5038d7SDag-Erling Smørgrav #include <ldns/config.h>
167b5038d7SDag-Erling Smørgrav 
177b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h>
187b5038d7SDag-Erling Smørgrav 
197b5038d7SDag-Erling Smørgrav /* TODO Jelte
207b5038d7SDag-Erling Smørgrav   add a pointer to a 'possiblecompression' structure
217b5038d7SDag-Erling Smørgrav   to all the needed functions?
227b5038d7SDag-Erling Smørgrav   something like an array of name, pointer values?
237b5038d7SDag-Erling Smørgrav   every dname part could be added to it
247b5038d7SDag-Erling Smørgrav */
257b5038d7SDag-Erling Smørgrav 
267b5038d7SDag-Erling Smørgrav ldns_status
277b5038d7SDag-Erling Smørgrav ldns_dname2buffer_wire(ldns_buffer *buffer, const ldns_rdf *name)
287b5038d7SDag-Erling Smørgrav {
297b5038d7SDag-Erling Smørgrav 	if (ldns_buffer_reserve(buffer, ldns_rdf_size(name))) {
307b5038d7SDag-Erling Smørgrav 		ldns_buffer_write(buffer, ldns_rdf_data(name), ldns_rdf_size(name));
317b5038d7SDag-Erling Smørgrav 	}
327b5038d7SDag-Erling Smørgrav 	return ldns_buffer_status(buffer);
337b5038d7SDag-Erling Smørgrav }
347b5038d7SDag-Erling Smørgrav 
357b5038d7SDag-Erling Smørgrav ldns_status
367b5038d7SDag-Erling Smørgrav ldns_rdf2buffer_wire(ldns_buffer *buffer, const ldns_rdf *rdf)
377b5038d7SDag-Erling Smørgrav {
387b5038d7SDag-Erling Smørgrav 	if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
397b5038d7SDag-Erling Smørgrav 		ldns_buffer_write(buffer, ldns_rdf_data(rdf), ldns_rdf_size(rdf));
407b5038d7SDag-Erling Smørgrav 	}
417b5038d7SDag-Erling Smørgrav 	return ldns_buffer_status(buffer);
427b5038d7SDag-Erling Smørgrav }
437b5038d7SDag-Erling Smørgrav 
447b5038d7SDag-Erling Smørgrav ldns_status
457b5038d7SDag-Erling Smørgrav ldns_rdf2buffer_wire_canonical(ldns_buffer *buffer, const ldns_rdf *rdf)
467b5038d7SDag-Erling Smørgrav {
477b5038d7SDag-Erling Smørgrav 	size_t i;
487b5038d7SDag-Erling Smørgrav 	uint8_t *rdf_data;
497b5038d7SDag-Erling Smørgrav 
507b5038d7SDag-Erling Smørgrav 	if (ldns_rdf_get_type(rdf) == LDNS_RDF_TYPE_DNAME) {
517b5038d7SDag-Erling Smørgrav 		if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
527b5038d7SDag-Erling Smørgrav 			rdf_data = ldns_rdf_data(rdf);
537b5038d7SDag-Erling Smørgrav 			for (i = 0; i < ldns_rdf_size(rdf); i++) {
547b5038d7SDag-Erling Smørgrav 				ldns_buffer_write_u8(buffer,
557b5038d7SDag-Erling Smørgrav 				    (uint8_t) LDNS_DNAME_NORMALIZE((int)rdf_data[i]));
567b5038d7SDag-Erling Smørgrav 			}
577b5038d7SDag-Erling Smørgrav 		}
587b5038d7SDag-Erling Smørgrav 	} else {
597b5038d7SDag-Erling Smørgrav 		/* direct copy for all other types */
607b5038d7SDag-Erling Smørgrav 		if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
617b5038d7SDag-Erling Smørgrav 			ldns_buffer_write(buffer,
627b5038d7SDag-Erling Smørgrav 						   ldns_rdf_data(rdf),
637b5038d7SDag-Erling Smørgrav 						   ldns_rdf_size(rdf));
647b5038d7SDag-Erling Smørgrav 		}
657b5038d7SDag-Erling Smørgrav 	}
667b5038d7SDag-Erling Smørgrav 	return ldns_buffer_status(buffer);
677b5038d7SDag-Erling Smørgrav }
687b5038d7SDag-Erling Smørgrav 
697b5038d7SDag-Erling Smørgrav /* convert a rr list to wireformat */
707b5038d7SDag-Erling Smørgrav ldns_status
717b5038d7SDag-Erling Smørgrav ldns_rr_list2buffer_wire(ldns_buffer *buffer,const ldns_rr_list *rr_list)
727b5038d7SDag-Erling Smørgrav {
737b5038d7SDag-Erling Smørgrav 	uint16_t rr_count;
747b5038d7SDag-Erling Smørgrav 	uint16_t i;
757b5038d7SDag-Erling Smørgrav 
767b5038d7SDag-Erling Smørgrav 	rr_count = ldns_rr_list_rr_count(rr_list);
777b5038d7SDag-Erling Smørgrav 	for(i = 0; i < rr_count; i++) {
787b5038d7SDag-Erling Smørgrav 		(void)ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i),
797b5038d7SDag-Erling Smørgrav 					  LDNS_SECTION_ANY);
807b5038d7SDag-Erling Smørgrav 	}
817b5038d7SDag-Erling Smørgrav 	return ldns_buffer_status(buffer);
827b5038d7SDag-Erling Smørgrav }
837b5038d7SDag-Erling Smørgrav 
847b5038d7SDag-Erling Smørgrav ldns_status
857b5038d7SDag-Erling Smørgrav ldns_rr2buffer_wire_canonical(ldns_buffer *buffer,
867b5038d7SDag-Erling Smørgrav 						const ldns_rr *rr,
877b5038d7SDag-Erling Smørgrav 						int section)
887b5038d7SDag-Erling Smørgrav {
897b5038d7SDag-Erling Smørgrav 	uint16_t i;
907b5038d7SDag-Erling Smørgrav 	uint16_t rdl_pos = 0;
917b5038d7SDag-Erling Smørgrav 	bool pre_rfc3597 = false;
927b5038d7SDag-Erling Smørgrav 	switch (ldns_rr_get_type(rr)) {
937b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_NS:
947b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_MD:
957b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_MF:
967b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_CNAME:
977b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_SOA:
987b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_MB:
997b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_MG:
1007b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_MR:
1017b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_PTR:
1027b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_HINFO:
1037b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_MINFO:
1047b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_MX:
1057b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_RP:
1067b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_AFSDB:
1077b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_RT:
1087b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_SIG:
1097b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_PX:
1107b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_NXT:
1117b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_NAPTR:
1127b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_KX:
1137b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_SRV:
1147b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_DNAME:
1157b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_A6:
1167b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_RRSIG:
1177b5038d7SDag-Erling Smørgrav 		pre_rfc3597 = true;
1187b5038d7SDag-Erling Smørgrav 		break;
1197b5038d7SDag-Erling Smørgrav 	default:
1207b5038d7SDag-Erling Smørgrav 		break;
1217b5038d7SDag-Erling Smørgrav 	}
1227b5038d7SDag-Erling Smørgrav 
1237b5038d7SDag-Erling Smørgrav 	if (ldns_rr_owner(rr)) {
1247b5038d7SDag-Erling Smørgrav 		(void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_owner(rr));
1257b5038d7SDag-Erling Smørgrav 	}
1267b5038d7SDag-Erling Smørgrav 
1277b5038d7SDag-Erling Smørgrav 	if (ldns_buffer_reserve(buffer, 4)) {
1287b5038d7SDag-Erling Smørgrav 		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
1297b5038d7SDag-Erling Smørgrav 		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
1307b5038d7SDag-Erling Smørgrav 	}
1317b5038d7SDag-Erling Smørgrav 
1327b5038d7SDag-Erling Smørgrav 	if (section != LDNS_SECTION_QUESTION) {
1337b5038d7SDag-Erling Smørgrav 		if (ldns_buffer_reserve(buffer, 6)) {
1347b5038d7SDag-Erling Smørgrav 			ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
1357b5038d7SDag-Erling Smørgrav 			/* remember pos for later */
1367b5038d7SDag-Erling Smørgrav 			rdl_pos = ldns_buffer_position(buffer);
1377b5038d7SDag-Erling Smørgrav 			ldns_buffer_write_u16(buffer, 0);
1387b5038d7SDag-Erling Smørgrav 		}
1397b5038d7SDag-Erling Smørgrav 
1407b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_rd_count(rr); i++) {
1417b5038d7SDag-Erling Smørgrav 			if (pre_rfc3597) {
1427b5038d7SDag-Erling Smørgrav 				(void) ldns_rdf2buffer_wire_canonical(
1437b5038d7SDag-Erling Smørgrav 						buffer, ldns_rr_rdf(rr, i));
1447b5038d7SDag-Erling Smørgrav 			} else {
1457b5038d7SDag-Erling Smørgrav 				(void) ldns_rdf2buffer_wire(
1467b5038d7SDag-Erling Smørgrav 						buffer, ldns_rr_rdf(rr, i));
1477b5038d7SDag-Erling Smørgrav 			}
1487b5038d7SDag-Erling Smørgrav 		}
1497b5038d7SDag-Erling Smørgrav 
1507b5038d7SDag-Erling Smørgrav 		if (rdl_pos != 0) {
1517b5038d7SDag-Erling Smørgrav 			ldns_buffer_write_u16_at(buffer, rdl_pos,
1527b5038d7SDag-Erling Smørgrav 			                         ldns_buffer_position(buffer)
1537b5038d7SDag-Erling Smørgrav 		        	                   - rdl_pos - 2);
1547b5038d7SDag-Erling Smørgrav 		}
1557b5038d7SDag-Erling Smørgrav 	}
1567b5038d7SDag-Erling Smørgrav 	return ldns_buffer_status(buffer);
1577b5038d7SDag-Erling Smørgrav }
1587b5038d7SDag-Erling Smørgrav 
1597b5038d7SDag-Erling Smørgrav ldns_status
1607b5038d7SDag-Erling Smørgrav ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
1617b5038d7SDag-Erling Smørgrav {
1627b5038d7SDag-Erling Smørgrav 	uint16_t i;
1637b5038d7SDag-Erling Smørgrav 	uint16_t rdl_pos = 0;
1647b5038d7SDag-Erling Smørgrav 
1657b5038d7SDag-Erling Smørgrav 	if (ldns_rr_owner(rr)) {
1667b5038d7SDag-Erling Smørgrav 		(void) ldns_dname2buffer_wire(buffer, ldns_rr_owner(rr));
1677b5038d7SDag-Erling Smørgrav 	}
1687b5038d7SDag-Erling Smørgrav 
1697b5038d7SDag-Erling Smørgrav 	if (ldns_buffer_reserve(buffer, 4)) {
1707b5038d7SDag-Erling Smørgrav 		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
1717b5038d7SDag-Erling Smørgrav 		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
1727b5038d7SDag-Erling Smørgrav 	}
1737b5038d7SDag-Erling Smørgrav 
1747b5038d7SDag-Erling Smørgrav 	if (section != LDNS_SECTION_QUESTION) {
1757b5038d7SDag-Erling Smørgrav 		if (ldns_buffer_reserve(buffer, 6)) {
1767b5038d7SDag-Erling Smørgrav 			ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
1777b5038d7SDag-Erling Smørgrav 			/* remember pos for later */
1787b5038d7SDag-Erling Smørgrav 			rdl_pos = ldns_buffer_position(buffer);
1797b5038d7SDag-Erling Smørgrav 			ldns_buffer_write_u16(buffer, 0);
1807b5038d7SDag-Erling Smørgrav 		}
1817b5038d7SDag-Erling Smørgrav 
1827b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_rd_count(rr); i++) {
1837b5038d7SDag-Erling Smørgrav 			(void) ldns_rdf2buffer_wire(
1847b5038d7SDag-Erling Smørgrav 					buffer, ldns_rr_rdf(rr, i));
1857b5038d7SDag-Erling Smørgrav 		}
1867b5038d7SDag-Erling Smørgrav 
1877b5038d7SDag-Erling Smørgrav 		if (rdl_pos != 0) {
1887b5038d7SDag-Erling Smørgrav 			ldns_buffer_write_u16_at(buffer, rdl_pos,
1897b5038d7SDag-Erling Smørgrav 			                         ldns_buffer_position(buffer)
1907b5038d7SDag-Erling Smørgrav 		        	                   - rdl_pos - 2);
1917b5038d7SDag-Erling Smørgrav 		}
1927b5038d7SDag-Erling Smørgrav 	}
1937b5038d7SDag-Erling Smørgrav 	return ldns_buffer_status(buffer);
1947b5038d7SDag-Erling Smørgrav }
1957b5038d7SDag-Erling Smørgrav 
1967b5038d7SDag-Erling Smørgrav ldns_status
1977b5038d7SDag-Erling Smørgrav ldns_rrsig2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
1987b5038d7SDag-Erling Smørgrav {
1997b5038d7SDag-Erling Smørgrav 	uint16_t i;
2007b5038d7SDag-Erling Smørgrav 
2017b5038d7SDag-Erling Smørgrav 	/* it must be a sig RR */
2027b5038d7SDag-Erling Smørgrav 	if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) {
2037b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
2047b5038d7SDag-Erling Smørgrav 	}
2057b5038d7SDag-Erling Smørgrav 
2067b5038d7SDag-Erling Smørgrav 	/* Convert all the rdfs, except the actual signature data
2077b5038d7SDag-Erling Smørgrav 	 * rdf number 8  - the last, hence: -1 */
2087b5038d7SDag-Erling Smørgrav 	for (i = 0; i < ldns_rr_rd_count(rr) - 1; i++) {
2097b5038d7SDag-Erling Smørgrav 		(void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_rdf(rr, i));
2107b5038d7SDag-Erling Smørgrav 	}
2117b5038d7SDag-Erling Smørgrav 
2127b5038d7SDag-Erling Smørgrav 	return ldns_buffer_status(buffer);
2137b5038d7SDag-Erling Smørgrav }
2147b5038d7SDag-Erling Smørgrav 
2157b5038d7SDag-Erling Smørgrav ldns_status
2167b5038d7SDag-Erling Smørgrav ldns_rr_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
2177b5038d7SDag-Erling Smørgrav {
2187b5038d7SDag-Erling Smørgrav 	uint16_t i;
2197b5038d7SDag-Erling Smørgrav 	/* convert all the rdf's */
2207b5038d7SDag-Erling Smørgrav 	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
2217b5038d7SDag-Erling Smørgrav 		(void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
2227b5038d7SDag-Erling Smørgrav 	}
2237b5038d7SDag-Erling Smørgrav 
2247b5038d7SDag-Erling Smørgrav 	return ldns_buffer_status(buffer);
2257b5038d7SDag-Erling Smørgrav }
2267b5038d7SDag-Erling Smørgrav 
2277b5038d7SDag-Erling Smørgrav /*
2287b5038d7SDag-Erling Smørgrav  * Copies the packet header data to the buffer in wire format
2297b5038d7SDag-Erling Smørgrav  */
2307b5038d7SDag-Erling Smørgrav static ldns_status
2317b5038d7SDag-Erling Smørgrav ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
2327b5038d7SDag-Erling Smørgrav {
2337b5038d7SDag-Erling Smørgrav 	uint8_t flags;
2347b5038d7SDag-Erling Smørgrav 	uint16_t arcount;
2357b5038d7SDag-Erling Smørgrav 
2367b5038d7SDag-Erling Smørgrav 	if (ldns_buffer_reserve(buffer, 12)) {
2377b5038d7SDag-Erling Smørgrav 		ldns_buffer_write_u16(buffer, ldns_pkt_id(packet));
2387b5038d7SDag-Erling Smørgrav 
2397b5038d7SDag-Erling Smørgrav 		flags = ldns_pkt_qr(packet) << 7
2407b5038d7SDag-Erling Smørgrav 		        | ldns_pkt_get_opcode(packet) << 3
2417b5038d7SDag-Erling Smørgrav 		        | ldns_pkt_aa(packet) << 2
2427b5038d7SDag-Erling Smørgrav 		        | ldns_pkt_tc(packet) << 1 | ldns_pkt_rd(packet);
2437b5038d7SDag-Erling Smørgrav 		ldns_buffer_write_u8(buffer, flags);
2447b5038d7SDag-Erling Smørgrav 
2457b5038d7SDag-Erling Smørgrav 		flags = ldns_pkt_ra(packet) << 7
2467b5038d7SDag-Erling Smørgrav 		        /*| ldns_pkt_z(packet) << 6*/
2477b5038d7SDag-Erling Smørgrav 		        | ldns_pkt_ad(packet) << 5
2487b5038d7SDag-Erling Smørgrav 		        | ldns_pkt_cd(packet) << 4 | ldns_pkt_get_rcode(packet);
2497b5038d7SDag-Erling Smørgrav 		ldns_buffer_write_u8(buffer, flags);
2507b5038d7SDag-Erling Smørgrav 
2517b5038d7SDag-Erling Smørgrav 		ldns_buffer_write_u16(buffer, ldns_pkt_qdcount(packet));
2527b5038d7SDag-Erling Smørgrav 		ldns_buffer_write_u16(buffer, ldns_pkt_ancount(packet));
2537b5038d7SDag-Erling Smørgrav 		ldns_buffer_write_u16(buffer, ldns_pkt_nscount(packet));
2547b5038d7SDag-Erling Smørgrav 		/* add EDNS0 and TSIG to additional if they are there */
2557b5038d7SDag-Erling Smørgrav 		arcount = ldns_pkt_arcount(packet);
2567b5038d7SDag-Erling Smørgrav 		if (ldns_pkt_tsig(packet)) {
2577b5038d7SDag-Erling Smørgrav 			arcount++;
2587b5038d7SDag-Erling Smørgrav 		}
2597b5038d7SDag-Erling Smørgrav 		if (ldns_pkt_edns(packet)) {
2607b5038d7SDag-Erling Smørgrav 			arcount++;
2617b5038d7SDag-Erling Smørgrav 		}
2627b5038d7SDag-Erling Smørgrav 		ldns_buffer_write_u16(buffer, arcount);
2637b5038d7SDag-Erling Smørgrav 	}
2647b5038d7SDag-Erling Smørgrav 
2657b5038d7SDag-Erling Smørgrav 	return ldns_buffer_status(buffer);
2667b5038d7SDag-Erling Smørgrav }
2677b5038d7SDag-Erling Smørgrav 
2687b5038d7SDag-Erling Smørgrav ldns_status
2697b5038d7SDag-Erling Smørgrav ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
2707b5038d7SDag-Erling Smørgrav {
2717b5038d7SDag-Erling Smørgrav 	ldns_rr_list *rr_list;
2727b5038d7SDag-Erling Smørgrav 	uint16_t i;
2737b5038d7SDag-Erling Smørgrav 
2747b5038d7SDag-Erling Smørgrav 	/* edns tmp vars */
2757b5038d7SDag-Erling Smørgrav 	ldns_rr *edns_rr;
2767b5038d7SDag-Erling Smørgrav 	uint8_t edata[4];
2777b5038d7SDag-Erling Smørgrav 
2787b5038d7SDag-Erling Smørgrav 	(void) ldns_hdr2buffer_wire(buffer, packet);
2797b5038d7SDag-Erling Smørgrav 
2807b5038d7SDag-Erling Smørgrav 	rr_list = ldns_pkt_question(packet);
2817b5038d7SDag-Erling Smørgrav 	if (rr_list) {
2827b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
2837b5038d7SDag-Erling Smørgrav 			(void) ldns_rr2buffer_wire(buffer,
2847b5038d7SDag-Erling Smørgrav 			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_QUESTION);
2857b5038d7SDag-Erling Smørgrav 		}
2867b5038d7SDag-Erling Smørgrav 	}
2877b5038d7SDag-Erling Smørgrav 	rr_list = ldns_pkt_answer(packet);
2887b5038d7SDag-Erling Smørgrav 	if (rr_list) {
2897b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
2907b5038d7SDag-Erling Smørgrav 			(void) ldns_rr2buffer_wire(buffer,
2917b5038d7SDag-Erling Smørgrav 			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER);
2927b5038d7SDag-Erling Smørgrav 		}
2937b5038d7SDag-Erling Smørgrav 	}
2947b5038d7SDag-Erling Smørgrav 	rr_list = ldns_pkt_authority(packet);
2957b5038d7SDag-Erling Smørgrav 	if (rr_list) {
2967b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
2977b5038d7SDag-Erling Smørgrav 			(void) ldns_rr2buffer_wire(buffer,
2987b5038d7SDag-Erling Smørgrav 			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_AUTHORITY);
2997b5038d7SDag-Erling Smørgrav 		}
3007b5038d7SDag-Erling Smørgrav 	}
3017b5038d7SDag-Erling Smørgrav 	rr_list = ldns_pkt_additional(packet);
3027b5038d7SDag-Erling Smørgrav 	if (rr_list) {
3037b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
3047b5038d7SDag-Erling Smørgrav 			(void) ldns_rr2buffer_wire(buffer,
3057b5038d7SDag-Erling Smørgrav 			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ADDITIONAL);
3067b5038d7SDag-Erling Smørgrav 		}
3077b5038d7SDag-Erling Smørgrav 	}
3087b5038d7SDag-Erling Smørgrav 
3097b5038d7SDag-Erling Smørgrav 	/* add EDNS to additional if it is needed */
3107b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_edns(packet)) {
3117b5038d7SDag-Erling Smørgrav 		edns_rr = ldns_rr_new();
3127b5038d7SDag-Erling Smørgrav 		if(!edns_rr) return LDNS_STATUS_MEM_ERR;
3137b5038d7SDag-Erling Smørgrav 		ldns_rr_set_owner(edns_rr,
3147b5038d7SDag-Erling Smørgrav 				ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "."));
3157b5038d7SDag-Erling Smørgrav 		ldns_rr_set_type(edns_rr, LDNS_RR_TYPE_OPT);
3167b5038d7SDag-Erling Smørgrav 		ldns_rr_set_class(edns_rr, ldns_pkt_edns_udp_size(packet));
3177b5038d7SDag-Erling Smørgrav 		edata[0] = ldns_pkt_edns_extended_rcode(packet);
3187b5038d7SDag-Erling Smørgrav 		edata[1] = ldns_pkt_edns_version(packet);
3197b5038d7SDag-Erling Smørgrav 		ldns_write_uint16(&edata[2], ldns_pkt_edns_z(packet));
3207b5038d7SDag-Erling Smørgrav 		ldns_rr_set_ttl(edns_rr, ldns_read_uint32(edata));
3217b5038d7SDag-Erling Smørgrav 		/* don't forget to add the edns rdata (if any) */
3227b5038d7SDag-Erling Smørgrav 		if (packet->_edns_data)
3237b5038d7SDag-Erling Smørgrav 			ldns_rr_push_rdf (edns_rr, packet->_edns_data);
3247b5038d7SDag-Erling Smørgrav 		(void)ldns_rr2buffer_wire(buffer, edns_rr, LDNS_SECTION_ADDITIONAL);
3257b5038d7SDag-Erling Smørgrav 		/* take the edns rdata back out of the rr before we free rr */
3267b5038d7SDag-Erling Smørgrav 		if (packet->_edns_data)
3277b5038d7SDag-Erling Smørgrav 			(void)ldns_rr_pop_rdf (edns_rr);
3287b5038d7SDag-Erling Smørgrav 		ldns_rr_free(edns_rr);
3297b5038d7SDag-Erling Smørgrav 	}
3307b5038d7SDag-Erling Smørgrav 
3317b5038d7SDag-Erling Smørgrav 	/* add TSIG to additional if it is there */
3327b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_tsig(packet)) {
3337b5038d7SDag-Erling Smørgrav 		(void) ldns_rr2buffer_wire(buffer,
3347b5038d7SDag-Erling Smørgrav 		                           ldns_pkt_tsig(packet), LDNS_SECTION_ADDITIONAL);
3357b5038d7SDag-Erling Smørgrav 	}
3367b5038d7SDag-Erling Smørgrav 
3377b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_OK;
3387b5038d7SDag-Erling Smørgrav }
3397b5038d7SDag-Erling Smørgrav 
3407b5038d7SDag-Erling Smørgrav ldns_status
3417b5038d7SDag-Erling Smørgrav ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size)
3427b5038d7SDag-Erling Smørgrav {
3437b5038d7SDag-Erling Smørgrav 	ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
3447b5038d7SDag-Erling Smørgrav 	ldns_status status;
3457b5038d7SDag-Erling Smørgrav 	*result_size = 0;
3467b5038d7SDag-Erling Smørgrav 	*dest = NULL;
3477b5038d7SDag-Erling Smørgrav 	if(!buffer) return LDNS_STATUS_MEM_ERR;
3487b5038d7SDag-Erling Smørgrav 
3497b5038d7SDag-Erling Smørgrav 	status = ldns_rdf2buffer_wire(buffer, rdf);
3507b5038d7SDag-Erling Smørgrav 	if (status == LDNS_STATUS_OK) {
3517b5038d7SDag-Erling Smørgrav 		*result_size =  ldns_buffer_position(buffer);
352*2787e39aSDag-Erling Smørgrav 		*dest = (uint8_t *) ldns_buffer_export(buffer);
3537b5038d7SDag-Erling Smørgrav 	}
3547b5038d7SDag-Erling Smørgrav 	ldns_buffer_free(buffer);
3557b5038d7SDag-Erling Smørgrav 	return status;
3567b5038d7SDag-Erling Smørgrav }
3577b5038d7SDag-Erling Smørgrav 
3587b5038d7SDag-Erling Smørgrav ldns_status
3597b5038d7SDag-Erling Smørgrav ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size)
3607b5038d7SDag-Erling Smørgrav {
3617b5038d7SDag-Erling Smørgrav 	ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
3627b5038d7SDag-Erling Smørgrav 	ldns_status status;
3637b5038d7SDag-Erling Smørgrav 	*result_size = 0;
3647b5038d7SDag-Erling Smørgrav 	*dest = NULL;
3657b5038d7SDag-Erling Smørgrav 	if(!buffer) return LDNS_STATUS_MEM_ERR;
3667b5038d7SDag-Erling Smørgrav 
3677b5038d7SDag-Erling Smørgrav 	status = ldns_rr2buffer_wire(buffer, rr, section);
3687b5038d7SDag-Erling Smørgrav 	if (status == LDNS_STATUS_OK) {
3697b5038d7SDag-Erling Smørgrav 		*result_size =  ldns_buffer_position(buffer);
370*2787e39aSDag-Erling Smørgrav 		*dest = (uint8_t *) ldns_buffer_export(buffer);
3717b5038d7SDag-Erling Smørgrav 	}
3727b5038d7SDag-Erling Smørgrav 	ldns_buffer_free(buffer);
3737b5038d7SDag-Erling Smørgrav 	return status;
3747b5038d7SDag-Erling Smørgrav }
3757b5038d7SDag-Erling Smørgrav 
3767b5038d7SDag-Erling Smørgrav ldns_status
3777b5038d7SDag-Erling Smørgrav ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size)
3787b5038d7SDag-Erling Smørgrav {
3797b5038d7SDag-Erling Smørgrav 	ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
3807b5038d7SDag-Erling Smørgrav 	ldns_status status;
3817b5038d7SDag-Erling Smørgrav 	*result_size = 0;
3827b5038d7SDag-Erling Smørgrav 	*dest = NULL;
3837b5038d7SDag-Erling Smørgrav 	if(!buffer) return LDNS_STATUS_MEM_ERR;
3847b5038d7SDag-Erling Smørgrav 
3857b5038d7SDag-Erling Smørgrav 	status = ldns_pkt2buffer_wire(buffer, packet);
3867b5038d7SDag-Erling Smørgrav 	if (status == LDNS_STATUS_OK) {
3877b5038d7SDag-Erling Smørgrav 		*result_size =  ldns_buffer_position(buffer);
388*2787e39aSDag-Erling Smørgrav 		*dest = (uint8_t *) ldns_buffer_export(buffer);
3897b5038d7SDag-Erling Smørgrav 	}
3907b5038d7SDag-Erling Smørgrav 	ldns_buffer_free(buffer);
3917b5038d7SDag-Erling Smørgrav 	return status;
3927b5038d7SDag-Erling Smørgrav }
393