ISC DHCP  4.4.3-P1
A reference DHCPv4 and DHCPv6 implementation
data.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2017-2022 Internet Systems Consortium, Inc. ("ISC")
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
14  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  *
16  * Internet Systems Consortium, Inc.
17  * PO Box 360
18  * Newmarket, NH 03857 USA
19  * <info@isc.org>
20  * http://www.isc.org/
21  */
22 
23 #include "data.h"
24 
25 #include <sys/types.h>
26 #include <arpa/inet.h>
27 #include <assert.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 struct string *
33 {
34  struct string *result;
35 
36  result = (struct string *)malloc(sizeof(struct string));
37  assert(result != NULL);
38  memset(result, 0, sizeof(struct string));
39 
40  return result;
41 }
42 
43 struct string *
44 makeString(int l, const char *s)
45 {
46  struct string *result;
47 
48  result = allocString();
49  if (l < 0)
50  result->length = strlen(s);
51  else
52  result->length = (size_t)l;
53  if (result->length > 0) {
54  result->content = (char *)malloc(result->length + 1);
55  assert(result->content != NULL);
56  memcpy(result->content, s, result->length);
57  result->content[result->length] = 0;
58  }
59 
60  return result;
61 }
62 
63 struct string *
64 makeStringExt(int l, const char *s, char fmt)
65 {
66  switch (fmt) {
67  case 'Z':
68  /* zero-length */
69  return allocString();
70 
71  case 'l': {
72  /* 32-bit signed integer */
73  int32_t x;
74  char buf[40];
75 
76  assert(s != NULL);
77  assert(l > 3);
78 
79  memcpy(&x, s, 4);
80  x = (int32_t)ntohl((uint32_t)x);
81  snprintf(buf, sizeof(buf), "%lld", (long long)x);
82  return makeString(-1, buf);
83  }
84 
85  case 'L': {
86  /* 32-bit unsigned integer */
87  uint32_t x;
88  char buf[40];
89 
90  assert(s != NULL);
91  assert(l > 3);
92 
93  memcpy(&x, s, 4);
94  x = ntohl(x);
95  snprintf(buf, sizeof(buf), "%llu", (unsigned long long)x);
96  return makeString(-1, buf);
97  }
98 
99  case 's': {
100  /* 16-bit signed integer */
101  int16_t x;
102  char buf[20];
103 
104  assert(s != NULL);
105  assert(l > 1);
106 
107  memcpy(&x, s, 2);
108  x = (int16_t)ntohs((uint16_t)x);
109  snprintf(buf, sizeof(buf), "%hd", x);
110  return makeString(-1, buf);
111  }
112 
113  case 'S': {
114  /* 16-bit unsigned integer */
115  uint16_t x;
116  char buf[20];
117 
118  assert(s != NULL);
119  assert(l > 1);
120 
121  memcpy(&x, s, 2);
122  x = ntohs(x);
123  snprintf(buf, sizeof(buf), "%hu", x);
124  return makeString(-1, buf);
125  }
126 
127  case 'b': {
128  /* 8-bit signed integer */
129  int8_t x;
130  char buf[10];
131 
132  assert(s != NULL);
133  assert(l > 0);
134 
135  memcpy(&x, s, 1);
136  snprintf(buf, sizeof(buf), "%hhd", x);
137  return makeString(-1, buf);
138  }
139 
140  case 'B': {
141  /* 8-bit unsigned integer */
142  uint8_t x;
143  char buf[10];
144 
145  assert(s != NULL);
146  assert(l > 0);
147 
148  memcpy(&x, s, 1);
149  snprintf(buf, sizeof(buf), "%hhu", x);
150  return makeString(-1, buf);
151  }
152 
153  case 'f': {
154  /* flag (true or false) */
155  uint8_t f;
156 
157  assert(s != NULL);
158  assert(l > 0);
159 
160  f = *s;
161  return makeString(-1, f ? "true" : "false");
162  }
163 
164  case 'X': {
165  /* binary data */
166  struct string *result;
167  size_t i;
168  char buf[4];
169 
170  assert((l == 0) || (s != NULL));
171 
172  result = allocString();
173  for (i = 0; i < l; i++) {
174  snprintf(buf, sizeof(buf), "%02hhx", (uint8_t)s[i]);
175  appendString(result, buf);
176  }
177  return result;
178  }
179 
180  case 'H': {
181  /* binary data with colons */
182  struct string *result;
183  size_t i;
184  isc_boolean_t first = ISC_TRUE;
185  char buf[4];
186 
187  assert((l == 0) || (s != NULL));
188 
189  result = allocString();
190  for (i = 0; i < l; i++) {
191  if (!first)
192  appendString(result, ":");
193  first = ISC_FALSE;
194  snprintf(buf, sizeof(buf), "%02hhx", (uint8_t)s[i]);
195  appendString(result, buf);
196  }
197  return result;
198  }
199 
200  case 'I': {
201  /* IPv4 address to text */
202  char buf[40 /* INET_ADDRSTRLEN == 26 */];
203 
204  assert(l > 3);
205  assert(inet_ntop(AF_INET, s, buf, sizeof(buf)) != NULL);
206  return makeString(-1, buf);
207  }
208 
209  case 'i': {
210  /* IPv4 address to hexa */
211  uint8_t a[4];
212  char buf[10];
213 
214  assert(inet_pton(AF_INET, s, a) == 1);
215  snprintf(buf, sizeof(buf), "%02hhx%02hhx%02hhx%02hhx",
216  a[0], a[1], a[2], a[3]);
217  return makeString(-1, buf);
218  }
219 
220  case '6': {
221  /* IPv6 address */
222  char buf[80 /* INET6_ADDRSTRLEN == 46 */];
223 
224  assert(l > 15);
225  assert(inet_ntop(AF_INET6, s, buf, sizeof(buf)) != NULL);
226  return makeString(-1, buf);
227  }
228 
229  case 'd': {
230  /* FQDN to DNS wire format */
231  struct string *result;
232  const char *p;
233  const char *dot;
234  char ll;
235 
236  assert(s[l] == '0');
237 
238  result = allocString();
239  p = s;
240  while ((dot = strchr(p, '.')) != NULL) {
241  int len;
242 
243  len = dot - p - 1;
244  if ((len & 0xc0) != 0)
245  return NULL;
246  if (dot - s >= l)
247  return NULL;
248  ll = len & 0x3f;
249  concatString(result, makeString(1, &ll));
250  concatString(result, makeString(len, p));
251  p = dot + 1;
252  if (p - s == l)
253  break;
254  }
255  if (dot == NULL) {
256  ll = 0;
257  concatString(result, makeString(1, &ll));
258  }
259  return result;
260  }
261 
262  default:
263  assert(0);
264  }
265 }
266 
267 struct string *
268 makeStringArray(int l, const char *s, char fmt)
269 {
270  struct string *result;
271  size_t step;
272  isc_boolean_t first = ISC_TRUE;
273 
274  switch (fmt) {
275  case '6':
276  step = 16;
277  break;
278  case 'l':
279  case 'L':
280  case 'I':
281  step = 4;
282  break;
283  case 's':
284  case 'S':
285  step = 2;
286  break;
287  case 'b':
288  case 'B':
289  case 'f':
290  step = 1;
291  break;
292  default:
293  assert(0);
294  }
295 
296  assert((l % step) == 0);
297 
298  result = allocString();
299  while (l > 0) {
300  if (!first)
301  appendString(result, ",");
302  first = ISC_FALSE;
303  concatString(result, makeStringExt(l, s, fmt));
304  s += step;
305  l -= step;
306  }
307  return result;
308 }
309 
310 void
311 appendString(struct string *s, const char *a)
312 {
313  size_t n;
314 
315  assert(s != NULL);
316 
317  if (a == NULL)
318  return;
319  n = strlen(a);
320  if (n == 0)
321  return;
322  s->content = (char *)realloc(s->content, s->length + n + 1);
323  assert(s->content != NULL);
324  memcpy(s->content + s->length, a, n);
325  s->length += n;
326  s->content[s->length] = 0;
327 }
328 
329 void
330 concatString(struct string *s, const struct string *a)
331 {
332  assert(s != NULL);
333  assert(a != NULL);
334 
335  s->content = (char *)realloc(s->content, s->length + a->length + 1);
336  assert(s->content != NULL);
337  memcpy(s->content + s->length, a->content, a->length);
338  s->length += a->length;
339  s->content[s->length] = 0;
340 }
341 
343 eqString(const struct string *s, const struct string *o)
344 {
345  assert(s != NULL);
346  assert(o != NULL);
347 
348  if (s->length != o->length)
349  return ISC_FALSE;
350  if (s->length == 0)
351  return ISC_TRUE;
352  return ISC_TF(memcmp(s->content, o->content, s->length) == 0);
353 }
354 
355 struct string *
356 quote(struct string *s)
357 {
358  struct string *result;
359 
360  result = makeString(-1, "'");
361  concatString(result, s);
362  appendString(result, "'");
363  return result;
364 }
365 
366 struct comment *
367 createComment(const char *line)
368 {
369  struct comment *comment;
370 
371  assert(line != NULL);
372 
373  comment = (struct comment *)malloc(sizeof(struct comment));
374  assert(comment != NULL);
375  memset(comment, 0, sizeof(struct comment));
376 
377  comment->line = strdup(line);
378 
379  return comment;
380 }
381 
382 int64_t
383 intValue(const struct element *e)
384 {
385  assert(e != NULL);
386  assert(e->type == ELEMENT_INTEGER);
387  return e->value.int_value;
388 }
389 
390 double
391 doubleValue(const struct element *e)
392 {
393  assert(e != NULL);
394  assert(e->type == ELEMENT_REAL);
395  return e->value.double_value;
396 }
397 
399 boolValue(const struct element *e)
400 {
401  assert(e != NULL);
402  assert(e->type == ELEMENT_BOOLEAN);
403  /* could check if 0 or 1 */
404  return e->value.bool_value;
405 }
406 
407 struct string *
409 {
410  assert(e != NULL);
411  assert(e->type == ELEMENT_STRING);
412  return &e->value.string_value;
413 }
414 
415 struct list *
416 listValue(struct element *e)
417 {
418  assert(e != NULL);
419  assert(e->type == ELEMENT_LIST);
420  return &e->value.list_value;
421 }
422 
423 struct map *
424 mapValue(struct element *e)
425 {
426  assert(e != NULL);
427  assert(e->type == ELEMENT_MAP);
428  return &e->value.map_value;
429 }
430 
431 struct element *
432 create(void)
433 {
434  struct element *elem;
435 
436  elem = (struct element *)malloc(sizeof(struct element));
437  assert(elem != NULL);
438  memset(elem, 0, sizeof(struct element));
439  TAILQ_INIT(&elem->comments);
440 
441  return elem;
442 }
443 
444 struct element *
445 createInt(int64_t i)
446 {
447  struct element *elem;
448 
449  elem = create();
450  elem->type = ELEMENT_INTEGER;
451  elem->value.int_value = i;
452 
453  return elem;
454 }
455 
456 struct element *
457 createDouble(double d)
458 {
459  struct element *elem;
460 
461  elem = create();
462  elem->type = ELEMENT_REAL;
463  elem->value.double_value = d;
464 
465  return elem;
466 }
467 
468 struct element *
470 {
471  struct element *elem;
472 
473  elem = create();
474  elem->type = ELEMENT_BOOLEAN;
475  elem->value.bool_value = b;
476 
477  return elem;
478 }
479 
480 struct element *
482 {
483  struct element *elem;
484 
485  elem = create();
486  elem->type = ELEMENT_NULL;
487 
488  return elem;
489 }
490 
491 struct element *
492 createString(const struct string *s)
493 {
494  struct element *elem;
495 
496  elem = create();
497  elem->type = ELEMENT_STRING;
498  elem->value.string_value = *s;
499 
500  return elem;
501 }
502 
503 struct element *
505 {
506  struct element *elem;
507 
508  elem = create();
509  elem->type = ELEMENT_LIST;
510  TAILQ_INIT(&elem->value.list_value);
511 
512  return elem;
513 }
514 
515 struct element *
517 {
518  struct element *elem;
519 
520  elem = create();
521  elem->type = ELEMENT_MAP;
522  TAILQ_INIT(&elem->value.map_value);
523 
524  return elem;
525 }
526 
527 static void
528 reset(struct element *e)
529 {
530  e->type = 0;
531  e->kind = 0;
532  assert(e->key == NULL);
533  memset(&e->value, 0, sizeof(e->value));
534 }
535 
536 void
537 resetInt(struct element *e, int64_t i)
538 {
539  assert(e != NULL);
540 
541  reset(e);
542  e->type = ELEMENT_INTEGER;
543  e->value.int_value = i;
544 }
545 
546 void
547 resetDouble(struct element *e, double d)
548 {
549  assert(e != NULL);
550 
551  reset(e);
552  e->type = ELEMENT_REAL;
553  e->value.double_value = d;
554 }
555 
556 void
558 {
559  assert(e != NULL);
560 
561  reset(e);
562  e->type = ELEMENT_BOOLEAN;
563  e->value.bool_value = b;
564 }
565 
566 void resetNull(struct element *e)
567 {
568  assert(e != NULL);
569 
570  reset(e);
571  e->type = ELEMENT_NULL;
572 }
573 
574 void
575 resetString(struct element *e, const struct string *s)
576 {
577  assert(e != NULL);
578 
579  reset(e);
580  e->type = ELEMENT_STRING;
581  e->value.string_value = *s;
582 }
583 
584 void
585 resetList(struct element *e)
586 {
587  assert(e != NULL);
588 
589  reset(e);
590  e->type = ELEMENT_LIST;
592 }
593 
594 void
595 resetMap(struct element *e)
596 {
597  assert(e != NULL);
598 
599  reset(e);
600  e->type = ELEMENT_MAP;
602 }
603 
604 void
605 resetBy(struct element *e, struct element *o)
606 {
607  assert(e != NULL);
608  assert(o != NULL);
609 
610  reset(e);
611  e->type = o->type;
612  e->kind = o->kind;
613  e->skip = o->skip;
614  e->key = o->key;
615  o->key = NULL;
616  TAILQ_CONCAT(&e->comments, &o->comments);
617 
618  switch (e->type) {
619  case ELEMENT_INTEGER:
620  e->value.int_value = o->value.int_value;
621  break;
622  case ELEMENT_REAL:
624  break;
625  case ELEMENT_BOOLEAN:
627  break;
628  case ELEMENT_STRING:
630  break;
631  case ELEMENT_LIST:
634  break;
635  case ELEMENT_MAP:
638  break;
639  default:
640  assert(0);
641  }
642  reset(o);
643 }
644 
645 struct element *
646 listGet(struct element *l, int i)
647 {
648  struct element *elem;
649 
650  assert(l != NULL);
651  assert(l->type == ELEMENT_LIST);
652  assert(i >= 0);
653 
654  elem = TAILQ_FIRST(&l->value.list_value);
655  assert(elem != NULL);
656  assert(elem->key == NULL);
657 
658  unsigned j;
659  for (j = i; j > 0; --j) {
660  elem = TAILQ_NEXT(elem);
661  assert(elem != NULL);
662  assert(elem->key == NULL);
663  }
664 
665  return elem;
666 }
667 
668 void
669 listSet(struct element *l, struct element *e, int i)
670 {
671  assert(l != NULL);
672  assert(l->type == ELEMENT_LIST);
673  assert(e != NULL);
674  assert(i >= 0);
675 
676  if (i == 0) {
678  } else {
679  struct element *prev;
680 
681  prev = TAILQ_FIRST(&l->value.list_value);
682  assert(prev != NULL);
683  assert(prev->key == NULL);
684 
685  unsigned j;
686  for (j = i; j > 1; --j) {
687  prev = TAILQ_NEXT(prev);
688  assert(prev != NULL);
689  assert(prev->key == NULL);
690  }
691 
692  TAILQ_INSERT_AFTER(&l->value.list_value, prev, e);
693  }
694 }
695 
696 void
697 listPush(struct element *l, struct element *e)
698 {
699  assert(l != NULL);
700  assert(l->type == ELEMENT_LIST);
701  assert(e != NULL);
702 
704 }
705 
706 void
707 listRemove(struct element *l, int i)
708 {
709  struct element *elem;
710 
711  assert(l != NULL);
712  assert(l->type == ELEMENT_LIST);
713  assert(i >= 0);
714 
715  elem = TAILQ_FIRST(&l->value.list_value);
716  assert(elem != NULL);
717  assert(elem->key == NULL);
718 
719  unsigned j;
720  for (j = i; j > 0; --j) {
721  elem = TAILQ_NEXT(elem);
722  assert(elem != NULL);
723  assert(elem->key == NULL);
724  }
725 
726  TAILQ_REMOVE(&l->value.list_value, elem);
727 }
728 
729 size_t
730 listSize(const struct element *l)
731 {
732  struct element *elem;
733  size_t cnt;
734 
735  assert(l != NULL);
736  assert(l->type == ELEMENT_LIST);
737 
738  cnt = 0;
739  TAILQ_FOREACH(elem, &l->value.list_value) {
740  assert(elem->key == NULL);
741  cnt++;
742  }
743 
744  return cnt;
745 }
746 
747 void
748 concat(struct element *l, struct element *o)
749 {
750  assert(l != NULL);
751  assert(l->type == ELEMENT_LIST);
752  assert(o != NULL);
753  assert(o->type == ELEMENT_LIST);
754 
756 }
757 
758 struct element *
759 mapGet(struct element *m, const char *k)
760 {
761  struct element *elem;
762 
763  assert(m != NULL);
764  assert(m->type == ELEMENT_MAP);
765  assert(k != NULL);
766 
767  TAILQ_FOREACH(elem, &m->value.map_value) {
768  assert(elem->key != NULL);
769  if (strcmp(elem->key, k) == 0)
770  break;
771  }
772 
773  return elem;
774 }
775 
776 void
777 mapSet(struct element *m, struct element *e, const char *k)
778 {
779  assert(m != NULL);
780  assert(m->type == ELEMENT_MAP);
781  assert(e != NULL);
782  assert(k != NULL);
783 #if 0
784  assert(mapGet(m, k) == NULL);
785 #endif
786  e->key = strdup(k);
787  assert(e->key != NULL);
789 }
790 
791 void
792 mapRemove(struct element *m, const char *k)
793 {
794  struct element *elem;
795 
796  assert(m != NULL);
797  assert(m->type == ELEMENT_MAP);
798  assert(k != NULL);
799 
800  TAILQ_FOREACH(elem, &m->value.map_value) {
801  assert(elem->key != NULL);
802  if (strcmp(elem->key, k) == 0)
803  break;
804  }
805 
806  assert(elem != NULL);
807  TAILQ_REMOVE(&m->value.map_value, elem);
808 }
809 
811 mapContains(const struct element *m, const char *k)
812 {
813  struct element *elem;
814 
815  assert(m != NULL);
816  assert(m->type == ELEMENT_MAP);
817  assert(k != NULL);
818 
819  TAILQ_FOREACH(elem, &m->value.map_value) {
820  assert(elem->key != NULL);
821  if (strcmp(elem->key, k) == 0)
822  break;
823  }
824 
825  return ISC_TF(elem != NULL);
826 }
827 
828 size_t
829 mapSize(const struct element *m)
830 {
831  struct element *elem;
832  size_t cnt;
833 
834  assert(m != NULL);
835  assert(m->type == ELEMENT_MAP);
836 
837  cnt = 0;
838  TAILQ_FOREACH(elem, &m->value.map_value) {
839  assert(elem->key != NULL);
840  cnt++;
841  }
842 
843  return cnt;
844 }
845 
846 void
847 merge(struct element *m, struct element *o)
848 {
849  struct element *elem;
850  struct element *ne;
851 
852  assert(m != NULL);
853  assert(m->type == ELEMENT_MAP);
854  assert(o != NULL);
855  assert(o->type == ELEMENT_MAP);
856 
857  TAILQ_FOREACH_SAFE(elem, &o->value.map_value, ne) {
858  assert(elem->key != NULL);
859  TAILQ_REMOVE(&o->value.map_value, elem);
860  if (!mapContains(m, elem->key)) {
861  TAILQ_INSERT_TAIL(&m->value.map_value, elem);
862  }
863  }
864 }
865 
866 const char *
867 type2name(int t)
868 {
869  switch (t) {
870  case ELEMENT_NONE:
871  return "not initialized?";
872  case ELEMENT_INTEGER:
873  return "integer";
874  case ELEMENT_REAL:
875  return "real";
876  case ELEMENT_BOOLEAN:
877  return "boolean";
878  case ELEMENT_NULL:
879  return "(unused) null";
880  case ELEMENT_STRING:
881  return "string";
882  case ELEMENT_LIST:
883  return "list";
884  case ELEMENT_MAP:
885  return "map";
886  default:
887 #if 0
888  assert(0);
889 #endif
890  return "unknown?";
891  }
892 }
893 
894 int
895 name2type(const char *n)
896 {
897  assert(n != NULL);
898  if (strcmp(n, "integer") == 0)
899  return ELEMENT_INTEGER;
900  if (strcmp(n, "real") == 0)
901  return ELEMENT_REAL;
902  if (strcmp(n, "boolean") == 0)
903  return ELEMENT_BOOLEAN;
904  if (strcmp(n, "null") == 0)
905  return ELEMENT_NULL;
906  if (strcmp(n, "string") == 0)
907  return ELEMENT_STRING;
908  if (strcmp(n, "list") == 0)
909  return ELEMENT_LIST;
910  if (strcmp(n, "map") == 0)
911  return ELEMENT_MAP;
912 #if 0
913  assert(0);
914 #endif
915  return ELEMENT_NONE;
916 }
917 
918 void
919 print(FILE *fp, const struct element *e, isc_boolean_t skip, unsigned indent)
920 {
921  assert(fp != NULL);
922  assert(e != NULL);
923 
924  switch (e->type) {
925  case ELEMENT_LIST:
926  printList(fp, &e->value.list_value, skip, indent);
927  return;
928  case ELEMENT_MAP:
929  printMap(fp, &e->value.map_value, skip, indent);
930  return;
931  case ELEMENT_STRING:
932  printString(fp, &e->value.string_value);
933  return;
934  case ELEMENT_INTEGER:
935  fprintf(fp, "%lld", (long long)e->value.int_value);
936  return;
937  case ELEMENT_REAL:
938  fprintf(fp, "%f", e->value.double_value);
939  return;
940  case ELEMENT_BOOLEAN:
941  if (e->value.bool_value)
942  fprintf(fp, "true");
943  else
944  fprintf(fp, "false");
945  return;
946  case ELEMENT_NULL:
947  fprintf(fp, "null");
948  return;
949  default:
950  assert(0);
951  }
952 }
953 
954 static void
955 addIndent(FILE *fp, int skip, unsigned indent)
956 {
957  unsigned sp;
958 
959  if (skip) {
960  fprintf(fp, "//");
961  if (indent > 2)
962  for (sp = 0; sp < indent - 2; ++sp)
963  fprintf(fp, " ");
964  } else
965  for (sp = 0; sp < indent; ++sp)
966  fprintf(fp, " ");
967 }
968 
969 void
970 printList(FILE *fp, const struct list *l, isc_boolean_t skip, unsigned indent)
971 {
972  struct element *elem;
973  struct comment *comment;
974  isc_boolean_t first;
975 
976  assert(fp != NULL);
977  assert(l != NULL);
978 
979  if (TAILQ_EMPTY(l)) {
980  fprintf(fp, "[ ]");
981  return;
982  }
983 
984  fprintf(fp, "[\n");
985  first = ISC_TRUE;
986  TAILQ_FOREACH(elem, l) {
987  isc_boolean_t skip_elem = skip;
988 
989  assert(elem->key == NULL);
990  if (!skip) {
991  skip_elem = elem->skip;
992  if (skip_to_end(elem)) {
993  if (!first)
994  fprintf(fp, "\n");
995  first = ISC_TRUE;
996  }
997  }
998  if (!first)
999  fprintf(fp, ",\n");
1000  first = ISC_FALSE;
1001  TAILQ_FOREACH(comment, &elem->comments) {
1002  addIndent(fp, skip_elem, indent + 2);
1003  fprintf(fp, "%s\n", comment->line);
1004  }
1005  addIndent(fp, skip_elem, indent + 2);
1006  print(fp, elem, skip_elem, indent + 2);
1007  }
1008  fprintf(fp, "\n");
1009  addIndent(fp, skip, indent);
1010  fprintf(fp, "]");
1011 }
1012 
1013 void
1014 printMap(FILE *fp, const struct map *m, isc_boolean_t skip, unsigned indent)
1015 {
1016  struct element *elem;
1017  struct comment *comment;
1018  isc_boolean_t first;
1019 
1020  assert(fp != NULL);
1021  assert(m != NULL);
1022 
1023  if (TAILQ_EMPTY(m)) {
1024  fprintf(fp, "{ }");
1025  return;
1026  }
1027 
1028  fprintf(fp, "{\n");
1029  first = ISC_TRUE;
1030  TAILQ_FOREACH(elem, m) {
1031  isc_boolean_t skip_elem = skip;
1032 
1033  assert(elem->key != NULL);
1034  if (!skip) {
1035  skip_elem = elem->skip;
1036  if (skip_to_end(elem)) {
1037  if (!first)
1038  fprintf(fp, "\n");
1039  first = ISC_TRUE;
1040  }
1041  }
1042  if (!first)
1043  fprintf(fp, ",\n");
1044  first = ISC_FALSE;
1045  TAILQ_FOREACH(comment, &elem->comments) {
1046  addIndent(fp, skip_elem, indent + 2);
1047  fprintf(fp, "%s\n", comment->line);
1048  }
1049  addIndent(fp, skip_elem, indent + 2);
1050  fprintf(fp, "\"%s\": ", elem->key);
1051  print(fp, elem, skip_elem, indent + 2);
1052  }
1053  fprintf(fp, "\n");
1054  addIndent(fp, skip, indent);
1055  fprintf(fp, "}");
1056 }
1057 
1058 void
1059 printString(FILE *fp, const struct string *s)
1060 {
1061  size_t i;
1062 
1063  assert(fp != NULL);
1064  assert(s != NULL);
1065 
1066  fprintf(fp, "\"");
1067  for (i = 0; i < s->length; i++) {
1068  char c = *(s->content + i);
1069 
1070  switch (c) {
1071  case '"':
1072  fprintf(fp, "\\\"");
1073  break;
1074  case '\\':
1075  fprintf(fp, "\\\\");
1076  break;
1077  case '\b':
1078  fprintf(fp, "\\b");
1079  break;
1080  case '\f':
1081  fprintf(fp, "\\f");
1082  break;
1083  case '\n':
1084  fprintf(fp, "\\n");
1085  break;
1086  case '\r':
1087  fprintf(fp, "\\r");
1088  break;
1089  case '\t':
1090  fprintf(fp, "\\t");
1091  break;
1092  default:
1093  if ((c >= 0) && (c < 0x20)) {
1094  fprintf(fp, "\\u%04x", (unsigned)c & 0xff);
1095  } else {
1096  fprintf(fp, "%c", c);
1097  }
1098  }
1099  }
1100  fprintf(fp, "\"");
1101 }
1102 
1104 skip_to_end(const struct element *e)
1105 {
1106  do {
1107  if (!e->skip)
1108  return ISC_FALSE;
1109  e = TAILQ_NEXT(e);
1110  } while (e != NULL);
1111  return ISC_TRUE;
1112 }
1113 
1114 struct element *
1115 copy(struct element *e)
1116 {
1117  struct element *result;
1118  struct comment *comment;
1119 
1120  assert(e != NULL);
1121 
1122  switch (e->type) {
1123  case ELEMENT_INTEGER:
1124  result = createInt(intValue(e));
1125  break;
1126  case ELEMENT_REAL:
1127  result = createDouble(doubleValue(e));
1128  break;
1129  case ELEMENT_BOOLEAN:
1130  result = createBool(boolValue(e));
1131  break;
1132  case ELEMENT_NULL:
1133  result = createNull();
1134  break;
1135  case ELEMENT_STRING:
1136  result = createString(stringValue(e));
1137  break;
1138  case ELEMENT_LIST:
1139  result = copyList(e);
1140  break;
1141  case ELEMENT_MAP:
1142  result = copyMap(e);
1143  break;
1144  default:
1145  assert(0);
1146  }
1147  result->kind = e->kind;
1148  result->skip = e->skip;
1149  /* don't copy key */
1150  /* copy comments */
1152  /* do not reuse comment variable! */
1153  struct comment *tmp;
1154 
1155  tmp = createComment(comment->line);
1156  TAILQ_INSERT_TAIL(&result->comments, tmp);
1157  }
1158  return result;
1159 }
1160 
1161 struct element *
1162 copyList(struct element *l)
1163 {
1164  struct element *result;
1165  size_t i;
1166 
1167  result = createList();
1168  for (i = 0; i < listSize(l); i++)
1169  listPush(result, copy(listGet(l, i)));
1170  return result;
1171 }
1172 
1173 struct element *
1174 copyMap(struct element *m)
1175 {
1176  struct element *result;
1177  struct element *item;
1178 
1179  result = createMap();
1180  TAILQ_FOREACH(item, &m->value.map_value)
1181  mapSet(result, copy(item), item->key);
1182  return result;
1183 }
1184 
1185 struct handle *
1186 mapPop(struct element *m)
1187 {
1188  struct element *item;
1189  struct handle *h;
1190 
1191  assert(m != NULL);
1192  assert(m->type == ELEMENT_MAP);
1193 
1194  h = (struct handle *)malloc(sizeof(struct handle));
1195  assert(h != NULL);
1196  memset(h, 0, sizeof(struct handle));
1197  TAILQ_INIT(&h->values);
1198 
1199  item = TAILQ_FIRST(&m->value.map_value);
1200  assert(item != NULL);
1201  assert(item->key != NULL);
1202  h->key = strdup(item->key);
1203  assert(h->key != NULL);
1204  h->value = item;
1205 
1206  TAILQ_REMOVE(&m->value.map_value, item);
1207 
1208  return h;
1209 }
1210 
1211 void
1212 derive(struct handle *src, struct handle *dst)
1213 {
1214  struct element *list;
1215  struct element *item;
1216  size_t i;
1217 
1218  if (dst == NULL)
1219  return;
1220  list = dst->value;
1221  assert(list != NULL);
1222  assert(list->type == ELEMENT_LIST);
1223  for (i = 0; i < listSize(list); i++) {
1224  item = listGet(list, i);
1225  assert(item != NULL);
1226  assert(item->type == ELEMENT_MAP);
1227  if (mapContains(item, src->key))
1228  continue;
1229  mapSet(item, copy(src->value), src->key);
1230  }
1231 }
1232 
1233 struct string *
1234 hexaValue(struct element *s)
1235 {
1236  struct string *h;
1237 
1238  assert(s != NULL);
1239  assert(s->type == ELEMENT_STRING);
1240 
1241  h = stringValue(s);
1242  assert(h->length >= 2);
1243 
1244  /* string leading 0x */
1245  return makeString(h->length - 2, h->content + 2);
1246 }
1247 
1248 struct element *
1249 createHexa(struct string *h)
1250 {
1251  struct string *s;
1252 
1253  assert(h != NULL);
1254 
1255  s = makeString(-1, "0x");
1256  concatString(s, h);
1257  return createString(s);
1258 }
#define ELEMENT_REAL
Definition: data.h:163
union value value
Definition: data.h:221
double double_value
Definition: data.h:207
const char int line
Definition: dhcpd.h:3802
struct element * createList(void)
Definition: data.c:504
#define ISC_FALSE
Definition: data.h:152
void resetBool(struct element *e, isc_boolean_t b)
Definition: data.c:557
isc_boolean_t boolValue(const struct element *e)
Definition: data.c:399
void printString(FILE *fp, const struct string *s)
Definition: data.c:1059
char * key
Definition: data.h:291
isc_boolean_t
Definition: data.h:150
isc_boolean_t bool_value
Definition: data.h:208
#define TAILQ_INIT(head)
Definition: data.h:72
void concatString(struct string *s, const struct string *a)
Definition: data.c:330
#define ELEMENT_NULL
Definition: data.h:165
struct handle * mapPop(struct element *m)
Definition: data.c:1186
size_t mapSize(const struct element *m)
Definition: data.c:829
struct list list_value
Definition: data.h:211
struct string * makeStringArray(int l, const char *s, char fmt)
Definition: data.c:268
struct element * createInt(int64_t i)
Definition: data.c:445
void resetString(struct element *e, const struct string *s)
Definition: data.c:575
struct element * createString(const struct string *s)
Definition: data.c:492
Definition: data.h:289
#define ISC_TF(x)
Definition: data.h:154
isc_boolean_t mapContains(const struct element *m, const char *k)
Definition: data.c:811
int64_t int_value
Definition: data.h:206
struct map map_value
Definition: data.h:212
void print(FILE *fp, const struct element *e, isc_boolean_t skip, unsigned indent)
Definition: data.c:919
struct comments comments
Definition: data.h:222
struct element * create(void)
Definition: data.c:432
void mapRemove(struct element *m, const char *k)
Definition: data.c:792
void listRemove(struct element *l, int i)
Definition: data.c:707
struct map * mapValue(struct element *e)
Definition: data.c:424
#define ELEMENT_NONE
Definition: data.h:161
struct element * createDouble(double d)
Definition: data.c:457
#define ISC_TRUE
Definition: data.h:153
void resetDouble(struct element *e, double d)
Definition: data.c:547
Definition: data.h:216
int kind
Definition: data.h:218
char * content
Definition: data.h:173
#define TAILQ_FOREACH_SAFE(var, head, tvar)
Definition: data.h:67
void resetMap(struct element *e)
Definition: data.c:595
void resetNull(struct element *e)
Definition: data.c:566
struct string * makeString(int l, const char *s)
Definition: data.c:44
void concat(struct element *l, struct element *o)
Definition: data.c:748
#define ELEMENT_LIST
Definition: data.h:167
void printList(FILE *fp, const struct list *l, isc_boolean_t skip, unsigned indent)
Definition: data.c:970
void resetList(struct element *e)
Definition: data.c:585
struct element * createHexa(struct string *h)
Definition: data.c:1249
struct element * copyMap(struct element *m)
Definition: data.c:1174
struct element * mapGet(struct element *m, const char *k)
Definition: data.c:759
void mapSet(struct element *m, struct element *e, const char *k)
Definition: data.c:777
#define TAILQ_INSERT_HEAD(head, elm)
Definition: data.h:95
struct handles values
Definition: data.h:293
#define TAILQ_FIRST(head)
Definition: data.h:60
void merge(struct element *m, struct element *o)
Definition: data.c:847
#define TAILQ_REMOVE(head, elm)
Definition: data.h:120
struct element * createBool(isc_boolean_t b)
Definition: data.c:469
struct element * value
Definition: data.h:292
struct string * allocString(void)
Definition: data.c:32
struct element * createNull(void)
Definition: data.c:481
Definition: data.h:190
#define TAILQ_INSERT_AFTER(head, listelm, elm)
Definition: data.h:77
void printMap(FILE *fp, const struct map *m, isc_boolean_t skip, unsigned indent)
Definition: data.c:1014
struct string string_value
Definition: data.h:210
#define ELEMENT_INTEGER
Definition: data.h:162
const char * type2name(int t)
Definition: data.c:867
struct string * hexaValue(struct element *s)
Definition: data.c:1234
struct string * stringValue(struct element *e)
Definition: data.c:408
#define TAILQ_INSERT_TAIL(head, elm)
Definition: data.h:105
#define ELEMENT_BOOLEAN
Definition: data.h:164
void derive(struct handle *src, struct handle *dst)
Definition: data.c:1212
isc_boolean_t eqString(const struct string *s, const struct string *o)
Definition: data.c:343
Definition: data.h:171
double doubleValue(const struct element *e)
Definition: data.c:391
struct element * createMap(void)
Definition: data.c:516
void indent(int)
#define TAILQ_CONCAT(head1, head2)
Definition: data.h:49
size_t listSize(const struct element *l)
Definition: data.c:730
#define TAILQ_NEXT(elm)
Definition: data.h:115
void appendString(struct string *s, const char *a)
Definition: data.c:311
void listPush(struct element *l, struct element *e)
Definition: data.c:697
int name2type(const char *n)
Definition: data.c:895
#define TAILQ_EMPTY(head)
Definition: data.h:58
char * line
Definition: data.h:191
int type
Definition: data.h:217
size_t length
Definition: data.h:172
#define ELEMENT_STRING
Definition: data.h:166
struct string * quote(struct string *s)
Definition: data.c:356
struct element * copy(struct element *e)
Definition: data.c:1115
struct string * makeStringExt(int l, const char *s, char fmt)
Definition: data.c:64
char * key
Definition: data.h:220
#define TAILQ_FOREACH(var, head)
Definition: data.h:62
void resetInt(struct element *e, int64_t i)
Definition: data.c:537
void listSet(struct element *l, struct element *e, int i)
Definition: data.c:669
struct list * listValue(struct element *e)
Definition: data.c:416
void resetBy(struct element *e, struct element *o)
Definition: data.c:605
struct element * copyList(struct element *l)
Definition: data.c:1162
isc_boolean_t skip_to_end(const struct element *e)
Definition: data.c:1104
int64_t intValue(const struct element *e)
Definition: data.c:383
struct element * listGet(struct element *l, int i)
Definition: data.c:646
isc_boolean_t skip
Definition: data.h:219
#define ELEMENT_MAP
Definition: data.h:168
struct comment * createComment(const char *line)
Definition: data.c:367