xref: /freebsd/contrib/ldns/packet.c (revision 9ed998a81bab54203604d08293089db875758686)
1 /*
2  * packet.c
3  *
4  * dns packet implementation
5  *
6  * a Net::DNS like library for C
7  *
8  * (c) NLnet Labs, 2004-2006
9  *
10  * See the file LICENSE for the license
11  */
12 
13 #include <ldns/config.h>
14 
15 #include <ldns/ldns.h>
16 #include <ldns/internal.h>
17 
18 #include <strings.h>
19 #include <limits.h>
20 
21 #ifdef HAVE_SSL
22 #include <openssl/rand.h>
23 #endif
24 
25 /* Access functions
26  * do this as functions to get type checking
27  */
28 
29 #define LDNS_EDNS_MASK_DO_BIT 0x8000
30 #define LDNS_EDNS_MASK_CO_BIT 0x4000
31 #define LDNS_EDNS_MASK_UNASSIGNED (0xFFFF & ~( LDNS_EDNS_MASK_DO_BIT \
32                                              | LDNS_EDNS_MASK_CO_BIT ))
33 
34 
35 /* TODO defines for 3600 */
36 /* convert to and from numerical flag values */
37 ldns_lookup_table ldns_edns_flags[] = {
38 	{ 3600, "do"},
39 	{ 0, NULL}
40 };
41 
42 /* read */
43 uint16_t
ldns_pkt_id(const ldns_pkt * packet)44 ldns_pkt_id(const ldns_pkt *packet)
45 {
46 	return packet->_header->_id;
47 }
48 
49 bool
ldns_pkt_qr(const ldns_pkt * packet)50 ldns_pkt_qr(const ldns_pkt *packet)
51 {
52 	return packet->_header->_qr;
53 }
54 
55 bool
ldns_pkt_aa(const ldns_pkt * packet)56 ldns_pkt_aa(const ldns_pkt *packet)
57 {
58 	return packet->_header->_aa;
59 }
60 
61 bool
ldns_pkt_tc(const ldns_pkt * packet)62 ldns_pkt_tc(const ldns_pkt *packet)
63 {
64 	return packet->_header->_tc;
65 }
66 
67 bool
ldns_pkt_rd(const ldns_pkt * packet)68 ldns_pkt_rd(const ldns_pkt *packet)
69 {
70 	return packet->_header->_rd;
71 }
72 
73 bool
ldns_pkt_cd(const ldns_pkt * packet)74 ldns_pkt_cd(const ldns_pkt *packet)
75 {
76 	return packet->_header->_cd;
77 }
78 
79 bool
ldns_pkt_ra(const ldns_pkt * packet)80 ldns_pkt_ra(const ldns_pkt *packet)
81 {
82 	return packet->_header->_ra;
83 }
84 
85 bool
ldns_pkt_ad(const ldns_pkt * packet)86 ldns_pkt_ad(const ldns_pkt *packet)
87 {
88 	return packet->_header->_ad;
89 }
90 
91 ldns_pkt_opcode
ldns_pkt_get_opcode(const ldns_pkt * packet)92 ldns_pkt_get_opcode(const ldns_pkt *packet)
93 {
94 	return packet->_header->_opcode;
95 }
96 
97 ldns_pkt_rcode
ldns_pkt_get_rcode(const ldns_pkt * packet)98 ldns_pkt_get_rcode(const ldns_pkt *packet)
99 {
100 	return packet->_header->_rcode;
101 }
102 
103 uint16_t
ldns_pkt_qdcount(const ldns_pkt * packet)104 ldns_pkt_qdcount(const ldns_pkt *packet)
105 {
106 	return packet->_header->_qdcount;
107 }
108 
109 uint16_t
ldns_pkt_ancount(const ldns_pkt * packet)110 ldns_pkt_ancount(const ldns_pkt *packet)
111 {
112 	return packet->_header->_ancount;
113 }
114 
115 uint16_t
ldns_pkt_nscount(const ldns_pkt * packet)116 ldns_pkt_nscount(const ldns_pkt *packet)
117 {
118 	return packet->_header->_nscount;
119 }
120 
121 uint16_t
ldns_pkt_arcount(const ldns_pkt * packet)122 ldns_pkt_arcount(const ldns_pkt *packet)
123 {
124 	return packet->_header->_arcount;
125 }
126 
127 ldns_rr_list *
ldns_pkt_question(const ldns_pkt * packet)128 ldns_pkt_question(const ldns_pkt *packet)
129 {
130 	return packet->_question;
131 }
132 
133 ldns_rr_list *
ldns_pkt_answer(const ldns_pkt * packet)134 ldns_pkt_answer(const ldns_pkt *packet)
135 {
136 	return packet->_answer;
137 }
138 
139 ldns_rr_list *
ldns_pkt_authority(const ldns_pkt * packet)140 ldns_pkt_authority(const ldns_pkt *packet)
141 {
142 	return packet->_authority;
143 }
144 
145 ldns_rr_list *
ldns_pkt_additional(const ldns_pkt * packet)146 ldns_pkt_additional(const ldns_pkt *packet)
147 {
148 	return packet->_additional;
149 }
150 
151 /* return ALL section concatenated */
152 ldns_rr_list *
ldns_pkt_all(const ldns_pkt * packet)153 ldns_pkt_all(const ldns_pkt *packet)
154 {
155 	ldns_rr_list *all, *prev_all;
156 
157 	all = ldns_rr_list_cat_clone(
158 			ldns_pkt_question(packet),
159 			ldns_pkt_answer(packet));
160 	prev_all = all;
161 	all = ldns_rr_list_cat_clone(all,
162 			ldns_pkt_authority(packet));
163 	ldns_rr_list_deep_free(prev_all);
164 	prev_all = all;
165 	all = ldns_rr_list_cat_clone(all,
166 			ldns_pkt_additional(packet));
167 	ldns_rr_list_deep_free(prev_all);
168 	return all;
169 }
170 
171 ldns_rr_list *
ldns_pkt_all_noquestion(const ldns_pkt * packet)172 ldns_pkt_all_noquestion(const ldns_pkt *packet)
173 {
174 	ldns_rr_list *all, *all2;
175 
176 	all = ldns_rr_list_cat_clone(
177 			ldns_pkt_answer(packet),
178 			ldns_pkt_authority(packet));
179 	all2 = ldns_rr_list_cat_clone(all,
180 			ldns_pkt_additional(packet));
181 
182 	ldns_rr_list_deep_free(all);
183 	return all2;
184 }
185 
186 size_t
ldns_pkt_size(const ldns_pkt * packet)187 ldns_pkt_size(const ldns_pkt *packet)
188 {
189 	return packet->_size;
190 }
191 
192 uint32_t
ldns_pkt_querytime(const ldns_pkt * packet)193 ldns_pkt_querytime(const ldns_pkt *packet)
194 {
195 	return packet->_querytime;
196 }
197 
198 ldns_rdf *
ldns_pkt_answerfrom(const ldns_pkt * packet)199 ldns_pkt_answerfrom(const ldns_pkt *packet)
200 {
201 	return packet->_answerfrom;
202 }
203 
204 struct timeval
ldns_pkt_timestamp(const ldns_pkt * packet)205 ldns_pkt_timestamp(const ldns_pkt *packet)
206 {
207 	return packet->timestamp;
208 }
209 
210 uint16_t
ldns_pkt_edns_udp_size(const ldns_pkt * packet)211 ldns_pkt_edns_udp_size(const ldns_pkt *packet)
212 {
213 	return packet->_edns_udp_size;
214 }
215 
216 uint8_t
ldns_pkt_edns_extended_rcode(const ldns_pkt * packet)217 ldns_pkt_edns_extended_rcode(const ldns_pkt *packet)
218 {
219 	return packet->_edns_extended_rcode;
220 }
221 
222 uint8_t
ldns_pkt_edns_version(const ldns_pkt * packet)223 ldns_pkt_edns_version(const ldns_pkt *packet)
224 {
225 	return packet->_edns_version;
226 }
227 
228 uint16_t
ldns_pkt_edns_z(const ldns_pkt * packet)229 ldns_pkt_edns_z(const ldns_pkt *packet)
230 {
231 	return packet->_edns_z;
232 }
233 
234 bool
ldns_pkt_edns_do(const ldns_pkt * packet)235 ldns_pkt_edns_do(const ldns_pkt *packet)
236 {
237 	return (packet->_edns_z & LDNS_EDNS_MASK_DO_BIT);
238 }
239 
240 void
ldns_pkt_set_edns_do(ldns_pkt * packet,bool value)241 ldns_pkt_set_edns_do(ldns_pkt *packet, bool value)
242 {
243 	if (value) {
244 		packet->_edns_z = packet->_edns_z | LDNS_EDNS_MASK_DO_BIT;
245 	} else {
246 		packet->_edns_z = packet->_edns_z & ~LDNS_EDNS_MASK_DO_BIT;
247 	}
248 }
249 
250 bool
ldns_pkt_edns_co(const ldns_pkt * packet)251 ldns_pkt_edns_co(const ldns_pkt *packet)
252 {
253 	return (packet->_edns_z & LDNS_EDNS_MASK_CO_BIT);
254 }
255 
256 void
ldns_pkt_set_edns_co(ldns_pkt * packet,bool value)257 ldns_pkt_set_edns_co(ldns_pkt *packet, bool value)
258 {
259 	if (value) {
260 		packet->_edns_z = packet->_edns_z | LDNS_EDNS_MASK_CO_BIT;
261 	} else {
262 		packet->_edns_z = packet->_edns_z & ~LDNS_EDNS_MASK_CO_BIT;
263 	}
264 }
265 
266 uint16_t
ldns_pkt_edns_unassigned(const ldns_pkt * packet)267 ldns_pkt_edns_unassigned(const ldns_pkt *packet)
268 {
269 	return (packet->_edns_z & LDNS_EDNS_MASK_UNASSIGNED);
270 }
271 
272 void
ldns_pkt_set_edns_unassigned(ldns_pkt * packet,uint16_t value)273 ldns_pkt_set_edns_unassigned(ldns_pkt *packet, uint16_t value)
274 {
275 	packet->_edns_z = (packet->_edns_z & ~LDNS_EDNS_MASK_UNASSIGNED)
276 			| (value & LDNS_EDNS_MASK_UNASSIGNED);
277 }
278 
279 ldns_rdf *
ldns_pkt_edns_data(const ldns_pkt * packet)280 ldns_pkt_edns_data(const ldns_pkt *packet)
281 {
282 	return packet->_edns_data;
283 }
284 
285 /* return only those rr that share the ownername */
286 ldns_rr_list *
ldns_pkt_rr_list_by_name(const ldns_pkt * packet,const ldns_rdf * ownername,ldns_pkt_section sec)287 ldns_pkt_rr_list_by_name(const ldns_pkt *packet,
288                          const ldns_rdf *ownername,
289                          ldns_pkt_section sec)
290 {
291 	ldns_rr_list *rrs;
292 	ldns_rr_list *ret;
293 	uint16_t i;
294 
295 	if (!packet) {
296 		return NULL;
297 	}
298 
299 	rrs = ldns_pkt_get_section_clone(packet, sec);
300 	ret = NULL;
301 
302 	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
303 		if (ldns_dname_compare(ldns_rr_owner(
304 						ldns_rr_list_rr(rrs, i)),
305 					ownername) == 0) {
306 			/* owner names match */
307 			if (ret == NULL) {
308 				ret = ldns_rr_list_new();
309 			}
310 			ldns_rr_list_push_rr(ret,
311 					     ldns_rr_clone(
312 						ldns_rr_list_rr(rrs, i))
313 					    );
314 		}
315 	}
316 
317 	ldns_rr_list_deep_free(rrs);
318 
319 	return ret;
320 }
321 
322 /* return only those rr that share a type */
323 ldns_rr_list *
ldns_pkt_rr_list_by_type(const ldns_pkt * packet,ldns_rr_type type,ldns_pkt_section sec)324 ldns_pkt_rr_list_by_type(const ldns_pkt *packet,
325                          ldns_rr_type type,
326                          ldns_pkt_section sec)
327 {
328 	ldns_rr_list *rrs;
329 	ldns_rr_list *new;
330 	uint16_t i;
331 
332 	if(!packet) {
333 		return NULL;
334 	}
335 
336 	rrs = ldns_pkt_get_section_clone(packet, sec);
337 	new = ldns_rr_list_new();
338 
339 	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
340 		if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i))) {
341 			/* types match */
342 			ldns_rr_list_push_rr(new,
343 			                     ldns_rr_clone(
344 			                     	ldns_rr_list_rr(rrs, i))
345 					     );
346 		}
347 	}
348 	ldns_rr_list_deep_free(rrs);
349 
350 	if (ldns_rr_list_rr_count(new) == 0) {
351 		ldns_rr_list_free(new);
352 		return NULL;
353 	} else {
354 		return new;
355 	}
356 }
357 
358 /* return only those rrs that share name and type */
359 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)360 ldns_pkt_rr_list_by_name_and_type(const ldns_pkt *packet,
361                                   const ldns_rdf *ownername,
362                                   ldns_rr_type type,
363                                   ldns_pkt_section sec)
364 {
365 	ldns_rr_list *rrs;
366 	ldns_rr_list *new;
367 	ldns_rr_list *ret;
368 	uint16_t i;
369 
370 	if(!packet) {
371 		return NULL;
372 	}
373 
374 	rrs = ldns_pkt_get_section_clone(packet, sec);
375 	new = ldns_rr_list_new();
376 	ret = NULL;
377 
378 	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
379 		if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i)) &&
380 		    ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(rrs, i)),
381 		                     ownername
382 		                    ) == 0
383 		   ) {
384 			/* types match */
385 			ldns_rr_list_push_rr(new, ldns_rr_clone(ldns_rr_list_rr(rrs, i)));
386 			ret = new;
387 		}
388 	}
389 	ldns_rr_list_deep_free(rrs);
390 	if (!ret) {
391 		ldns_rr_list_free(new);
392 	}
393 	return ret;
394 }
395 
396 bool
ldns_pkt_rr(const ldns_pkt * pkt,ldns_pkt_section sec,const ldns_rr * rr)397 ldns_pkt_rr(const ldns_pkt *pkt, ldns_pkt_section sec, const ldns_rr *rr)
398 {
399 	bool result = false;
400 
401 	switch (sec) {
402 	case LDNS_SECTION_QUESTION:
403 		return ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
404 	case LDNS_SECTION_ANSWER:
405 		return ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr);
406 	case LDNS_SECTION_AUTHORITY:
407 		return ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr);
408 	case LDNS_SECTION_ADDITIONAL:
409 		return ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
410 	case LDNS_SECTION_ANY:
411 		result = ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
412 		/* fallthrough */
413 	case LDNS_SECTION_ANY_NOQUESTION:
414 		result = result
415 		    || ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr)
416 		    || ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr)
417 		    || ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
418 	}
419 
420 	return result;
421 }
422 
423 uint16_t
ldns_pkt_section_count(const ldns_pkt * packet,ldns_pkt_section s)424 ldns_pkt_section_count(const ldns_pkt *packet, ldns_pkt_section s)
425 {
426 	switch(s) {
427 	case LDNS_SECTION_QUESTION:
428 		return ldns_pkt_qdcount(packet);
429 	case LDNS_SECTION_ANSWER:
430 		return ldns_pkt_ancount(packet);
431 	case LDNS_SECTION_AUTHORITY:
432 		return ldns_pkt_nscount(packet);
433 	case LDNS_SECTION_ADDITIONAL:
434 		return ldns_pkt_arcount(packet);
435 	case LDNS_SECTION_ANY:
436 		return ldns_pkt_qdcount(packet) +
437 			ldns_pkt_ancount(packet) +
438 			ldns_pkt_nscount(packet) +
439 			ldns_pkt_arcount(packet);
440 	case LDNS_SECTION_ANY_NOQUESTION:
441 		return ldns_pkt_ancount(packet) +
442 			ldns_pkt_nscount(packet) +
443 			ldns_pkt_arcount(packet);
444 	default:
445 		return 0;
446 	}
447 }
448 
449 bool
ldns_pkt_empty(ldns_pkt * p)450 ldns_pkt_empty(ldns_pkt *p)
451 {
452 	if (!p) {
453 		return true; /* NULL is empty? */
454 	}
455 	if (ldns_pkt_section_count(p, LDNS_SECTION_ANY) > 0) {
456 		return false;
457 	} else {
458 		return true;
459     }
460 }
461 
462 
463 ldns_rr_list *
ldns_pkt_get_section_clone(const ldns_pkt * packet,ldns_pkt_section s)464 ldns_pkt_get_section_clone(const ldns_pkt *packet, ldns_pkt_section s)
465 {
466 	switch(s) {
467 	case LDNS_SECTION_QUESTION:
468 		return ldns_rr_list_clone(ldns_pkt_question(packet));
469 	case LDNS_SECTION_ANSWER:
470 		return ldns_rr_list_clone(ldns_pkt_answer(packet));
471 	case LDNS_SECTION_AUTHORITY:
472 		return ldns_rr_list_clone(ldns_pkt_authority(packet));
473 	case LDNS_SECTION_ADDITIONAL:
474 		return ldns_rr_list_clone(ldns_pkt_additional(packet));
475 	case LDNS_SECTION_ANY:
476 		/* these are already clones */
477 		return ldns_pkt_all(packet);
478 	case LDNS_SECTION_ANY_NOQUESTION:
479 		return ldns_pkt_all_noquestion(packet);
480 	default:
481 		return NULL;
482 	}
483 }
484 
ldns_pkt_tsig(const ldns_pkt * pkt)485 ldns_rr *ldns_pkt_tsig(const ldns_pkt *pkt) {
486 	return pkt->_tsig_rr;
487 }
488 
489 /* write */
490 void
ldns_pkt_set_id(ldns_pkt * packet,uint16_t id)491 ldns_pkt_set_id(ldns_pkt *packet, uint16_t id)
492 {
493 	packet->_header->_id = id;
494 }
495 
496 void
ldns_pkt_set_random_id(ldns_pkt * packet)497 ldns_pkt_set_random_id(ldns_pkt *packet)
498 {
499 	uint16_t rid = ldns_get_random();
500 	ldns_pkt_set_id(packet, rid);
501 }
502 
503 
504 void
ldns_pkt_set_qr(ldns_pkt * packet,bool qr)505 ldns_pkt_set_qr(ldns_pkt *packet, bool qr)
506 {
507 	packet->_header->_qr = qr;
508 }
509 
510 void
ldns_pkt_set_aa(ldns_pkt * packet,bool aa)511 ldns_pkt_set_aa(ldns_pkt *packet, bool aa)
512 {
513 	packet->_header->_aa = aa;
514 }
515 
516 void
ldns_pkt_set_tc(ldns_pkt * packet,bool tc)517 ldns_pkt_set_tc(ldns_pkt *packet, bool tc)
518 {
519 	packet->_header->_tc = tc;
520 }
521 
522 void
ldns_pkt_set_rd(ldns_pkt * packet,bool rd)523 ldns_pkt_set_rd(ldns_pkt *packet, bool rd)
524 {
525 	packet->_header->_rd = rd;
526 }
527 
528 void
ldns_pkt_set_additional(ldns_pkt * p,ldns_rr_list * rr)529 ldns_pkt_set_additional(ldns_pkt *p, ldns_rr_list *rr)
530 {
531 	p->_additional = rr;
532 }
533 
534 void
ldns_pkt_set_question(ldns_pkt * p,ldns_rr_list * rr)535 ldns_pkt_set_question(ldns_pkt *p, ldns_rr_list *rr)
536 {
537 	p->_question = rr;
538 }
539 
540 void
ldns_pkt_set_answer(ldns_pkt * p,ldns_rr_list * rr)541 ldns_pkt_set_answer(ldns_pkt *p, ldns_rr_list *rr)
542 {
543 	p->_answer = rr;
544 }
545 
546 void
ldns_pkt_set_authority(ldns_pkt * p,ldns_rr_list * rr)547 ldns_pkt_set_authority(ldns_pkt *p, ldns_rr_list *rr)
548 {
549 	p->_authority = rr;
550 }
551 
552 void
ldns_pkt_set_cd(ldns_pkt * packet,bool cd)553 ldns_pkt_set_cd(ldns_pkt *packet, bool cd)
554 {
555 	packet->_header->_cd = cd;
556 }
557 
558 void
ldns_pkt_set_ra(ldns_pkt * packet,bool ra)559 ldns_pkt_set_ra(ldns_pkt *packet, bool ra)
560 {
561 	packet->_header->_ra = ra;
562 }
563 
564 void
ldns_pkt_set_ad(ldns_pkt * packet,bool ad)565 ldns_pkt_set_ad(ldns_pkt *packet, bool ad)
566 {
567 	packet->_header->_ad = ad;
568 }
569 
570 void
ldns_pkt_set_opcode(ldns_pkt * packet,ldns_pkt_opcode opcode)571 ldns_pkt_set_opcode(ldns_pkt *packet, ldns_pkt_opcode opcode)
572 {
573 	packet->_header->_opcode = opcode;
574 }
575 
576 void
ldns_pkt_set_rcode(ldns_pkt * packet,uint8_t rcode)577 ldns_pkt_set_rcode(ldns_pkt *packet, uint8_t rcode)
578 {
579 	packet->_header->_rcode = rcode;
580 }
581 
582 void
ldns_pkt_set_qdcount(ldns_pkt * packet,uint16_t qdcount)583 ldns_pkt_set_qdcount(ldns_pkt *packet, uint16_t qdcount)
584 {
585 	packet->_header->_qdcount = qdcount;
586 }
587 
588 void
ldns_pkt_set_ancount(ldns_pkt * packet,uint16_t ancount)589 ldns_pkt_set_ancount(ldns_pkt *packet, uint16_t ancount)
590 {
591 	packet->_header->_ancount = ancount;
592 }
593 
594 void
ldns_pkt_set_nscount(ldns_pkt * packet,uint16_t nscount)595 ldns_pkt_set_nscount(ldns_pkt *packet, uint16_t nscount)
596 {
597 	packet->_header->_nscount = nscount;
598 }
599 
600 void
ldns_pkt_set_arcount(ldns_pkt * packet,uint16_t arcount)601 ldns_pkt_set_arcount(ldns_pkt *packet, uint16_t arcount)
602 {
603 	packet->_header->_arcount = arcount;
604 }
605 
606 void
ldns_pkt_set_querytime(ldns_pkt * packet,uint32_t time)607 ldns_pkt_set_querytime(ldns_pkt *packet, uint32_t time)
608 {
609 	packet->_querytime = time;
610 }
611 
612 void
ldns_pkt_set_answerfrom(ldns_pkt * packet,ldns_rdf * answerfrom)613 ldns_pkt_set_answerfrom(ldns_pkt *packet, ldns_rdf *answerfrom)
614 {
615 	packet->_answerfrom = answerfrom;
616 }
617 
618 void
ldns_pkt_set_timestamp(ldns_pkt * packet,struct timeval timeval)619 ldns_pkt_set_timestamp(ldns_pkt *packet, struct timeval timeval)
620 {
621 	packet->timestamp.tv_sec = timeval.tv_sec;
622 	packet->timestamp.tv_usec = timeval.tv_usec;
623 }
624 
625 void
ldns_pkt_set_size(ldns_pkt * packet,size_t s)626 ldns_pkt_set_size(ldns_pkt *packet, size_t s)
627 {
628 	packet->_size = s;
629 }
630 
631 void
ldns_pkt_set_edns_udp_size(ldns_pkt * packet,uint16_t s)632 ldns_pkt_set_edns_udp_size(ldns_pkt *packet, uint16_t s)
633 {
634 	packet->_edns_udp_size = s;
635 }
636 
637 void
ldns_pkt_set_edns_extended_rcode(ldns_pkt * packet,uint8_t c)638 ldns_pkt_set_edns_extended_rcode(ldns_pkt *packet, uint8_t c)
639 {
640 	packet->_edns_extended_rcode = c;
641 }
642 
643 void
ldns_pkt_set_edns_version(ldns_pkt * packet,uint8_t v)644 ldns_pkt_set_edns_version(ldns_pkt *packet, uint8_t v)
645 {
646 	packet->_edns_version = v;
647 }
648 
649 void
ldns_pkt_set_edns_z(ldns_pkt * packet,uint16_t z)650 ldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z)
651 {
652 	packet->_edns_z = z;
653 }
654 
655 void
ldns_pkt_set_edns_data(ldns_pkt * packet,ldns_rdf * data)656 ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data)
657 {
658 	packet->_edns_data = data;
659 }
660 
661 void
ldns_pkt_set_edns_option_list(ldns_pkt * packet,ldns_edns_option_list * list)662 ldns_pkt_set_edns_option_list(ldns_pkt *packet, ldns_edns_option_list *list)
663 {
664 	if (packet->_edns_list)
665 		ldns_edns_option_list_deep_free(packet->_edns_list);
666 	packet->_edns_list = list;
667 }
668 
669 
670 void
ldns_pkt_set_section_count(ldns_pkt * packet,ldns_pkt_section s,uint16_t count)671 ldns_pkt_set_section_count(ldns_pkt *packet, ldns_pkt_section s, uint16_t count)
672 {
673 	switch(s) {
674 		case LDNS_SECTION_QUESTION:
675 			ldns_pkt_set_qdcount(packet, count);
676 			break;
677 		case LDNS_SECTION_ANSWER:
678 			ldns_pkt_set_ancount(packet, count);
679 			break;
680 		case LDNS_SECTION_AUTHORITY:
681 			ldns_pkt_set_nscount(packet, count);
682 			break;
683 		case LDNS_SECTION_ADDITIONAL:
684 			ldns_pkt_set_arcount(packet, count);
685 			break;
686 		case LDNS_SECTION_ANY:
687 		case LDNS_SECTION_ANY_NOQUESTION:
688 			break;
689 	}
690 }
691 
ldns_pkt_set_tsig(ldns_pkt * pkt,ldns_rr * rr)692 void ldns_pkt_set_tsig(ldns_pkt *pkt, ldns_rr *rr)
693 {
694 	pkt->_tsig_rr = rr;
695 }
696 
697 bool
ldns_pkt_push_rr(ldns_pkt * packet,ldns_pkt_section section,ldns_rr * rr)698 ldns_pkt_push_rr(ldns_pkt *packet, ldns_pkt_section section, ldns_rr *rr)
699 {
700 	switch(section) {
701 		case LDNS_SECTION_QUESTION:
702 			if (!ldns_rr_list_push_rr(ldns_pkt_question(packet), rr)) {
703 				return false;
704 			}
705 			ldns_pkt_set_qdcount(packet, ldns_pkt_qdcount(packet) + 1);
706 			break;
707 		case LDNS_SECTION_ANSWER:
708 			if (!ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr)) {
709 				return false;
710 			}
711 			ldns_pkt_set_ancount(packet, ldns_pkt_ancount(packet) + 1);
712 			break;
713 		case LDNS_SECTION_AUTHORITY:
714 			if (!ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr)) {
715 				return false;
716 			}
717 			ldns_pkt_set_nscount(packet, ldns_pkt_nscount(packet) + 1);
718 			break;
719 		case LDNS_SECTION_ADDITIONAL:
720 			if (!ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr)) {
721 				return false;
722 			}
723 			ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) + 1);
724 			break;
725 		case LDNS_SECTION_ANY:
726 		case LDNS_SECTION_ANY_NOQUESTION:
727 			/* shouldn't this error? */
728 			break;
729 	}
730 	return true;
731 }
732 
733 bool
ldns_pkt_safe_push_rr(ldns_pkt * pkt,ldns_pkt_section sec,ldns_rr * rr)734 ldns_pkt_safe_push_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr)
735 {
736 
737 	/* check to see if its there */
738 	if (ldns_pkt_rr(pkt, sec, rr)) {
739 		/* already there */
740 		return false;
741 	}
742 	return ldns_pkt_push_rr(pkt, sec, rr);
743 }
744 
745 bool
ldns_pkt_push_rr_list(ldns_pkt * p,ldns_pkt_section s,ldns_rr_list * list)746 ldns_pkt_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
747 {
748 	size_t i;
749 	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
750 		if (!ldns_pkt_push_rr(p, s, ldns_rr_list_rr(list, i))) {
751 			return false;
752 		}
753 	}
754 	return true;
755 }
756 
757 bool
ldns_pkt_safe_push_rr_list(ldns_pkt * p,ldns_pkt_section s,ldns_rr_list * list)758 ldns_pkt_safe_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
759 {
760 	size_t i;
761 	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
762 		if (!ldns_pkt_safe_push_rr(p, s, ldns_rr_list_rr(list, i))) {
763 			return false;
764 		}
765 	}
766 	return true;
767 }
768 
769 bool
ldns_pkt_edns(const ldns_pkt * pkt)770 ldns_pkt_edns(const ldns_pkt *pkt)
771 {
772 	return (ldns_pkt_edns_udp_size(pkt) > 0 ||
773 		ldns_pkt_edns_extended_rcode(pkt) > 0 ||
774 		ldns_pkt_edns_data(pkt) ||
775 		ldns_pkt_edns_do(pkt) ||
776 		ldns_pkt_edns_co(pkt) ||
777 		pkt->_edns_list ||
778                 pkt->_edns_present
779 	       );
780 }
781 
782 ldns_edns_option_list*
783 pkt_edns_data2edns_option_list(const ldns_rdf *edns_data);
784 ldns_edns_option_list*
pkt_edns_data2edns_option_list(const ldns_rdf * edns_data)785 pkt_edns_data2edns_option_list(const ldns_rdf *edns_data)
786 {
787 	size_t pos = 0;
788 	ldns_edns_option_list* edns_list;
789 	size_t max;
790 	const uint8_t* wire;
791 
792 	if (!edns_data)
793 		return NULL;
794 
795 	max = ldns_rdf_size(edns_data);
796 	wire = ldns_rdf_data(edns_data);
797 	if (!max)
798 		return NULL;
799 
800 	if (!(edns_list = ldns_edns_option_list_new()))
801 		return NULL;
802 
803 	while (pos < max) {
804 		ldns_edns_option* edns;
805 		uint8_t *data;
806 
807 		if (pos + 4 > max) { /* make sure the header fits */
808 			ldns_edns_option_list_deep_free(edns_list);
809 			return NULL;
810 		}
811 		ldns_edns_option_code code = ldns_read_uint16(&wire[pos]);
812 		size_t size = ldns_read_uint16(&wire[pos+2]);
813 		pos += 4;
814 
815 		if (pos + size > max) { /* make sure the size fits the data */
816 			ldns_edns_option_list_deep_free(edns_list);
817 			return NULL;
818 		}
819 		data = LDNS_XMALLOC(uint8_t, size);
820 
821 		if (!data) {
822 			ldns_edns_option_list_deep_free(edns_list);
823 			return NULL;
824 		}
825 		memcpy(data, &wire[pos], size);
826 		pos += size;
827 
828 		edns = ldns_edns_new(code, size, data);
829 
830 		if (!edns) {
831 			ldns_edns_option_list_deep_free(edns_list);
832 			return NULL;
833 		}
834 		if (!ldns_edns_option_list_push(edns_list, edns)) {
835 			ldns_edns_option_list_deep_free(edns_list);
836 			return NULL;
837 		}
838 	}
839 	return edns_list;
840 
841 }
842 
843 ldns_edns_option_list*
ldns_pkt_edns_get_option_list(ldns_pkt * packet)844 ldns_pkt_edns_get_option_list(ldns_pkt *packet)
845 {
846 	/* return the list if it already exists */
847 	if (packet->_edns_list != NULL)
848 		return packet->_edns_list;
849 
850 	/* if the list doesn't exists, we create it by parsing the
851 	 * packet->_edns_data
852 	 */
853 	if (!ldns_pkt_edns_data(packet))
854 		return NULL;
855 
856 	return ( packet->_edns_list
857 	       = pkt_edns_data2edns_option_list(ldns_pkt_edns_data(packet)));
858 }
859 
860 
861 /* Create/destroy/convert functions
862  */
863 ldns_pkt *
ldns_pkt_new(void)864 ldns_pkt_new(void)
865 {
866 	ldns_pkt *packet;
867 	packet = LDNS_MALLOC(ldns_pkt);
868 	if (!packet) {
869 		return NULL;
870 	}
871 
872 	packet->_header = LDNS_MALLOC(ldns_hdr);
873 	if (!packet->_header) {
874 		LDNS_FREE(packet);
875 		return NULL;
876 	}
877 
878 	packet->_question = ldns_rr_list_new();
879 	packet->_answer = ldns_rr_list_new();
880 	packet->_authority = ldns_rr_list_new();
881 	packet->_additional = ldns_rr_list_new();
882 
883 	/* default everything to false */
884 	ldns_pkt_set_qr(packet, false);
885 	ldns_pkt_set_aa(packet, false);
886 	ldns_pkt_set_tc(packet, false);
887 	ldns_pkt_set_rd(packet, false);
888 	ldns_pkt_set_ra(packet, false);
889 	ldns_pkt_set_ad(packet, false);
890 	ldns_pkt_set_cd(packet, false);
891 
892 	ldns_pkt_set_opcode(packet, LDNS_PACKET_QUERY);
893 	ldns_pkt_set_rcode(packet, 0);
894 	ldns_pkt_set_id(packet, 0);
895 	ldns_pkt_set_size(packet, 0);
896 	ldns_pkt_set_querytime(packet, 0);
897 	memset(&packet->timestamp, 0, sizeof(packet->timestamp));
898 	ldns_pkt_set_answerfrom(packet, NULL);
899 	ldns_pkt_set_section_count(packet, LDNS_SECTION_QUESTION, 0);
900 	ldns_pkt_set_section_count(packet, LDNS_SECTION_ANSWER, 0);
901 	ldns_pkt_set_section_count(packet, LDNS_SECTION_AUTHORITY, 0);
902 	ldns_pkt_set_section_count(packet, LDNS_SECTION_ADDITIONAL, 0);
903 
904 	ldns_pkt_set_edns_udp_size(packet, 0);
905 	ldns_pkt_set_edns_extended_rcode(packet, 0);
906 	ldns_pkt_set_edns_version(packet, 0);
907 	ldns_pkt_set_edns_z(packet, 0);
908 	ldns_pkt_set_edns_data(packet, NULL);
909 	packet->_edns_list = NULL;
910 	packet->_edns_present = false;
911 
912 	ldns_pkt_set_tsig(packet, NULL);
913 
914 	return packet;
915 }
916 
917 void
ldns_pkt_free(ldns_pkt * packet)918 ldns_pkt_free(ldns_pkt *packet)
919 {
920 	if (packet) {
921 		LDNS_FREE(packet->_header);
922 		ldns_rr_list_deep_free(packet->_question);
923 		ldns_rr_list_deep_free(packet->_answer);
924 		ldns_rr_list_deep_free(packet->_authority);
925 		ldns_rr_list_deep_free(packet->_additional);
926 		ldns_rr_free(packet->_tsig_rr);
927 		ldns_rdf_deep_free(packet->_edns_data);
928 		ldns_edns_option_list_deep_free(packet->_edns_list);
929 		ldns_rdf_deep_free(packet->_answerfrom);
930 		LDNS_FREE(packet);
931 	}
932 }
933 
934 bool
ldns_pkt_set_flags(ldns_pkt * packet,uint16_t flags)935 ldns_pkt_set_flags(ldns_pkt *packet, uint16_t flags)
936 {
937 	if (!packet) {
938 		return false;
939 	}
940 	if ((flags & LDNS_QR) == LDNS_QR) {
941 		ldns_pkt_set_qr(packet, true);
942 	}
943 	if ((flags & LDNS_AA) == LDNS_AA) {
944 		ldns_pkt_set_aa(packet, true);
945 	}
946 	if ((flags & LDNS_RD) == LDNS_RD) {
947 		ldns_pkt_set_rd(packet, true);
948 	}
949 	if ((flags & LDNS_TC) == LDNS_TC) {
950 		ldns_pkt_set_tc(packet, true);
951 	}
952 	if ((flags & LDNS_CD) == LDNS_CD) {
953 		ldns_pkt_set_cd(packet, true);
954 	}
955 	if ((flags & LDNS_RA) == LDNS_RA) {
956 		ldns_pkt_set_ra(packet, true);
957 	}
958 	if ((flags & LDNS_AD) == LDNS_AD) {
959 		ldns_pkt_set_ad(packet, true);
960 	}
961 	return true;
962 }
963 
964 
965 static ldns_rr*
ldns_pkt_authsoa(const ldns_rdf * rr_name,ldns_rr_class rr_class)966 ldns_pkt_authsoa(const ldns_rdf* rr_name, ldns_rr_class rr_class)
967 {
968 	ldns_rr* soa_rr = ldns_rr_new();
969 	ldns_rdf *owner_rdf;
970 	ldns_rdf *mname_rdf;
971 	ldns_rdf *rname_rdf;
972 	ldns_rdf *serial_rdf;
973 	ldns_rdf *refresh_rdf;
974 	ldns_rdf *retry_rdf;
975 	ldns_rdf *expire_rdf;
976 	ldns_rdf *minimum_rdf;
977 
978 	if (!soa_rr) {
979 		return NULL;
980 	}
981 	owner_rdf = ldns_rdf_clone(rr_name);
982 	if (!owner_rdf) {
983 		ldns_rr_free(soa_rr);
984 		return NULL;
985 	}
986 
987 	ldns_rr_set_owner(soa_rr, owner_rdf);
988 	ldns_rr_set_type(soa_rr, LDNS_RR_TYPE_SOA);
989 	ldns_rr_set_class(soa_rr, rr_class);
990 	ldns_rr_set_question(soa_rr, false);
991 
992 	if (ldns_str2rdf_dname(&mname_rdf, ".") != LDNS_STATUS_OK) {
993 		ldns_rr_free(soa_rr);
994 		return NULL;
995 	} else {
996 		ldns_rr_push_rdf(soa_rr, mname_rdf);
997 	}
998 	if (ldns_str2rdf_dname(&rname_rdf, ".") != LDNS_STATUS_OK) {
999 		ldns_rr_free(soa_rr);
1000 		return NULL;
1001 	} else {
1002 		ldns_rr_push_rdf(soa_rr, rname_rdf);
1003 	}
1004 	serial_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
1005 	if (!serial_rdf) {
1006 		ldns_rr_free(soa_rr);
1007 		return NULL;
1008 	} else {
1009 		ldns_rr_push_rdf(soa_rr, serial_rdf);
1010 	}
1011 	refresh_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
1012 	if (!refresh_rdf) {
1013 		ldns_rr_free(soa_rr);
1014 		return NULL;
1015 	} else {
1016 		ldns_rr_push_rdf(soa_rr, refresh_rdf);
1017 	}
1018 	retry_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
1019 	if (!retry_rdf) {
1020 		ldns_rr_free(soa_rr);
1021 		return NULL;
1022 	} else {
1023 		ldns_rr_push_rdf(soa_rr, retry_rdf);
1024 	}
1025 	expire_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
1026 	if (!expire_rdf) {
1027 		ldns_rr_free(soa_rr);
1028 		return NULL;
1029 	} else {
1030 		ldns_rr_push_rdf(soa_rr, expire_rdf);
1031 	}
1032 	minimum_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
1033 	if (!minimum_rdf) {
1034 		ldns_rr_free(soa_rr);
1035 		return NULL;
1036 	} else {
1037 		ldns_rr_push_rdf(soa_rr, minimum_rdf);
1038 	}
1039 	return soa_rr;
1040 }
1041 
1042 
1043 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)1044 ldns_pkt_query_new_frm_str_internal(ldns_pkt **p, const char *name,
1045 	ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags,
1046 	ldns_rr* authsoa_rr)
1047 {
1048 	ldns_pkt *packet;
1049 	ldns_rr *question_rr;
1050 	ldns_rdf *name_rdf;
1051 
1052 	packet = ldns_pkt_new();
1053 	if (!packet) {
1054 		return LDNS_STATUS_MEM_ERR;
1055 	}
1056 
1057 	if (!ldns_pkt_set_flags(packet, flags)) {
1058 		ldns_pkt_free(packet);
1059 		return LDNS_STATUS_ERR;
1060 	}
1061 
1062 	question_rr = ldns_rr_new();
1063 	if (!question_rr) {
1064 		ldns_pkt_free(packet);
1065 		return LDNS_STATUS_MEM_ERR;
1066 	}
1067 
1068 	if (rr_type == 0) {
1069 		rr_type = LDNS_RR_TYPE_A;
1070 	}
1071 	if (rr_class == 0) {
1072 		rr_class = LDNS_RR_CLASS_IN;
1073 	}
1074 
1075 	if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) {
1076 		ldns_rr_set_owner(question_rr, name_rdf);
1077 		ldns_rr_set_type(question_rr, rr_type);
1078 		ldns_rr_set_class(question_rr, rr_class);
1079                 ldns_rr_set_question(question_rr, true);
1080 
1081 		ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr);
1082 	} else {
1083 		ldns_rr_free(question_rr);
1084 		ldns_pkt_free(packet);
1085 		return LDNS_STATUS_ERR;
1086 	}
1087 
1088 	if (authsoa_rr) {
1089 		ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, authsoa_rr);
1090 	}
1091 
1092 	packet->_tsig_rr = NULL;
1093 	ldns_pkt_set_answerfrom(packet, NULL);
1094 	if (p) {
1095 		*p = packet;
1096 		return LDNS_STATUS_OK;
1097 	} else {
1098 		ldns_pkt_free(packet);
1099 		return LDNS_STATUS_NULL;
1100 	}
1101 }
1102 
1103 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)1104 ldns_pkt_query_new_frm_str(ldns_pkt **p, const char *name,
1105 	ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags)
1106 {
1107 	return ldns_pkt_query_new_frm_str_internal(p, name, rr_type,
1108 		rr_class, flags, NULL);
1109 }
1110 
1111 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)1112 ldns_pkt_ixfr_request_new_frm_str(ldns_pkt **p, const char *name,
1113 	ldns_rr_class rr_class, uint16_t flags, ldns_rr *soa)
1114 {
1115 	ldns_rr* authsoa_rr = soa;
1116 	if (!authsoa_rr) {
1117 		ldns_rdf *name_rdf;
1118 		if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) {
1119 			authsoa_rr = ldns_pkt_authsoa(name_rdf, rr_class);
1120 		}
1121 		ldns_rdf_free(name_rdf);
1122 	}
1123 	return ldns_pkt_query_new_frm_str_internal(p, name, LDNS_RR_TYPE_IXFR,
1124 		rr_class, flags, authsoa_rr);
1125 }
1126 
1127 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)1128 ldns_pkt_query_new_internal(ldns_rdf *rr_name, ldns_rr_type rr_type,
1129 	ldns_rr_class rr_class,	uint16_t flags, ldns_rr* authsoa_rr)
1130 {
1131 	ldns_pkt *packet;
1132 	ldns_rr *question_rr;
1133 
1134 	packet = ldns_pkt_new();
1135 	if (!packet) {
1136 		return NULL;
1137 	}
1138 
1139 	if (!ldns_pkt_set_flags(packet, flags)) {
1140 		return NULL;
1141 	}
1142 
1143 	question_rr = ldns_rr_new();
1144 	if (!question_rr) {
1145 		ldns_pkt_free(packet);
1146 		return NULL;
1147 	}
1148 
1149 	if (rr_type == 0) {
1150 		rr_type = LDNS_RR_TYPE_A;
1151 	}
1152 	if (rr_class == 0) {
1153 		rr_class = LDNS_RR_CLASS_IN;
1154 	}
1155 
1156 	ldns_rr_set_owner(question_rr, rr_name);
1157 	ldns_rr_set_type(question_rr, rr_type);
1158 	ldns_rr_set_class(question_rr, rr_class);
1159         ldns_rr_set_question(question_rr, true);
1160 	ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr);
1161 
1162 	if (authsoa_rr) {
1163 		ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, authsoa_rr);
1164 	}
1165 
1166 	packet->_tsig_rr = NULL;
1167 	return packet;
1168 }
1169 
1170 ldns_pkt *
ldns_pkt_query_new(ldns_rdf * rr_name,ldns_rr_type rr_type,ldns_rr_class rr_class,uint16_t flags)1171 ldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type,
1172 	ldns_rr_class rr_class,	uint16_t flags)
1173 {
1174 	return ldns_pkt_query_new_internal(rr_name, rr_type,
1175 		rr_class, flags, NULL);
1176 }
1177 
1178 ldns_pkt *
ldns_pkt_ixfr_request_new(ldns_rdf * rr_name,ldns_rr_class rr_class,uint16_t flags,ldns_rr * soa)1179 ldns_pkt_ixfr_request_new(ldns_rdf *rr_name, ldns_rr_class rr_class,
1180 	uint16_t flags, ldns_rr* soa)
1181 {
1182 	ldns_rr* authsoa_rr = soa;
1183 	if (!authsoa_rr) {
1184 		authsoa_rr = ldns_pkt_authsoa(rr_name, rr_class);
1185 	}
1186 	return ldns_pkt_query_new_internal(rr_name, LDNS_RR_TYPE_IXFR,
1187 		rr_class, flags, authsoa_rr);
1188 }
1189 
1190 ldns_pkt_type
ldns_pkt_reply_type(const ldns_pkt * p)1191 ldns_pkt_reply_type(const ldns_pkt *p)
1192 {
1193 	ldns_rr_list *tmp;
1194 
1195 	if (!p) {
1196 		return LDNS_PACKET_UNKNOWN;
1197 	}
1198 
1199 	if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NXDOMAIN) {
1200 		return LDNS_PACKET_NXDOMAIN;
1201 	}
1202 
1203 	if (ldns_pkt_ancount(p) == 0 && ldns_pkt_arcount(p) == 0
1204 			&& ldns_pkt_nscount(p) == 1) {
1205 
1206 		/* check for SOA */
1207 		tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_SOA,
1208 					LDNS_SECTION_AUTHORITY);
1209 		if (tmp) {
1210 			ldns_rr_list_deep_free(tmp);
1211 			return LDNS_PACKET_NODATA;
1212 		} else {
1213 			/* I have no idea ... */
1214 		}
1215 	}
1216 
1217 	if (ldns_pkt_ancount(p) == 0 && ldns_pkt_nscount(p) > 0) {
1218 		tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS,
1219 		                               LDNS_SECTION_AUTHORITY);
1220 		if (tmp) {
1221 			/* there are nameservers here */
1222 			ldns_rr_list_deep_free(tmp);
1223 			return LDNS_PACKET_REFERRAL;
1224 		} else {
1225 			/* I have no idea */
1226 		}
1227 		ldns_rr_list_deep_free(tmp);
1228 	}
1229 
1230 	/* if we cannot determine the packet type, we say it's an
1231 	 * answer...
1232 	 */
1233 	return LDNS_PACKET_ANSWER;
1234 }
1235 
1236 ldns_pkt *
ldns_pkt_clone(const ldns_pkt * pkt)1237 ldns_pkt_clone(const ldns_pkt *pkt)
1238 {
1239 	ldns_pkt *new_pkt;
1240 
1241 	if (!pkt) {
1242 		return NULL;
1243 	}
1244 	new_pkt = ldns_pkt_new();
1245 
1246 	ldns_pkt_set_id(new_pkt, ldns_pkt_id(pkt));
1247 	ldns_pkt_set_qr(new_pkt, ldns_pkt_qr(pkt));
1248 	ldns_pkt_set_aa(new_pkt, ldns_pkt_aa(pkt));
1249 	ldns_pkt_set_tc(new_pkt, ldns_pkt_tc(pkt));
1250 	ldns_pkt_set_rd(new_pkt, ldns_pkt_rd(pkt));
1251 	ldns_pkt_set_cd(new_pkt, ldns_pkt_cd(pkt));
1252 	ldns_pkt_set_ra(new_pkt, ldns_pkt_ra(pkt));
1253 	ldns_pkt_set_ad(new_pkt, ldns_pkt_ad(pkt));
1254 	ldns_pkt_set_opcode(new_pkt, ldns_pkt_get_opcode(pkt));
1255 	ldns_pkt_set_rcode(new_pkt, ldns_pkt_get_rcode(pkt));
1256 	ldns_pkt_set_qdcount(new_pkt, ldns_pkt_qdcount(pkt));
1257 	ldns_pkt_set_ancount(new_pkt, ldns_pkt_ancount(pkt));
1258 	ldns_pkt_set_nscount(new_pkt, ldns_pkt_nscount(pkt));
1259 	ldns_pkt_set_arcount(new_pkt, ldns_pkt_arcount(pkt));
1260 	if (ldns_pkt_answerfrom(pkt))
1261 		ldns_pkt_set_answerfrom(new_pkt,
1262 			ldns_rdf_clone(ldns_pkt_answerfrom(pkt)));
1263 	ldns_pkt_set_timestamp(new_pkt, ldns_pkt_timestamp(pkt));
1264 	ldns_pkt_set_querytime(new_pkt, ldns_pkt_querytime(pkt));
1265 	ldns_pkt_set_size(new_pkt, ldns_pkt_size(pkt));
1266 	ldns_pkt_set_tsig(new_pkt, ldns_rr_clone(ldns_pkt_tsig(pkt)));
1267 
1268 	ldns_pkt_set_edns_udp_size(new_pkt, ldns_pkt_edns_udp_size(pkt));
1269 	ldns_pkt_set_edns_extended_rcode(new_pkt,
1270 		ldns_pkt_edns_extended_rcode(pkt));
1271 	ldns_pkt_set_edns_version(new_pkt, ldns_pkt_edns_version(pkt));
1272 	new_pkt->_edns_present = pkt->_edns_present;
1273 	ldns_pkt_set_edns_z(new_pkt, ldns_pkt_edns_z(pkt));
1274 	if(ldns_pkt_edns_data(pkt))
1275 		ldns_pkt_set_edns_data(new_pkt,
1276 			ldns_rdf_clone(ldns_pkt_edns_data(pkt)));
1277 	ldns_pkt_set_edns_do(new_pkt, ldns_pkt_edns_do(pkt));
1278 	ldns_pkt_set_edns_co(new_pkt, ldns_pkt_edns_co(pkt));
1279 	if (pkt->_edns_list)
1280 		ldns_pkt_set_edns_option_list(new_pkt,
1281 			ldns_edns_option_list_clone(pkt->_edns_list));
1282 
1283 	ldns_rr_list_deep_free(new_pkt->_question);
1284 	ldns_rr_list_deep_free(new_pkt->_answer);
1285 	ldns_rr_list_deep_free(new_pkt->_authority);
1286 	ldns_rr_list_deep_free(new_pkt->_additional);
1287 	new_pkt->_question = ldns_rr_list_clone(ldns_pkt_question(pkt));
1288 	new_pkt->_answer = ldns_rr_list_clone(ldns_pkt_answer(pkt));
1289 	new_pkt->_authority = ldns_rr_list_clone(ldns_pkt_authority(pkt));
1290 	new_pkt->_additional = ldns_rr_list_clone(ldns_pkt_additional(pkt));
1291 	return new_pkt;
1292 }
1293