xref: /freebsd/contrib/ldns/packet.c (revision 986ba33c7a3bc8f5ba13c7a9d6512602f6e32c61)
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>
167b5038d7SDag-Erling Smørgrav 
177b5038d7SDag-Erling Smørgrav #include <strings.h>
187b5038d7SDag-Erling Smørgrav #include <limits.h>
197b5038d7SDag-Erling Smørgrav 
207b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
217b5038d7SDag-Erling Smørgrav #include <openssl/rand.h>
227b5038d7SDag-Erling Smørgrav #endif
237b5038d7SDag-Erling Smørgrav 
247b5038d7SDag-Erling Smørgrav /* Access functions
257b5038d7SDag-Erling Smørgrav  * do this as functions to get type checking
267b5038d7SDag-Erling Smørgrav  */
277b5038d7SDag-Erling Smørgrav 
287b5038d7SDag-Erling Smørgrav #define LDNS_EDNS_MASK_DO_BIT 0x8000
297b5038d7SDag-Erling Smørgrav 
307b5038d7SDag-Erling Smørgrav /* TODO defines for 3600 */
317b5038d7SDag-Erling Smørgrav /* convert to and from numerical flag values */
327b5038d7SDag-Erling Smørgrav ldns_lookup_table ldns_edns_flags[] = {
337b5038d7SDag-Erling Smørgrav 	{ 3600, "do"},
347b5038d7SDag-Erling Smørgrav 	{ 0, NULL}
357b5038d7SDag-Erling Smørgrav };
367b5038d7SDag-Erling Smørgrav 
377b5038d7SDag-Erling Smørgrav /* read */
387b5038d7SDag-Erling Smørgrav uint16_t
397b5038d7SDag-Erling Smørgrav ldns_pkt_id(const ldns_pkt *packet)
407b5038d7SDag-Erling Smørgrav {
417b5038d7SDag-Erling Smørgrav 	return packet->_header->_id;
427b5038d7SDag-Erling Smørgrav }
437b5038d7SDag-Erling Smørgrav 
447b5038d7SDag-Erling Smørgrav bool
457b5038d7SDag-Erling Smørgrav ldns_pkt_qr(const ldns_pkt *packet)
467b5038d7SDag-Erling Smørgrav {
477b5038d7SDag-Erling Smørgrav 	return packet->_header->_qr;
487b5038d7SDag-Erling Smørgrav }
497b5038d7SDag-Erling Smørgrav 
507b5038d7SDag-Erling Smørgrav bool
517b5038d7SDag-Erling Smørgrav ldns_pkt_aa(const ldns_pkt *packet)
527b5038d7SDag-Erling Smørgrav {
537b5038d7SDag-Erling Smørgrav 	return packet->_header->_aa;
547b5038d7SDag-Erling Smørgrav }
557b5038d7SDag-Erling Smørgrav 
567b5038d7SDag-Erling Smørgrav bool
577b5038d7SDag-Erling Smørgrav ldns_pkt_tc(const ldns_pkt *packet)
587b5038d7SDag-Erling Smørgrav {
597b5038d7SDag-Erling Smørgrav 	return packet->_header->_tc;
607b5038d7SDag-Erling Smørgrav }
617b5038d7SDag-Erling Smørgrav 
627b5038d7SDag-Erling Smørgrav bool
637b5038d7SDag-Erling Smørgrav ldns_pkt_rd(const ldns_pkt *packet)
647b5038d7SDag-Erling Smørgrav {
657b5038d7SDag-Erling Smørgrav 	return packet->_header->_rd;
667b5038d7SDag-Erling Smørgrav }
677b5038d7SDag-Erling Smørgrav 
687b5038d7SDag-Erling Smørgrav bool
697b5038d7SDag-Erling Smørgrav ldns_pkt_cd(const ldns_pkt *packet)
707b5038d7SDag-Erling Smørgrav {
717b5038d7SDag-Erling Smørgrav 	return packet->_header->_cd;
727b5038d7SDag-Erling Smørgrav }
737b5038d7SDag-Erling Smørgrav 
747b5038d7SDag-Erling Smørgrav bool
757b5038d7SDag-Erling Smørgrav ldns_pkt_ra(const ldns_pkt *packet)
767b5038d7SDag-Erling Smørgrav {
777b5038d7SDag-Erling Smørgrav 	return packet->_header->_ra;
787b5038d7SDag-Erling Smørgrav }
797b5038d7SDag-Erling Smørgrav 
807b5038d7SDag-Erling Smørgrav bool
817b5038d7SDag-Erling Smørgrav ldns_pkt_ad(const ldns_pkt *packet)
827b5038d7SDag-Erling Smørgrav {
837b5038d7SDag-Erling Smørgrav 	return packet->_header->_ad;
847b5038d7SDag-Erling Smørgrav }
857b5038d7SDag-Erling Smørgrav 
867b5038d7SDag-Erling Smørgrav ldns_pkt_opcode
877b5038d7SDag-Erling Smørgrav ldns_pkt_get_opcode(const ldns_pkt *packet)
887b5038d7SDag-Erling Smørgrav {
897b5038d7SDag-Erling Smørgrav 	return packet->_header->_opcode;
907b5038d7SDag-Erling Smørgrav }
917b5038d7SDag-Erling Smørgrav 
927b5038d7SDag-Erling Smørgrav ldns_pkt_rcode
937b5038d7SDag-Erling Smørgrav ldns_pkt_get_rcode(const ldns_pkt *packet)
947b5038d7SDag-Erling Smørgrav {
957b5038d7SDag-Erling Smørgrav 	return packet->_header->_rcode;
967b5038d7SDag-Erling Smørgrav }
977b5038d7SDag-Erling Smørgrav 
987b5038d7SDag-Erling Smørgrav uint16_t
997b5038d7SDag-Erling Smørgrav ldns_pkt_qdcount(const ldns_pkt *packet)
1007b5038d7SDag-Erling Smørgrav {
1017b5038d7SDag-Erling Smørgrav 	return packet->_header->_qdcount;
1027b5038d7SDag-Erling Smørgrav }
1037b5038d7SDag-Erling Smørgrav 
1047b5038d7SDag-Erling Smørgrav uint16_t
1057b5038d7SDag-Erling Smørgrav ldns_pkt_ancount(const ldns_pkt *packet)
1067b5038d7SDag-Erling Smørgrav {
1077b5038d7SDag-Erling Smørgrav 	return packet->_header->_ancount;
1087b5038d7SDag-Erling Smørgrav }
1097b5038d7SDag-Erling Smørgrav 
1107b5038d7SDag-Erling Smørgrav uint16_t
1117b5038d7SDag-Erling Smørgrav ldns_pkt_nscount(const ldns_pkt *packet)
1127b5038d7SDag-Erling Smørgrav {
1137b5038d7SDag-Erling Smørgrav 	return packet->_header->_nscount;
1147b5038d7SDag-Erling Smørgrav }
1157b5038d7SDag-Erling Smørgrav 
1167b5038d7SDag-Erling Smørgrav uint16_t
1177b5038d7SDag-Erling Smørgrav ldns_pkt_arcount(const ldns_pkt *packet)
1187b5038d7SDag-Erling Smørgrav {
1197b5038d7SDag-Erling Smørgrav 	return packet->_header->_arcount;
1207b5038d7SDag-Erling Smørgrav }
1217b5038d7SDag-Erling Smørgrav 
1227b5038d7SDag-Erling Smørgrav ldns_rr_list *
1237b5038d7SDag-Erling Smørgrav ldns_pkt_question(const ldns_pkt *packet)
1247b5038d7SDag-Erling Smørgrav {
1257b5038d7SDag-Erling Smørgrav 	return packet->_question;
1267b5038d7SDag-Erling Smørgrav }
1277b5038d7SDag-Erling Smørgrav 
1287b5038d7SDag-Erling Smørgrav ldns_rr_list *
1297b5038d7SDag-Erling Smørgrav ldns_pkt_answer(const ldns_pkt *packet)
1307b5038d7SDag-Erling Smørgrav {
1317b5038d7SDag-Erling Smørgrav 	return packet->_answer;
1327b5038d7SDag-Erling Smørgrav }
1337b5038d7SDag-Erling Smørgrav 
1347b5038d7SDag-Erling Smørgrav ldns_rr_list *
1357b5038d7SDag-Erling Smørgrav ldns_pkt_authority(const ldns_pkt *packet)
1367b5038d7SDag-Erling Smørgrav {
1377b5038d7SDag-Erling Smørgrav 	return packet->_authority;
1387b5038d7SDag-Erling Smørgrav }
1397b5038d7SDag-Erling Smørgrav 
1407b5038d7SDag-Erling Smørgrav ldns_rr_list *
1417b5038d7SDag-Erling Smørgrav ldns_pkt_additional(const ldns_pkt *packet)
1427b5038d7SDag-Erling Smørgrav {
1437b5038d7SDag-Erling Smørgrav 	return packet->_additional;
1447b5038d7SDag-Erling Smørgrav }
1457b5038d7SDag-Erling Smørgrav 
1467b5038d7SDag-Erling Smørgrav /* return ALL section concatenated */
1477b5038d7SDag-Erling Smørgrav ldns_rr_list *
1487b5038d7SDag-Erling Smørgrav ldns_pkt_all(const ldns_pkt *packet)
1497b5038d7SDag-Erling Smørgrav {
1507b5038d7SDag-Erling Smørgrav 	ldns_rr_list *all, *prev_all;
1517b5038d7SDag-Erling Smørgrav 
1527b5038d7SDag-Erling Smørgrav 	all = ldns_rr_list_cat_clone(
1537b5038d7SDag-Erling Smørgrav 			ldns_pkt_question(packet),
1547b5038d7SDag-Erling Smørgrav 			ldns_pkt_answer(packet));
1557b5038d7SDag-Erling Smørgrav 	prev_all = all;
1567b5038d7SDag-Erling Smørgrav 	all = ldns_rr_list_cat_clone(all,
1577b5038d7SDag-Erling Smørgrav 			ldns_pkt_authority(packet));
1587b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(prev_all);
1597b5038d7SDag-Erling Smørgrav 	prev_all = all;
1607b5038d7SDag-Erling Smørgrav 	all = ldns_rr_list_cat_clone(all,
1617b5038d7SDag-Erling Smørgrav 			ldns_pkt_additional(packet));
1627b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(prev_all);
1637b5038d7SDag-Erling Smørgrav 	return all;
1647b5038d7SDag-Erling Smørgrav }
1657b5038d7SDag-Erling Smørgrav 
1667b5038d7SDag-Erling Smørgrav ldns_rr_list *
1677b5038d7SDag-Erling Smørgrav ldns_pkt_all_noquestion(const ldns_pkt *packet)
1687b5038d7SDag-Erling Smørgrav {
1697b5038d7SDag-Erling Smørgrav 	ldns_rr_list *all, *all2;
1707b5038d7SDag-Erling Smørgrav 
1717b5038d7SDag-Erling Smørgrav 	all = ldns_rr_list_cat_clone(
1727b5038d7SDag-Erling Smørgrav 			ldns_pkt_answer(packet),
1737b5038d7SDag-Erling Smørgrav 			ldns_pkt_authority(packet));
1747b5038d7SDag-Erling Smørgrav 	all2 = ldns_rr_list_cat_clone(all,
1757b5038d7SDag-Erling Smørgrav 			ldns_pkt_additional(packet));
1767b5038d7SDag-Erling Smørgrav 
1777b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(all);
1787b5038d7SDag-Erling Smørgrav 	return all2;
1797b5038d7SDag-Erling Smørgrav }
1807b5038d7SDag-Erling Smørgrav 
1817b5038d7SDag-Erling Smørgrav size_t
1827b5038d7SDag-Erling Smørgrav ldns_pkt_size(const ldns_pkt *packet)
1837b5038d7SDag-Erling Smørgrav {
1847b5038d7SDag-Erling Smørgrav 	return packet->_size;
1857b5038d7SDag-Erling Smørgrav }
1867b5038d7SDag-Erling Smørgrav 
1877b5038d7SDag-Erling Smørgrav uint32_t
1887b5038d7SDag-Erling Smørgrav ldns_pkt_querytime(const ldns_pkt *packet)
1897b5038d7SDag-Erling Smørgrav {
1907b5038d7SDag-Erling Smørgrav 	return packet->_querytime;
1917b5038d7SDag-Erling Smørgrav }
1927b5038d7SDag-Erling Smørgrav 
1937b5038d7SDag-Erling Smørgrav ldns_rdf *
1947b5038d7SDag-Erling Smørgrav ldns_pkt_answerfrom(const ldns_pkt *packet)
1957b5038d7SDag-Erling Smørgrav {
1967b5038d7SDag-Erling Smørgrav 	return packet->_answerfrom;
1977b5038d7SDag-Erling Smørgrav }
1987b5038d7SDag-Erling Smørgrav 
1997b5038d7SDag-Erling Smørgrav struct timeval
2007b5038d7SDag-Erling Smørgrav ldns_pkt_timestamp(const ldns_pkt *packet)
2017b5038d7SDag-Erling Smørgrav {
2027b5038d7SDag-Erling Smørgrav 	return packet->timestamp;
2037b5038d7SDag-Erling Smørgrav }
2047b5038d7SDag-Erling Smørgrav 
2057b5038d7SDag-Erling Smørgrav uint16_t
2067b5038d7SDag-Erling Smørgrav ldns_pkt_edns_udp_size(const ldns_pkt *packet)
2077b5038d7SDag-Erling Smørgrav {
2087b5038d7SDag-Erling Smørgrav 	return packet->_edns_udp_size;
2097b5038d7SDag-Erling Smørgrav }
2107b5038d7SDag-Erling Smørgrav 
2117b5038d7SDag-Erling Smørgrav uint8_t
2127b5038d7SDag-Erling Smørgrav ldns_pkt_edns_extended_rcode(const ldns_pkt *packet)
2137b5038d7SDag-Erling Smørgrav {
2147b5038d7SDag-Erling Smørgrav 	return packet->_edns_extended_rcode;
2157b5038d7SDag-Erling Smørgrav }
2167b5038d7SDag-Erling Smørgrav 
2177b5038d7SDag-Erling Smørgrav uint8_t
2187b5038d7SDag-Erling Smørgrav ldns_pkt_edns_version(const ldns_pkt *packet)
2197b5038d7SDag-Erling Smørgrav {
2207b5038d7SDag-Erling Smørgrav 	return packet->_edns_version;
2217b5038d7SDag-Erling Smørgrav }
2227b5038d7SDag-Erling Smørgrav 
2237b5038d7SDag-Erling Smørgrav uint16_t
2247b5038d7SDag-Erling Smørgrav ldns_pkt_edns_z(const ldns_pkt *packet)
2257b5038d7SDag-Erling Smørgrav {
2267b5038d7SDag-Erling Smørgrav 	return packet->_edns_z;
2277b5038d7SDag-Erling Smørgrav }
2287b5038d7SDag-Erling Smørgrav 
2297b5038d7SDag-Erling Smørgrav bool
2307b5038d7SDag-Erling Smørgrav ldns_pkt_edns_do(const ldns_pkt *packet)
2317b5038d7SDag-Erling Smørgrav {
2327b5038d7SDag-Erling Smørgrav 	return (packet->_edns_z & LDNS_EDNS_MASK_DO_BIT);
2337b5038d7SDag-Erling Smørgrav }
2347b5038d7SDag-Erling Smørgrav 
2357b5038d7SDag-Erling Smørgrav void
2367b5038d7SDag-Erling Smørgrav ldns_pkt_set_edns_do(ldns_pkt *packet, bool value)
2377b5038d7SDag-Erling Smørgrav {
2387b5038d7SDag-Erling Smørgrav 	if (value) {
2397b5038d7SDag-Erling Smørgrav 		packet->_edns_z = packet->_edns_z | LDNS_EDNS_MASK_DO_BIT;
2407b5038d7SDag-Erling Smørgrav 	} else {
2417b5038d7SDag-Erling Smørgrav 		packet->_edns_z = packet->_edns_z & ~LDNS_EDNS_MASK_DO_BIT;
2427b5038d7SDag-Erling Smørgrav 	}
2437b5038d7SDag-Erling Smørgrav }
2447b5038d7SDag-Erling Smørgrav 
2457b5038d7SDag-Erling Smørgrav ldns_rdf *
2467b5038d7SDag-Erling Smørgrav ldns_pkt_edns_data(const ldns_pkt *packet)
2477b5038d7SDag-Erling Smørgrav {
2487b5038d7SDag-Erling Smørgrav 	return packet->_edns_data;
2497b5038d7SDag-Erling Smørgrav }
2507b5038d7SDag-Erling Smørgrav 
2517b5038d7SDag-Erling Smørgrav /* return only those rr that share the ownername */
2527b5038d7SDag-Erling Smørgrav ldns_rr_list *
253*986ba33cSDag-Erling Smørgrav ldns_pkt_rr_list_by_name(const ldns_pkt *packet,
254*986ba33cSDag-Erling Smørgrav                          const ldns_rdf *ownername,
2557b5038d7SDag-Erling Smørgrav                          ldns_pkt_section sec)
2567b5038d7SDag-Erling Smørgrav {
2577b5038d7SDag-Erling Smørgrav 	ldns_rr_list *rrs;
2587b5038d7SDag-Erling Smørgrav 	ldns_rr_list *ret;
2597b5038d7SDag-Erling Smørgrav 	uint16_t i;
2607b5038d7SDag-Erling Smørgrav 
2617b5038d7SDag-Erling Smørgrav 	if (!packet) {
2627b5038d7SDag-Erling Smørgrav 		return NULL;
2637b5038d7SDag-Erling Smørgrav 	}
2647b5038d7SDag-Erling Smørgrav 
2657b5038d7SDag-Erling Smørgrav 	rrs = ldns_pkt_get_section_clone(packet, sec);
2667b5038d7SDag-Erling Smørgrav 	ret = NULL;
2677b5038d7SDag-Erling Smørgrav 
2687b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
26917d15b25SDag-Erling Smørgrav 		if (ldns_dname_compare(ldns_rr_owner(
2707b5038d7SDag-Erling Smørgrav 						ldns_rr_list_rr(rrs, i)),
2717b5038d7SDag-Erling Smørgrav 					ownername) == 0) {
2727b5038d7SDag-Erling Smørgrav 			/* owner names match */
2732787e39aSDag-Erling Smørgrav 			if (ret == NULL) {
2742787e39aSDag-Erling Smørgrav 				ret = ldns_rr_list_new();
2752787e39aSDag-Erling Smørgrav 			}
276*986ba33cSDag-Erling Smørgrav 			ldns_rr_list_push_rr(ret,
277*986ba33cSDag-Erling Smørgrav 					     ldns_rr_clone(
278*986ba33cSDag-Erling Smørgrav 						ldns_rr_list_rr(rrs, i))
279*986ba33cSDag-Erling Smørgrav 					    );
2807b5038d7SDag-Erling Smørgrav 		}
2817b5038d7SDag-Erling Smørgrav 	}
282*986ba33cSDag-Erling Smørgrav 
283*986ba33cSDag-Erling Smørgrav 	ldns_rr_list_deep_free(rrs);
284*986ba33cSDag-Erling Smørgrav 
2857b5038d7SDag-Erling Smørgrav 	return ret;
2867b5038d7SDag-Erling Smørgrav }
2877b5038d7SDag-Erling Smørgrav 
2887b5038d7SDag-Erling Smørgrav /* return only those rr that share a type */
2897b5038d7SDag-Erling Smørgrav ldns_rr_list *
2907b5038d7SDag-Erling Smørgrav ldns_pkt_rr_list_by_type(const ldns_pkt *packet,
2917b5038d7SDag-Erling Smørgrav                          ldns_rr_type type,
2927b5038d7SDag-Erling Smørgrav                          ldns_pkt_section sec)
2937b5038d7SDag-Erling Smørgrav {
2947b5038d7SDag-Erling Smørgrav 	ldns_rr_list *rrs;
2957b5038d7SDag-Erling Smørgrav 	ldns_rr_list *new;
2967b5038d7SDag-Erling Smørgrav 	uint16_t i;
2977b5038d7SDag-Erling Smørgrav 
2987b5038d7SDag-Erling Smørgrav 	if(!packet) {
2997b5038d7SDag-Erling Smørgrav 		return NULL;
3007b5038d7SDag-Erling Smørgrav 	}
3017b5038d7SDag-Erling Smørgrav 
3027b5038d7SDag-Erling Smørgrav 	rrs = ldns_pkt_get_section_clone(packet, sec);
3037b5038d7SDag-Erling Smørgrav 	new = ldns_rr_list_new();
3047b5038d7SDag-Erling Smørgrav 
3057b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
3067b5038d7SDag-Erling Smørgrav 		if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i))) {
3077b5038d7SDag-Erling Smørgrav 			/* types match */
3087b5038d7SDag-Erling Smørgrav 			ldns_rr_list_push_rr(new,
3097b5038d7SDag-Erling Smørgrav 			                     ldns_rr_clone(
3107b5038d7SDag-Erling Smørgrav 			                     	ldns_rr_list_rr(rrs, i))
3117b5038d7SDag-Erling Smørgrav 					     );
3127b5038d7SDag-Erling Smørgrav 		}
3137b5038d7SDag-Erling Smørgrav 	}
3147b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(rrs);
3157b5038d7SDag-Erling Smørgrav 
3167b5038d7SDag-Erling Smørgrav 	if (ldns_rr_list_rr_count(new) == 0) {
3177b5038d7SDag-Erling Smørgrav 		ldns_rr_list_free(new);
3187b5038d7SDag-Erling Smørgrav 		return NULL;
3197b5038d7SDag-Erling Smørgrav 	} else {
3207b5038d7SDag-Erling Smørgrav 		return new;
3217b5038d7SDag-Erling Smørgrav 	}
3227b5038d7SDag-Erling Smørgrav }
3237b5038d7SDag-Erling Smørgrav 
3247b5038d7SDag-Erling Smørgrav /* return only those rrs that share name and type */
3257b5038d7SDag-Erling Smørgrav ldns_rr_list *
3267b5038d7SDag-Erling Smørgrav ldns_pkt_rr_list_by_name_and_type(const ldns_pkt *packet,
3277b5038d7SDag-Erling Smørgrav                                   const ldns_rdf *ownername,
3287b5038d7SDag-Erling Smørgrav                                   ldns_rr_type type,
3297b5038d7SDag-Erling Smørgrav                                   ldns_pkt_section sec)
3307b5038d7SDag-Erling Smørgrav {
3317b5038d7SDag-Erling Smørgrav 	ldns_rr_list *rrs;
3327b5038d7SDag-Erling Smørgrav 	ldns_rr_list *new;
3337b5038d7SDag-Erling Smørgrav 	ldns_rr_list *ret;
3347b5038d7SDag-Erling Smørgrav 	uint16_t i;
3357b5038d7SDag-Erling Smørgrav 
3367b5038d7SDag-Erling Smørgrav 	if(!packet) {
3377b5038d7SDag-Erling Smørgrav 		return NULL;
3387b5038d7SDag-Erling Smørgrav 	}
3397b5038d7SDag-Erling Smørgrav 
3407b5038d7SDag-Erling Smørgrav 	rrs = ldns_pkt_get_section_clone(packet, sec);
3417b5038d7SDag-Erling Smørgrav 	new = ldns_rr_list_new();
3427b5038d7SDag-Erling Smørgrav 	ret = NULL;
3437b5038d7SDag-Erling Smørgrav 
3447b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
3457b5038d7SDag-Erling Smørgrav 		if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i)) &&
34617d15b25SDag-Erling Smørgrav 		    ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(rrs, i)),
3477b5038d7SDag-Erling Smørgrav 		                     ownername
3487b5038d7SDag-Erling Smørgrav 		                    ) == 0
3497b5038d7SDag-Erling Smørgrav 		   ) {
3507b5038d7SDag-Erling Smørgrav 			/* types match */
3517b5038d7SDag-Erling Smørgrav 			ldns_rr_list_push_rr(new, ldns_rr_clone(ldns_rr_list_rr(rrs, i)));
3527b5038d7SDag-Erling Smørgrav 			ret = new;
3537b5038d7SDag-Erling Smørgrav 		}
3547b5038d7SDag-Erling Smørgrav 	}
3557b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(rrs);
3567b5038d7SDag-Erling Smørgrav 	if (!ret) {
3577b5038d7SDag-Erling Smørgrav 		ldns_rr_list_free(new);
3587b5038d7SDag-Erling Smørgrav 	}
3597b5038d7SDag-Erling Smørgrav 	return ret;
3607b5038d7SDag-Erling Smørgrav }
3617b5038d7SDag-Erling Smørgrav 
3627b5038d7SDag-Erling Smørgrav bool
363*986ba33cSDag-Erling Smørgrav ldns_pkt_rr(const ldns_pkt *pkt, ldns_pkt_section sec, const ldns_rr *rr)
3647b5038d7SDag-Erling Smørgrav {
3657b5038d7SDag-Erling Smørgrav 	bool result = false;
3667b5038d7SDag-Erling Smørgrav 
3677b5038d7SDag-Erling Smørgrav 	switch (sec) {
3687b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_QUESTION:
3697b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
3707b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANSWER:
3717b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr);
3727b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_AUTHORITY:
3737b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr);
3747b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ADDITIONAL:
3757b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
3767b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANY:
3777b5038d7SDag-Erling Smørgrav 		result = ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
3787b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANY_NOQUESTION:
3797b5038d7SDag-Erling Smørgrav 		result = result
3807b5038d7SDag-Erling Smørgrav 		    || ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr)
3817b5038d7SDag-Erling Smørgrav 		    || ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr)
3827b5038d7SDag-Erling Smørgrav 		    || ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
3837b5038d7SDag-Erling Smørgrav 	}
3847b5038d7SDag-Erling Smørgrav 
3857b5038d7SDag-Erling Smørgrav 	return result;
3867b5038d7SDag-Erling Smørgrav }
3877b5038d7SDag-Erling Smørgrav 
38817d15b25SDag-Erling Smørgrav uint16_t
3897b5038d7SDag-Erling Smørgrav ldns_pkt_section_count(const ldns_pkt *packet, ldns_pkt_section s)
3907b5038d7SDag-Erling Smørgrav {
3917b5038d7SDag-Erling Smørgrav 	switch(s) {
3927b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_QUESTION:
3937b5038d7SDag-Erling Smørgrav 		return ldns_pkt_qdcount(packet);
3947b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANSWER:
3957b5038d7SDag-Erling Smørgrav 		return ldns_pkt_ancount(packet);
3967b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_AUTHORITY:
3977b5038d7SDag-Erling Smørgrav 		return ldns_pkt_nscount(packet);
3987b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ADDITIONAL:
3997b5038d7SDag-Erling Smørgrav 		return ldns_pkt_arcount(packet);
4007b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANY:
4017b5038d7SDag-Erling Smørgrav 		return ldns_pkt_qdcount(packet) +
4027b5038d7SDag-Erling Smørgrav 			ldns_pkt_ancount(packet) +
4037b5038d7SDag-Erling Smørgrav 			ldns_pkt_nscount(packet) +
4047b5038d7SDag-Erling Smørgrav 			ldns_pkt_arcount(packet);
4057b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANY_NOQUESTION:
4067b5038d7SDag-Erling Smørgrav 		return ldns_pkt_ancount(packet) +
4077b5038d7SDag-Erling Smørgrav 			ldns_pkt_nscount(packet) +
4087b5038d7SDag-Erling Smørgrav 			ldns_pkt_arcount(packet);
4097b5038d7SDag-Erling Smørgrav 	default:
4107b5038d7SDag-Erling Smørgrav 		return 0;
4117b5038d7SDag-Erling Smørgrav 	}
4127b5038d7SDag-Erling Smørgrav }
4137b5038d7SDag-Erling Smørgrav 
4147b5038d7SDag-Erling Smørgrav bool
4157b5038d7SDag-Erling Smørgrav ldns_pkt_empty(ldns_pkt *p)
4167b5038d7SDag-Erling Smørgrav {
4177b5038d7SDag-Erling Smørgrav 	if (!p) {
4187b5038d7SDag-Erling Smørgrav 		return true; /* NULL is empty? */
4197b5038d7SDag-Erling Smørgrav 	}
4207b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_section_count(p, LDNS_SECTION_ANY) > 0) {
4217b5038d7SDag-Erling Smørgrav 		return false;
4227b5038d7SDag-Erling Smørgrav 	} else {
4237b5038d7SDag-Erling Smørgrav 		return true;
4247b5038d7SDag-Erling Smørgrav     }
4257b5038d7SDag-Erling Smørgrav }
4267b5038d7SDag-Erling Smørgrav 
4277b5038d7SDag-Erling Smørgrav 
4287b5038d7SDag-Erling Smørgrav ldns_rr_list *
4297b5038d7SDag-Erling Smørgrav ldns_pkt_get_section_clone(const ldns_pkt *packet, ldns_pkt_section s)
4307b5038d7SDag-Erling Smørgrav {
4317b5038d7SDag-Erling Smørgrav 	switch(s) {
4327b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_QUESTION:
4337b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_clone(ldns_pkt_question(packet));
4347b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANSWER:
4357b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_clone(ldns_pkt_answer(packet));
4367b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_AUTHORITY:
4377b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_clone(ldns_pkt_authority(packet));
4387b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ADDITIONAL:
4397b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_clone(ldns_pkt_additional(packet));
4407b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANY:
4417b5038d7SDag-Erling Smørgrav 		/* these are already clones */
4427b5038d7SDag-Erling Smørgrav 		return ldns_pkt_all(packet);
4437b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANY_NOQUESTION:
4447b5038d7SDag-Erling Smørgrav 		return ldns_pkt_all_noquestion(packet);
4457b5038d7SDag-Erling Smørgrav 	default:
4467b5038d7SDag-Erling Smørgrav 		return NULL;
4477b5038d7SDag-Erling Smørgrav 	}
4487b5038d7SDag-Erling Smørgrav }
4497b5038d7SDag-Erling Smørgrav 
4507b5038d7SDag-Erling Smørgrav ldns_rr *ldns_pkt_tsig(const ldns_pkt *pkt) {
4517b5038d7SDag-Erling Smørgrav 	return pkt->_tsig_rr;
4527b5038d7SDag-Erling Smørgrav }
4537b5038d7SDag-Erling Smørgrav 
4547b5038d7SDag-Erling Smørgrav /* write */
4557b5038d7SDag-Erling Smørgrav void
4567b5038d7SDag-Erling Smørgrav ldns_pkt_set_id(ldns_pkt *packet, uint16_t id)
4577b5038d7SDag-Erling Smørgrav {
4587b5038d7SDag-Erling Smørgrav 	packet->_header->_id = id;
4597b5038d7SDag-Erling Smørgrav }
4607b5038d7SDag-Erling Smørgrav 
4617b5038d7SDag-Erling Smørgrav void
4627b5038d7SDag-Erling Smørgrav ldns_pkt_set_random_id(ldns_pkt *packet)
4637b5038d7SDag-Erling Smørgrav {
4647b5038d7SDag-Erling Smørgrav 	uint16_t rid = ldns_get_random();
4657b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_id(packet, rid);
4667b5038d7SDag-Erling Smørgrav }
4677b5038d7SDag-Erling Smørgrav 
4687b5038d7SDag-Erling Smørgrav 
4697b5038d7SDag-Erling Smørgrav void
4707b5038d7SDag-Erling Smørgrav ldns_pkt_set_qr(ldns_pkt *packet, bool qr)
4717b5038d7SDag-Erling Smørgrav {
4727b5038d7SDag-Erling Smørgrav 	packet->_header->_qr = qr;
4737b5038d7SDag-Erling Smørgrav }
4747b5038d7SDag-Erling Smørgrav 
4757b5038d7SDag-Erling Smørgrav void
4767b5038d7SDag-Erling Smørgrav ldns_pkt_set_aa(ldns_pkt *packet, bool aa)
4777b5038d7SDag-Erling Smørgrav {
4787b5038d7SDag-Erling Smørgrav 	packet->_header->_aa = aa;
4797b5038d7SDag-Erling Smørgrav }
4807b5038d7SDag-Erling Smørgrav 
4817b5038d7SDag-Erling Smørgrav void
4827b5038d7SDag-Erling Smørgrav ldns_pkt_set_tc(ldns_pkt *packet, bool tc)
4837b5038d7SDag-Erling Smørgrav {
4847b5038d7SDag-Erling Smørgrav 	packet->_header->_tc = tc;
4857b5038d7SDag-Erling Smørgrav }
4867b5038d7SDag-Erling Smørgrav 
4877b5038d7SDag-Erling Smørgrav void
4887b5038d7SDag-Erling Smørgrav ldns_pkt_set_rd(ldns_pkt *packet, bool rd)
4897b5038d7SDag-Erling Smørgrav {
4907b5038d7SDag-Erling Smørgrav 	packet->_header->_rd = rd;
4917b5038d7SDag-Erling Smørgrav }
4927b5038d7SDag-Erling Smørgrav 
4937b5038d7SDag-Erling Smørgrav void
4947b5038d7SDag-Erling Smørgrav ldns_pkt_set_additional(ldns_pkt *p, ldns_rr_list *rr)
4957b5038d7SDag-Erling Smørgrav {
4967b5038d7SDag-Erling Smørgrav 	p->_additional = rr;
4977b5038d7SDag-Erling Smørgrav }
4987b5038d7SDag-Erling Smørgrav 
4997b5038d7SDag-Erling Smørgrav void
5007b5038d7SDag-Erling Smørgrav ldns_pkt_set_question(ldns_pkt *p, ldns_rr_list *rr)
5017b5038d7SDag-Erling Smørgrav {
5027b5038d7SDag-Erling Smørgrav 	p->_question = rr;
5037b5038d7SDag-Erling Smørgrav }
5047b5038d7SDag-Erling Smørgrav 
5057b5038d7SDag-Erling Smørgrav void
5067b5038d7SDag-Erling Smørgrav ldns_pkt_set_answer(ldns_pkt *p, ldns_rr_list *rr)
5077b5038d7SDag-Erling Smørgrav {
5087b5038d7SDag-Erling Smørgrav 	p->_answer = rr;
5097b5038d7SDag-Erling Smørgrav }
5107b5038d7SDag-Erling Smørgrav 
5117b5038d7SDag-Erling Smørgrav void
5127b5038d7SDag-Erling Smørgrav ldns_pkt_set_authority(ldns_pkt *p, ldns_rr_list *rr)
5137b5038d7SDag-Erling Smørgrav {
5147b5038d7SDag-Erling Smørgrav 	p->_authority = rr;
5157b5038d7SDag-Erling Smørgrav }
5167b5038d7SDag-Erling Smørgrav 
5177b5038d7SDag-Erling Smørgrav void
5187b5038d7SDag-Erling Smørgrav ldns_pkt_set_cd(ldns_pkt *packet, bool cd)
5197b5038d7SDag-Erling Smørgrav {
5207b5038d7SDag-Erling Smørgrav 	packet->_header->_cd = cd;
5217b5038d7SDag-Erling Smørgrav }
5227b5038d7SDag-Erling Smørgrav 
5237b5038d7SDag-Erling Smørgrav void
5247b5038d7SDag-Erling Smørgrav ldns_pkt_set_ra(ldns_pkt *packet, bool ra)
5257b5038d7SDag-Erling Smørgrav {
5267b5038d7SDag-Erling Smørgrav 	packet->_header->_ra = ra;
5277b5038d7SDag-Erling Smørgrav }
5287b5038d7SDag-Erling Smørgrav 
5297b5038d7SDag-Erling Smørgrav void
5307b5038d7SDag-Erling Smørgrav ldns_pkt_set_ad(ldns_pkt *packet, bool ad)
5317b5038d7SDag-Erling Smørgrav {
5327b5038d7SDag-Erling Smørgrav 	packet->_header->_ad = ad;
5337b5038d7SDag-Erling Smørgrav }
5347b5038d7SDag-Erling Smørgrav 
5357b5038d7SDag-Erling Smørgrav void
5367b5038d7SDag-Erling Smørgrav ldns_pkt_set_opcode(ldns_pkt *packet, ldns_pkt_opcode opcode)
5377b5038d7SDag-Erling Smørgrav {
5387b5038d7SDag-Erling Smørgrav 	packet->_header->_opcode = opcode;
5397b5038d7SDag-Erling Smørgrav }
5407b5038d7SDag-Erling Smørgrav 
5417b5038d7SDag-Erling Smørgrav void
5427b5038d7SDag-Erling Smørgrav ldns_pkt_set_rcode(ldns_pkt *packet, uint8_t rcode)
5437b5038d7SDag-Erling Smørgrav {
5447b5038d7SDag-Erling Smørgrav 	packet->_header->_rcode = rcode;
5457b5038d7SDag-Erling Smørgrav }
5467b5038d7SDag-Erling Smørgrav 
5477b5038d7SDag-Erling Smørgrav void
5487b5038d7SDag-Erling Smørgrav ldns_pkt_set_qdcount(ldns_pkt *packet, uint16_t qdcount)
5497b5038d7SDag-Erling Smørgrav {
5507b5038d7SDag-Erling Smørgrav 	packet->_header->_qdcount = qdcount;
5517b5038d7SDag-Erling Smørgrav }
5527b5038d7SDag-Erling Smørgrav 
5537b5038d7SDag-Erling Smørgrav void
5547b5038d7SDag-Erling Smørgrav ldns_pkt_set_ancount(ldns_pkt *packet, uint16_t ancount)
5557b5038d7SDag-Erling Smørgrav {
5567b5038d7SDag-Erling Smørgrav 	packet->_header->_ancount = ancount;
5577b5038d7SDag-Erling Smørgrav }
5587b5038d7SDag-Erling Smørgrav 
5597b5038d7SDag-Erling Smørgrav void
5607b5038d7SDag-Erling Smørgrav ldns_pkt_set_nscount(ldns_pkt *packet, uint16_t nscount)
5617b5038d7SDag-Erling Smørgrav {
5627b5038d7SDag-Erling Smørgrav 	packet->_header->_nscount = nscount;
5637b5038d7SDag-Erling Smørgrav }
5647b5038d7SDag-Erling Smørgrav 
5657b5038d7SDag-Erling Smørgrav void
5667b5038d7SDag-Erling Smørgrav ldns_pkt_set_arcount(ldns_pkt *packet, uint16_t arcount)
5677b5038d7SDag-Erling Smørgrav {
5687b5038d7SDag-Erling Smørgrav 	packet->_header->_arcount = arcount;
5697b5038d7SDag-Erling Smørgrav }
5707b5038d7SDag-Erling Smørgrav 
5717b5038d7SDag-Erling Smørgrav void
5727b5038d7SDag-Erling Smørgrav ldns_pkt_set_querytime(ldns_pkt *packet, uint32_t time)
5737b5038d7SDag-Erling Smørgrav {
5747b5038d7SDag-Erling Smørgrav 	packet->_querytime = time;
5757b5038d7SDag-Erling Smørgrav }
5767b5038d7SDag-Erling Smørgrav 
5777b5038d7SDag-Erling Smørgrav void
5787b5038d7SDag-Erling Smørgrav ldns_pkt_set_answerfrom(ldns_pkt *packet, ldns_rdf *answerfrom)
5797b5038d7SDag-Erling Smørgrav {
5807b5038d7SDag-Erling Smørgrav 	packet->_answerfrom = answerfrom;
5817b5038d7SDag-Erling Smørgrav }
5827b5038d7SDag-Erling Smørgrav 
5837b5038d7SDag-Erling Smørgrav void
5847b5038d7SDag-Erling Smørgrav ldns_pkt_set_timestamp(ldns_pkt *packet, struct timeval timeval)
5857b5038d7SDag-Erling Smørgrav {
5867b5038d7SDag-Erling Smørgrav 	packet->timestamp.tv_sec = timeval.tv_sec;
5877b5038d7SDag-Erling Smørgrav 	packet->timestamp.tv_usec = timeval.tv_usec;
5887b5038d7SDag-Erling Smørgrav }
5897b5038d7SDag-Erling Smørgrav 
5907b5038d7SDag-Erling Smørgrav void
5917b5038d7SDag-Erling Smørgrav ldns_pkt_set_size(ldns_pkt *packet, size_t s)
5927b5038d7SDag-Erling Smørgrav {
5937b5038d7SDag-Erling Smørgrav 	packet->_size = s;
5947b5038d7SDag-Erling Smørgrav }
5957b5038d7SDag-Erling Smørgrav 
5967b5038d7SDag-Erling Smørgrav void
5977b5038d7SDag-Erling Smørgrav ldns_pkt_set_edns_udp_size(ldns_pkt *packet, uint16_t s)
5987b5038d7SDag-Erling Smørgrav {
5997b5038d7SDag-Erling Smørgrav 	packet->_edns_udp_size = s;
6007b5038d7SDag-Erling Smørgrav }
6017b5038d7SDag-Erling Smørgrav 
6027b5038d7SDag-Erling Smørgrav void
6037b5038d7SDag-Erling Smørgrav ldns_pkt_set_edns_extended_rcode(ldns_pkt *packet, uint8_t c)
6047b5038d7SDag-Erling Smørgrav {
6057b5038d7SDag-Erling Smørgrav 	packet->_edns_extended_rcode = c;
6067b5038d7SDag-Erling Smørgrav }
6077b5038d7SDag-Erling Smørgrav 
6087b5038d7SDag-Erling Smørgrav void
6097b5038d7SDag-Erling Smørgrav ldns_pkt_set_edns_version(ldns_pkt *packet, uint8_t v)
6107b5038d7SDag-Erling Smørgrav {
6117b5038d7SDag-Erling Smørgrav 	packet->_edns_version = v;
6127b5038d7SDag-Erling Smørgrav }
6137b5038d7SDag-Erling Smørgrav 
6147b5038d7SDag-Erling Smørgrav void
6157b5038d7SDag-Erling Smørgrav ldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z)
6167b5038d7SDag-Erling Smørgrav {
6177b5038d7SDag-Erling Smørgrav 	packet->_edns_z = z;
6187b5038d7SDag-Erling Smørgrav }
6197b5038d7SDag-Erling Smørgrav 
6207b5038d7SDag-Erling Smørgrav void
6217b5038d7SDag-Erling Smørgrav ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data)
6227b5038d7SDag-Erling Smørgrav {
6237b5038d7SDag-Erling Smørgrav 	packet->_edns_data = data;
6247b5038d7SDag-Erling Smørgrav }
6257b5038d7SDag-Erling Smørgrav 
6267b5038d7SDag-Erling Smørgrav void
6277b5038d7SDag-Erling Smørgrav ldns_pkt_set_section_count(ldns_pkt *packet, ldns_pkt_section s, uint16_t count)
6287b5038d7SDag-Erling Smørgrav {
6297b5038d7SDag-Erling Smørgrav 	switch(s) {
6307b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_QUESTION:
6317b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_qdcount(packet, count);
6327b5038d7SDag-Erling Smørgrav 			break;
6337b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ANSWER:
6347b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_ancount(packet, count);
6357b5038d7SDag-Erling Smørgrav 			break;
6367b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_AUTHORITY:
6377b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_nscount(packet, count);
6387b5038d7SDag-Erling Smørgrav 			break;
6397b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ADDITIONAL:
6407b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_arcount(packet, count);
6417b5038d7SDag-Erling Smørgrav 			break;
6427b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ANY:
6437b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ANY_NOQUESTION:
6447b5038d7SDag-Erling Smørgrav 			break;
6457b5038d7SDag-Erling Smørgrav 	}
6467b5038d7SDag-Erling Smørgrav }
6477b5038d7SDag-Erling Smørgrav 
6487b5038d7SDag-Erling Smørgrav void ldns_pkt_set_tsig(ldns_pkt *pkt, ldns_rr *rr)
6497b5038d7SDag-Erling Smørgrav {
6507b5038d7SDag-Erling Smørgrav 	pkt->_tsig_rr = rr;
6517b5038d7SDag-Erling Smørgrav }
6527b5038d7SDag-Erling Smørgrav 
6537b5038d7SDag-Erling Smørgrav bool
6547b5038d7SDag-Erling Smørgrav ldns_pkt_push_rr(ldns_pkt *packet, ldns_pkt_section section, ldns_rr *rr)
6557b5038d7SDag-Erling Smørgrav {
6567b5038d7SDag-Erling Smørgrav 	switch(section) {
6577b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_QUESTION:
6582787e39aSDag-Erling Smørgrav 			if (!ldns_rr_list_push_rr(ldns_pkt_question(packet), rr)) {
6592787e39aSDag-Erling Smørgrav 				return false;
6602787e39aSDag-Erling Smørgrav 			}
6617b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_qdcount(packet, ldns_pkt_qdcount(packet) + 1);
6627b5038d7SDag-Erling Smørgrav 			break;
6637b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ANSWER:
6642787e39aSDag-Erling Smørgrav 			if (!ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr)) {
6652787e39aSDag-Erling Smørgrav 				return false;
6662787e39aSDag-Erling Smørgrav 			}
6677b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_ancount(packet, ldns_pkt_ancount(packet) + 1);
6687b5038d7SDag-Erling Smørgrav 			break;
6697b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_AUTHORITY:
6702787e39aSDag-Erling Smørgrav 			if (!ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr)) {
6712787e39aSDag-Erling Smørgrav 				return false;
6722787e39aSDag-Erling Smørgrav 			}
6737b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_nscount(packet, ldns_pkt_nscount(packet) + 1);
6747b5038d7SDag-Erling Smørgrav 			break;
6757b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ADDITIONAL:
6762787e39aSDag-Erling Smørgrav 			if (!ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr)) {
6772787e39aSDag-Erling Smørgrav 				return false;
6782787e39aSDag-Erling Smørgrav 			}
6797b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) + 1);
6807b5038d7SDag-Erling Smørgrav 			break;
6817b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ANY:
6827b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ANY_NOQUESTION:
6837b5038d7SDag-Erling Smørgrav 			/* shouldn't this error? */
6847b5038d7SDag-Erling Smørgrav 			break;
6857b5038d7SDag-Erling Smørgrav 	}
6867b5038d7SDag-Erling Smørgrav 	return true;
6877b5038d7SDag-Erling Smørgrav }
6887b5038d7SDag-Erling Smørgrav 
6897b5038d7SDag-Erling Smørgrav bool
6907b5038d7SDag-Erling Smørgrav ldns_pkt_safe_push_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr)
6917b5038d7SDag-Erling Smørgrav {
6927b5038d7SDag-Erling Smørgrav 
6937b5038d7SDag-Erling Smørgrav 	/* check to see if its there */
6947b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_rr(pkt, sec, rr)) {
6957b5038d7SDag-Erling Smørgrav 		/* already there */
6967b5038d7SDag-Erling Smørgrav 		return false;
6977b5038d7SDag-Erling Smørgrav 	}
6987b5038d7SDag-Erling Smørgrav 	return ldns_pkt_push_rr(pkt, sec, rr);
6997b5038d7SDag-Erling Smørgrav }
7007b5038d7SDag-Erling Smørgrav 
7017b5038d7SDag-Erling Smørgrav bool
7027b5038d7SDag-Erling Smørgrav ldns_pkt_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
7037b5038d7SDag-Erling Smørgrav {
7047b5038d7SDag-Erling Smørgrav 	size_t i;
7057b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
7067b5038d7SDag-Erling Smørgrav 		if (!ldns_pkt_push_rr(p, s, ldns_rr_list_rr(list, i))) {
7077b5038d7SDag-Erling Smørgrav 			return false;
7087b5038d7SDag-Erling Smørgrav 		}
7097b5038d7SDag-Erling Smørgrav 	}
7107b5038d7SDag-Erling Smørgrav 	return true;
7117b5038d7SDag-Erling Smørgrav }
7127b5038d7SDag-Erling Smørgrav 
7137b5038d7SDag-Erling Smørgrav bool
7147b5038d7SDag-Erling Smørgrav ldns_pkt_safe_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
7157b5038d7SDag-Erling Smørgrav {
7167b5038d7SDag-Erling Smørgrav 	size_t i;
7177b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
7187b5038d7SDag-Erling Smørgrav 		if (!ldns_pkt_safe_push_rr(p, s, ldns_rr_list_rr(list, i))) {
7197b5038d7SDag-Erling Smørgrav 			return false;
7207b5038d7SDag-Erling Smørgrav 		}
7217b5038d7SDag-Erling Smørgrav 	}
7227b5038d7SDag-Erling Smørgrav 	return true;
7237b5038d7SDag-Erling Smørgrav }
7247b5038d7SDag-Erling Smørgrav 
7257b5038d7SDag-Erling Smørgrav bool
7267b5038d7SDag-Erling Smørgrav ldns_pkt_edns(const ldns_pkt *pkt) {
7277b5038d7SDag-Erling Smørgrav 	return (ldns_pkt_edns_udp_size(pkt) > 0 ||
7287b5038d7SDag-Erling Smørgrav 		ldns_pkt_edns_extended_rcode(pkt) > 0 ||
7297b5038d7SDag-Erling Smørgrav 		ldns_pkt_edns_data(pkt) ||
730*986ba33cSDag-Erling Smørgrav 		ldns_pkt_edns_do(pkt) ||
731*986ba33cSDag-Erling Smørgrav                 pkt->_edns_present
7327b5038d7SDag-Erling Smørgrav 	       );
7337b5038d7SDag-Erling Smørgrav }
7347b5038d7SDag-Erling Smørgrav 
7357b5038d7SDag-Erling Smørgrav 
7367b5038d7SDag-Erling Smørgrav /* Create/destroy/convert functions
7377b5038d7SDag-Erling Smørgrav  */
7387b5038d7SDag-Erling Smørgrav ldns_pkt *
7397b5038d7SDag-Erling Smørgrav ldns_pkt_new(void)
7407b5038d7SDag-Erling Smørgrav {
7417b5038d7SDag-Erling Smørgrav 	ldns_pkt *packet;
7427b5038d7SDag-Erling Smørgrav 	packet = LDNS_MALLOC(ldns_pkt);
7437b5038d7SDag-Erling Smørgrav 	if (!packet) {
7447b5038d7SDag-Erling Smørgrav 		return NULL;
7457b5038d7SDag-Erling Smørgrav 	}
7467b5038d7SDag-Erling Smørgrav 
7477b5038d7SDag-Erling Smørgrav 	packet->_header = LDNS_MALLOC(ldns_hdr);
7487b5038d7SDag-Erling Smørgrav 	if (!packet->_header) {
7497b5038d7SDag-Erling Smørgrav 		LDNS_FREE(packet);
7507b5038d7SDag-Erling Smørgrav 		return NULL;
7517b5038d7SDag-Erling Smørgrav 	}
7527b5038d7SDag-Erling Smørgrav 
7537b5038d7SDag-Erling Smørgrav 	packet->_question = ldns_rr_list_new();
7547b5038d7SDag-Erling Smørgrav 	packet->_answer = ldns_rr_list_new();
7557b5038d7SDag-Erling Smørgrav 	packet->_authority = ldns_rr_list_new();
7567b5038d7SDag-Erling Smørgrav 	packet->_additional = ldns_rr_list_new();
7577b5038d7SDag-Erling Smørgrav 
7587b5038d7SDag-Erling Smørgrav 	/* default everything to false */
7597b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_qr(packet, false);
7607b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_aa(packet, false);
7617b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_tc(packet, false);
7627b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_rd(packet, false);
7637b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_ra(packet, false);
7647b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_ad(packet, false);
7657b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_cd(packet, false);
7667b5038d7SDag-Erling Smørgrav 
7677b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_opcode(packet, LDNS_PACKET_QUERY);
7687b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_rcode(packet, 0);
7697b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_id(packet, 0);
7707b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_size(packet, 0);
7717b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_querytime(packet, 0);
7727b5038d7SDag-Erling Smørgrav 	memset(&packet->timestamp, 0, sizeof(packet->timestamp));
7737b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_answerfrom(packet, NULL);
7747b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_section_count(packet, LDNS_SECTION_QUESTION, 0);
7757b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_section_count(packet, LDNS_SECTION_ANSWER, 0);
7767b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_section_count(packet, LDNS_SECTION_AUTHORITY, 0);
7777b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_section_count(packet, LDNS_SECTION_ADDITIONAL, 0);
7787b5038d7SDag-Erling Smørgrav 
7797b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_udp_size(packet, 0);
7807b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_extended_rcode(packet, 0);
7817b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_version(packet, 0);
7827b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_z(packet, 0);
7837b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_data(packet, NULL);
784*986ba33cSDag-Erling Smørgrav 	packet->_edns_present = false;
7857b5038d7SDag-Erling Smørgrav 
7867b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_tsig(packet, NULL);
7877b5038d7SDag-Erling Smørgrav 
7887b5038d7SDag-Erling Smørgrav 	return packet;
7897b5038d7SDag-Erling Smørgrav }
7907b5038d7SDag-Erling Smørgrav 
7917b5038d7SDag-Erling Smørgrav void
7927b5038d7SDag-Erling Smørgrav ldns_pkt_free(ldns_pkt *packet)
7937b5038d7SDag-Erling Smørgrav {
7947b5038d7SDag-Erling Smørgrav 	if (packet) {
7957b5038d7SDag-Erling Smørgrav 		LDNS_FREE(packet->_header);
7967b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(packet->_question);
7977b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(packet->_answer);
7987b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(packet->_authority);
7997b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(packet->_additional);
8007b5038d7SDag-Erling Smørgrav 		ldns_rr_free(packet->_tsig_rr);
8017b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(packet->_edns_data);
8022787e39aSDag-Erling Smørgrav 		ldns_rdf_deep_free(packet->_answerfrom);
8037b5038d7SDag-Erling Smørgrav 		LDNS_FREE(packet);
8047b5038d7SDag-Erling Smørgrav 	}
8057b5038d7SDag-Erling Smørgrav }
8067b5038d7SDag-Erling Smørgrav 
8077b5038d7SDag-Erling Smørgrav bool
8087b5038d7SDag-Erling Smørgrav ldns_pkt_set_flags(ldns_pkt *packet, uint16_t flags)
8097b5038d7SDag-Erling Smørgrav {
8107b5038d7SDag-Erling Smørgrav 	if (!packet) {
8117b5038d7SDag-Erling Smørgrav 		return false;
8127b5038d7SDag-Erling Smørgrav 	}
8137b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_QR) == LDNS_QR) {
8147b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_qr(packet, true);
8157b5038d7SDag-Erling Smørgrav 	}
8167b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_AA) == LDNS_AA) {
8177b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_aa(packet, true);
8187b5038d7SDag-Erling Smørgrav 	}
8197b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_RD) == LDNS_RD) {
8207b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_rd(packet, true);
8217b5038d7SDag-Erling Smørgrav 	}
8227b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_TC) == LDNS_TC) {
8237b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_tc(packet, true);
8247b5038d7SDag-Erling Smørgrav 	}
8257b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_CD) == LDNS_CD) {
8267b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_cd(packet, true);
8277b5038d7SDag-Erling Smørgrav 	}
8287b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_RA) == LDNS_RA) {
8297b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_ra(packet, true);
8307b5038d7SDag-Erling Smørgrav 	}
8317b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_AD) == LDNS_AD) {
8327b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_ad(packet, true);
8337b5038d7SDag-Erling Smørgrav 	}
8347b5038d7SDag-Erling Smørgrav 	return true;
8357b5038d7SDag-Erling Smørgrav }
8367b5038d7SDag-Erling Smørgrav 
8372787e39aSDag-Erling Smørgrav 
83817d15b25SDag-Erling Smørgrav static ldns_rr*
839*986ba33cSDag-Erling Smørgrav ldns_pkt_authsoa(const ldns_rdf* rr_name, ldns_rr_class rr_class)
8402787e39aSDag-Erling Smørgrav {
8412787e39aSDag-Erling Smørgrav 	ldns_rr* soa_rr = ldns_rr_new();
8422787e39aSDag-Erling Smørgrav 	ldns_rdf *owner_rdf;
8432787e39aSDag-Erling Smørgrav 	ldns_rdf *mname_rdf;
8442787e39aSDag-Erling Smørgrav 	ldns_rdf *rname_rdf;
8452787e39aSDag-Erling Smørgrav 	ldns_rdf *serial_rdf;
8462787e39aSDag-Erling Smørgrav 	ldns_rdf *refresh_rdf;
8472787e39aSDag-Erling Smørgrav 	ldns_rdf *retry_rdf;
8482787e39aSDag-Erling Smørgrav 	ldns_rdf *expire_rdf;
8492787e39aSDag-Erling Smørgrav 	ldns_rdf *minimum_rdf;
8502787e39aSDag-Erling Smørgrav 
8512787e39aSDag-Erling Smørgrav 	if (!soa_rr) {
85217d15b25SDag-Erling Smørgrav 		return NULL;
8532787e39aSDag-Erling Smørgrav 	}
8542787e39aSDag-Erling Smørgrav 	owner_rdf = ldns_rdf_clone(rr_name);
8552787e39aSDag-Erling Smørgrav 	if (!owner_rdf) {
8562787e39aSDag-Erling Smørgrav 		ldns_rr_free(soa_rr);
85717d15b25SDag-Erling Smørgrav 		return NULL;
8582787e39aSDag-Erling Smørgrav 	}
8592787e39aSDag-Erling Smørgrav 
8602787e39aSDag-Erling Smørgrav 	ldns_rr_set_owner(soa_rr, owner_rdf);
8612787e39aSDag-Erling Smørgrav 	ldns_rr_set_type(soa_rr, LDNS_RR_TYPE_SOA);
8622787e39aSDag-Erling Smørgrav 	ldns_rr_set_class(soa_rr, rr_class);
8632787e39aSDag-Erling Smørgrav 	ldns_rr_set_question(soa_rr, false);
8642787e39aSDag-Erling Smørgrav 
8652787e39aSDag-Erling Smørgrav 	if (ldns_str2rdf_dname(&mname_rdf, ".") != LDNS_STATUS_OK) {
8662787e39aSDag-Erling Smørgrav 		ldns_rr_free(soa_rr);
86717d15b25SDag-Erling Smørgrav 		return NULL;
8682787e39aSDag-Erling Smørgrav 	} else {
8692787e39aSDag-Erling Smørgrav 		ldns_rr_push_rdf(soa_rr, mname_rdf);
8702787e39aSDag-Erling Smørgrav 	}
8712787e39aSDag-Erling Smørgrav 	if (ldns_str2rdf_dname(&rname_rdf, ".") != LDNS_STATUS_OK) {
8722787e39aSDag-Erling Smørgrav 		ldns_rr_free(soa_rr);
87317d15b25SDag-Erling Smørgrav 		return NULL;
8742787e39aSDag-Erling Smørgrav 	} else {
8752787e39aSDag-Erling Smørgrav 		ldns_rr_push_rdf(soa_rr, rname_rdf);
8762787e39aSDag-Erling Smørgrav 	}
8772787e39aSDag-Erling Smørgrav 	serial_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
8782787e39aSDag-Erling Smørgrav 	if (!serial_rdf) {
8792787e39aSDag-Erling Smørgrav 		ldns_rr_free(soa_rr);
88017d15b25SDag-Erling Smørgrav 		return NULL;
8812787e39aSDag-Erling Smørgrav 	} else {
8822787e39aSDag-Erling Smørgrav 		ldns_rr_push_rdf(soa_rr, serial_rdf);
8832787e39aSDag-Erling Smørgrav 	}
8842787e39aSDag-Erling Smørgrav 	refresh_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
8852787e39aSDag-Erling Smørgrav 	if (!refresh_rdf) {
8862787e39aSDag-Erling Smørgrav 		ldns_rr_free(soa_rr);
88717d15b25SDag-Erling Smørgrav 		return NULL;
8882787e39aSDag-Erling Smørgrav 	} else {
8892787e39aSDag-Erling Smørgrav 		ldns_rr_push_rdf(soa_rr, refresh_rdf);
8902787e39aSDag-Erling Smørgrav 	}
8912787e39aSDag-Erling Smørgrav 	retry_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
8922787e39aSDag-Erling Smørgrav 	if (!retry_rdf) {
8932787e39aSDag-Erling Smørgrav 		ldns_rr_free(soa_rr);
89417d15b25SDag-Erling Smørgrav 		return NULL;
8952787e39aSDag-Erling Smørgrav 	} else {
8962787e39aSDag-Erling Smørgrav 		ldns_rr_push_rdf(soa_rr, retry_rdf);
8972787e39aSDag-Erling Smørgrav 	}
8982787e39aSDag-Erling Smørgrav 	expire_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
8992787e39aSDag-Erling Smørgrav 	if (!expire_rdf) {
9002787e39aSDag-Erling Smørgrav 		ldns_rr_free(soa_rr);
90117d15b25SDag-Erling Smørgrav 		return NULL;
9022787e39aSDag-Erling Smørgrav 	} else {
9032787e39aSDag-Erling Smørgrav 		ldns_rr_push_rdf(soa_rr, expire_rdf);
9042787e39aSDag-Erling Smørgrav 	}
9052787e39aSDag-Erling Smørgrav 	minimum_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
9062787e39aSDag-Erling Smørgrav 	if (!minimum_rdf) {
9072787e39aSDag-Erling Smørgrav 		ldns_rr_free(soa_rr);
90817d15b25SDag-Erling Smørgrav 		return NULL;
9092787e39aSDag-Erling Smørgrav 	} else {
9102787e39aSDag-Erling Smørgrav 		ldns_rr_push_rdf(soa_rr, minimum_rdf);
9112787e39aSDag-Erling Smørgrav 	}
91217d15b25SDag-Erling Smørgrav 	return soa_rr;
9132787e39aSDag-Erling Smørgrav }
9142787e39aSDag-Erling Smørgrav 
9152787e39aSDag-Erling Smørgrav 
91617d15b25SDag-Erling Smørgrav static ldns_status
91717d15b25SDag-Erling Smørgrav ldns_pkt_query_new_frm_str_internal(ldns_pkt **p, const char *name,
91817d15b25SDag-Erling Smørgrav 	ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags,
91917d15b25SDag-Erling Smørgrav 	ldns_rr* authsoa_rr)
9207b5038d7SDag-Erling Smørgrav {
9217b5038d7SDag-Erling Smørgrav 	ldns_pkt *packet;
9227b5038d7SDag-Erling Smørgrav 	ldns_rr *question_rr;
9237b5038d7SDag-Erling Smørgrav 	ldns_rdf *name_rdf;
9247b5038d7SDag-Erling Smørgrav 
9257b5038d7SDag-Erling Smørgrav 	packet = ldns_pkt_new();
9267b5038d7SDag-Erling Smørgrav 	if (!packet) {
9277b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_MEM_ERR;
9287b5038d7SDag-Erling Smørgrav 	}
9297b5038d7SDag-Erling Smørgrav 
9307b5038d7SDag-Erling Smørgrav 	if (!ldns_pkt_set_flags(packet, flags)) {
9317b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
9327b5038d7SDag-Erling Smørgrav 	}
9337b5038d7SDag-Erling Smørgrav 
9347b5038d7SDag-Erling Smørgrav 	question_rr = ldns_rr_new();
9357b5038d7SDag-Erling Smørgrav 	if (!question_rr) {
9367b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_MEM_ERR;
9377b5038d7SDag-Erling Smørgrav 	}
9387b5038d7SDag-Erling Smørgrav 
9397b5038d7SDag-Erling Smørgrav 	if (rr_type == 0) {
9407b5038d7SDag-Erling Smørgrav 		rr_type = LDNS_RR_TYPE_A;
9417b5038d7SDag-Erling Smørgrav 	}
9427b5038d7SDag-Erling Smørgrav 	if (rr_class == 0) {
9437b5038d7SDag-Erling Smørgrav 		rr_class = LDNS_RR_CLASS_IN;
9447b5038d7SDag-Erling Smørgrav 	}
9457b5038d7SDag-Erling Smørgrav 
9467b5038d7SDag-Erling Smørgrav 	if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) {
9477b5038d7SDag-Erling Smørgrav 		ldns_rr_set_owner(question_rr, name_rdf);
9487b5038d7SDag-Erling Smørgrav 		ldns_rr_set_type(question_rr, rr_type);
9497b5038d7SDag-Erling Smørgrav 		ldns_rr_set_class(question_rr, rr_class);
9507b5038d7SDag-Erling Smørgrav                 ldns_rr_set_question(question_rr, true);
9517b5038d7SDag-Erling Smørgrav 
9527b5038d7SDag-Erling Smørgrav 		ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr);
9537b5038d7SDag-Erling Smørgrav 	} else {
9547b5038d7SDag-Erling Smørgrav 		ldns_rr_free(question_rr);
9557b5038d7SDag-Erling Smørgrav 		ldns_pkt_free(packet);
9567b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
9577b5038d7SDag-Erling Smørgrav 	}
9587b5038d7SDag-Erling Smørgrav 
95917d15b25SDag-Erling Smørgrav 	if (authsoa_rr) {
96017d15b25SDag-Erling Smørgrav 		ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, authsoa_rr);
9612787e39aSDag-Erling Smørgrav 	}
9627b5038d7SDag-Erling Smørgrav 
9632787e39aSDag-Erling Smørgrav 	packet->_tsig_rr = NULL;
9647b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_answerfrom(packet, NULL);
9657b5038d7SDag-Erling Smørgrav 	if (p) {
9667b5038d7SDag-Erling Smørgrav 		*p = packet;
9677b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_OK;
9687b5038d7SDag-Erling Smørgrav 	} else {
9692787e39aSDag-Erling Smørgrav 		ldns_pkt_free(packet);
9707b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_NULL;
9717b5038d7SDag-Erling Smørgrav 	}
9727b5038d7SDag-Erling Smørgrav }
9737b5038d7SDag-Erling Smørgrav 
97417d15b25SDag-Erling Smørgrav ldns_status
97517d15b25SDag-Erling Smørgrav ldns_pkt_query_new_frm_str(ldns_pkt **p, const char *name,
97617d15b25SDag-Erling Smørgrav 	ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags)
97717d15b25SDag-Erling Smørgrav {
97817d15b25SDag-Erling Smørgrav 	return ldns_pkt_query_new_frm_str_internal(p, name, rr_type,
97917d15b25SDag-Erling Smørgrav 		rr_class, flags, NULL);
98017d15b25SDag-Erling Smørgrav }
98117d15b25SDag-Erling Smørgrav 
98217d15b25SDag-Erling Smørgrav ldns_status
98317d15b25SDag-Erling Smørgrav ldns_pkt_ixfr_request_new_frm_str(ldns_pkt **p, const char *name,
98417d15b25SDag-Erling Smørgrav 	ldns_rr_class rr_class, uint16_t flags, ldns_rr *soa)
98517d15b25SDag-Erling Smørgrav {
98617d15b25SDag-Erling Smørgrav 	ldns_rr* authsoa_rr = soa;
98717d15b25SDag-Erling Smørgrav 	if (!authsoa_rr) {
98817d15b25SDag-Erling Smørgrav 		ldns_rdf *name_rdf;
98917d15b25SDag-Erling Smørgrav 		if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) {
99017d15b25SDag-Erling Smørgrav 			authsoa_rr = ldns_pkt_authsoa(name_rdf, rr_class);
99117d15b25SDag-Erling Smørgrav 		}
99217d15b25SDag-Erling Smørgrav 		ldns_rdf_free(name_rdf);
99317d15b25SDag-Erling Smørgrav 	}
99417d15b25SDag-Erling Smørgrav 	return ldns_pkt_query_new_frm_str_internal(p, name, LDNS_RR_TYPE_IXFR,
99517d15b25SDag-Erling Smørgrav 		rr_class, flags, authsoa_rr);
99617d15b25SDag-Erling Smørgrav }
99717d15b25SDag-Erling Smørgrav 
99817d15b25SDag-Erling Smørgrav static ldns_pkt *
99917d15b25SDag-Erling Smørgrav ldns_pkt_query_new_internal(ldns_rdf *rr_name, ldns_rr_type rr_type,
100017d15b25SDag-Erling Smørgrav 	ldns_rr_class rr_class,	uint16_t flags, ldns_rr* authsoa_rr)
10017b5038d7SDag-Erling Smørgrav {
10027b5038d7SDag-Erling Smørgrav 	ldns_pkt *packet;
10037b5038d7SDag-Erling Smørgrav 	ldns_rr *question_rr;
10047b5038d7SDag-Erling Smørgrav 
10057b5038d7SDag-Erling Smørgrav 	packet = ldns_pkt_new();
10067b5038d7SDag-Erling Smørgrav 	if (!packet) {
10077b5038d7SDag-Erling Smørgrav 		return NULL;
10087b5038d7SDag-Erling Smørgrav 	}
10097b5038d7SDag-Erling Smørgrav 
10107b5038d7SDag-Erling Smørgrav 	if (!ldns_pkt_set_flags(packet, flags)) {
10117b5038d7SDag-Erling Smørgrav 		return NULL;
10127b5038d7SDag-Erling Smørgrav 	}
10137b5038d7SDag-Erling Smørgrav 
10147b5038d7SDag-Erling Smørgrav 	question_rr = ldns_rr_new();
10157b5038d7SDag-Erling Smørgrav 	if (!question_rr) {
10162787e39aSDag-Erling Smørgrav 		ldns_pkt_free(packet);
10177b5038d7SDag-Erling Smørgrav 		return NULL;
10187b5038d7SDag-Erling Smørgrav 	}
10197b5038d7SDag-Erling Smørgrav 
10207b5038d7SDag-Erling Smørgrav 	if (rr_type == 0) {
10217b5038d7SDag-Erling Smørgrav 		rr_type = LDNS_RR_TYPE_A;
10227b5038d7SDag-Erling Smørgrav 	}
10237b5038d7SDag-Erling Smørgrav 	if (rr_class == 0) {
10247b5038d7SDag-Erling Smørgrav 		rr_class = LDNS_RR_CLASS_IN;
10257b5038d7SDag-Erling Smørgrav 	}
10267b5038d7SDag-Erling Smørgrav 
10277b5038d7SDag-Erling Smørgrav 	ldns_rr_set_owner(question_rr, rr_name);
10287b5038d7SDag-Erling Smørgrav 	ldns_rr_set_type(question_rr, rr_type);
10297b5038d7SDag-Erling Smørgrav 	ldns_rr_set_class(question_rr, rr_class);
10307b5038d7SDag-Erling Smørgrav         ldns_rr_set_question(question_rr, true);
10317b5038d7SDag-Erling Smørgrav 	ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr);
10327b5038d7SDag-Erling Smørgrav 
103317d15b25SDag-Erling Smørgrav 	if (authsoa_rr) {
103417d15b25SDag-Erling Smørgrav 		ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, authsoa_rr);
10352787e39aSDag-Erling Smørgrav 	}
10362787e39aSDag-Erling Smørgrav 
10372787e39aSDag-Erling Smørgrav 	packet->_tsig_rr = NULL;
10387b5038d7SDag-Erling Smørgrav 	return packet;
10397b5038d7SDag-Erling Smørgrav }
10407b5038d7SDag-Erling Smørgrav 
104117d15b25SDag-Erling Smørgrav ldns_pkt *
104217d15b25SDag-Erling Smørgrav ldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type,
104317d15b25SDag-Erling Smørgrav 	ldns_rr_class rr_class,	uint16_t flags)
104417d15b25SDag-Erling Smørgrav {
104517d15b25SDag-Erling Smørgrav 	return ldns_pkt_query_new_internal(rr_name, rr_type,
104617d15b25SDag-Erling Smørgrav 		rr_class, flags, NULL);
104717d15b25SDag-Erling Smørgrav }
104817d15b25SDag-Erling Smørgrav 
104917d15b25SDag-Erling Smørgrav ldns_pkt *
105017d15b25SDag-Erling Smørgrav ldns_pkt_ixfr_request_new(ldns_rdf *rr_name, ldns_rr_class rr_class,
105117d15b25SDag-Erling Smørgrav 	uint16_t flags, ldns_rr* soa)
105217d15b25SDag-Erling Smørgrav {
105317d15b25SDag-Erling Smørgrav 	ldns_rr* authsoa_rr = soa;
105417d15b25SDag-Erling Smørgrav 	if (!authsoa_rr) {
105517d15b25SDag-Erling Smørgrav 		authsoa_rr = ldns_pkt_authsoa(rr_name, rr_class);
105617d15b25SDag-Erling Smørgrav 	}
105717d15b25SDag-Erling Smørgrav 	return ldns_pkt_query_new_internal(rr_name, LDNS_RR_TYPE_IXFR,
105817d15b25SDag-Erling Smørgrav 		rr_class, flags, authsoa_rr);
105917d15b25SDag-Erling Smørgrav }
106017d15b25SDag-Erling Smørgrav 
10617b5038d7SDag-Erling Smørgrav ldns_pkt_type
1062*986ba33cSDag-Erling Smørgrav ldns_pkt_reply_type(const ldns_pkt *p)
10637b5038d7SDag-Erling Smørgrav {
10647b5038d7SDag-Erling Smørgrav 	ldns_rr_list *tmp;
10657b5038d7SDag-Erling Smørgrav 
10667b5038d7SDag-Erling Smørgrav 	if (!p) {
10677b5038d7SDag-Erling Smørgrav 		return LDNS_PACKET_UNKNOWN;
10687b5038d7SDag-Erling Smørgrav 	}
10697b5038d7SDag-Erling Smørgrav 
10707b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NXDOMAIN) {
10717b5038d7SDag-Erling Smørgrav 		return LDNS_PACKET_NXDOMAIN;
10727b5038d7SDag-Erling Smørgrav 	}
10737b5038d7SDag-Erling Smørgrav 
10747b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_ancount(p) == 0 && ldns_pkt_arcount(p) == 0
10757b5038d7SDag-Erling Smørgrav 			&& ldns_pkt_nscount(p) == 1) {
10767b5038d7SDag-Erling Smørgrav 
10777b5038d7SDag-Erling Smørgrav 		/* check for SOA */
10787b5038d7SDag-Erling Smørgrav 		tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_SOA,
10797b5038d7SDag-Erling Smørgrav 					LDNS_SECTION_AUTHORITY);
10807b5038d7SDag-Erling Smørgrav 		if (tmp) {
10817b5038d7SDag-Erling Smørgrav 			ldns_rr_list_deep_free(tmp);
10827b5038d7SDag-Erling Smørgrav 			return LDNS_PACKET_NODATA;
10837b5038d7SDag-Erling Smørgrav 		} else {
10847b5038d7SDag-Erling Smørgrav 			/* I have no idea ... */
10857b5038d7SDag-Erling Smørgrav 		}
10867b5038d7SDag-Erling Smørgrav 	}
10877b5038d7SDag-Erling Smørgrav 
10887b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_ancount(p) == 0 && ldns_pkt_nscount(p) > 0) {
10897b5038d7SDag-Erling Smørgrav 		tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS,
10907b5038d7SDag-Erling Smørgrav 		                               LDNS_SECTION_AUTHORITY);
10917b5038d7SDag-Erling Smørgrav 		if (tmp) {
10927b5038d7SDag-Erling Smørgrav 			/* there are nameservers here */
10937b5038d7SDag-Erling Smørgrav 			ldns_rr_list_deep_free(tmp);
10947b5038d7SDag-Erling Smørgrav 			return LDNS_PACKET_REFERRAL;
10957b5038d7SDag-Erling Smørgrav 		} else {
10967b5038d7SDag-Erling Smørgrav 			/* I have no idea */
10977b5038d7SDag-Erling Smørgrav 		}
10987b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(tmp);
10997b5038d7SDag-Erling Smørgrav 	}
11007b5038d7SDag-Erling Smørgrav 
11017b5038d7SDag-Erling Smørgrav 	/* if we cannot determine the packet type, we say it's an
11027b5038d7SDag-Erling Smørgrav 	 * answer...
11037b5038d7SDag-Erling Smørgrav 	 */
11047b5038d7SDag-Erling Smørgrav 	return LDNS_PACKET_ANSWER;
11057b5038d7SDag-Erling Smørgrav }
11067b5038d7SDag-Erling Smørgrav 
11077b5038d7SDag-Erling Smørgrav ldns_pkt *
1108*986ba33cSDag-Erling Smørgrav ldns_pkt_clone(const ldns_pkt *pkt)
11097b5038d7SDag-Erling Smørgrav {
11107b5038d7SDag-Erling Smørgrav 	ldns_pkt *new_pkt;
11117b5038d7SDag-Erling Smørgrav 
11127b5038d7SDag-Erling Smørgrav 	if (!pkt) {
11137b5038d7SDag-Erling Smørgrav 		return NULL;
11147b5038d7SDag-Erling Smørgrav 	}
11157b5038d7SDag-Erling Smørgrav 	new_pkt = ldns_pkt_new();
11167b5038d7SDag-Erling Smørgrav 
11177b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_id(new_pkt, ldns_pkt_id(pkt));
11187b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_qr(new_pkt, ldns_pkt_qr(pkt));
11197b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_aa(new_pkt, ldns_pkt_aa(pkt));
11207b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_tc(new_pkt, ldns_pkt_tc(pkt));
11217b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_rd(new_pkt, ldns_pkt_rd(pkt));
11227b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_cd(new_pkt, ldns_pkt_cd(pkt));
11237b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_ra(new_pkt, ldns_pkt_ra(pkt));
11247b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_ad(new_pkt, ldns_pkt_ad(pkt));
11257b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_opcode(new_pkt, ldns_pkt_get_opcode(pkt));
11267b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_rcode(new_pkt, ldns_pkt_get_rcode(pkt));
11277b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_qdcount(new_pkt, ldns_pkt_qdcount(pkt));
11287b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_ancount(new_pkt, ldns_pkt_ancount(pkt));
11297b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_nscount(new_pkt, ldns_pkt_nscount(pkt));
11307b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_arcount(new_pkt, ldns_pkt_arcount(pkt));
11312787e39aSDag-Erling Smørgrav 	if (ldns_pkt_answerfrom(pkt))
11322787e39aSDag-Erling Smørgrav 		ldns_pkt_set_answerfrom(new_pkt,
11332787e39aSDag-Erling Smørgrav 			ldns_rdf_clone(ldns_pkt_answerfrom(pkt)));
1134*986ba33cSDag-Erling Smørgrav 	ldns_pkt_set_timestamp(new_pkt, ldns_pkt_timestamp(pkt));
11357b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_querytime(new_pkt, ldns_pkt_querytime(pkt));
11367b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_size(new_pkt, ldns_pkt_size(pkt));
11377b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_tsig(new_pkt, ldns_rr_clone(ldns_pkt_tsig(pkt)));
11387b5038d7SDag-Erling Smørgrav 
11397b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_udp_size(new_pkt, ldns_pkt_edns_udp_size(pkt));
11407b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_extended_rcode(new_pkt,
11417b5038d7SDag-Erling Smørgrav 		ldns_pkt_edns_extended_rcode(pkt));
11427b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_version(new_pkt, ldns_pkt_edns_version(pkt));
1143*986ba33cSDag-Erling Smørgrav 	new_pkt->_edns_present = pkt->_edns_present;
11447b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_z(new_pkt, ldns_pkt_edns_z(pkt));
11457b5038d7SDag-Erling Smørgrav 	if(ldns_pkt_edns_data(pkt))
11467b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_edns_data(new_pkt,
11477b5038d7SDag-Erling Smørgrav 			ldns_rdf_clone(ldns_pkt_edns_data(pkt)));
11487b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_do(new_pkt, ldns_pkt_edns_do(pkt));
11497b5038d7SDag-Erling Smørgrav 
11507b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(new_pkt->_question);
11517b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(new_pkt->_answer);
11527b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(new_pkt->_authority);
11537b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(new_pkt->_additional);
11547b5038d7SDag-Erling Smørgrav 	new_pkt->_question = ldns_rr_list_clone(ldns_pkt_question(pkt));
11557b5038d7SDag-Erling Smørgrav 	new_pkt->_answer = ldns_rr_list_clone(ldns_pkt_answer(pkt));
11567b5038d7SDag-Erling Smørgrav 	new_pkt->_authority = ldns_rr_list_clone(ldns_pkt_authority(pkt));
11577b5038d7SDag-Erling Smørgrav 	new_pkt->_additional = ldns_rr_list_clone(ldns_pkt_additional(pkt));
11587b5038d7SDag-Erling Smørgrav 	return new_pkt;
11597b5038d7SDag-Erling Smørgrav }
1160