OpenDNSSEC-signer  1.4.1
buffer.c
Go to the documentation of this file.
1 /*
2  * $Id: buffer.c 4958 2011-04-18 07:11:09Z matthijs $
3  *
4  * Copyright (c) 2011 NLNet Labs. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
51 #include "config.h"
52 #include "shared/log.h"
53 #include "wire/buffer.h"
54 
55 #include <string.h>
56 
57 static const char* buffer_str = "buffer";
58 
64 buffer_create(allocator_type* allocator, size_t capacity)
65 {
66  buffer_type* buffer = NULL;
67  if (!allocator || !capacity) {
68  return NULL;
69  }
70  buffer = (buffer_type *) allocator_alloc(allocator, sizeof(buffer_type));
71  if (!buffer) {
72  return NULL;
73  }
74  buffer->data = (uint8_t*) calloc(capacity, sizeof(uint8_t));
75  buffer->position = 0;
76  buffer->limit = capacity;
77  buffer->capacity = capacity;
78  buffer->fixed = 0;
79  return buffer;
80 }
81 
82 
87 void
88 buffer_create_from(buffer_type* buffer, void* data, size_t size)
89 {
90  ods_log_assert(buffer);
91  buffer->data = (uint8_t*) data;
92  buffer->position = 0;
93  buffer->limit = size;
94  buffer->capacity = size;
95  buffer->fixed = 1;
96  return;
97 }
98 
99 
104 void
106 {
107  ods_log_assert(buffer);
108  buffer->position = 0;
109  buffer->limit = buffer->capacity;
110  return;
111 }
112 
113 
118 void
120 {
121  ods_log_assert(buffer);
122  buffer->limit = buffer->position;
123  buffer->position = 0;
124  return;
125 }
126 
127 
132 void
134 {
135  ods_log_assert(buffer);
136  buffer->position = 0;
137  return;
138 }
139 
140 
145 size_t
147 {
148  ods_log_assert(buffer);
149  return buffer->position;
150 }
151 
152 
157 void
158 buffer_set_position(buffer_type* buffer, size_t pos)
159 {
160  ods_log_assert(buffer);
161  ods_log_assert(pos <= buffer->limit);
162  buffer->position = pos;
163  return;
164 }
165 
166 
171 void
172 buffer_skip(buffer_type* buffer, ssize_t count)
173 {
174  ods_log_assert(buffer);
175  ods_log_assert(buffer->position + count <= buffer->limit);
176  buffer->position += count;
177  return;
178 }
179 
180 
185 static int
186 get_bit(uint8_t bits[], size_t index)
187 {
188  return bits[index / 8] & (1 << (7 - index % 8));
189 }
190 
191 
196 static void
197 set_bit(uint8_t bits[], size_t index)
198 {
199  bits[index / 8] |= (1 << (7 - index % 8));
200  return;
201 }
202 
203 
208 static int
209 label_is_pointer(const uint8_t* label)
210 {
211  ods_log_assert(label);
212  return (label[0] & 0xc0) == 0xc0;
213 }
214 
215 
220 static uint16_t
221 label_pointer_location(const uint8_t* label)
222 {
223  ods_log_assert(label);
224  ods_log_assert(label_is_pointer(label));
225  return ((uint16_t) (label[0] & ~0xc0) << 8) | (uint16_t) label[1];
226 }
227 
228 
233 static int
234 label_is_normal(const uint8_t* label)
235 {
236  ods_log_assert(label);
237  return (label[0] & 0xc0) == 0;
238 }
239 
240 /*
241  * Is root label?
242  *
243  */
244 static inline int
245 label_is_root(const uint8_t* label)
246 {
247  ods_log_assert(label);
248  return label[0] == 0;
249 }
250 
251 
252 /*
253  * Label length.
254  *
255  */
256 static uint8_t
257 label_length(const uint8_t* label)
258 {
259  ods_log_assert(label);
260  ods_log_assert(label_is_normal(label));
261  return label[0];
262 }
263 
264 
269 size_t
270 buffer_read_dname(buffer_type* buffer, uint8_t* dname, unsigned allow_pointers)
271 {
272  int done = 0;
273  uint8_t visited[(MAX_PACKET_SIZE+7)/8];
274  size_t dname_length = 0;
275  const uint8_t *label = NULL;
276  ssize_t mark = -1;
277  ods_log_assert(buffer);
278  memset(visited, 0, (buffer_limit(buffer)+7)/8);
279 
280  while (!done) {
281  if (!buffer_available(buffer, 1)) {
282  return 0;
283  }
284  if (get_bit(visited, buffer_position(buffer))) {
285  ods_log_error("[%s] dname loop!", buffer_str);
286  return 0;
287  }
288  set_bit(visited, buffer_position(buffer));
289  label = buffer_current(buffer);
290  if (label_is_pointer(label)) {
291  size_t pointer = 0;
292  if (!allow_pointers) {
293  return 0;
294  }
295  if (!buffer_available(buffer, 2)) {
296  return 0;
297  }
298  pointer = label_pointer_location(label);
299  if (pointer >= buffer_limit(buffer)) {
300  return 0;
301  }
302  buffer_skip(buffer, 2);
303  if (mark == -1) {
304  mark = buffer_position(buffer);
305  }
306  buffer_set_position(buffer, pointer);
307  } else if (label_is_normal(label)) {
308  size_t length = label_length(label) + 1;
309  done = label_is_root(label);
310  if (!buffer_available(buffer, length)) {
311  return 0;
312  }
313  if (dname_length + length >= MAXDOMAINLEN+1) {
314  return 0;
315  }
316  buffer_read(buffer, dname + dname_length, length);
317  dname_length += length;
318  } else {
319  return 0;
320  }
321  }
322  if (mark != -1) {
323  buffer_set_position(buffer, mark);
324  }
325  return dname_length;
326 }
327 
328 
333 int
335 {
336  ods_log_assert(buffer);
337  while (1) {
338  uint8_t label_size = 0;
339  if (!buffer_available(buffer, 1)) {
340  return 0;
341  }
342  label_size = buffer_read_u8(buffer);
343  if (label_size == 0) {
344  break;
345  } else if ((label_size & 0xc0) != 0) {
346  if (!buffer_available(buffer, 1)) {
347  return 0;
348  }
349  buffer_skip(buffer, 1);
350  break;
351  } else if (!buffer_available(buffer, label_size)) {
352  return 0;
353  } else {
354  buffer_skip(buffer, label_size);
355  }
356  }
357  return 1;
358 }
359 
360 
365 int
366 buffer_skip_rr(buffer_type* buffer, unsigned qrr)
367 {
368  if (!buffer_skip_dname(buffer)) {
369  return 0;
370  }
371  if (qrr) {
372  if (!buffer_available(buffer, 4)) {
373  return 0;
374  }
375  buffer_skip(buffer, 4);
376  } else {
377  uint16_t rdata_size;
378  if (!buffer_available(buffer, 10)) {
379  return 0;
380  }
381  buffer_skip(buffer, 8);
382  rdata_size = buffer_read_u16(buffer);
383  if (!buffer_available(buffer, rdata_size)) {
384  return 0;
385  }
386  buffer_skip(buffer, rdata_size);
387  }
388  return 1;
389 }
390 
391 
396 size_t
398 {
399  ods_log_assert(buffer);
400  return buffer->limit;
401 }
402 
403 
408 void
409 buffer_set_limit(buffer_type* buffer, size_t limit)
410 {
411  ods_log_assert(buffer);
412  ods_log_assert(limit <= buffer->capacity);
413  buffer->limit = limit;
414  if (buffer->position > buffer->limit) {
415  buffer->position = buffer->limit;
416  }
417  return;
418 }
419 
420 
425 size_t
427 {
428  ods_log_assert(buffer);
429  return buffer->capacity;
430 }
431 
432 
437 uint8_t*
438 buffer_at(buffer_type* buffer, size_t at)
439 {
440  ods_log_assert(buffer);
441  ods_log_assert(at <= buffer->limit);
442  return buffer->data + at;
443 }
444 
445 
450 uint8_t*
452 {
453  ods_log_assert(buffer);
454  return buffer_at(buffer, 0);
455 }
456 
457 
462 uint8_t*
464 {
465  ods_log_assert(buffer);
466  return buffer_at(buffer, buffer->limit);
467 }
468 
469 
474 uint8_t*
476 {
477  ods_log_assert(buffer);
478  return buffer_at(buffer, buffer->position);
479 }
480 
481 
486 static size_t
487 buffer_remaining_at(buffer_type* buffer, size_t at)
488 {
489  ods_log_assert(buffer);
490  ods_log_assert(at <= buffer->limit);
491  return buffer->limit - at;
492 }
493 
494 
499 size_t
501 {
502  ods_log_assert(buffer);
503  return buffer_remaining_at(buffer, buffer->position);
504 }
505 
506 
511 static int
512 buffer_available_at(buffer_type *buffer, size_t at, size_t count)
513 {
514  ods_log_assert(buffer);
515  return count <= buffer_remaining_at(buffer, at);
516 }
517 
518 
523 int
524 buffer_available(buffer_type *buffer, size_t count)
525 {
526  ods_log_assert(buffer);
527  return buffer_available_at(buffer, buffer->position, count);
528 }
529 
530 
535 static void
536 buffer_write_u8_at(buffer_type* buffer, size_t at, uint8_t data)
537 {
538  ods_log_assert(buffer);
539  ods_log_assert(buffer_available_at(buffer, at, sizeof(data)));
540  buffer->data[at] = data;
541  return;
542 }
543 
544 
549 void
550 buffer_write_u16_at(buffer_type* buffer, size_t at, uint16_t data)
551 {
552  ods_log_assert(buffer);
553  ods_log_assert(buffer_available_at(buffer, at, sizeof(data)));
554  write_uint16(buffer->data + at, data);
555  return;
556 }
557 
558 
563 static void
564 buffer_write_u32_at(buffer_type* buffer, size_t at, uint32_t data)
565 {
566  ods_log_assert(buffer);
567  ods_log_assert(buffer_available_at(buffer, at, sizeof(data)));
568  write_uint32(buffer->data + at, data);
569  return;
570 }
571 
572 
577 void
578 buffer_write(buffer_type* buffer, const void* data, size_t count)
579 {
580  ods_log_assert(buffer);
581  ods_log_assert(buffer_available(buffer, count));
582  memcpy(buffer->data + buffer->position, data, count);
583  buffer->position += count;
584  return;
585 }
586 
587 
592 void
593 buffer_write_u8(buffer_type* buffer, uint8_t data)
594 {
595  ods_log_assert(buffer);
596  buffer_write_u8_at(buffer, buffer->position, data);
597  buffer->position += sizeof(data);
598  return;
599 }
600 
601 
606 void
607 buffer_write_u16(buffer_type* buffer, uint16_t data)
608 {
609  ods_log_assert(buffer);
610  buffer_write_u16_at(buffer, buffer->position, data);
611  buffer->position += sizeof(data);
612  return;
613 }
614 
615 
620 void
621 buffer_write_u32(buffer_type* buffer, uint32_t data)
622 {
623  ods_log_assert(buffer);
624  buffer_write_u32_at(buffer, buffer->position, data);
625  buffer->position += sizeof(data);
626  return;
627 }
628 
629 
634 void
635 buffer_write_rdf(buffer_type* buffer, ldns_rdf* rdf)
636 {
637  ods_log_assert(buffer);
638  ods_log_assert(rdf);
639  buffer_write(buffer, ldns_rdf_data(rdf), ldns_rdf_size(rdf));
640  /* position updated by buffer_write() */
641  return;
642 }
643 
644 
649 int
650 buffer_write_rr(buffer_type* buffer, ldns_rr* rr)
651 {
652  size_t i = 0;
653  size_t tc_mark = 0;
654  size_t rdlength_pos = 0;
655  uint16_t rdlength = 0;
656  ods_log_assert(buffer);
657  ods_log_assert(rr);
658  /* set truncation mark, in case rr does not fit */
659  tc_mark = buffer_position(buffer);
660  /* owner type class ttl */
661  if (!buffer_available(buffer, ldns_rdf_size(ldns_rr_owner(rr)))) {
662  goto buffer_tc;
663  }
664  buffer_write_rdf(buffer, ldns_rr_owner(rr));
665  if (!buffer_available(buffer, sizeof(uint16_t) + sizeof(uint16_t) +
666  sizeof(uint32_t) + sizeof(rdlength))) {
667  goto buffer_tc;
668  }
669  buffer_write_u16(buffer, (uint16_t) ldns_rr_get_type(rr));
670  buffer_write_u16(buffer, (uint16_t) ldns_rr_get_class(rr));
671  buffer_write_u32(buffer, (uint32_t) ldns_rr_ttl(rr));
672  /* skip rdlength */
673  rdlength_pos = buffer_position(buffer);
674  buffer_skip(buffer, sizeof(rdlength));
675  /* write rdata */
676  for (i=0; i < ldns_rr_rd_count(rr); i++) {
677  if (!buffer_available(buffer, ldns_rdf_size(ldns_rr_rdf(rr, i)))) {
678  goto buffer_tc;
679  }
680  buffer_write_rdf(buffer, ldns_rr_rdf(rr, i));
681  }
682  /* write rdlength */
683  rdlength = buffer_position(buffer) - rdlength_pos - sizeof(rdlength);
684  buffer_write_u16_at(buffer, rdlength_pos, rdlength);
685  /* position updated by buffer_write() */
686  return 1;
687 
688 buffer_tc:
689  buffer_set_position(buffer, tc_mark);
690  return 0;
691 }
692 
693 
698 static uint8_t
699 buffer_read_u8_at(buffer_type* buffer, size_t at)
700 {
701  ods_log_assert(buffer);
702  ods_log_assert(at < buffer->capacity);
703  return buffer->data[at];
704 
705 }
706 
707 
712 static uint16_t
713 buffer_read_u16_at(buffer_type* buffer, size_t at)
714 {
715  ods_log_assert(buffer);
716  return read_uint16(buffer->data + at);
717 }
718 
719 
724 static uint32_t
725 buffer_read_u32_at(buffer_type* buffer, size_t at)
726 {
727  ods_log_assert(buffer);
728  return read_uint32(buffer->data + at);
729 }
730 
731 
736 void
737 buffer_read(buffer_type* buffer, void* data, size_t count)
738 {
739  ods_log_assert(buffer);
740  ods_log_assert(buffer_available(buffer, count));
741  memcpy(data, buffer->data + buffer->position, count);
742  buffer->position += count;
743  return;
744 }
745 
746 
751 uint8_t
753 {
754  uint16_t result = 0;
755  ods_log_assert(buffer);
756  result = buffer_read_u8_at(buffer, buffer->position);
757  buffer->position += sizeof(uint8_t);
758  return result;
759 }
760 
761 
766 uint16_t
768 {
769  uint16_t result = 0;
770  ods_log_assert(buffer);
771  result = buffer_read_u16_at(buffer, buffer->position);
772  buffer->position += sizeof(uint16_t);
773  return result;
774 }
775 
776 
781 uint32_t
783 {
784  uint32_t result = 0;
785  ods_log_assert(buffer);
786  result = buffer_read_u32_at(buffer, buffer->position);
787  buffer->position += sizeof(uint32_t);
788  return result;
789 }
790 
791 
796 uint16_t
798 {
799  ods_log_assert(buffer);
800  return buffer_read_u16_at(buffer, 0);
801 }
802 
807 static uint16_t
808 random_id(void)
809 {
810  return ldns_get_random();
811 }
812 
817 void
819 {
820  uint16_t qid = 0;
821  ods_log_assert(buffer);
822  qid = random_id();
823  buffer_write_u16_at(buffer, 0, qid);
824  return;
825 }
826 
827 
832 uint16_t
834 {
835  ods_log_assert(buffer);
836  return (uint16_t) buffer_read_u16_at(buffer, 2);
837 }
838 
839 
844 void
845 buffer_pkt_set_flags(buffer_type* buffer, uint16_t flags)
846 {
847  ods_log_assert(buffer);
848  buffer_write_u16_at(buffer, 2, flags);
849  return;
850 }
851 
852 
857 int
859 {
860  ods_log_assert(buffer);
861  return (int) QR(buffer);
862 }
863 
864 
869 void
871 {
872  ods_log_assert(buffer);
873  QR_SET(buffer);
874  return;
875 }
876 
877 
882 void
884 {
885  ods_log_assert(buffer);
886  QR_CLR(buffer);
887  return;
888 }
889 
890 
895 ldns_pkt_opcode
897 {
898  ods_log_assert(buffer);
899  return (ldns_pkt_opcode) OPCODE(buffer);
900 }
901 
902 
907 void
908 buffer_pkt_set_opcode(buffer_type* buffer, ldns_pkt_opcode opcode)
909 {
910  ods_log_assert(buffer);
911  OPCODE_SET(buffer, opcode);
912  return;
913 }
914 
915 
920 int
922 {
923  ods_log_assert(buffer);
924  return (int) AA(buffer);
925 }
926 
927 
932 void
934 {
935  ods_log_assert(buffer);
936  AA_SET(buffer);
937  return;
938 }
939 
940 
945 int
947 {
948  ods_log_assert(buffer);
949  return (int) TC(buffer);
950 }
951 
952 
957 int
959 {
960  ods_log_assert(buffer);
961  return (int) RD(buffer);
962 }
963 
964 
969 int
971 {
972  ods_log_assert(buffer);
973  return (int) RA(buffer);
974 }
975 
976 
981 int
983 {
984  ods_log_assert(buffer);
985  return (int) AD(buffer);
986 }
987 
988 
993 int
995 {
996  ods_log_assert(buffer);
997  return (int) CD(buffer);
998 }
999 
1000 
1005 ldns_pkt_rcode
1007 {
1008  ods_log_assert(buffer);
1009  return (ldns_pkt_rcode) RCODE(buffer);
1010 }
1011 
1012 
1017 void
1018 buffer_pkt_set_rcode(buffer_type* buffer, ldns_pkt_rcode rcode)
1019 {
1020  ods_log_assert(buffer);
1021  RCODE_SET(buffer, rcode);
1022  return;
1023 }
1024 
1025 
1030 uint16_t
1032 {
1033  ods_log_assert(buffer);
1034  return buffer_read_u16_at(buffer, 4);
1035 }
1036 
1037 
1042 void
1043 buffer_pkt_set_qdcount(buffer_type* buffer, uint16_t count)
1044 {
1045  ods_log_assert(buffer);
1046  buffer_write_u16_at(buffer, 4, count);
1047  return;
1048 }
1049 
1050 
1055 uint16_t
1057 {
1058  ods_log_assert(buffer);
1059  return buffer_read_u16_at(buffer, 6);
1060 }
1061 
1062 
1067 void
1068 buffer_pkt_set_ancount(buffer_type* buffer, uint16_t count)
1069 {
1070  ods_log_assert(buffer);
1071  buffer_write_u16_at(buffer, 6, count);
1072  return;
1073 }
1074 
1075 
1080 uint16_t
1082 {
1083  ods_log_assert(buffer);
1084  return buffer_read_u16_at(buffer, 8);
1085 }
1086 
1087 
1092 void
1093 buffer_pkt_set_nscount(buffer_type* buffer, uint16_t count)
1094 {
1095  ods_log_assert(buffer);
1096  buffer_write_u16_at(buffer, 8, count);
1097  return;
1098 }
1099 
1100 
1105 uint16_t
1107 {
1108  ods_log_assert(buffer);
1109  return buffer_read_u16_at(buffer, 10);
1110 }
1111 
1112 
1117 void
1118 buffer_pkt_set_arcount(buffer_type* buffer, uint16_t count)
1119 {
1120  ods_log_assert(buffer);
1121  buffer_write_u16_at(buffer, 10, count);
1122  return;
1123 }
1124 
1125 
1130 static void
1131 buffer_pkt_new(buffer_type* buffer, ldns_rdf* qname, ldns_rr_type qtype,
1132  ldns_rr_class qclass, ldns_pkt_opcode opcode)
1133 {
1134  ods_log_assert(buffer);
1135  ods_log_assert(qname);
1136  ods_log_assert(qtype);
1137  ods_log_assert(qclass);
1138  /* The header */
1139  buffer_clear(buffer);
1140  buffer_pkt_set_random_id(buffer);
1141  buffer_pkt_set_opcode(buffer, opcode);
1142  buffer_pkt_clear_qr(buffer);
1143  buffer_pkt_set_rcode(buffer, LDNS_RCODE_NOERROR);
1144  buffer_pkt_set_qdcount(buffer, 1);
1145  buffer_pkt_set_ancount(buffer, 0);
1146  buffer_pkt_set_nscount(buffer, 0);
1147  buffer_pkt_set_arcount(buffer, 0);
1149  /* The question record */
1150  buffer_write_rdf(buffer, qname);
1151  buffer_write_u16(buffer, qtype);
1152  buffer_write_u16(buffer, qclass);
1153  return;
1154 }
1155 
1156 
1161 void
1162 buffer_pkt_query(buffer_type* buffer, ldns_rdf* qname, ldns_rr_type qtype,
1163  ldns_rr_class qclass)
1164 {
1165  buffer_pkt_new(buffer, qname, qtype, qclass, LDNS_PACKET_QUERY);
1166  buffer_pkt_set_flags(buffer, 0);
1167  return;
1168 }
1169 
1170 
1175 void
1176 buffer_pkt_notify(buffer_type* buffer, ldns_rdf* qname, ldns_rr_class qclass)
1177 {
1178  buffer_pkt_new(buffer, qname, LDNS_RR_TYPE_SOA, qclass,
1179  LDNS_PACKET_NOTIFY);
1180  return;
1181 }
1182 
1183 
1188 void
1189 buffer_pkt_axfr(buffer_type* buffer, ldns_rdf* qname, ldns_rr_class qclass)
1190 {
1191  buffer_pkt_new(buffer, qname, LDNS_RR_TYPE_AXFR, qclass,
1192  LDNS_PACKET_QUERY);
1193  buffer_pkt_set_qr(buffer);
1194  return;
1195 }
1196 
1197 
1202 void
1203 buffer_pkt_print(FILE* fd, buffer_type* buffer)
1204 {
1205  ldns_status status = LDNS_STATUS_OK;
1206  ldns_pkt* pkt = NULL;
1207  ods_log_assert(fd);
1208  ods_log_assert(buffer);
1209  status = ldns_wire2pkt(&pkt, buffer_begin(buffer),
1210  buffer_remaining(buffer));
1211  if (status == LDNS_STATUS_OK) {
1212  ods_log_assert(pkt);
1213  ldns_pkt_print(fd, pkt);
1214  ldns_pkt_free(pkt);
1215  } else {
1216  fprintf(fd, ";;\n");
1217  fprintf(fd, ";; Bogus packet: %s\n", ldns_get_errorstr_by_id(status));
1218  fprintf(fd, ";;\n");
1219  fprintf(fd, ";;\n");
1220  fprintf(fd, "\n");
1221  }
1222  return;
1223 }
1224 
1225 
1230 void
1232 {
1233  if (!buffer || !allocator) {
1234  return;
1235  }
1236  free((void*)buffer->data);
1237  allocator_deallocate(allocator, (void*) buffer);
1238  return;
1239 }
1240 
1241