xref: /freebsd/contrib/ldns/packet.c (revision 5afab0e5)
17b5038d7SDag-Erling Smørgrav /*
27b5038d7SDag-Erling Smørgrav  * packet.c
37b5038d7SDag-Erling Smørgrav  *
47b5038d7SDag-Erling Smørgrav  * dns packet implementation
57b5038d7SDag-Erling Smørgrav  *
67b5038d7SDag-Erling Smørgrav  * a Net::DNS like library for C
77b5038d7SDag-Erling Smørgrav  *
87b5038d7SDag-Erling Smørgrav  * (c) NLnet Labs, 2004-2006
97b5038d7SDag-Erling Smørgrav  *
107b5038d7SDag-Erling Smørgrav  * See the file LICENSE for the license
117b5038d7SDag-Erling Smørgrav  */
127b5038d7SDag-Erling Smørgrav 
137b5038d7SDag-Erling Smørgrav #include <ldns/config.h>
147b5038d7SDag-Erling Smørgrav 
157b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h>
16*5afab0e5SDag-Erling Smørgrav #include <ldns/internal.h>
177b5038d7SDag-Erling Smørgrav 
187b5038d7SDag-Erling Smørgrav #include <strings.h>
197b5038d7SDag-Erling Smørgrav #include <limits.h>
207b5038d7SDag-Erling Smørgrav 
217b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
227b5038d7SDag-Erling Smørgrav #include <openssl/rand.h>
237b5038d7SDag-Erling Smørgrav #endif
247b5038d7SDag-Erling Smørgrav 
257b5038d7SDag-Erling Smørgrav /* Access functions
267b5038d7SDag-Erling Smørgrav  * do this as functions to get type checking
277b5038d7SDag-Erling Smørgrav  */
287b5038d7SDag-Erling Smørgrav 
297b5038d7SDag-Erling Smørgrav #define LDNS_EDNS_MASK_DO_BIT 0x8000
30*5afab0e5SDag-Erling Smørgrav #define LDNS_EDNS_MASK_UNASSIGNED (0xFFFF & ~LDNS_EDNS_MASK_DO_BIT)
317b5038d7SDag-Erling Smørgrav 
327b5038d7SDag-Erling Smørgrav /* TODO defines for 3600 */
337b5038d7SDag-Erling Smørgrav /* convert to and from numerical flag values */
347b5038d7SDag-Erling Smørgrav ldns_lookup_table ldns_edns_flags[] = {
357b5038d7SDag-Erling Smørgrav 	{ 3600, "do"},
367b5038d7SDag-Erling Smørgrav 	{ 0, NULL}
377b5038d7SDag-Erling Smørgrav };
387b5038d7SDag-Erling Smørgrav 
397b5038d7SDag-Erling Smørgrav /* read */
407b5038d7SDag-Erling Smørgrav uint16_t
ldns_pkt_id(const ldns_pkt * packet)417b5038d7SDag-Erling Smørgrav ldns_pkt_id(const ldns_pkt *packet)
427b5038d7SDag-Erling Smørgrav {
437b5038d7SDag-Erling Smørgrav 	return packet->_header->_id;
447b5038d7SDag-Erling Smørgrav }
457b5038d7SDag-Erling Smørgrav 
467b5038d7SDag-Erling Smørgrav bool
ldns_pkt_qr(const ldns_pkt * packet)477b5038d7SDag-Erling Smørgrav ldns_pkt_qr(const ldns_pkt *packet)
487b5038d7SDag-Erling Smørgrav {
497b5038d7SDag-Erling Smørgrav 	return packet->_header->_qr;
507b5038d7SDag-Erling Smørgrav }
517b5038d7SDag-Erling Smørgrav 
527b5038d7SDag-Erling Smørgrav bool
ldns_pkt_aa(const ldns_pkt * packet)537b5038d7SDag-Erling Smørgrav ldns_pkt_aa(const ldns_pkt *packet)
547b5038d7SDag-Erling Smørgrav {
557b5038d7SDag-Erling Smørgrav 	return packet->_header->_aa;
567b5038d7SDag-Erling Smørgrav }
577b5038d7SDag-Erling Smørgrav 
587b5038d7SDag-Erling Smørgrav bool
ldns_pkt_tc(const ldns_pkt * packet)597b5038d7SDag-Erling Smørgrav ldns_pkt_tc(const ldns_pkt *packet)
607b5038d7SDag-Erling Smørgrav {
617b5038d7SDag-Erling Smørgrav 	return packet->_header->_tc;
627b5038d7SDag-Erling Smørgrav }
637b5038d7SDag-Erling Smørgrav 
647b5038d7SDag-Erling Smørgrav bool
ldns_pkt_rd(const ldns_pkt * packet)657b5038d7SDag-Erling Smørgrav ldns_pkt_rd(const ldns_pkt *packet)
667b5038d7SDag-Erling Smørgrav {
677b5038d7SDag-Erling Smørgrav 	return packet->_header->_rd;
687b5038d7SDag-Erling Smørgrav }
697b5038d7SDag-Erling Smørgrav 
707b5038d7SDag-Erling Smørgrav bool
ldns_pkt_cd(const ldns_pkt * packet)717b5038d7SDag-Erling Smørgrav ldns_pkt_cd(const ldns_pkt *packet)
727b5038d7SDag-Erling Smørgrav {
737b5038d7SDag-Erling Smørgrav 	return packet->_header->_cd;
747b5038d7SDag-Erling Smørgrav }
757b5038d7SDag-Erling Smørgrav 
767b5038d7SDag-Erling Smørgrav bool
ldns_pkt_ra(const ldns_pkt * packet)777b5038d7SDag-Erling Smørgrav ldns_pkt_ra(const ldns_pkt *packet)
787b5038d7SDag-Erling Smørgrav {
797b5038d7SDag-Erling Smørgrav 	return packet->_header->_ra;
807b5038d7SDag-Erling Smørgrav }
817b5038d7SDag-Erling Smørgrav 
827b5038d7SDag-Erling Smørgrav bool
ldns_pkt_ad(const ldns_pkt * packet)837b5038d7SDag-Erling Smørgrav ldns_pkt_ad(const ldns_pkt *packet)
847b5038d7SDag-Erling Smørgrav {
857b5038d7SDag-Erling Smørgrav 	return packet->_header->_ad;
867b5038d7SDag-Erling Smørgrav }
877b5038d7SDag-Erling Smørgrav 
887b5038d7SDag-Erling Smørgrav ldns_pkt_opcode
ldns_pkt_get_opcode(const ldns_pkt * packet)897b5038d7SDag-Erling Smørgrav ldns_pkt_get_opcode(const ldns_pkt *packet)
907b5038d7SDag-Erling Smørgrav {
917b5038d7SDag-Erling Smørgrav 	return packet->_header->_opcode;
927b5038d7SDag-Erling Smørgrav }
937b5038d7SDag-Erling Smørgrav 
947b5038d7SDag-Erling Smørgrav ldns_pkt_rcode
ldns_pkt_get_rcode(const ldns_pkt * packet)957b5038d7SDag-Erling Smørgrav ldns_pkt_get_rcode(const ldns_pkt *packet)
967b5038d7SDag-Erling Smørgrav {
977b5038d7SDag-Erling Smørgrav 	return packet->_header->_rcode;
987b5038d7SDag-Erling Smørgrav }
997b5038d7SDag-Erling Smørgrav 
1007b5038d7SDag-Erling Smørgrav uint16_t
ldns_pkt_qdcount(const ldns_pkt * packet)1017b5038d7SDag-Erling Smørgrav ldns_pkt_qdcount(const ldns_pkt *packet)
1027b5038d7SDag-Erling Smørgrav {
1037b5038d7SDag-Erling Smørgrav 	return packet->_header->_qdcount;
1047b5038d7SDag-Erling Smørgrav }
1057b5038d7SDag-Erling Smørgrav 
1067b5038d7SDag-Erling Smørgrav uint16_t
ldns_pkt_ancount(const ldns_pkt * packet)1077b5038d7SDag-Erling Smørgrav ldns_pkt_ancount(const ldns_pkt *packet)
1087b5038d7SDag-Erling Smørgrav {
1097b5038d7SDag-Erling Smørgrav 	return packet->_header->_ancount;
1107b5038d7SDag-Erling Smørgrav }
1117b5038d7SDag-Erling Smørgrav 
1127b5038d7SDag-Erling Smørgrav uint16_t
ldns_pkt_nscount(const ldns_pkt * packet)1137b5038d7SDag-Erling Smørgrav ldns_pkt_nscount(const ldns_pkt *packet)
1147b5038d7SDag-Erling Smørgrav {
1157b5038d7SDag-Erling Smørgrav 	return packet->_header->_nscount;
1167b5038d7SDag-Erling Smørgrav }
1177b5038d7SDag-Erling Smørgrav 
1187b5038d7SDag-Erling Smørgrav uint16_t
ldns_pkt_arcount(const ldns_pkt * packet)1197b5038d7SDag-Erling Smørgrav ldns_pkt_arcount(const ldns_pkt *packet)
1207b5038d7SDag-Erling Smørgrav {
1217b5038d7SDag-Erling Smørgrav 	return packet->_header->_arcount;
1227b5038d7SDag-Erling Smørgrav }
1237b5038d7SDag-Erling Smørgrav 
1247b5038d7SDag-Erling Smørgrav ldns_rr_list *
ldns_pkt_question(const ldns_pkt * packet)1257b5038d7SDag-Erling Smørgrav ldns_pkt_question(const ldns_pkt *packet)
1267b5038d7SDag-Erling Smørgrav {
1277b5038d7SDag-Erling Smørgrav 	return packet->_question;
1287b5038d7SDag-Erling Smørgrav }
1297b5038d7SDag-Erling Smørgrav 
1307b5038d7SDag-Erling Smørgrav ldns_rr_list *
ldns_pkt_answer(const ldns_pkt * packet)1317b5038d7SDag-Erling Smørgrav ldns_pkt_answer(const ldns_pkt *packet)
1327b5038d7SDag-Erling Smørgrav {
1337b5038d7SDag-Erling Smørgrav 	return packet->_answer;
1347b5038d7SDag-Erling Smørgrav }
1357b5038d7SDag-Erling Smørgrav 
1367b5038d7SDag-Erling Smørgrav ldns_rr_list *
ldns_pkt_authority(const ldns_pkt * packet)1377b5038d7SDag-Erling Smørgrav ldns_pkt_authority(const ldns_pkt *packet)
1387b5038d7SDag-Erling Smørgrav {
1397b5038d7SDag-Erling Smørgrav 	return packet->_authority;
1407b5038d7SDag-Erling Smørgrav }
1417b5038d7SDag-Erling Smørgrav 
1427b5038d7SDag-Erling Smørgrav ldns_rr_list *
ldns_pkt_additional(const ldns_pkt * packet)1437b5038d7SDag-Erling Smørgrav ldns_pkt_additional(const ldns_pkt *packet)
1447b5038d7SDag-Erling Smørgrav {
1457b5038d7SDag-Erling Smørgrav 	return packet->_additional;
1467b5038d7SDag-Erling Smørgrav }
1477b5038d7SDag-Erling Smørgrav 
1487b5038d7SDag-Erling Smørgrav /* return ALL section concatenated */
1497b5038d7SDag-Erling Smørgrav ldns_rr_list *
ldns_pkt_all(const ldns_pkt * packet)1507b5038d7SDag-Erling Smørgrav ldns_pkt_all(const ldns_pkt *packet)
1517b5038d7SDag-Erling Smørgrav {
1527b5038d7SDag-Erling Smørgrav 	ldns_rr_list *all, *prev_all;
1537b5038d7SDag-Erling Smørgrav 
1547b5038d7SDag-Erling Smørgrav 	all = ldns_rr_list_cat_clone(
1557b5038d7SDag-Erling Smørgrav 			ldns_pkt_question(packet),
1567b5038d7SDag-Erling Smørgrav 			ldns_pkt_answer(packet));
1577b5038d7SDag-Erling Smørgrav 	prev_all = all;
1587b5038d7SDag-Erling Smørgrav 	all = ldns_rr_list_cat_clone(all,
1597b5038d7SDag-Erling Smørgrav 			ldns_pkt_authority(packet));
1607b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(prev_all);
1617b5038d7SDag-Erling Smørgrav 	prev_all = all;
1627b5038d7SDag-Erling Smørgrav 	all = ldns_rr_list_cat_clone(all,
1637b5038d7SDag-Erling Smørgrav 			ldns_pkt_additional(packet));
1647b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(prev_all);
1657b5038d7SDag-Erling Smørgrav 	return all;
1667b5038d7SDag-Erling Smørgrav }
1677b5038d7SDag-Erling Smørgrav 
1687b5038d7SDag-Erling Smørgrav ldns_rr_list *
ldns_pkt_all_noquestion(const ldns_pkt * packet)1697b5038d7SDag-Erling Smørgrav ldns_pkt_all_noquestion(const ldns_pkt *packet)
1707b5038d7SDag-Erling Smørgrav {
1717b5038d7SDag-Erling Smørgrav 	ldns_rr_list *all, *all2;
1727b5038d7SDag-Erling Smørgrav 
1737b5038d7SDag-Erling Smørgrav 	all = ldns_rr_list_cat_clone(
1747b5038d7SDag-Erling Smørgrav 			ldns_pkt_answer(packet),
1757b5038d7SDag-Erling Smørgrav 			ldns_pkt_authority(packet));
1767b5038d7SDag-Erling Smørgrav 	all2 = ldns_rr_list_cat_clone(all,
1777b5038d7SDag-Erling Smørgrav 			ldns_pkt_additional(packet));
1787b5038d7SDag-Erling Smørgrav 
1797b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(all);
1807b5038d7SDag-Erling Smørgrav 	return all2;
1817b5038d7SDag-Erling Smørgrav }
1827b5038d7SDag-Erling Smørgrav 
1837b5038d7SDag-Erling Smørgrav size_t
ldns_pkt_size(const ldns_pkt * packet)1847b5038d7SDag-Erling Smørgrav ldns_pkt_size(const ldns_pkt *packet)
1857b5038d7SDag-Erling Smørgrav {
1867b5038d7SDag-Erling Smørgrav 	return packet->_size;
1877b5038d7SDag-Erling Smørgrav }
1887b5038d7SDag-Erling Smørgrav 
1897b5038d7SDag-Erling Smørgrav uint32_t
ldns_pkt_querytime(const ldns_pkt * packet)1907b5038d7SDag-Erling Smørgrav ldns_pkt_querytime(const ldns_pkt *packet)
1917b5038d7SDag-Erling Smørgrav {
1927b5038d7SDag-Erling Smørgrav 	return packet->_querytime;
1937b5038d7SDag-Erling Smørgrav }
1947b5038d7SDag-Erling Smørgrav 
1957b5038d7SDag-Erling Smørgrav ldns_rdf *
ldns_pkt_answerfrom(const ldns_pkt * packet)1967b5038d7SDag-Erling Smørgrav ldns_pkt_answerfrom(const ldns_pkt *packet)
1977b5038d7SDag-Erling Smørgrav {
1987b5038d7SDag-Erling Smørgrav 	return packet->_answerfrom;
1997b5038d7SDag-Erling Smørgrav }
2007b5038d7SDag-Erling Smørgrav 
2017b5038d7SDag-Erling Smørgrav struct timeval
ldns_pkt_timestamp(const ldns_pkt * packet)2027b5038d7SDag-Erling Smørgrav ldns_pkt_timestamp(const ldns_pkt *packet)
2037b5038d7SDag-Erling Smørgrav {
2047b5038d7SDag-Erling Smørgrav 	return packet->timestamp;
2057b5038d7SDag-Erling Smørgrav }
2067b5038d7SDag-Erling Smørgrav 
2077b5038d7SDag-Erling Smørgrav uint16_t
ldns_pkt_edns_udp_size(const ldns_pkt * packet)2087b5038d7SDag-Erling Smørgrav ldns_pkt_edns_udp_size(const ldns_pkt *packet)
2097b5038d7SDag-Erling Smørgrav {
2107b5038d7SDag-Erling Smørgrav 	return packet->_edns_udp_size;
2117b5038d7SDag-Erling Smørgrav }
2127b5038d7SDag-Erling Smørgrav 
2137b5038d7SDag-Erling Smørgrav uint8_t
ldns_pkt_edns_extended_rcode(const ldns_pkt * packet)2147b5038d7SDag-Erling Smørgrav ldns_pkt_edns_extended_rcode(const ldns_pkt *packet)
2157b5038d7SDag-Erling Smørgrav {
2167b5038d7SDag-Erling Smørgrav 	return packet->_edns_extended_rcode;
2177b5038d7SDag-Erling Smørgrav }
2187b5038d7SDag-Erling Smørgrav 
2197b5038d7SDag-Erling Smørgrav uint8_t
ldns_pkt_edns_version(const ldns_pkt * packet)2207b5038d7SDag-Erling Smørgrav ldns_pkt_edns_version(const ldns_pkt *packet)
2217b5038d7SDag-Erling Smørgrav {
2227b5038d7SDag-Erling Smørgrav 	return packet->_edns_version;
2237b5038d7SDag-Erling Smørgrav }
2247b5038d7SDag-Erling Smørgrav 
2257b5038d7SDag-Erling Smørgrav uint16_t
ldns_pkt_edns_z(const ldns_pkt * packet)2267b5038d7SDag-Erling Smørgrav ldns_pkt_edns_z(const ldns_pkt *packet)
2277b5038d7SDag-Erling Smørgrav {
2287b5038d7SDag-Erling Smørgrav 	return packet->_edns_z;
2297b5038d7SDag-Erling Smørgrav }
2307b5038d7SDag-Erling Smørgrav 
2317b5038d7SDag-Erling Smørgrav bool
ldns_pkt_edns_do(const ldns_pkt * packet)2327b5038d7SDag-Erling Smørgrav ldns_pkt_edns_do(const ldns_pkt *packet)
2337b5038d7SDag-Erling Smørgrav {
2347b5038d7SDag-Erling Smørgrav 	return (packet->_edns_z & LDNS_EDNS_MASK_DO_BIT);
2357b5038d7SDag-Erling Smørgrav }
2367b5038d7SDag-Erling Smørgrav 
2377b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_edns_do(ldns_pkt * packet,bool value)2387b5038d7SDag-Erling Smørgrav ldns_pkt_set_edns_do(ldns_pkt *packet, bool value)
2397b5038d7SDag-Erling Smørgrav {
2407b5038d7SDag-Erling Smørgrav 	if (value) {
2417b5038d7SDag-Erling Smørgrav 		packet->_edns_z = packet->_edns_z | LDNS_EDNS_MASK_DO_BIT;
2427b5038d7SDag-Erling Smørgrav 	} else {
2437b5038d7SDag-Erling Smørgrav 		packet->_edns_z = packet->_edns_z & ~LDNS_EDNS_MASK_DO_BIT;
2447b5038d7SDag-Erling Smørgrav 	}
2457b5038d7SDag-Erling Smørgrav }
2467b5038d7SDag-Erling Smørgrav 
247*5afab0e5SDag-Erling Smørgrav uint16_t
ldns_pkt_edns_unassigned(const ldns_pkt * packet)248*5afab0e5SDag-Erling Smørgrav ldns_pkt_edns_unassigned(const ldns_pkt *packet)
249*5afab0e5SDag-Erling Smørgrav {
250*5afab0e5SDag-Erling Smørgrav 	return (packet->_edns_z & LDNS_EDNS_MASK_UNASSIGNED);
251*5afab0e5SDag-Erling Smørgrav }
252*5afab0e5SDag-Erling Smørgrav 
253*5afab0e5SDag-Erling Smørgrav void
ldns_pkt_set_edns_unassigned(ldns_pkt * packet,uint16_t value)254*5afab0e5SDag-Erling Smørgrav ldns_pkt_set_edns_unassigned(ldns_pkt *packet, uint16_t value)
255*5afab0e5SDag-Erling Smørgrav {
256*5afab0e5SDag-Erling Smørgrav 	packet->_edns_z = (packet->_edns_z & ~LDNS_EDNS_MASK_UNASSIGNED)
257*5afab0e5SDag-Erling Smørgrav 			| (value & LDNS_EDNS_MASK_UNASSIGNED);
258*5afab0e5SDag-Erling Smørgrav }
259*5afab0e5SDag-Erling Smørgrav 
2607b5038d7SDag-Erling Smørgrav ldns_rdf *
ldns_pkt_edns_data(const ldns_pkt * packet)2617b5038d7SDag-Erling Smørgrav ldns_pkt_edns_data(const ldns_pkt *packet)
2627b5038d7SDag-Erling Smørgrav {
2637b5038d7SDag-Erling Smørgrav 	return packet->_edns_data;
2647b5038d7SDag-Erling Smørgrav }
2657b5038d7SDag-Erling Smørgrav 
2667b5038d7SDag-Erling Smørgrav /* return only those rr that share the ownername */
2677b5038d7SDag-Erling Smørgrav ldns_rr_list *
ldns_pkt_rr_list_by_name(const ldns_pkt * packet,const ldns_rdf * ownername,ldns_pkt_section sec)268986ba33cSDag-Erling Smørgrav ldns_pkt_rr_list_by_name(const ldns_pkt *packet,
269986ba33cSDag-Erling Smørgrav                          const ldns_rdf *ownername,
2707b5038d7SDag-Erling Smørgrav                          ldns_pkt_section sec)
2717b5038d7SDag-Erling Smørgrav {
2727b5038d7SDag-Erling Smørgrav 	ldns_rr_list *rrs;
2737b5038d7SDag-Erling Smørgrav 	ldns_rr_list *ret;
2747b5038d7SDag-Erling Smørgrav 	uint16_t i;
2757b5038d7SDag-Erling Smørgrav 
2767b5038d7SDag-Erling Smørgrav 	if (!packet) {
2777b5038d7SDag-Erling Smørgrav 		return NULL;
2787b5038d7SDag-Erling Smørgrav 	}
2797b5038d7SDag-Erling Smørgrav 
2807b5038d7SDag-Erling Smørgrav 	rrs = ldns_pkt_get_section_clone(packet, sec);
2817b5038d7SDag-Erling Smørgrav 	ret = NULL;
2827b5038d7SDag-Erling Smørgrav 
2837b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
28417d15b25SDag-Erling Smørgrav 		if (ldns_dname_compare(ldns_rr_owner(
2857b5038d7SDag-Erling Smørgrav 						ldns_rr_list_rr(rrs, i)),
2867b5038d7SDag-Erling Smørgrav 					ownername) == 0) {
2877b5038d7SDag-Erling Smørgrav 			/* owner names match */
2882787e39aSDag-Erling Smørgrav 			if (ret == NULL) {
2892787e39aSDag-Erling Smørgrav 				ret = ldns_rr_list_new();
2902787e39aSDag-Erling Smørgrav 			}
291986ba33cSDag-Erling Smørgrav 			ldns_rr_list_push_rr(ret,
292986ba33cSDag-Erling Smørgrav 					     ldns_rr_clone(
293986ba33cSDag-Erling Smørgrav 						ldns_rr_list_rr(rrs, i))
294986ba33cSDag-Erling Smørgrav 					    );
2957b5038d7SDag-Erling Smørgrav 		}
2967b5038d7SDag-Erling Smørgrav 	}
297986ba33cSDag-Erling Smørgrav 
298986ba33cSDag-Erling Smørgrav 	ldns_rr_list_deep_free(rrs);
299986ba33cSDag-Erling Smørgrav 
3007b5038d7SDag-Erling Smørgrav 	return ret;
3017b5038d7SDag-Erling Smørgrav }
3027b5038d7SDag-Erling Smørgrav 
3037b5038d7SDag-Erling Smørgrav /* return only those rr that share a type */
3047b5038d7SDag-Erling Smørgrav ldns_rr_list *
ldns_pkt_rr_list_by_type(const ldns_pkt * packet,ldns_rr_type type,ldns_pkt_section sec)3057b5038d7SDag-Erling Smørgrav ldns_pkt_rr_list_by_type(const ldns_pkt *packet,
3067b5038d7SDag-Erling Smørgrav                          ldns_rr_type type,
3077b5038d7SDag-Erling Smørgrav                          ldns_pkt_section sec)
3087b5038d7SDag-Erling Smørgrav {
3097b5038d7SDag-Erling Smørgrav 	ldns_rr_list *rrs;
3107b5038d7SDag-Erling Smørgrav 	ldns_rr_list *new;
3117b5038d7SDag-Erling Smørgrav 	uint16_t i;
3127b5038d7SDag-Erling Smørgrav 
3137b5038d7SDag-Erling Smørgrav 	if(!packet) {
3147b5038d7SDag-Erling Smørgrav 		return NULL;
3157b5038d7SDag-Erling Smørgrav 	}
3167b5038d7SDag-Erling Smørgrav 
3177b5038d7SDag-Erling Smørgrav 	rrs = ldns_pkt_get_section_clone(packet, sec);
3187b5038d7SDag-Erling Smørgrav 	new = ldns_rr_list_new();
3197b5038d7SDag-Erling Smørgrav 
3207b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
3217b5038d7SDag-Erling Smørgrav 		if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i))) {
3227b5038d7SDag-Erling Smørgrav 			/* types match */
3237b5038d7SDag-Erling Smørgrav 			ldns_rr_list_push_rr(new,
3247b5038d7SDag-Erling Smørgrav 			                     ldns_rr_clone(
3257b5038d7SDag-Erling Smørgrav 			                     	ldns_rr_list_rr(rrs, i))
3267b5038d7SDag-Erling Smørgrav 					     );
3277b5038d7SDag-Erling Smørgrav 		}
3287b5038d7SDag-Erling Smørgrav 	}
3297b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(rrs);
3307b5038d7SDag-Erling Smørgrav 
3317b5038d7SDag-Erling Smørgrav 	if (ldns_rr_list_rr_count(new) == 0) {
3327b5038d7SDag-Erling Smørgrav 		ldns_rr_list_free(new);
3337b5038d7SDag-Erling Smørgrav 		return NULL;
3347b5038d7SDag-Erling Smørgrav 	} else {
3357b5038d7SDag-Erling Smørgrav 		return new;
3367b5038d7SDag-Erling Smørgrav 	}
3377b5038d7SDag-Erling Smørgrav }
3387b5038d7SDag-Erling Smørgrav 
3397b5038d7SDag-Erling Smørgrav /* return only those rrs that share name and type */
3407b5038d7SDag-Erling Smørgrav ldns_rr_list *
ldns_pkt_rr_list_by_name_and_type(const ldns_pkt * packet,const ldns_rdf * ownername,ldns_rr_type type,ldns_pkt_section sec)3417b5038d7SDag-Erling Smørgrav ldns_pkt_rr_list_by_name_and_type(const ldns_pkt *packet,
3427b5038d7SDag-Erling Smørgrav                                   const ldns_rdf *ownername,
3437b5038d7SDag-Erling Smørgrav                                   ldns_rr_type type,
3447b5038d7SDag-Erling Smørgrav                                   ldns_pkt_section sec)
3457b5038d7SDag-Erling Smørgrav {
3467b5038d7SDag-Erling Smørgrav 	ldns_rr_list *rrs;
3477b5038d7SDag-Erling Smørgrav 	ldns_rr_list *new;
3487b5038d7SDag-Erling Smørgrav 	ldns_rr_list *ret;
3497b5038d7SDag-Erling Smørgrav 	uint16_t i;
3507b5038d7SDag-Erling Smørgrav 
3517b5038d7SDag-Erling Smørgrav 	if(!packet) {
3527b5038d7SDag-Erling Smørgrav 		return NULL;
3537b5038d7SDag-Erling Smørgrav 	}
3547b5038d7SDag-Erling Smørgrav 
3557b5038d7SDag-Erling Smørgrav 	rrs = ldns_pkt_get_section_clone(packet, sec);
3567b5038d7SDag-Erling Smørgrav 	new = ldns_rr_list_new();
3577b5038d7SDag-Erling Smørgrav 	ret = NULL;
3587b5038d7SDag-Erling Smørgrav 
3597b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
3607b5038d7SDag-Erling Smørgrav 		if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i)) &&
36117d15b25SDag-Erling Smørgrav 		    ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(rrs, i)),
3627b5038d7SDag-Erling Smørgrav 		                     ownername
3637b5038d7SDag-Erling Smørgrav 		                    ) == 0
3647b5038d7SDag-Erling Smørgrav 		   ) {
3657b5038d7SDag-Erling Smørgrav 			/* types match */
3667b5038d7SDag-Erling Smørgrav 			ldns_rr_list_push_rr(new, ldns_rr_clone(ldns_rr_list_rr(rrs, i)));
3677b5038d7SDag-Erling Smørgrav 			ret = new;
3687b5038d7SDag-Erling Smørgrav 		}
3697b5038d7SDag-Erling Smørgrav 	}
3707b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(rrs);
3717b5038d7SDag-Erling Smørgrav 	if (!ret) {
3727b5038d7SDag-Erling Smørgrav 		ldns_rr_list_free(new);
3737b5038d7SDag-Erling Smørgrav 	}
3747b5038d7SDag-Erling Smørgrav 	return ret;
3757b5038d7SDag-Erling Smørgrav }
3767b5038d7SDag-Erling Smørgrav 
3777b5038d7SDag-Erling Smørgrav bool
ldns_pkt_rr(const ldns_pkt * pkt,ldns_pkt_section sec,const ldns_rr * rr)378986ba33cSDag-Erling Smørgrav ldns_pkt_rr(const ldns_pkt *pkt, ldns_pkt_section sec, const ldns_rr *rr)
3797b5038d7SDag-Erling Smørgrav {
3807b5038d7SDag-Erling Smørgrav 	bool result = false;
3817b5038d7SDag-Erling Smørgrav 
3827b5038d7SDag-Erling Smørgrav 	switch (sec) {
3837b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_QUESTION:
3847b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
3857b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANSWER:
3867b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr);
3877b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_AUTHORITY:
3887b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr);
3897b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ADDITIONAL:
3907b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
3917b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANY:
3927b5038d7SDag-Erling Smørgrav 		result = ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
393*5afab0e5SDag-Erling Smørgrav 		/* fallthrough */
3947b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANY_NOQUESTION:
3957b5038d7SDag-Erling Smørgrav 		result = result
3967b5038d7SDag-Erling Smørgrav 		    || ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr)
3977b5038d7SDag-Erling Smørgrav 		    || ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr)
3987b5038d7SDag-Erling Smørgrav 		    || ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
3997b5038d7SDag-Erling Smørgrav 	}
4007b5038d7SDag-Erling Smørgrav 
4017b5038d7SDag-Erling Smørgrav 	return result;
4027b5038d7SDag-Erling Smørgrav }
4037b5038d7SDag-Erling Smørgrav 
40417d15b25SDag-Erling Smørgrav uint16_t
ldns_pkt_section_count(const ldns_pkt * packet,ldns_pkt_section s)4057b5038d7SDag-Erling Smørgrav ldns_pkt_section_count(const ldns_pkt *packet, ldns_pkt_section s)
4067b5038d7SDag-Erling Smørgrav {
4077b5038d7SDag-Erling Smørgrav 	switch(s) {
4087b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_QUESTION:
4097b5038d7SDag-Erling Smørgrav 		return ldns_pkt_qdcount(packet);
4107b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANSWER:
4117b5038d7SDag-Erling Smørgrav 		return ldns_pkt_ancount(packet);
4127b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_AUTHORITY:
4137b5038d7SDag-Erling Smørgrav 		return ldns_pkt_nscount(packet);
4147b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ADDITIONAL:
4157b5038d7SDag-Erling Smørgrav 		return ldns_pkt_arcount(packet);
4167b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANY:
4177b5038d7SDag-Erling Smørgrav 		return ldns_pkt_qdcount(packet) +
4187b5038d7SDag-Erling Smørgrav 			ldns_pkt_ancount(packet) +
4197b5038d7SDag-Erling Smørgrav 			ldns_pkt_nscount(packet) +
4207b5038d7SDag-Erling Smørgrav 			ldns_pkt_arcount(packet);
4217b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANY_NOQUESTION:
4227b5038d7SDag-Erling Smørgrav 		return ldns_pkt_ancount(packet) +
4237b5038d7SDag-Erling Smørgrav 			ldns_pkt_nscount(packet) +
4247b5038d7SDag-Erling Smørgrav 			ldns_pkt_arcount(packet);
4257b5038d7SDag-Erling Smørgrav 	default:
4267b5038d7SDag-Erling Smørgrav 		return 0;
4277b5038d7SDag-Erling Smørgrav 	}
4287b5038d7SDag-Erling Smørgrav }
4297b5038d7SDag-Erling Smørgrav 
4307b5038d7SDag-Erling Smørgrav bool
ldns_pkt_empty(ldns_pkt * p)4317b5038d7SDag-Erling Smørgrav ldns_pkt_empty(ldns_pkt *p)
4327b5038d7SDag-Erling Smørgrav {
4337b5038d7SDag-Erling Smørgrav 	if (!p) {
4347b5038d7SDag-Erling Smørgrav 		return true; /* NULL is empty? */
4357b5038d7SDag-Erling Smørgrav 	}
4367b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_section_count(p, LDNS_SECTION_ANY) > 0) {
4377b5038d7SDag-Erling Smørgrav 		return false;
4387b5038d7SDag-Erling Smørgrav 	} else {
4397b5038d7SDag-Erling Smørgrav 		return true;
4407b5038d7SDag-Erling Smørgrav     }
4417b5038d7SDag-Erling Smørgrav }
4427b5038d7SDag-Erling Smørgrav 
4437b5038d7SDag-Erling Smørgrav 
4447b5038d7SDag-Erling Smørgrav ldns_rr_list *
ldns_pkt_get_section_clone(const ldns_pkt * packet,ldns_pkt_section s)4457b5038d7SDag-Erling Smørgrav ldns_pkt_get_section_clone(const ldns_pkt *packet, ldns_pkt_section s)
4467b5038d7SDag-Erling Smørgrav {
4477b5038d7SDag-Erling Smørgrav 	switch(s) {
4487b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_QUESTION:
4497b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_clone(ldns_pkt_question(packet));
4507b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANSWER:
4517b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_clone(ldns_pkt_answer(packet));
4527b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_AUTHORITY:
4537b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_clone(ldns_pkt_authority(packet));
4547b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ADDITIONAL:
4557b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_clone(ldns_pkt_additional(packet));
4567b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANY:
4577b5038d7SDag-Erling Smørgrav 		/* these are already clones */
4587b5038d7SDag-Erling Smørgrav 		return ldns_pkt_all(packet);
4597b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANY_NOQUESTION:
4607b5038d7SDag-Erling Smørgrav 		return ldns_pkt_all_noquestion(packet);
4617b5038d7SDag-Erling Smørgrav 	default:
4627b5038d7SDag-Erling Smørgrav 		return NULL;
4637b5038d7SDag-Erling Smørgrav 	}
4647b5038d7SDag-Erling Smørgrav }
4657b5038d7SDag-Erling Smørgrav 
ldns_pkt_tsig(const ldns_pkt * pkt)4667b5038d7SDag-Erling Smørgrav ldns_rr *ldns_pkt_tsig(const ldns_pkt *pkt) {
4677b5038d7SDag-Erling Smørgrav 	return pkt->_tsig_rr;
4687b5038d7SDag-Erling Smørgrav }
4697b5038d7SDag-Erling Smørgrav 
4707b5038d7SDag-Erling Smørgrav /* write */
4717b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_id(ldns_pkt * packet,uint16_t id)4727b5038d7SDag-Erling Smørgrav ldns_pkt_set_id(ldns_pkt *packet, uint16_t id)
4737b5038d7SDag-Erling Smørgrav {
4747b5038d7SDag-Erling Smørgrav 	packet->_header->_id = id;
4757b5038d7SDag-Erling Smørgrav }
4767b5038d7SDag-Erling Smørgrav 
4777b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_random_id(ldns_pkt * packet)4787b5038d7SDag-Erling Smørgrav ldns_pkt_set_random_id(ldns_pkt *packet)
4797b5038d7SDag-Erling Smørgrav {
4807b5038d7SDag-Erling Smørgrav 	uint16_t rid = ldns_get_random();
4817b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_id(packet, rid);
4827b5038d7SDag-Erling Smørgrav }
4837b5038d7SDag-Erling Smørgrav 
4847b5038d7SDag-Erling Smørgrav 
4857b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_qr(ldns_pkt * packet,bool qr)4867b5038d7SDag-Erling Smørgrav ldns_pkt_set_qr(ldns_pkt *packet, bool qr)
4877b5038d7SDag-Erling Smørgrav {
4887b5038d7SDag-Erling Smørgrav 	packet->_header->_qr = qr;
4897b5038d7SDag-Erling Smørgrav }
4907b5038d7SDag-Erling Smørgrav 
4917b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_aa(ldns_pkt * packet,bool aa)4927b5038d7SDag-Erling Smørgrav ldns_pkt_set_aa(ldns_pkt *packet, bool aa)
4937b5038d7SDag-Erling Smørgrav {
4947b5038d7SDag-Erling Smørgrav 	packet->_header->_aa = aa;
4957b5038d7SDag-Erling Smørgrav }
4967b5038d7SDag-Erling Smørgrav 
4977b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_tc(ldns_pkt * packet,bool tc)4987b5038d7SDag-Erling Smørgrav ldns_pkt_set_tc(ldns_pkt *packet, bool tc)
4997b5038d7SDag-Erling Smørgrav {
5007b5038d7SDag-Erling Smørgrav 	packet->_header->_tc = tc;
5017b5038d7SDag-Erling Smørgrav }
5027b5038d7SDag-Erling Smørgrav 
5037b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_rd(ldns_pkt * packet,bool rd)5047b5038d7SDag-Erling Smørgrav ldns_pkt_set_rd(ldns_pkt *packet, bool rd)
5057b5038d7SDag-Erling Smørgrav {
5067b5038d7SDag-Erling Smørgrav 	packet->_header->_rd = rd;
5077b5038d7SDag-Erling Smørgrav }
5087b5038d7SDag-Erling Smørgrav 
5097b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_additional(ldns_pkt * p,ldns_rr_list * rr)5107b5038d7SDag-Erling Smørgrav ldns_pkt_set_additional(ldns_pkt *p, ldns_rr_list *rr)
5117b5038d7SDag-Erling Smørgrav {
5127b5038d7SDag-Erling Smørgrav 	p->_additional = rr;
5137b5038d7SDag-Erling Smørgrav }
5147b5038d7SDag-Erling Smørgrav 
5157b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_question(ldns_pkt * p,ldns_rr_list * rr)5167b5038d7SDag-Erling Smørgrav ldns_pkt_set_question(ldns_pkt *p, ldns_rr_list *rr)
5177b5038d7SDag-Erling Smørgrav {
5187b5038d7SDag-Erling Smørgrav 	p->_question = rr;
5197b5038d7SDag-Erling Smørgrav }
5207b5038d7SDag-Erling Smørgrav 
5217b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_answer(ldns_pkt * p,ldns_rr_list * rr)5227b5038d7SDag-Erling Smørgrav ldns_pkt_set_answer(ldns_pkt *p, ldns_rr_list *rr)
5237b5038d7SDag-Erling Smørgrav {
5247b5038d7SDag-Erling Smørgrav 	p->_answer = rr;
5257b5038d7SDag-Erling Smørgrav }
5267b5038d7SDag-Erling Smørgrav 
5277b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_authority(ldns_pkt * p,ldns_rr_list * rr)5287b5038d7SDag-Erling Smørgrav ldns_pkt_set_authority(ldns_pkt *p, ldns_rr_list *rr)
5297b5038d7SDag-Erling Smørgrav {
5307b5038d7SDag-Erling Smørgrav 	p->_authority = rr;
5317b5038d7SDag-Erling Smørgrav }
5327b5038d7SDag-Erling Smørgrav 
5337b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_cd(ldns_pkt * packet,bool cd)5347b5038d7SDag-Erling Smørgrav ldns_pkt_set_cd(ldns_pkt *packet, bool cd)
5357b5038d7SDag-Erling Smørgrav {
5367b5038d7SDag-Erling Smørgrav 	packet->_header->_cd = cd;
5377b5038d7SDag-Erling Smørgrav }
5387b5038d7SDag-Erling Smørgrav 
5397b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_ra(ldns_pkt * packet,bool ra)5407b5038d7SDag-Erling Smørgrav ldns_pkt_set_ra(ldns_pkt *packet, bool ra)
5417b5038d7SDag-Erling Smørgrav {
5427b5038d7SDag-Erling Smørgrav 	packet->_header->_ra = ra;
5437b5038d7SDag-Erling Smørgrav }
5447b5038d7SDag-Erling Smørgrav 
5457b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_ad(ldns_pkt * packet,bool ad)5467b5038d7SDag-Erling Smørgrav ldns_pkt_set_ad(ldns_pkt *packet, bool ad)
5477b5038d7SDag-Erling Smørgrav {
5487b5038d7SDag-Erling Smørgrav 	packet->_header->_ad = ad;
5497b5038d7SDag-Erling Smørgrav }
5507b5038d7SDag-Erling Smørgrav 
5517b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_opcode(ldns_pkt * packet,ldns_pkt_opcode opcode)5527b5038d7SDag-Erling Smørgrav ldns_pkt_set_opcode(ldns_pkt *packet, ldns_pkt_opcode opcode)
5537b5038d7SDag-Erling Smørgrav {
5547b5038d7SDag-Erling Smørgrav 	packet->_header->_opcode = opcode;
5557b5038d7SDag-Erling Smørgrav }
5567b5038d7SDag-Erling Smørgrav 
5577b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_rcode(ldns_pkt * packet,uint8_t rcode)5587b5038d7SDag-Erling Smørgrav ldns_pkt_set_rcode(ldns_pkt *packet, uint8_t rcode)
5597b5038d7SDag-Erling Smørgrav {
5607b5038d7SDag-Erling Smørgrav 	packet->_header->_rcode = rcode;
5617b5038d7SDag-Erling Smørgrav }
5627b5038d7SDag-Erling Smørgrav 
5637b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_qdcount(ldns_pkt * packet,uint16_t qdcount)5647b5038d7SDag-Erling Smørgrav ldns_pkt_set_qdcount(ldns_pkt *packet, uint16_t qdcount)
5657b5038d7SDag-Erling Smørgrav {
5667b5038d7SDag-Erling Smørgrav 	packet->_header->_qdcount = qdcount;
5677b5038d7SDag-Erling Smørgrav }
5687b5038d7SDag-Erling Smørgrav 
5697b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_ancount(ldns_pkt * packet,uint16_t ancount)5707b5038d7SDag-Erling Smørgrav ldns_pkt_set_ancount(ldns_pkt *packet, uint16_t ancount)
5717b5038d7SDag-Erling Smørgrav {
5727b5038d7SDag-Erling Smørgrav 	packet->_header->_ancount = ancount;
5737b5038d7SDag-Erling Smørgrav }
5747b5038d7SDag-Erling Smørgrav 
5757b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_nscount(ldns_pkt * packet,uint16_t nscount)5767b5038d7SDag-Erling Smørgrav ldns_pkt_set_nscount(ldns_pkt *packet, uint16_t nscount)
5777b5038d7SDag-Erling Smørgrav {
5787b5038d7SDag-Erling Smørgrav 	packet->_header->_nscount = nscount;
5797b5038d7SDag-Erling Smørgrav }
5807b5038d7SDag-Erling Smørgrav 
5817b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_arcount(ldns_pkt * packet,uint16_t arcount)5827b5038d7SDag-Erling Smørgrav ldns_pkt_set_arcount(ldns_pkt *packet, uint16_t arcount)
5837b5038d7SDag-Erling Smørgrav {
5847b5038d7SDag-Erling Smørgrav 	packet->_header->_arcount = arcount;
5857b5038d7SDag-Erling Smørgrav }
5867b5038d7SDag-Erling Smørgrav 
5877b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_querytime(ldns_pkt * packet,uint32_t time)5887b5038d7SDag-Erling Smørgrav ldns_pkt_set_querytime(ldns_pkt *packet, uint32_t time)
5897b5038d7SDag-Erling Smørgrav {
5907b5038d7SDag-Erling Smørgrav 	packet->_querytime = time;
5917b5038d7SDag-Erling Smørgrav }
5927b5038d7SDag-Erling Smørgrav 
5937b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_answerfrom(ldns_pkt * packet,ldns_rdf * answerfrom)5947b5038d7SDag-Erling Smørgrav ldns_pkt_set_answerfrom(ldns_pkt *packet, ldns_rdf *answerfrom)
5957b5038d7SDag-Erling Smørgrav {
5967b5038d7SDag-Erling Smørgrav 	packet->_answerfrom = answerfrom;
5977b5038d7SDag-Erling Smørgrav }
5987b5038d7SDag-Erling Smørgrav 
5997b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_timestamp(ldns_pkt * packet,struct timeval timeval)6007b5038d7SDag-Erling Smørgrav ldns_pkt_set_timestamp(ldns_pkt *packet, struct timeval timeval)
6017b5038d7SDag-Erling Smørgrav {
6027b5038d7SDag-Erling Smørgrav 	packet->timestamp.tv_sec = timeval.tv_sec;
6037b5038d7SDag-Erling Smørgrav 	packet->timestamp.tv_usec = timeval.tv_usec;
6047b5038d7SDag-Erling Smørgrav }
6057b5038d7SDag-Erling Smørgrav 
6067b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_size(ldns_pkt * packet,size_t s)6077b5038d7SDag-Erling Smørgrav ldns_pkt_set_size(ldns_pkt *packet, size_t s)
6087b5038d7SDag-Erling Smørgrav {
6097b5038d7SDag-Erling Smørgrav 	packet->_size = s;
6107b5038d7SDag-Erling Smørgrav }
6117b5038d7SDag-Erling Smørgrav 
6127b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_edns_udp_size(ldns_pkt * packet,uint16_t s)6137b5038d7SDag-Erling Smørgrav ldns_pkt_set_edns_udp_size(ldns_pkt *packet, uint16_t s)
6147b5038d7SDag-Erling Smørgrav {
6157b5038d7SDag-Erling Smørgrav 	packet->_edns_udp_size = s;
6167b5038d7SDag-Erling Smørgrav }
6177b5038d7SDag-Erling Smørgrav 
6187b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_edns_extended_rcode(ldns_pkt * packet,uint8_t c)6197b5038d7SDag-Erling Smørgrav ldns_pkt_set_edns_extended_rcode(ldns_pkt *packet, uint8_t c)
6207b5038d7SDag-Erling Smørgrav {
6217b5038d7SDag-Erling Smørgrav 	packet->_edns_extended_rcode = c;
6227b5038d7SDag-Erling Smørgrav }
6237b5038d7SDag-Erling Smørgrav 
6247b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_edns_version(ldns_pkt * packet,uint8_t v)6257b5038d7SDag-Erling Smørgrav ldns_pkt_set_edns_version(ldns_pkt *packet, uint8_t v)
6267b5038d7SDag-Erling Smørgrav {
6277b5038d7SDag-Erling Smørgrav 	packet->_edns_version = v;
6287b5038d7SDag-Erling Smørgrav }
6297b5038d7SDag-Erling Smørgrav 
6307b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_edns_z(ldns_pkt * packet,uint16_t z)6317b5038d7SDag-Erling Smørgrav ldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z)
6327b5038d7SDag-Erling Smørgrav {
6337b5038d7SDag-Erling Smørgrav 	packet->_edns_z = z;
6347b5038d7SDag-Erling Smørgrav }
6357b5038d7SDag-Erling Smørgrav 
6367b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_edns_data(ldns_pkt * packet,ldns_rdf * data)6377b5038d7SDag-Erling Smørgrav ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data)
6387b5038d7SDag-Erling Smørgrav {
6397b5038d7SDag-Erling Smørgrav 	packet->_edns_data = data;
6407b5038d7SDag-Erling Smørgrav }
6417b5038d7SDag-Erling Smørgrav 
6427b5038d7SDag-Erling Smørgrav void
ldns_pkt_set_edns_option_list(ldns_pkt * packet,ldns_edns_option_list * list)643*5afab0e5SDag-Erling Smørgrav ldns_pkt_set_edns_option_list(ldns_pkt *packet, ldns_edns_option_list *list)
644*5afab0e5SDag-Erling Smørgrav {
645*5afab0e5SDag-Erling Smørgrav 	if (packet->_edns_list)
646*5afab0e5SDag-Erling Smørgrav 		ldns_edns_option_list_deep_free(packet->_edns_list);
647*5afab0e5SDag-Erling Smørgrav 	packet->_edns_list = list;
648*5afab0e5SDag-Erling Smørgrav }
649*5afab0e5SDag-Erling Smørgrav 
650*5afab0e5SDag-Erling Smørgrav 
651*5afab0e5SDag-Erling Smørgrav void
ldns_pkt_set_section_count(ldns_pkt * packet,ldns_pkt_section s,uint16_t count)6527b5038d7SDag-Erling Smørgrav ldns_pkt_set_section_count(ldns_pkt *packet, ldns_pkt_section s, uint16_t count)
6537b5038d7SDag-Erling Smørgrav {
6547b5038d7SDag-Erling Smørgrav 	switch(s) {
6557b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_QUESTION:
6567b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_qdcount(packet, count);
6577b5038d7SDag-Erling Smørgrav 			break;
6587b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ANSWER:
6597b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_ancount(packet, count);
6607b5038d7SDag-Erling Smørgrav 			break;
6617b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_AUTHORITY:
6627b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_nscount(packet, count);
6637b5038d7SDag-Erling Smørgrav 			break;
6647b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ADDITIONAL:
6657b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_arcount(packet, count);
6667b5038d7SDag-Erling Smørgrav 			break;
6677b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ANY:
6687b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ANY_NOQUESTION:
6697b5038d7SDag-Erling Smørgrav 			break;
6707b5038d7SDag-Erling Smørgrav 	}
6717b5038d7SDag-Erling Smørgrav }
6727b5038d7SDag-Erling Smørgrav 
ldns_pkt_set_tsig(ldns_pkt * pkt,ldns_rr * rr)6737b5038d7SDag-Erling Smørgrav void ldns_pkt_set_tsig(ldns_pkt *pkt, ldns_rr *rr)
6747b5038d7SDag-Erling Smørgrav {
6757b5038d7SDag-Erling Smørgrav 	pkt->_tsig_rr = rr;
6767b5038d7SDag-Erling Smørgrav }
6777b5038d7SDag-Erling Smørgrav 
6787b5038d7SDag-Erling Smørgrav bool
ldns_pkt_push_rr(ldns_pkt * packet,ldns_pkt_section section,ldns_rr * rr)6797b5038d7SDag-Erling Smørgrav ldns_pkt_push_rr(ldns_pkt *packet, ldns_pkt_section section, ldns_rr *rr)
6807b5038d7SDag-Erling Smørgrav {
6817b5038d7SDag-Erling Smørgrav 	switch(section) {
6827b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_QUESTION:
6832787e39aSDag-Erling Smørgrav 			if (!ldns_rr_list_push_rr(ldns_pkt_question(packet), rr)) {
6842787e39aSDag-Erling Smørgrav 				return false;
6852787e39aSDag-Erling Smørgrav 			}
6867b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_qdcount(packet, ldns_pkt_qdcount(packet) + 1);
6877b5038d7SDag-Erling Smørgrav 			break;
6887b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ANSWER:
6892787e39aSDag-Erling Smørgrav 			if (!ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr)) {
6902787e39aSDag-Erling Smørgrav 				return false;
6912787e39aSDag-Erling Smørgrav 			}
6927b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_ancount(packet, ldns_pkt_ancount(packet) + 1);
6937b5038d7SDag-Erling Smørgrav 			break;
6947b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_AUTHORITY:
6952787e39aSDag-Erling Smørgrav 			if (!ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr)) {
6962787e39aSDag-Erling Smørgrav 				return false;
6972787e39aSDag-Erling Smørgrav 			}
6987b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_nscount(packet, ldns_pkt_nscount(packet) + 1);
6997b5038d7SDag-Erling Smørgrav 			break;
7007b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ADDITIONAL:
7012787e39aSDag-Erling Smørgrav 			if (!ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr)) {
7022787e39aSDag-Erling Smørgrav 				return false;
7032787e39aSDag-Erling Smørgrav 			}
7047b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) + 1);
7057b5038d7SDag-Erling Smørgrav 			break;
7067b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ANY:
7077b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ANY_NOQUESTION:
7087b5038d7SDag-Erling Smørgrav 			/* shouldn't this error? */
7097b5038d7SDag-Erling Smørgrav 			break;
7107b5038d7SDag-Erling Smørgrav 	}
7117b5038d7SDag-Erling Smørgrav 	return true;
7127b5038d7SDag-Erling Smørgrav }
7137b5038d7SDag-Erling Smørgrav 
7147b5038d7SDag-Erling Smørgrav bool
ldns_pkt_safe_push_rr(ldns_pkt * pkt,ldns_pkt_section sec,ldns_rr * rr)7157b5038d7SDag-Erling Smørgrav ldns_pkt_safe_push_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr)
7167b5038d7SDag-Erling Smørgrav {
7177b5038d7SDag-Erling Smørgrav 
7187b5038d7SDag-Erling Smørgrav 	/* check to see if its there */
7197b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_rr(pkt, sec, rr)) {
7207b5038d7SDag-Erling Smørgrav 		/* already there */
7217b5038d7SDag-Erling Smørgrav 		return false;
7227b5038d7SDag-Erling Smørgrav 	}
7237b5038d7SDag-Erling Smørgrav 	return ldns_pkt_push_rr(pkt, sec, rr);
7247b5038d7SDag-Erling Smørgrav }
7257b5038d7SDag-Erling Smørgrav 
7267b5038d7SDag-Erling Smørgrav bool
ldns_pkt_push_rr_list(ldns_pkt * p,ldns_pkt_section s,ldns_rr_list * list)7277b5038d7SDag-Erling Smørgrav ldns_pkt_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
7287b5038d7SDag-Erling Smørgrav {
7297b5038d7SDag-Erling Smørgrav 	size_t i;
7307b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
7317b5038d7SDag-Erling Smørgrav 		if (!ldns_pkt_push_rr(p, s, ldns_rr_list_rr(list, i))) {
7327b5038d7SDag-Erling Smørgrav 			return false;
7337b5038d7SDag-Erling Smørgrav 		}
7347b5038d7SDag-Erling Smørgrav 	}
7357b5038d7SDag-Erling Smørgrav 	return true;
7367b5038d7SDag-Erling Smørgrav }
7377b5038d7SDag-Erling Smørgrav 
7387b5038d7SDag-Erling Smørgrav bool
ldns_pkt_safe_push_rr_list(ldns_pkt * p,ldns_pkt_section s,ldns_rr_list * list)7397b5038d7SDag-Erling Smørgrav ldns_pkt_safe_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
7407b5038d7SDag-Erling Smørgrav {
7417b5038d7SDag-Erling Smørgrav 	size_t i;
7427b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
7437b5038d7SDag-Erling Smørgrav 		if (!ldns_pkt_safe_push_rr(p, s, ldns_rr_list_rr(list, i))) {
7447b5038d7SDag-Erling Smørgrav 			return false;
7457b5038d7SDag-Erling Smørgrav 		}
7467b5038d7SDag-Erling Smørgrav 	}
7477b5038d7SDag-Erling Smørgrav 	return true;
7487b5038d7SDag-Erling Smørgrav }
7497b5038d7SDag-Erling Smørgrav 
7507b5038d7SDag-Erling Smørgrav bool
ldns_pkt_edns(const ldns_pkt * pkt)751*5afab0e5SDag-Erling Smørgrav ldns_pkt_edns(const ldns_pkt *pkt)
752*5afab0e5SDag-Erling Smørgrav {
7537b5038d7SDag-Erling Smørgrav 	return (ldns_pkt_edns_udp_size(pkt) > 0 ||
7547b5038d7SDag-Erling Smørgrav 		ldns_pkt_edns_extended_rcode(pkt) > 0 ||
7557b5038d7SDag-Erling Smørgrav 		ldns_pkt_edns_data(pkt) ||
756986ba33cSDag-Erling Smørgrav 		ldns_pkt_edns_do(pkt) ||
757*5afab0e5SDag-Erling Smørgrav 		pkt->_edns_list ||
758986ba33cSDag-Erling Smørgrav                 pkt->_edns_present
7597b5038d7SDag-Erling Smørgrav 	       );
7607b5038d7SDag-Erling Smørgrav }
7617b5038d7SDag-Erling Smørgrav 
762*5afab0e5SDag-Erling Smørgrav ldns_edns_option_list*
pkt_edns_data2edns_option_list(const ldns_rdf * edns_data)763*5afab0e5SDag-Erling Smørgrav pkt_edns_data2edns_option_list(const ldns_rdf *edns_data)
764*5afab0e5SDag-Erling Smørgrav {
765*5afab0e5SDag-Erling Smørgrav 	size_t pos = 0;
766*5afab0e5SDag-Erling Smørgrav 	ldns_edns_option_list* edns_list;
767*5afab0e5SDag-Erling Smørgrav 	size_t max;
768*5afab0e5SDag-Erling Smørgrav 	const uint8_t* wire;
769*5afab0e5SDag-Erling Smørgrav 
770*5afab0e5SDag-Erling Smørgrav 	if (!edns_data)
771*5afab0e5SDag-Erling Smørgrav 		return NULL;
772*5afab0e5SDag-Erling Smørgrav 
773*5afab0e5SDag-Erling Smørgrav 	max = ldns_rdf_size(edns_data);
774*5afab0e5SDag-Erling Smørgrav 	wire = ldns_rdf_data(edns_data);
775*5afab0e5SDag-Erling Smørgrav 	if (!max)
776*5afab0e5SDag-Erling Smørgrav 		return NULL;
777*5afab0e5SDag-Erling Smørgrav 
778*5afab0e5SDag-Erling Smørgrav 	if (!(edns_list = ldns_edns_option_list_new()))
779*5afab0e5SDag-Erling Smørgrav 		return NULL;
780*5afab0e5SDag-Erling Smørgrav 
781*5afab0e5SDag-Erling Smørgrav 	while (pos < max) {
782*5afab0e5SDag-Erling Smørgrav 		ldns_edns_option* edns;
783*5afab0e5SDag-Erling Smørgrav 		uint8_t *data;
784*5afab0e5SDag-Erling Smørgrav 
785*5afab0e5SDag-Erling Smørgrav 		if (pos + 4 > max) { /* make sure the header is  */
786*5afab0e5SDag-Erling Smørgrav 			ldns_edns_option_list_deep_free(edns_list);
787*5afab0e5SDag-Erling Smørgrav 			return NULL;
788*5afab0e5SDag-Erling Smørgrav 		}
789*5afab0e5SDag-Erling Smørgrav 		ldns_edns_option_code code = ldns_read_uint16(&wire[pos]);
790*5afab0e5SDag-Erling Smørgrav 		size_t size = ldns_read_uint16(&wire[pos+2]);
791*5afab0e5SDag-Erling Smørgrav 		pos += 4;
792*5afab0e5SDag-Erling Smørgrav 
793*5afab0e5SDag-Erling Smørgrav 		if (pos + size > max) { /* make sure the size fits the data */
794*5afab0e5SDag-Erling Smørgrav 			ldns_edns_option_list_deep_free(edns_list);
795*5afab0e5SDag-Erling Smørgrav 			return NULL;
796*5afab0e5SDag-Erling Smørgrav 		}
797*5afab0e5SDag-Erling Smørgrav 		data = LDNS_XMALLOC(uint8_t, size);
798*5afab0e5SDag-Erling Smørgrav 
799*5afab0e5SDag-Erling Smørgrav 		if (!data) {
800*5afab0e5SDag-Erling Smørgrav 			ldns_edns_option_list_deep_free(edns_list);
801*5afab0e5SDag-Erling Smørgrav 			return NULL;
802*5afab0e5SDag-Erling Smørgrav 		}
803*5afab0e5SDag-Erling Smørgrav 		memcpy(data, &wire[pos], size);
804*5afab0e5SDag-Erling Smørgrav 		pos += size;
805*5afab0e5SDag-Erling Smørgrav 
806*5afab0e5SDag-Erling Smørgrav 		edns = ldns_edns_new(code, size, data);
807*5afab0e5SDag-Erling Smørgrav 
808*5afab0e5SDag-Erling Smørgrav 		if (!edns) {
809*5afab0e5SDag-Erling Smørgrav 			ldns_edns_option_list_deep_free(edns_list);
810*5afab0e5SDag-Erling Smørgrav 			return NULL;
811*5afab0e5SDag-Erling Smørgrav 		}
812*5afab0e5SDag-Erling Smørgrav 		if (!ldns_edns_option_list_push(edns_list, edns)) {
813*5afab0e5SDag-Erling Smørgrav 			ldns_edns_option_list_deep_free(edns_list);
814*5afab0e5SDag-Erling Smørgrav 			return NULL;
815*5afab0e5SDag-Erling Smørgrav 		}
816*5afab0e5SDag-Erling Smørgrav 	}
817*5afab0e5SDag-Erling Smørgrav 	return edns_list;
818*5afab0e5SDag-Erling Smørgrav 
819*5afab0e5SDag-Erling Smørgrav }
820*5afab0e5SDag-Erling Smørgrav 
821*5afab0e5SDag-Erling Smørgrav ldns_edns_option_list*
ldns_pkt_edns_get_option_list(ldns_pkt * packet)822*5afab0e5SDag-Erling Smørgrav ldns_pkt_edns_get_option_list(ldns_pkt *packet)
823*5afab0e5SDag-Erling Smørgrav {
824*5afab0e5SDag-Erling Smørgrav 	/* return the list if it already exists */
825*5afab0e5SDag-Erling Smørgrav 	if (packet->_edns_list != NULL)
826*5afab0e5SDag-Erling Smørgrav 		return packet->_edns_list;
827*5afab0e5SDag-Erling Smørgrav 
828*5afab0e5SDag-Erling Smørgrav 	/* if the list doesn't exists, we create it by parsing the
829*5afab0e5SDag-Erling Smørgrav 	 * packet->_edns_data
830*5afab0e5SDag-Erling Smørgrav 	 */
831*5afab0e5SDag-Erling Smørgrav 	if (!ldns_pkt_edns_data(packet))
832*5afab0e5SDag-Erling Smørgrav 		return NULL;
833*5afab0e5SDag-Erling Smørgrav 
834*5afab0e5SDag-Erling Smørgrav 	return ( packet->_edns_list
835*5afab0e5SDag-Erling Smørgrav 	       = pkt_edns_data2edns_option_list(ldns_pkt_edns_data(packet)));
836*5afab0e5SDag-Erling Smørgrav }
837*5afab0e5SDag-Erling Smørgrav 
8387b5038d7SDag-Erling Smørgrav 
8397b5038d7SDag-Erling Smørgrav /* Create/destroy/convert functions
8407b5038d7SDag-Erling Smørgrav  */
8417b5038d7SDag-Erling Smørgrav ldns_pkt *
ldns_pkt_new(void)8427b5038d7SDag-Erling Smørgrav ldns_pkt_new(void)
8437b5038d7SDag-Erling Smørgrav {
8447b5038d7SDag-Erling Smørgrav 	ldns_pkt *packet;
8457b5038d7SDag-Erling Smørgrav 	packet = LDNS_MALLOC(ldns_pkt);
8467b5038d7SDag-Erling Smørgrav 	if (!packet) {
8477b5038d7SDag-Erling Smørgrav 		return NULL;
8487b5038d7SDag-Erling Smørgrav 	}
8497b5038d7SDag-Erling Smørgrav 
8507b5038d7SDag-Erling Smørgrav 	packet->_header = LDNS_MALLOC(ldns_hdr);
8517b5038d7SDag-Erling Smørgrav 	if (!packet->_header) {
8527b5038d7SDag-Erling Smørgrav 		LDNS_FREE(packet);
8537b5038d7SDag-Erling Smørgrav 		return NULL;
8547b5038d7SDag-Erling Smørgrav 	}
8557b5038d7SDag-Erling Smørgrav 
8567b5038d7SDag-Erling Smørgrav 	packet->_question = ldns_rr_list_new();
8577b5038d7SDag-Erling Smørgrav 	packet->_answer = ldns_rr_list_new();
8587b5038d7SDag-Erling Smørgrav 	packet->_authority = ldns_rr_list_new();
8597b5038d7SDag-Erling Smørgrav 	packet->_additional = ldns_rr_list_new();
8607b5038d7SDag-Erling Smørgrav 
8617b5038d7SDag-Erling Smørgrav 	/* default everything to false */
8627b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_qr(packet, false);
8637b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_aa(packet, false);
8647b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_tc(packet, false);
8657b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_rd(packet, false);
8667b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_ra(packet, false);
8677b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_ad(packet, false);
8687b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_cd(packet, false);
8697b5038d7SDag-Erling Smørgrav 
8707b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_opcode(packet, LDNS_PACKET_QUERY);
8717b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_rcode(packet, 0);
8727b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_id(packet, 0);
8737b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_size(packet, 0);
8747b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_querytime(packet, 0);
8757b5038d7SDag-Erling Smørgrav 	memset(&packet->timestamp, 0, sizeof(packet->timestamp));
8767b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_answerfrom(packet, NULL);
8777b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_section_count(packet, LDNS_SECTION_QUESTION, 0);
8787b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_section_count(packet, LDNS_SECTION_ANSWER, 0);
8797b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_section_count(packet, LDNS_SECTION_AUTHORITY, 0);
8807b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_section_count(packet, LDNS_SECTION_ADDITIONAL, 0);
8817b5038d7SDag-Erling Smørgrav 
8827b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_udp_size(packet, 0);
8837b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_extended_rcode(packet, 0);
8847b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_version(packet, 0);
8857b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_z(packet, 0);
8867b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_data(packet, NULL);
887*5afab0e5SDag-Erling Smørgrav 	packet->_edns_list = NULL;
888986ba33cSDag-Erling Smørgrav 	packet->_edns_present = false;
8897b5038d7SDag-Erling Smørgrav 
8907b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_tsig(packet, NULL);
8917b5038d7SDag-Erling Smørgrav 
8927b5038d7SDag-Erling Smørgrav 	return packet;
8937b5038d7SDag-Erling Smørgrav }
8947b5038d7SDag-Erling Smørgrav 
8957b5038d7SDag-Erling Smørgrav void
ldns_pkt_free(ldns_pkt * packet)8967b5038d7SDag-Erling Smørgrav ldns_pkt_free(ldns_pkt *packet)
8977b5038d7SDag-Erling Smørgrav {
8987b5038d7SDag-Erling Smørgrav 	if (packet) {
8997b5038d7SDag-Erling Smørgrav 		LDNS_FREE(packet->_header);
9007b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(packet->_question);
9017b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(packet->_answer);
9027b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(packet->_authority);
9037b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(packet->_additional);
9047b5038d7SDag-Erling Smørgrav 		ldns_rr_free(packet->_tsig_rr);
9057b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(packet->_edns_data);
906*5afab0e5SDag-Erling Smørgrav 		ldns_edns_option_list_deep_free(packet->_edns_list);
9072787e39aSDag-Erling Smørgrav 		ldns_rdf_deep_free(packet->_answerfrom);
9087b5038d7SDag-Erling Smørgrav 		LDNS_FREE(packet);
9097b5038d7SDag-Erling Smørgrav 	}
9107b5038d7SDag-Erling Smørgrav }
9117b5038d7SDag-Erling Smørgrav 
9127b5038d7SDag-Erling Smørgrav bool
ldns_pkt_set_flags(ldns_pkt * packet,uint16_t flags)9137b5038d7SDag-Erling Smørgrav ldns_pkt_set_flags(ldns_pkt *packet, uint16_t flags)
9147b5038d7SDag-Erling Smørgrav {
9157b5038d7SDag-Erling Smørgrav 	if (!packet) {
9167b5038d7SDag-Erling Smørgrav 		return false;
9177b5038d7SDag-Erling Smørgrav 	}
9187b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_QR) == LDNS_QR) {
9197b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_qr(packet, true);
9207b5038d7SDag-Erling Smørgrav 	}
9217b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_AA) == LDNS_AA) {
9227b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_aa(packet, true);
9237b5038d7SDag-Erling Smørgrav 	}
9247b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_RD) == LDNS_RD) {
9257b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_rd(packet, true);
9267b5038d7SDag-Erling Smørgrav 	}
9277b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_TC) == LDNS_TC) {
9287b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_tc(packet, true);
9297b5038d7SDag-Erling Smørgrav 	}
9307b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_CD) == LDNS_CD) {
9317b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_cd(packet, true);
9327b5038d7SDag-Erling Smørgrav 	}
9337b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_RA) == LDNS_RA) {
9347b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_ra(packet, true);
9357b5038d7SDag-Erling Smørgrav 	}
9367b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_AD) == LDNS_AD) {
9377b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_ad(packet, true);
9387b5038d7SDag-Erling Smørgrav 	}
9397b5038d7SDag-Erling Smørgrav 	return true;
9407b5038d7SDag-Erling Smørgrav }
9417b5038d7SDag-Erling Smørgrav 
9422787e39aSDag-Erling Smørgrav 
94317d15b25SDag-Erling Smørgrav static ldns_rr*
ldns_pkt_authsoa(const ldns_rdf * rr_name,ldns_rr_class rr_class)944986ba33cSDag-Erling Smørgrav ldns_pkt_authsoa(const ldns_rdf* rr_name, ldns_rr_class rr_class)
9452787e39aSDag-Erling Smørgrav {
9462787e39aSDag-Erling Smørgrav 	ldns_rr* soa_rr = ldns_rr_new();
9472787e39aSDag-Erling Smørgrav 	ldns_rdf *owner_rdf;
9482787e39aSDag-Erling Smørgrav 	ldns_rdf *mname_rdf;
9492787e39aSDag-Erling Smørgrav 	ldns_rdf *rname_rdf;
9502787e39aSDag-Erling Smørgrav 	ldns_rdf *serial_rdf;
9512787e39aSDag-Erling Smørgrav 	ldns_rdf *refresh_rdf;
9522787e39aSDag-Erling Smørgrav 	ldns_rdf *retry_rdf;
9532787e39aSDag-Erling Smørgrav 	ldns_rdf *expire_rdf;
9542787e39aSDag-Erling Smørgrav 	ldns_rdf *minimum_rdf;
9552787e39aSDag-Erling Smørgrav 
9562787e39aSDag-Erling Smørgrav 	if (!soa_rr) {
95717d15b25SDag-Erling Smørgrav 		return NULL;
9582787e39aSDag-Erling Smørgrav 	}
9592787e39aSDag-Erling Smørgrav 	owner_rdf = ldns_rdf_clone(rr_name);
9602787e39aSDag-Erling Smørgrav 	if (!owner_rdf) {
9612787e39aSDag-Erling Smørgrav 		ldns_rr_free(soa_rr);
96217d15b25SDag-Erling Smørgrav 		return NULL;
9632787e39aSDag-Erling Smørgrav 	}
9642787e39aSDag-Erling Smørgrav 
9652787e39aSDag-Erling Smørgrav 	ldns_rr_set_owner(soa_rr, owner_rdf);
9662787e39aSDag-Erling Smørgrav 	ldns_rr_set_type(soa_rr, LDNS_RR_TYPE_SOA);
9672787e39aSDag-Erling Smørgrav 	ldns_rr_set_class(soa_rr, rr_class);
9682787e39aSDag-Erling Smørgrav 	ldns_rr_set_question(soa_rr, false);
9692787e39aSDag-Erling Smørgrav 
9702787e39aSDag-Erling Smørgrav 	if (ldns_str2rdf_dname(&mname_rdf, ".") != LDNS_STATUS_OK) {
9712787e39aSDag-Erling Smørgrav 		ldns_rr_free(soa_rr);
97217d15b25SDag-Erling Smørgrav 		return NULL;
9732787e39aSDag-Erling Smørgrav 	} else {
9742787e39aSDag-Erling Smørgrav 		ldns_rr_push_rdf(soa_rr, mname_rdf);
9752787e39aSDag-Erling Smørgrav 	}
9762787e39aSDag-Erling Smørgrav 	if (ldns_str2rdf_dname(&rname_rdf, ".") != LDNS_STATUS_OK) {
9772787e39aSDag-Erling Smørgrav 		ldns_rr_free(soa_rr);
97817d15b25SDag-Erling Smørgrav 		return NULL;
9792787e39aSDag-Erling Smørgrav 	} else {
9802787e39aSDag-Erling Smørgrav 		ldns_rr_push_rdf(soa_rr, rname_rdf);
9812787e39aSDag-Erling Smørgrav 	}
9822787e39aSDag-Erling Smørgrav 	serial_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
9832787e39aSDag-Erling Smørgrav 	if (!serial_rdf) {
9842787e39aSDag-Erling Smørgrav 		ldns_rr_free(soa_rr);
98517d15b25SDag-Erling Smørgrav 		return NULL;
9862787e39aSDag-Erling Smørgrav 	} else {
9872787e39aSDag-Erling Smørgrav 		ldns_rr_push_rdf(soa_rr, serial_rdf);
9882787e39aSDag-Erling Smørgrav 	}
9892787e39aSDag-Erling Smørgrav 	refresh_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
9902787e39aSDag-Erling Smørgrav 	if (!refresh_rdf) {
9912787e39aSDag-Erling Smørgrav 		ldns_rr_free(soa_rr);
99217d15b25SDag-Erling Smørgrav 		return NULL;
9932787e39aSDag-Erling Smørgrav 	} else {
9942787e39aSDag-Erling Smørgrav 		ldns_rr_push_rdf(soa_rr, refresh_rdf);
9952787e39aSDag-Erling Smørgrav 	}
9962787e39aSDag-Erling Smørgrav 	retry_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
9972787e39aSDag-Erling Smørgrav 	if (!retry_rdf) {
9982787e39aSDag-Erling Smørgrav 		ldns_rr_free(soa_rr);
99917d15b25SDag-Erling Smørgrav 		return NULL;
10002787e39aSDag-Erling Smørgrav 	} else {
10012787e39aSDag-Erling Smørgrav 		ldns_rr_push_rdf(soa_rr, retry_rdf);
10022787e39aSDag-Erling Smørgrav 	}
10032787e39aSDag-Erling Smørgrav 	expire_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
10042787e39aSDag-Erling Smørgrav 	if (!expire_rdf) {
10052787e39aSDag-Erling Smørgrav 		ldns_rr_free(soa_rr);
100617d15b25SDag-Erling Smørgrav 		return NULL;
10072787e39aSDag-Erling Smørgrav 	} else {
10082787e39aSDag-Erling Smørgrav 		ldns_rr_push_rdf(soa_rr, expire_rdf);
10092787e39aSDag-Erling Smørgrav 	}
10102787e39aSDag-Erling Smørgrav 	minimum_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
10112787e39aSDag-Erling Smørgrav 	if (!minimum_rdf) {
10122787e39aSDag-Erling Smørgrav 		ldns_rr_free(soa_rr);
101317d15b25SDag-Erling Smørgrav 		return NULL;
10142787e39aSDag-Erling Smørgrav 	} else {
10152787e39aSDag-Erling Smørgrav 		ldns_rr_push_rdf(soa_rr, minimum_rdf);
10162787e39aSDag-Erling Smørgrav 	}
101717d15b25SDag-Erling Smørgrav 	return soa_rr;
10182787e39aSDag-Erling Smørgrav }
10192787e39aSDag-Erling Smørgrav 
10202787e39aSDag-Erling Smørgrav 
102117d15b25SDag-Erling Smørgrav static ldns_status
ldns_pkt_query_new_frm_str_internal(ldns_pkt ** p,const char * name,ldns_rr_type rr_type,ldns_rr_class rr_class,uint16_t flags,ldns_rr * authsoa_rr)102217d15b25SDag-Erling Smørgrav ldns_pkt_query_new_frm_str_internal(ldns_pkt **p, const char *name,
102317d15b25SDag-Erling Smørgrav 	ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags,
102417d15b25SDag-Erling Smørgrav 	ldns_rr* authsoa_rr)
10257b5038d7SDag-Erling Smørgrav {
10267b5038d7SDag-Erling Smørgrav 	ldns_pkt *packet;
10277b5038d7SDag-Erling Smørgrav 	ldns_rr *question_rr;
10287b5038d7SDag-Erling Smørgrav 	ldns_rdf *name_rdf;
10297b5038d7SDag-Erling Smørgrav 
10307b5038d7SDag-Erling Smørgrav 	packet = ldns_pkt_new();
10317b5038d7SDag-Erling Smørgrav 	if (!packet) {
10327b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_MEM_ERR;
10337b5038d7SDag-Erling Smørgrav 	}
10347b5038d7SDag-Erling Smørgrav 
10357b5038d7SDag-Erling Smørgrav 	if (!ldns_pkt_set_flags(packet, flags)) {
1036*5afab0e5SDag-Erling Smørgrav 		ldns_pkt_free(packet);
10377b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
10387b5038d7SDag-Erling Smørgrav 	}
10397b5038d7SDag-Erling Smørgrav 
10407b5038d7SDag-Erling Smørgrav 	question_rr = ldns_rr_new();
10417b5038d7SDag-Erling Smørgrav 	if (!question_rr) {
1042*5afab0e5SDag-Erling Smørgrav 		ldns_pkt_free(packet);
10437b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_MEM_ERR;
10447b5038d7SDag-Erling Smørgrav 	}
10457b5038d7SDag-Erling Smørgrav 
10467b5038d7SDag-Erling Smørgrav 	if (rr_type == 0) {
10477b5038d7SDag-Erling Smørgrav 		rr_type = LDNS_RR_TYPE_A;
10487b5038d7SDag-Erling Smørgrav 	}
10497b5038d7SDag-Erling Smørgrav 	if (rr_class == 0) {
10507b5038d7SDag-Erling Smørgrav 		rr_class = LDNS_RR_CLASS_IN;
10517b5038d7SDag-Erling Smørgrav 	}
10527b5038d7SDag-Erling Smørgrav 
10537b5038d7SDag-Erling Smørgrav 	if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) {
10547b5038d7SDag-Erling Smørgrav 		ldns_rr_set_owner(question_rr, name_rdf);
10557b5038d7SDag-Erling Smørgrav 		ldns_rr_set_type(question_rr, rr_type);
10567b5038d7SDag-Erling Smørgrav 		ldns_rr_set_class(question_rr, rr_class);
10577b5038d7SDag-Erling Smørgrav                 ldns_rr_set_question(question_rr, true);
10587b5038d7SDag-Erling Smørgrav 
10597b5038d7SDag-Erling Smørgrav 		ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr);
10607b5038d7SDag-Erling Smørgrav 	} else {
10617b5038d7SDag-Erling Smørgrav 		ldns_rr_free(question_rr);
10627b5038d7SDag-Erling Smørgrav 		ldns_pkt_free(packet);
10637b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
10647b5038d7SDag-Erling Smørgrav 	}
10657b5038d7SDag-Erling Smørgrav 
106617d15b25SDag-Erling Smørgrav 	if (authsoa_rr) {
106717d15b25SDag-Erling Smørgrav 		ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, authsoa_rr);
10682787e39aSDag-Erling Smørgrav 	}
10697b5038d7SDag-Erling Smørgrav 
10702787e39aSDag-Erling Smørgrav 	packet->_tsig_rr = NULL;
10717b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_answerfrom(packet, NULL);
10727b5038d7SDag-Erling Smørgrav 	if (p) {
10737b5038d7SDag-Erling Smørgrav 		*p = packet;
10747b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_OK;
10757b5038d7SDag-Erling Smørgrav 	} else {
10762787e39aSDag-Erling Smørgrav 		ldns_pkt_free(packet);
10777b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_NULL;
10787b5038d7SDag-Erling Smørgrav 	}
10797b5038d7SDag-Erling Smørgrav }
10807b5038d7SDag-Erling Smørgrav 
108117d15b25SDag-Erling Smørgrav ldns_status
ldns_pkt_query_new_frm_str(ldns_pkt ** p,const char * name,ldns_rr_type rr_type,ldns_rr_class rr_class,uint16_t flags)108217d15b25SDag-Erling Smørgrav ldns_pkt_query_new_frm_str(ldns_pkt **p, const char *name,
108317d15b25SDag-Erling Smørgrav 	ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags)
108417d15b25SDag-Erling Smørgrav {
108517d15b25SDag-Erling Smørgrav 	return ldns_pkt_query_new_frm_str_internal(p, name, rr_type,
108617d15b25SDag-Erling Smørgrav 		rr_class, flags, NULL);
108717d15b25SDag-Erling Smørgrav }
108817d15b25SDag-Erling Smørgrav 
108917d15b25SDag-Erling Smørgrav ldns_status
ldns_pkt_ixfr_request_new_frm_str(ldns_pkt ** p,const char * name,ldns_rr_class rr_class,uint16_t flags,ldns_rr * soa)109017d15b25SDag-Erling Smørgrav ldns_pkt_ixfr_request_new_frm_str(ldns_pkt **p, const char *name,
109117d15b25SDag-Erling Smørgrav 	ldns_rr_class rr_class, uint16_t flags, ldns_rr *soa)
109217d15b25SDag-Erling Smørgrav {
109317d15b25SDag-Erling Smørgrav 	ldns_rr* authsoa_rr = soa;
109417d15b25SDag-Erling Smørgrav 	if (!authsoa_rr) {
109517d15b25SDag-Erling Smørgrav 		ldns_rdf *name_rdf;
109617d15b25SDag-Erling Smørgrav 		if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) {
109717d15b25SDag-Erling Smørgrav 			authsoa_rr = ldns_pkt_authsoa(name_rdf, rr_class);
109817d15b25SDag-Erling Smørgrav 		}
109917d15b25SDag-Erling Smørgrav 		ldns_rdf_free(name_rdf);
110017d15b25SDag-Erling Smørgrav 	}
110117d15b25SDag-Erling Smørgrav 	return ldns_pkt_query_new_frm_str_internal(p, name, LDNS_RR_TYPE_IXFR,
110217d15b25SDag-Erling Smørgrav 		rr_class, flags, authsoa_rr);
110317d15b25SDag-Erling Smørgrav }
110417d15b25SDag-Erling Smørgrav 
110517d15b25SDag-Erling Smørgrav static ldns_pkt *
ldns_pkt_query_new_internal(ldns_rdf * rr_name,ldns_rr_type rr_type,ldns_rr_class rr_class,uint16_t flags,ldns_rr * authsoa_rr)110617d15b25SDag-Erling Smørgrav ldns_pkt_query_new_internal(ldns_rdf *rr_name, ldns_rr_type rr_type,
110717d15b25SDag-Erling Smørgrav 	ldns_rr_class rr_class,	uint16_t flags, ldns_rr* authsoa_rr)
11087b5038d7SDag-Erling Smørgrav {
11097b5038d7SDag-Erling Smørgrav 	ldns_pkt *packet;
11107b5038d7SDag-Erling Smørgrav 	ldns_rr *question_rr;
11117b5038d7SDag-Erling Smørgrav 
11127b5038d7SDag-Erling Smørgrav 	packet = ldns_pkt_new();
11137b5038d7SDag-Erling Smørgrav 	if (!packet) {
11147b5038d7SDag-Erling Smørgrav 		return NULL;
11157b5038d7SDag-Erling Smørgrav 	}
11167b5038d7SDag-Erling Smørgrav 
11177b5038d7SDag-Erling Smørgrav 	if (!ldns_pkt_set_flags(packet, flags)) {
11187b5038d7SDag-Erling Smørgrav 		return NULL;
11197b5038d7SDag-Erling Smørgrav 	}
11207b5038d7SDag-Erling Smørgrav 
11217b5038d7SDag-Erling Smørgrav 	question_rr = ldns_rr_new();
11227b5038d7SDag-Erling Smørgrav 	if (!question_rr) {
11232787e39aSDag-Erling Smørgrav 		ldns_pkt_free(packet);
11247b5038d7SDag-Erling Smørgrav 		return NULL;
11257b5038d7SDag-Erling Smørgrav 	}
11267b5038d7SDag-Erling Smørgrav 
11277b5038d7SDag-Erling Smørgrav 	if (rr_type == 0) {
11287b5038d7SDag-Erling Smørgrav 		rr_type = LDNS_RR_TYPE_A;
11297b5038d7SDag-Erling Smørgrav 	}
11307b5038d7SDag-Erling Smørgrav 	if (rr_class == 0) {
11317b5038d7SDag-Erling Smørgrav 		rr_class = LDNS_RR_CLASS_IN;
11327b5038d7SDag-Erling Smørgrav 	}
11337b5038d7SDag-Erling Smørgrav 
11347b5038d7SDag-Erling Smørgrav 	ldns_rr_set_owner(question_rr, rr_name);
11357b5038d7SDag-Erling Smørgrav 	ldns_rr_set_type(question_rr, rr_type);
11367b5038d7SDag-Erling Smørgrav 	ldns_rr_set_class(question_rr, rr_class);
11377b5038d7SDag-Erling Smørgrav         ldns_rr_set_question(question_rr, true);
11387b5038d7SDag-Erling Smørgrav 	ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr);
11397b5038d7SDag-Erling Smørgrav 
114017d15b25SDag-Erling Smørgrav 	if (authsoa_rr) {
114117d15b25SDag-Erling Smørgrav 		ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, authsoa_rr);
11422787e39aSDag-Erling Smørgrav 	}
11432787e39aSDag-Erling Smørgrav 
11442787e39aSDag-Erling Smørgrav 	packet->_tsig_rr = NULL;
11457b5038d7SDag-Erling Smørgrav 	return packet;
11467b5038d7SDag-Erling Smørgrav }
11477b5038d7SDag-Erling Smørgrav 
114817d15b25SDag-Erling Smørgrav ldns_pkt *
ldns_pkt_query_new(ldns_rdf * rr_name,ldns_rr_type rr_type,ldns_rr_class rr_class,uint16_t flags)114917d15b25SDag-Erling Smørgrav ldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type,
115017d15b25SDag-Erling Smørgrav 	ldns_rr_class rr_class,	uint16_t flags)
115117d15b25SDag-Erling Smørgrav {
115217d15b25SDag-Erling Smørgrav 	return ldns_pkt_query_new_internal(rr_name, rr_type,
115317d15b25SDag-Erling Smørgrav 		rr_class, flags, NULL);
115417d15b25SDag-Erling Smørgrav }
115517d15b25SDag-Erling Smørgrav 
115617d15b25SDag-Erling Smørgrav ldns_pkt *
ldns_pkt_ixfr_request_new(ldns_rdf * rr_name,ldns_rr_class rr_class,uint16_t flags,ldns_rr * soa)115717d15b25SDag-Erling Smørgrav ldns_pkt_ixfr_request_new(ldns_rdf *rr_name, ldns_rr_class rr_class,
115817d15b25SDag-Erling Smørgrav 	uint16_t flags, ldns_rr* soa)
115917d15b25SDag-Erling Smørgrav {
116017d15b25SDag-Erling Smørgrav 	ldns_rr* authsoa_rr = soa;
116117d15b25SDag-Erling Smørgrav 	if (!authsoa_rr) {
116217d15b25SDag-Erling Smørgrav 		authsoa_rr = ldns_pkt_authsoa(rr_name, rr_class);
116317d15b25SDag-Erling Smørgrav 	}
116417d15b25SDag-Erling Smørgrav 	return ldns_pkt_query_new_internal(rr_name, LDNS_RR_TYPE_IXFR,
116517d15b25SDag-Erling Smørgrav 		rr_class, flags, authsoa_rr);
116617d15b25SDag-Erling Smørgrav }
116717d15b25SDag-Erling Smørgrav 
11687b5038d7SDag-Erling Smørgrav ldns_pkt_type
ldns_pkt_reply_type(const ldns_pkt * p)1169986ba33cSDag-Erling Smørgrav ldns_pkt_reply_type(const ldns_pkt *p)
11707b5038d7SDag-Erling Smørgrav {
11717b5038d7SDag-Erling Smørgrav 	ldns_rr_list *tmp;
11727b5038d7SDag-Erling Smørgrav 
11737b5038d7SDag-Erling Smørgrav 	if (!p) {
11747b5038d7SDag-Erling Smørgrav 		return LDNS_PACKET_UNKNOWN;
11757b5038d7SDag-Erling Smørgrav 	}
11767b5038d7SDag-Erling Smørgrav 
11777b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NXDOMAIN) {
11787b5038d7SDag-Erling Smørgrav 		return LDNS_PACKET_NXDOMAIN;
11797b5038d7SDag-Erling Smørgrav 	}
11807b5038d7SDag-Erling Smørgrav 
11817b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_ancount(p) == 0 && ldns_pkt_arcount(p) == 0
11827b5038d7SDag-Erling Smørgrav 			&& ldns_pkt_nscount(p) == 1) {
11837b5038d7SDag-Erling Smørgrav 
11847b5038d7SDag-Erling Smørgrav 		/* check for SOA */
11857b5038d7SDag-Erling Smørgrav 		tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_SOA,
11867b5038d7SDag-Erling Smørgrav 					LDNS_SECTION_AUTHORITY);
11877b5038d7SDag-Erling Smørgrav 		if (tmp) {
11887b5038d7SDag-Erling Smørgrav 			ldns_rr_list_deep_free(tmp);
11897b5038d7SDag-Erling Smørgrav 			return LDNS_PACKET_NODATA;
11907b5038d7SDag-Erling Smørgrav 		} else {
11917b5038d7SDag-Erling Smørgrav 			/* I have no idea ... */
11927b5038d7SDag-Erling Smørgrav 		}
11937b5038d7SDag-Erling Smørgrav 	}
11947b5038d7SDag-Erling Smørgrav 
11957b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_ancount(p) == 0 && ldns_pkt_nscount(p) > 0) {
11967b5038d7SDag-Erling Smørgrav 		tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS,
11977b5038d7SDag-Erling Smørgrav 		                               LDNS_SECTION_AUTHORITY);
11987b5038d7SDag-Erling Smørgrav 		if (tmp) {
11997b5038d7SDag-Erling Smørgrav 			/* there are nameservers here */
12007b5038d7SDag-Erling Smørgrav 			ldns_rr_list_deep_free(tmp);
12017b5038d7SDag-Erling Smørgrav 			return LDNS_PACKET_REFERRAL;
12027b5038d7SDag-Erling Smørgrav 		} else {
12037b5038d7SDag-Erling Smørgrav 			/* I have no idea */
12047b5038d7SDag-Erling Smørgrav 		}
12057b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(tmp);
12067b5038d7SDag-Erling Smørgrav 	}
12077b5038d7SDag-Erling Smørgrav 
12087b5038d7SDag-Erling Smørgrav 	/* if we cannot determine the packet type, we say it's an
12097b5038d7SDag-Erling Smørgrav 	 * answer...
12107b5038d7SDag-Erling Smørgrav 	 */
12117b5038d7SDag-Erling Smørgrav 	return LDNS_PACKET_ANSWER;
12127b5038d7SDag-Erling Smørgrav }
12137b5038d7SDag-Erling Smørgrav 
12147b5038d7SDag-Erling Smørgrav ldns_pkt *
ldns_pkt_clone(const ldns_pkt * pkt)1215986ba33cSDag-Erling Smørgrav ldns_pkt_clone(const ldns_pkt *pkt)
12167b5038d7SDag-Erling Smørgrav {
12177b5038d7SDag-Erling Smørgrav 	ldns_pkt *new_pkt;
12187b5038d7SDag-Erling Smørgrav 
12197b5038d7SDag-Erling Smørgrav 	if (!pkt) {
12207b5038d7SDag-Erling Smørgrav 		return NULL;
12217b5038d7SDag-Erling Smørgrav 	}
12227b5038d7SDag-Erling Smørgrav 	new_pkt = ldns_pkt_new();
12237b5038d7SDag-Erling Smørgrav 
12247b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_id(new_pkt, ldns_pkt_id(pkt));
12257b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_qr(new_pkt, ldns_pkt_qr(pkt));
12267b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_aa(new_pkt, ldns_pkt_aa(pkt));
12277b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_tc(new_pkt, ldns_pkt_tc(pkt));
12287b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_rd(new_pkt, ldns_pkt_rd(pkt));
12297b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_cd(new_pkt, ldns_pkt_cd(pkt));
12307b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_ra(new_pkt, ldns_pkt_ra(pkt));
12317b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_ad(new_pkt, ldns_pkt_ad(pkt));
12327b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_opcode(new_pkt, ldns_pkt_get_opcode(pkt));
12337b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_rcode(new_pkt, ldns_pkt_get_rcode(pkt));
12347b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_qdcount(new_pkt, ldns_pkt_qdcount(pkt));
12357b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_ancount(new_pkt, ldns_pkt_ancount(pkt));
12367b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_nscount(new_pkt, ldns_pkt_nscount(pkt));
12377b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_arcount(new_pkt, ldns_pkt_arcount(pkt));
12382787e39aSDag-Erling Smørgrav 	if (ldns_pkt_answerfrom(pkt))
12392787e39aSDag-Erling Smørgrav 		ldns_pkt_set_answerfrom(new_pkt,
12402787e39aSDag-Erling Smørgrav 			ldns_rdf_clone(ldns_pkt_answerfrom(pkt)));
1241986ba33cSDag-Erling Smørgrav 	ldns_pkt_set_timestamp(new_pkt, ldns_pkt_timestamp(pkt));
12427b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_querytime(new_pkt, ldns_pkt_querytime(pkt));
12437b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_size(new_pkt, ldns_pkt_size(pkt));
12447b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_tsig(new_pkt, ldns_rr_clone(ldns_pkt_tsig(pkt)));
12457b5038d7SDag-Erling Smørgrav 
12467b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_udp_size(new_pkt, ldns_pkt_edns_udp_size(pkt));
12477b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_extended_rcode(new_pkt,
12487b5038d7SDag-Erling Smørgrav 		ldns_pkt_edns_extended_rcode(pkt));
12497b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_version(new_pkt, ldns_pkt_edns_version(pkt));
1250986ba33cSDag-Erling Smørgrav 	new_pkt->_edns_present = pkt->_edns_present;
12517b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_z(new_pkt, ldns_pkt_edns_z(pkt));
12527b5038d7SDag-Erling Smørgrav 	if(ldns_pkt_edns_data(pkt))
12537b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_edns_data(new_pkt,
12547b5038d7SDag-Erling Smørgrav 			ldns_rdf_clone(ldns_pkt_edns_data(pkt)));
12557b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_do(new_pkt, ldns_pkt_edns_do(pkt));
1256*5afab0e5SDag-Erling Smørgrav 	if (pkt->_edns_list)
1257*5afab0e5SDag-Erling Smørgrav 		ldns_pkt_set_edns_option_list(new_pkt,
1258*5afab0e5SDag-Erling Smørgrav 			ldns_edns_option_list_clone(pkt->_edns_list));
12597b5038d7SDag-Erling Smørgrav 
12607b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(new_pkt->_question);
12617b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(new_pkt->_answer);
12627b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(new_pkt->_authority);
12637b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(new_pkt->_additional);
12647b5038d7SDag-Erling Smørgrav 	new_pkt->_question = ldns_rr_list_clone(ldns_pkt_question(pkt));
12657b5038d7SDag-Erling Smørgrav 	new_pkt->_answer = ldns_rr_list_clone(ldns_pkt_answer(pkt));
12667b5038d7SDag-Erling Smørgrav 	new_pkt->_authority = ldns_rr_list_clone(ldns_pkt_authority(pkt));
12677b5038d7SDag-Erling Smørgrav 	new_pkt->_additional = ldns_rr_list_clone(ldns_pkt_additional(pkt));
12687b5038d7SDag-Erling Smørgrav 	return new_pkt;
12697b5038d7SDag-Erling Smørgrav }
1270