1 /*
2  * Copyright (c) 2011 NLNet Labs. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26 
27 /**
28  * Packet buffer.
29  *
30  *                                    1  1  1  1  1  1
31  *      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
32  *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
33  * 01 |                      ID                       |
34  *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
35  * 23 |QR|   Opcode  |AA|TC|RD|RA| Z|AD|CD|   RCODE   |
36  *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
37  * 45 |                    QDCOUNT                    |
38  *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
39  * 67 |                    ANCOUNT                    |
40  *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
41  * 89 |                    NSCOUNT                    |
42  *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
43  * 01 |                    ARCOUNT                    |
44  *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
45  *
46  */
47 
48 
49 #include "config.h"
50 #include "log.h"
51 #include "wire/buffer.h"
52 
53 #include <string.h>
54 
55 static const char* buffer_str = "buffer";
56 
57 ods_lookup_table ods_rcode_str[] = {
58     { LDNS_RCODE_NOERROR, "NOERROR" },
59     { LDNS_RCODE_FORMERR, "FORMERR" },
60     { LDNS_RCODE_SERVFAIL, "SERVFAIL" },
61     { LDNS_RCODE_NXDOMAIN, "NXDOMAIN" },
62     { LDNS_RCODE_NOTIMPL, "NOTIMPL" },
63     { LDNS_RCODE_REFUSED, "REFUSED" },
64     { LDNS_RCODE_YXDOMAIN, "YXDOMAIN" },
65     { LDNS_RCODE_YXRRSET, "YXRRSET" },
66     { LDNS_RCODE_NXRRSET, "NXRRSET" },
67     { LDNS_RCODE_NOTAUTH, "NOTAUTH" },
68     { LDNS_RCODE_NOTZONE, "NOTZONE" },
69     { 0, NULL }
70 };
71 
72 
73 /**
74  * Create a new buffer with the specified capacity.
75  *
76  */
77 buffer_type*
buffer_create(size_t capacity)78 buffer_create(size_t capacity)
79 {
80     buffer_type* buffer = NULL;
81     if (!capacity) {
82         return NULL;
83     }
84     CHECKALLOC(buffer = (buffer_type *) malloc(sizeof(buffer_type)));
85     buffer->data = (uint8_t*) calloc(capacity, sizeof(uint8_t));
86     buffer->position = 0;
87     buffer->limit = capacity;
88     buffer->capacity = capacity;
89     buffer->fixed = 0;
90     return buffer;
91 }
92 
93 
94 /**
95  * Clear the buffer and make it ready for writing.
96  *
97  */
98 void
buffer_clear(buffer_type * buffer)99 buffer_clear(buffer_type* buffer)
100 {
101     ods_log_assert(buffer);
102     buffer->position = 0;
103     buffer->limit = buffer->capacity;
104 }
105 
106 
107 /**
108  * Flip the buffer and make it ready for reading.
109  *
110  */
111 void
buffer_flip(buffer_type * buffer)112 buffer_flip(buffer_type* buffer)
113 {
114     ods_log_assert(buffer);
115     buffer->limit = buffer->position;
116     buffer->position = 0;
117 }
118 
119 
120 /**
121  * Get the buffer's position.
122  *
123  */
124 size_t
buffer_position(buffer_type * buffer)125 buffer_position(buffer_type* buffer)
126 {
127     ods_log_assert(buffer);
128     return buffer->position;
129 }
130 
131 
132 /**
133  * Set the buffer's position.
134  *
135  */
136 void
buffer_set_position(buffer_type * buffer,size_t pos)137 buffer_set_position(buffer_type* buffer, size_t pos)
138 {
139     ods_log_assert(buffer);
140     ods_log_assert(pos <= buffer->limit);
141     buffer->position = pos;
142 }
143 
144 
145 /**
146  * Change the buffer's position.
147  *
148  */
149 void
buffer_skip(buffer_type * buffer,ssize_t count)150 buffer_skip(buffer_type* buffer, ssize_t count)
151 {
152     ods_log_assert(buffer);
153     ods_log_assert(buffer->position + count <= buffer->limit);
154     buffer->position += count;
155 }
156 
157 
158 /**
159  * Get bit.
160  *
161  */
162 static int
get_bit(uint8_t bits[],size_t index)163 get_bit(uint8_t bits[], size_t index)
164 {
165     return bits[index / 8] & (1 << (7 - index % 8));
166 }
167 
168 
169 /**
170  * Set bit.
171  *
172  */
173 static void
set_bit(uint8_t bits[],size_t index)174 set_bit(uint8_t bits[], size_t index)
175 {
176     bits[index / 8] |= (1 << (7 - index % 8));
177 }
178 
179 
180 /**
181  * Is pointer label>
182  *
183  */
184 static int
label_is_pointer(const uint8_t * label)185 label_is_pointer(const uint8_t* label)
186 {
187     ods_log_assert(label);
188     return (label[0] & 0xc0) == 0xc0;
189 }
190 
191 
192 /**
193  * Pointer label location.
194  *
195  */
196 static uint16_t
label_pointer_location(const uint8_t * label)197 label_pointer_location(const uint8_t* label)
198 {
199     ods_log_assert(label);
200     ods_log_assert(label_is_pointer(label));
201     return ((uint16_t) (label[0] & ~0xc0) << 8) | (uint16_t) label[1];
202 }
203 
204 
205 /**
206  * Is normal label?
207  *
208  */
209 static int
label_is_normal(const uint8_t * label)210 label_is_normal(const uint8_t* label)
211 {
212     ods_log_assert(label);
213     return (label[0] & 0xc0) == 0;
214 }
215 
216 /*
217  * Is root label?
218  *
219  */
220 static inline int
label_is_root(const uint8_t * label)221 label_is_root(const uint8_t* label)
222 {
223     ods_log_assert(label);
224     return label[0] == 0;
225 }
226 
227 
228 /*
229  * Label length.
230  *
231  */
232 static uint8_t
label_length(const uint8_t * label)233 label_length(const uint8_t* label)
234 {
235     ods_log_assert(label);
236     ods_log_assert(label_is_normal(label));
237     return label[0];
238 }
239 
240 
241 /**
242  * Read dname from buffer.
243  *
244  */
245 size_t
buffer_read_dname(buffer_type * buffer,uint8_t * dname,unsigned allow_pointers)246 buffer_read_dname(buffer_type* buffer, uint8_t* dname, unsigned allow_pointers)
247 {
248     int done = 0;
249     uint8_t visited[(MAX_PACKET_SIZE+7)/8];
250     size_t dname_length = 0;
251     const uint8_t *label = NULL;
252     ssize_t mark = -1;
253     ods_log_assert(buffer);
254     memset(visited, 0, (buffer_limit(buffer)+7)/8);
255 
256     while (!done) {
257         if (!buffer_available(buffer, 1)) {
258             return 0;
259         }
260         if (get_bit(visited, buffer_position(buffer))) {
261             ods_log_error("[%s] dname loop!", buffer_str);
262             return 0;
263         }
264         set_bit(visited, buffer_position(buffer));
265         label = buffer_current(buffer);
266         if (label_is_pointer(label)) {
267             size_t pointer = 0;
268             if (!allow_pointers) {
269                 return 0;
270             }
271             if (!buffer_available(buffer, 2)) {
272                 return 0;
273             }
274             pointer = label_pointer_location(label);
275             if (pointer >= buffer_limit(buffer)) {
276                 return 0;
277             }
278             buffer_skip(buffer, 2);
279             if (mark == -1) {
280                 mark = buffer_position(buffer);
281             }
282             buffer_set_position(buffer, pointer);
283         } else if (label_is_normal(label)) {
284             size_t length = label_length(label) + 1;
285             done = label_is_root(label);
286             if (!buffer_available(buffer, length)) {
287                 return 0;
288             }
289             if (dname_length + length >= MAXDOMAINLEN+1) {
290                 return 0;
291             }
292             buffer_read(buffer, dname + dname_length, length);
293             dname_length += length;
294         } else {
295             return 0;
296         }
297      }
298      if (mark != -1) {
299         buffer_set_position(buffer, mark);
300      }
301      return dname_length;
302 }
303 
304 
305 /**
306  * Change the buffer's position so that one dname is skipped.
307  *
308  */
309 int
buffer_skip_dname(buffer_type * buffer)310 buffer_skip_dname(buffer_type* buffer)
311 {
312     ods_log_assert(buffer);
313     while (1) {
314         uint8_t label_size = 0;
315         if (!buffer_available(buffer, 1)) {
316             return 0;
317         }
318         label_size = buffer_read_u8(buffer);
319         if (label_size == 0) {
320             break;
321         } else if ((label_size & 0xc0) != 0) {
322             if (!buffer_available(buffer, 1)) {
323                 return 0;
324             }
325             buffer_skip(buffer, 1);
326             break;
327         } else if (!buffer_available(buffer, label_size)) {
328             return 0;
329         } else {
330             buffer_skip(buffer, label_size);
331         }
332     }
333     return 1;
334 }
335 
336 
337 /**
338  * Change the buffer's position so that one RR is skipped.
339  *
340  */
341 int
buffer_skip_rr(buffer_type * buffer,unsigned qrr)342 buffer_skip_rr(buffer_type* buffer, unsigned qrr)
343 {
344     if (!buffer_skip_dname(buffer)) {
345         return 0;
346     }
347     if (qrr) {
348         if (!buffer_available(buffer, 4)) {
349             return 0;
350         }
351         buffer_skip(buffer, 4);
352     } else {
353         uint16_t rdata_size;
354         if (!buffer_available(buffer, 10)) {
355             return 0;
356         }
357         buffer_skip(buffer, 8);
358         rdata_size = buffer_read_u16(buffer);
359         if (!buffer_available(buffer, rdata_size)) {
360             return 0;
361         }
362         buffer_skip(buffer, rdata_size);
363     }
364     return 1;
365 }
366 
367 
368 /**
369  * Get the buffer's limit.
370  *
371  */
372 size_t
buffer_limit(buffer_type * buffer)373 buffer_limit(buffer_type* buffer)
374 {
375     ods_log_assert(buffer);
376     return buffer->limit;
377 }
378 
379 
380 /**
381  * Set the buffer's limit.
382  *
383  */
384 void
buffer_set_limit(buffer_type * buffer,size_t limit)385 buffer_set_limit(buffer_type* buffer, size_t limit)
386 {
387     ods_log_assert(buffer);
388     ods_log_assert(limit <= buffer->capacity);
389     buffer->limit = limit;
390     if (buffer->position > buffer->limit) {
391         buffer->position = buffer->limit;
392     }
393 }
394 
395 
396 /**
397  * Get the buffer's capacity.
398  *
399  */
400 size_t
buffer_capacity(buffer_type * buffer)401 buffer_capacity(buffer_type* buffer)
402 {
403     ods_log_assert(buffer);
404     return buffer->capacity;
405 }
406 
407 
408 /**
409  * Return a pointer to the data at the indicated position.
410  *
411  */
412 uint8_t*
buffer_at(buffer_type * buffer,size_t at)413 buffer_at(buffer_type* buffer, size_t at)
414 {
415     ods_log_assert(buffer);
416     ods_log_assert(at <= buffer->limit);
417     return buffer->data + at;
418 }
419 
420 
421 /**
422  * Return a pointer to the data at the beginning of the buffer.
423  *
424  */
425 uint8_t*
buffer_begin(buffer_type * buffer)426 buffer_begin(buffer_type* buffer)
427 {
428     ods_log_assert(buffer);
429     return buffer_at(buffer, 0);
430 }
431 
432 
433 /**
434  * Return a pointer to the data at the buffer's current position.
435  *
436  */
437 uint8_t*
buffer_current(buffer_type * buffer)438 buffer_current(buffer_type* buffer)
439 {
440     ods_log_assert(buffer);
441     return buffer_at(buffer, buffer->position);
442 }
443 
444 
445 /**
446  * The number of bytes remaining between the at and limit.
447  *
448  */
449 static size_t
buffer_remaining_at(buffer_type * buffer,size_t at)450 buffer_remaining_at(buffer_type* buffer, size_t at)
451 {
452     ods_log_assert(buffer);
453     ods_log_assert(at <= buffer->limit);
454     return buffer->limit - at;
455 }
456 
457 
458 /**
459  * The number of bytes remaining between the buffer's position and limit.
460  *
461  */
462 size_t
buffer_remaining(buffer_type * buffer)463 buffer_remaining(buffer_type* buffer)
464 {
465     ods_log_assert(buffer);
466     return buffer_remaining_at(buffer, buffer->position);
467 }
468 
469 
470 /**
471  * Check if the buffer has enough bytes available at indicated position.
472  *
473  */
474 static int
buffer_available_at(buffer_type * buffer,size_t at,size_t count)475 buffer_available_at(buffer_type *buffer, size_t at, size_t count)
476 {
477     ods_log_assert(buffer);
478     return count <= buffer_remaining_at(buffer, at);
479 }
480 
481 
482 /**
483  * Check if the buffer has enough bytes available.
484  *
485  */
486 int
buffer_available(buffer_type * buffer,size_t count)487 buffer_available(buffer_type *buffer, size_t count)
488 {
489     ods_log_assert(buffer);
490     return buffer_available_at(buffer, buffer->position, count);
491 }
492 
493 
494 /**
495  * Write to buffer at indicated position.
496  *
497  */
498 static void
buffer_write_u8_at(buffer_type * buffer,size_t at,uint8_t data)499 buffer_write_u8_at(buffer_type* buffer, size_t at, uint8_t data)
500 {
501     ods_log_assert(buffer);
502     ods_log_assert(buffer_available_at(buffer, at, sizeof(data)));
503     buffer->data[at] = data;
504 }
505 
506 
507 /**
508  * Write to buffer at indicated position.
509  *
510  */
511 void
buffer_write_u16_at(buffer_type * buffer,size_t at,uint16_t data)512 buffer_write_u16_at(buffer_type* buffer, size_t at, uint16_t data)
513 {
514     ods_log_assert(buffer);
515     ods_log_assert(buffer_available_at(buffer, at, sizeof(data)));
516     write_uint16(buffer->data + at, data);
517 }
518 
519 
520 /**
521  * Write to buffer at indicated position.
522  *
523  */
524 static void
buffer_write_u32_at(buffer_type * buffer,size_t at,uint32_t data)525 buffer_write_u32_at(buffer_type* buffer, size_t at, uint32_t data)
526 {
527     ods_log_assert(buffer);
528     ods_log_assert(buffer_available_at(buffer, at, sizeof(data)));
529     write_uint32(buffer->data + at, data);
530 }
531 
532 
533 /**
534  * Write to buffer.
535  *
536  */
537 void
buffer_write(buffer_type * buffer,const void * data,size_t count)538 buffer_write(buffer_type* buffer, const void* data, size_t count)
539 {
540     ods_log_assert(buffer);
541     ods_log_assert(buffer_available(buffer, count));
542     memcpy(buffer->data + buffer->position, data, count);
543     buffer->position += count;
544 }
545 
546 
547 /**
548  * Write uint8_t to buffer.
549  *
550  */
551 void
buffer_write_u8(buffer_type * buffer,uint8_t data)552 buffer_write_u8(buffer_type* buffer, uint8_t data)
553 {
554     ods_log_assert(buffer);
555     buffer_write_u8_at(buffer, buffer->position, data);
556     buffer->position += sizeof(data);
557 }
558 
559 
560 /**
561  * Write uint16_t to buffer.
562  *
563  */
564 void
buffer_write_u16(buffer_type * buffer,uint16_t data)565 buffer_write_u16(buffer_type* buffer, uint16_t data)
566 {
567     ods_log_assert(buffer);
568     buffer_write_u16_at(buffer, buffer->position, data);
569     buffer->position += sizeof(data);
570 }
571 
572 
573 /**
574  * Write uint32_t to buffer.
575  *
576  */
577 void
buffer_write_u32(buffer_type * buffer,uint32_t data)578 buffer_write_u32(buffer_type* buffer, uint32_t data)
579 {
580     ods_log_assert(buffer);
581     buffer_write_u32_at(buffer, buffer->position, data);
582     buffer->position += sizeof(data);
583 }
584 
585 
586 /**
587  * Write rdf to buffer.
588  *
589  */
590 void
buffer_write_rdf(buffer_type * buffer,ldns_rdf * rdf)591 buffer_write_rdf(buffer_type* buffer, ldns_rdf* rdf)
592 {
593     ods_log_assert(buffer);
594     ods_log_assert(rdf);
595     buffer_write(buffer, ldns_rdf_data(rdf), ldns_rdf_size(rdf));
596     /* position updated by buffer_write() */
597 }
598 
599 
600 /**
601  * Write rr to buffer.
602  *
603  */
604 int
buffer_write_rr(buffer_type * buffer,ldns_rr * rr)605 buffer_write_rr(buffer_type* buffer, ldns_rr* rr)
606 {
607     size_t i = 0;
608     size_t tc_mark = 0;
609     size_t rdlength_pos = 0;
610     uint16_t rdlength = 0;
611     ods_log_assert(buffer);
612     ods_log_assert(rr);
613     /* set truncation mark, in case rr does not fit */
614     tc_mark = buffer_position(buffer);
615     /* owner type class ttl */
616     if (!buffer_available(buffer, ldns_rdf_size(ldns_rr_owner(rr)))) {
617         goto buffer_tc;
618     }
619     buffer_write_rdf(buffer, ldns_rr_owner(rr));
620     if (!buffer_available(buffer, sizeof(uint16_t) + sizeof(uint16_t) +
621         sizeof(uint32_t) + sizeof(rdlength))) {
622         goto buffer_tc;
623     }
624     buffer_write_u16(buffer, (uint16_t) ldns_rr_get_type(rr));
625     buffer_write_u16(buffer, (uint16_t) ldns_rr_get_class(rr));
626     buffer_write_u32(buffer, (uint32_t) ldns_rr_ttl(rr));
627     /* skip rdlength */
628     rdlength_pos = buffer_position(buffer);
629     buffer_skip(buffer, sizeof(rdlength));
630     /* write rdata */
631     for (i=0; i < ldns_rr_rd_count(rr); i++) {
632         if (!buffer_available(buffer, ldns_rdf_size(ldns_rr_rdf(rr, i)))) {
633             goto buffer_tc;
634         }
635         buffer_write_rdf(buffer, ldns_rr_rdf(rr, i));
636     }
637     /* write rdlength */
638     rdlength = buffer_position(buffer) - rdlength_pos - sizeof(rdlength);
639     buffer_write_u16_at(buffer, rdlength_pos, rdlength);
640     /* position updated by buffer_write() */
641     return 1;
642 
643 buffer_tc:
644     buffer_set_position(buffer, tc_mark);
645     return 0;
646 }
647 
648 
649 /**
650  * Read uint8_t from buffer at indicated position.
651  *
652  */
653 static uint8_t
buffer_read_u8_at(buffer_type * buffer,size_t at)654 buffer_read_u8_at(buffer_type* buffer, size_t at)
655 {
656     ods_log_assert(buffer);
657     ods_log_assert(at < buffer->capacity);
658     return buffer->data[at];
659 
660 }
661 
662 
663 /**
664  * Read uint16_t from buffer at indicated position.
665  *
666  */
667 static uint16_t
buffer_read_u16_at(buffer_type * buffer,size_t at)668 buffer_read_u16_at(buffer_type* buffer, size_t at)
669 {
670     ods_log_assert(buffer);
671     return read_uint16(buffer->data + at);
672 }
673 
674 
675 /**
676  * Read uint32_t from buffer at indicated position.
677  *
678  */
679 static uint32_t
buffer_read_u32_at(buffer_type * buffer,size_t at)680 buffer_read_u32_at(buffer_type* buffer, size_t at)
681 {
682     ods_log_assert(buffer);
683     return read_uint32(buffer->data + at);
684 }
685 
686 
687 /**
688  * Read from buffer.
689  *
690  */
691 void
buffer_read(buffer_type * buffer,void * data,size_t count)692 buffer_read(buffer_type* buffer, void* data, size_t count)
693 {
694     ods_log_assert(buffer);
695     ods_log_assert(buffer_available(buffer, count));
696     memcpy(data, buffer->data + buffer->position, count);
697     buffer->position += count;
698 }
699 
700 
701 /**
702  * Read uint8_t from buffer.
703  *
704  */
705 uint8_t
buffer_read_u8(buffer_type * buffer)706 buffer_read_u8(buffer_type* buffer)
707 {
708     uint16_t result = 0;
709     ods_log_assert(buffer);
710     result = buffer_read_u8_at(buffer, buffer->position);
711     buffer->position += sizeof(uint8_t);
712     return result;
713 }
714 
715 
716 /**
717  * Read uint16_t from buffer.
718  *
719  */
720 uint16_t
buffer_read_u16(buffer_type * buffer)721 buffer_read_u16(buffer_type* buffer)
722 {
723     uint16_t result = 0;
724     ods_log_assert(buffer);
725     result = buffer_read_u16_at(buffer, buffer->position);
726     buffer->position += sizeof(uint16_t);
727     return result;
728 }
729 
730 
731 /**
732  * Read uint32_t from buffer.
733  *
734  */
735 uint32_t
buffer_read_u32(buffer_type * buffer)736 buffer_read_u32(buffer_type* buffer)
737 {
738     uint32_t result = 0;
739     ods_log_assert(buffer);
740     result = buffer_read_u32_at(buffer, buffer->position);
741     buffer->position += sizeof(uint32_t);
742     return result;
743 }
744 
745 
746 /**
747  * Get query id from buffer.
748  *
749  */
750 uint16_t
buffer_pkt_id(buffer_type * buffer)751 buffer_pkt_id(buffer_type* buffer)
752 {
753     ods_log_assert(buffer);
754     return buffer_read_u16_at(buffer, 0);
755 }
756 
757 /**
758  * Get a random query id.
759  *
760  */
761 static uint16_t
random_id(void)762 random_id(void)
763 {
764     return ldns_get_random();
765 }
766 
767 /**
768  * Set random query id in buffer.
769  *
770  */
771 void
buffer_pkt_set_random_id(buffer_type * buffer)772 buffer_pkt_set_random_id(buffer_type* buffer)
773 {
774     uint16_t qid = 0;
775     ods_log_assert(buffer);
776     qid = random_id();
777     buffer_write_u16_at(buffer, 0, qid);
778 }
779 
780 
781 /**
782  * Get flags from buffer.
783  *
784  */
785 uint16_t
buffer_pkt_flags(buffer_type * buffer)786 buffer_pkt_flags(buffer_type* buffer)
787 {
788     ods_log_assert(buffer);
789     return (uint16_t) buffer_read_u16_at(buffer, 2);
790 }
791 
792 
793 /**
794  * Set flags in buffer.
795  *
796  */
797 void
buffer_pkt_set_flags(buffer_type * buffer,uint16_t flags)798 buffer_pkt_set_flags(buffer_type* buffer, uint16_t flags)
799 {
800     ods_log_assert(buffer);
801     buffer_write_u16_at(buffer, 2, flags);
802 }
803 
804 
805 /**
806  * Get QR bit from buffer.
807  *
808  */
809 int
buffer_pkt_qr(buffer_type * buffer)810 buffer_pkt_qr(buffer_type* buffer)
811 {
812     ods_log_assert(buffer);
813     return (int) QR(buffer);
814 }
815 
816 
817 /**
818  * Set QR bit in buffer.
819  *
820  */
821 void
buffer_pkt_set_qr(buffer_type * buffer)822 buffer_pkt_set_qr(buffer_type* buffer)
823 {
824     ods_log_assert(buffer);
825     QR_SET(buffer);
826 }
827 
828 
829 /**
830  * Clear QR bit in buffer.
831  *
832  */
833 void
buffer_pkt_clear_qr(buffer_type * buffer)834 buffer_pkt_clear_qr(buffer_type* buffer)
835 {
836     ods_log_assert(buffer);
837     QR_CLR(buffer);
838 }
839 
840 
841 /**
842  * Get OPCODE from buffer.
843  *
844  */
845 ldns_pkt_opcode
buffer_pkt_opcode(buffer_type * buffer)846 buffer_pkt_opcode(buffer_type* buffer)
847 {
848     ods_log_assert(buffer);
849     return (ldns_pkt_opcode) OPCODE(buffer);
850 }
851 
852 
853 /**
854  * Set OPCODE in buffer.
855  *
856  */
857 void
buffer_pkt_set_opcode(buffer_type * buffer,ldns_pkt_opcode opcode)858 buffer_pkt_set_opcode(buffer_type* buffer, ldns_pkt_opcode opcode)
859 {
860     ods_log_assert(buffer);
861     OPCODE_SET(buffer, opcode);
862 }
863 
864 
865 /**
866  * Get AA bit from buffer.
867  *
868  */
869 int
buffer_pkt_aa(buffer_type * buffer)870 buffer_pkt_aa(buffer_type* buffer)
871 {
872     ods_log_assert(buffer);
873     return (int) AA(buffer);
874 }
875 
876 
877 /**
878  * Set AA bit in buffer.
879  *
880  */
881 void
buffer_pkt_set_aa(buffer_type * buffer)882 buffer_pkt_set_aa(buffer_type* buffer)
883 {
884     ods_log_assert(buffer);
885     AA_SET(buffer);
886 }
887 
888 
889 /**
890  * Get TC bit from buffer.
891  *
892  */
893 int
buffer_pkt_tc(buffer_type * buffer)894 buffer_pkt_tc(buffer_type* buffer)
895 {
896     ods_log_assert(buffer);
897     return (int) TC(buffer);
898 }
899 
900 
901 /**
902  * Get RD bit from buffer.
903  *
904  */
905 int
buffer_pkt_rd(buffer_type * buffer)906 buffer_pkt_rd(buffer_type* buffer)
907 {
908     ods_log_assert(buffer);
909     return (int) RD(buffer);
910 }
911 
912 
913 /**
914  * Get RA bit from buffer.
915  *
916  */
917 int
buffer_pkt_ra(buffer_type * buffer)918 buffer_pkt_ra(buffer_type* buffer)
919 {
920     ods_log_assert(buffer);
921     return (int) RA(buffer);
922 }
923 
924 
925 /**
926  * Get AD bit from buffer.
927  *
928  */
929 int
buffer_pkt_ad(buffer_type * buffer)930 buffer_pkt_ad(buffer_type* buffer)
931 {
932     ods_log_assert(buffer);
933     return (int) AD(buffer);
934 }
935 
936 
937 /**
938  * Get CD bit from buffer.
939  *
940  */
941 int
buffer_pkt_cd(buffer_type * buffer)942 buffer_pkt_cd(buffer_type* buffer)
943 {
944     ods_log_assert(buffer);
945     return (int) CD(buffer);
946 }
947 
948 
949 /**
950  * Get RCODE from buffer.
951  *
952  */
953 ldns_pkt_rcode
buffer_pkt_rcode(buffer_type * buffer)954 buffer_pkt_rcode(buffer_type* buffer)
955 {
956     ods_log_assert(buffer);
957     return (ldns_pkt_rcode) RCODE(buffer);
958 }
959 
960 
961 /**
962  * Set RCODE in buffer.
963  *
964  */
965 void
buffer_pkt_set_rcode(buffer_type * buffer,ldns_pkt_rcode rcode)966 buffer_pkt_set_rcode(buffer_type* buffer, ldns_pkt_rcode rcode)
967 {
968     ods_log_assert(buffer);
969     RCODE_SET(buffer, rcode);
970 }
971 
972 
973 /**
974  * Look up a descriptive text by each rcode.
975  *
976  */
977 const char*
buffer_rcode2str(ldns_pkt_rcode rcode)978 buffer_rcode2str(ldns_pkt_rcode rcode)
979 {
980     ods_lookup_table *lt;
981     lt = ods_lookup_by_id(ods_rcode_str, rcode);
982     if (lt) {
983         return lt->name;
984     }
985     return NULL;
986 }
987 
988 
989 /**
990  * Get QDCOUNT from buffer.
991  *
992  */
993 uint16_t
buffer_pkt_qdcount(buffer_type * buffer)994 buffer_pkt_qdcount(buffer_type* buffer)
995 {
996     ods_log_assert(buffer);
997     return buffer_read_u16_at(buffer, 4);
998 }
999 
1000 
1001 /**
1002  * Set QDCOUNT in buffer.
1003  *
1004  */
1005 void
buffer_pkt_set_qdcount(buffer_type * buffer,uint16_t count)1006 buffer_pkt_set_qdcount(buffer_type* buffer, uint16_t count)
1007 {
1008     ods_log_assert(buffer);
1009     buffer_write_u16_at(buffer, 4, count);
1010 }
1011 
1012 
1013 /**
1014  * Get ANCOUNT from buffer.
1015  *
1016  */
1017 uint16_t
buffer_pkt_ancount(buffer_type * buffer)1018 buffer_pkt_ancount(buffer_type* buffer)
1019 {
1020     ods_log_assert(buffer);
1021     return buffer_read_u16_at(buffer, 6);
1022 }
1023 
1024 
1025 /**
1026  * Set ANCOUNT in buffer.
1027  *
1028  */
1029 void
buffer_pkt_set_ancount(buffer_type * buffer,uint16_t count)1030 buffer_pkt_set_ancount(buffer_type* buffer, uint16_t count)
1031 {
1032     ods_log_assert(buffer);
1033     buffer_write_u16_at(buffer, 6, count);
1034 }
1035 
1036 
1037 /**
1038  * Get NSCOUNT from buffer.
1039  *
1040  */
1041 uint16_t
buffer_pkt_nscount(buffer_type * buffer)1042 buffer_pkt_nscount(buffer_type* buffer)
1043 {
1044     ods_log_assert(buffer);
1045     return buffer_read_u16_at(buffer, 8);
1046 }
1047 
1048 
1049 /**
1050  * Set NSCOUNT in buffer.
1051  *
1052  */
1053 void
buffer_pkt_set_nscount(buffer_type * buffer,uint16_t count)1054 buffer_pkt_set_nscount(buffer_type* buffer, uint16_t count)
1055 {
1056     ods_log_assert(buffer);
1057     buffer_write_u16_at(buffer, 8, count);
1058 }
1059 
1060 
1061 /**
1062  * Get ARCOUNT from buffer.
1063  *
1064  */
1065 uint16_t
buffer_pkt_arcount(buffer_type * buffer)1066 buffer_pkt_arcount(buffer_type* buffer)
1067 {
1068     ods_log_assert(buffer);
1069     return buffer_read_u16_at(buffer, 10);
1070 }
1071 
1072 
1073 /**
1074  * Set ARCOUNT in buffer.
1075  *
1076  */
1077 void
buffer_pkt_set_arcount(buffer_type * buffer,uint16_t count)1078 buffer_pkt_set_arcount(buffer_type* buffer, uint16_t count)
1079 {
1080     ods_log_assert(buffer);
1081     buffer_write_u16_at(buffer, 10, count);
1082 }
1083 
1084 
1085 /**
1086  * Make a new packet.
1087  *
1088  */
1089 static void
buffer_pkt_new(buffer_type * buffer,ldns_rdf * qname,ldns_rr_type qtype,ldns_rr_class qclass,ldns_pkt_opcode opcode)1090 buffer_pkt_new(buffer_type* buffer, ldns_rdf* qname, ldns_rr_type qtype,
1091    ldns_rr_class qclass, ldns_pkt_opcode opcode)
1092 {
1093     ods_log_assert(buffer);
1094     ods_log_assert(qname);
1095     ods_log_assert(qtype);
1096     ods_log_assert(qclass);
1097     /* The header */
1098     buffer_clear(buffer);
1099     buffer_pkt_set_random_id(buffer);
1100     buffer_pkt_set_opcode(buffer, opcode);
1101     buffer_pkt_clear_qr(buffer);
1102     buffer_pkt_set_rcode(buffer, LDNS_RCODE_NOERROR);
1103     buffer_pkt_set_qdcount(buffer, 1);
1104     buffer_pkt_set_ancount(buffer, 0);
1105     buffer_pkt_set_nscount(buffer, 0);
1106     buffer_pkt_set_arcount(buffer, 0);
1107     buffer_skip(buffer, BUFFER_PKT_HEADER_SIZE);
1108     /* The question record */
1109     buffer_write_rdf(buffer, qname);
1110     buffer_write_u16(buffer, qtype);
1111     buffer_write_u16(buffer, qclass);
1112 }
1113 
1114 
1115 /**
1116  * Make a new query.
1117  *
1118  */
1119 void
buffer_pkt_query(buffer_type * buffer,ldns_rdf * qname,ldns_rr_type qtype,ldns_rr_class qclass)1120 buffer_pkt_query(buffer_type* buffer, ldns_rdf* qname, ldns_rr_type qtype,
1121    ldns_rr_class qclass)
1122 {
1123     buffer_pkt_new(buffer, qname, qtype, qclass, LDNS_PACKET_QUERY);
1124     buffer_pkt_set_flags(buffer, 0);
1125 }
1126 
1127 
1128 /**
1129  * Make a new notify.
1130  *
1131  */
1132 void
buffer_pkt_notify(buffer_type * buffer,ldns_rdf * qname,ldns_rr_class qclass)1133 buffer_pkt_notify(buffer_type* buffer, ldns_rdf* qname, ldns_rr_class qclass)
1134 {
1135     buffer_pkt_new(buffer, qname, LDNS_RR_TYPE_SOA, qclass,
1136         LDNS_PACKET_NOTIFY);
1137 }
1138 
1139 
1140 /**
1141  * Clean up buffer.
1142  *
1143  */
1144 void
buffer_cleanup(buffer_type * buffer)1145 buffer_cleanup(buffer_type* buffer)
1146 {
1147     if (!buffer) {
1148         return;
1149     }
1150     free(buffer->data);
1151     free(buffer);
1152 }
1153 
1154 
1155