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