ISC DHCP 4.4.3-P1
A reference DHCPv4 and DHCPv6 implementation
 
Loading...
Searching...
No Matches
eval.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 * https://www.isc.org/
21 *
22 */
23
24#include "keama.h"
25
26#include <sys/errno.h>
27#include <sys/types.h>
28#include <arpa/inet.h>
29#include <ctype.h>
30#include <netdb.h>
31#include <stdarg.h>
32#include <stdio.h>
33#include <string.h>
34#include <unistd.h>
35
36static struct element *eval_equal_expression(struct element *,
37 struct element *);
38static isc_boolean_t cmp_hexa(struct element *, isc_boolean_t,
39 struct element *,isc_boolean_t);
40static void debug(const char* fmt, ...);
41
42struct element *
43eval_expression(struct element *expr, isc_boolean_t *modifiedp)
44{
45 if ((expr->type == ELEMENT_BOOLEAN) ||
46 (expr->type == ELEMENT_INTEGER) ||
47 (expr->type == ELEMENT_STRING))
48 return expr;
49
50 if (is_boolean_expression(expr))
51 return eval_boolean_expression(expr, modifiedp);
52 if (is_numeric_expression(expr))
53 return eval_numeric_expression(expr, modifiedp);
54 if (is_data_expression(expr))
55 return eval_data_expression(expr, modifiedp);
56 debug("can't type expression");
57 return expr;
58}
59
60/*
61 * boolean_expression :== CHECK STRING |
62 * NOT boolean-expression |
63 * data-expression EQUAL data-expression |
64 * data-expression BANG EQUAL data-expression |
65 * data-expression REGEX_MATCH data-expression |
66 * boolean-expression AND boolean-expression |
67 * boolean-expression OR boolean-expression
68 * EXISTS OPTION-NAME
69 */
70
71struct element *
73{
74 /* trivial case: already done */
75 if (expr->type == ELEMENT_BOOLEAN)
76 return expr;
77
78 /*
79 * From is_boolean_expression
80 */
81
82 if (expr->type != ELEMENT_MAP)
83 return expr;
84
85
86 /* check */
87 if (mapContains(expr, "check"))
88 /*
89 * syntax := { "check": <collection_name> }
90 * semantic: check_collection
91 * on server try to match classes of the collection
92 */
93 return expr;
94
95
96 /* exists */
97 if (mapContains(expr, "exists"))
98 /*
99 * syntax := { "exists":
100 * { "universe": <option_space_old>,
101 * "name": <option_name> }
102 * }
103 * semantic: check universe/code from incoming packet
104 */
105 return expr;
106
107 /* variable-exists */
108 if (mapContains(expr, "variable-exists"))
109 /*
110 * syntax := { "variable-exists": <variable_name> }
111 * semantics: find_binding(scope, name)
112 */
113 return expr;
114
115 /* equal */
116 if (mapContains(expr, "equal")) {
117 /*
118 * syntax := { "equal":
119 * { "left": <expression>,
120 * "right": <expression> }
121 * }
122 * semantics: evaluate branches and return true
123 * if same type and same value
124 */
125 struct element *arg;
126 struct element *left;
127 struct element *right;
128 struct element *equal;
129 struct comments comments;
130 isc_boolean_t lmodified = ISC_FALSE;
131 isc_boolean_t rmodified = ISC_FALSE;
132
133 arg = mapGet(expr, "equal");
134 if ((arg == NULL) || (arg->type != ELEMENT_MAP))
135 return expr;
136 left = mapGet(arg, "left");
137 if (left == NULL)
138 return expr;
139 right = mapGet(arg, "right");
140 if (right == NULL)
141 return expr;
142 left = eval_expression(left, &lmodified);
143 if (lmodified) {
144 mapRemove(arg, "left");
145 mapSet(arg, left, "left");
146 }
147 right = eval_expression(right, &rmodified);
148 if (rmodified) {
149 mapRemove(arg, "right");
150 mapSet(arg, right, "right");
151 }
152
153 equal = eval_equal_expression(left, right);
154 if ((equal == NULL) || (equal->type != ELEMENT_BOOLEAN))
155 return expr;
156 *modifiedp = ISC_TRUE;
157 TAILQ_INIT(&comments);
158 TAILQ_CONCAT(&comments, &expr->comments);
159 TAILQ_CONCAT(&comments, &arg->comments);
160 TAILQ_CONCAT(&comments, &equal->comments);
161 TAILQ_CONCAT(&equal->comments, &comments);
162 return equal;
163 }
164
165 /* not-equal */
166 if (mapContains(expr, "not-equal")) {
167 /*
168 * syntax := { "not-equal":
169 * { "left": <expression>,
170 * "right": <expression> }
171 * }
172 * semantics: evaluate branches and return true
173 * if different type or different value
174 */
175 struct element *arg;
176 struct element *left;
177 struct element *right;
178 struct element *equal;
179 struct element *result;
180 isc_boolean_t lmodified = ISC_FALSE;
181 isc_boolean_t rmodified = ISC_FALSE;
182
183 arg = mapGet(expr, "not-equal");
184 if ((arg == NULL) || (arg->type != ELEMENT_MAP))
185 return expr;
186 left = mapGet(arg, "left");
187 if (left == NULL)
188 return expr;
189 right = mapGet(arg, "right");
190 if (right == NULL)
191 return expr;
192 left = eval_expression(left, &lmodified);
193 if (lmodified) {
194 mapRemove(arg, "left");
195 mapSet(arg, left, "left");
196 }
197 right = eval_expression(right, &rmodified);
198 if (rmodified) {
199 mapRemove(arg, "right");
200 mapSet(arg, right, "right");
201 }
202
203 equal = eval_equal_expression(left, right);
204 if ((equal == NULL) || (equal->type != ELEMENT_BOOLEAN))
205 return expr;
206 *modifiedp = ISC_TRUE;
207 result = createBool(ISC_TF(!boolValue(equal)));
208 TAILQ_CONCAT(&result->comments, &expr->comments);
209 TAILQ_CONCAT(&result->comments, &arg->comments);
210 TAILQ_CONCAT(&result->comments, &equal->comments);
211 return result;
212 }
213
214 /* regex-match */
215 if (mapContains(expr, "regex-match"))
216 /*
217 * syntax := { "regex-match":
218 * { "left": <data_expression>,
219 * "right": <data_expression> }
220 * }
221 * semantics: evaluate branches, compile right as a
222 * regex and apply it to left
223 */
224 return expr;
225
226 /* iregex-match */
227 if (mapContains(expr, "iregex-match"))
228 /*
229 * syntax := { "regex-match":
230 * { "left": <data_expression>,
231 * "right": <data_expression> }
232 * }
233 * semantics: evaluate branches, compile right as a
234 * case insensistive regex and apply it to left
235 */
236 return expr;
237
238 /* and */
239 if (mapContains(expr, "and")) {
240 /*
241 * syntax := { "and":
242 * { "left": <boolean_expression>,
243 * "right": <boolean_expression> }
244 * }
245 * semantics: evaluate branches, return true
246 * if both are true
247 */
248 struct element *arg;
249 struct element *left;
250 struct element *right;
251 struct element *result;
252 isc_boolean_t lmodified = ISC_FALSE;
253 isc_boolean_t rmodified = ISC_FALSE;
254
255 arg = mapGet(expr, "and");
256 if ((arg == NULL) || (arg->type != ELEMENT_MAP))
257 return expr;
258 left = mapGet(arg, "left");
259 if (left == NULL)
260 return expr;
261 right = mapGet(arg, "right");
262 if (right == NULL)
263 debug("can't get and right branch");
264 left = eval_boolean_expression(left, &lmodified);
265 if (lmodified) {
266 mapRemove(arg, "left");
267 mapSet(arg, left, "left");
268 }
269 right = eval_boolean_expression(right, &rmodified);
270 if (rmodified) {
271 mapRemove(arg, "right");
272 mapSet(arg, right, "right");
273 }
274
275 if (left->type == ELEMENT_BOOLEAN) {
276 *modifiedp = ISC_TRUE;
277 if (!boolValue(left))
278 result = createBool(ISC_FALSE);
279 else {
280 result = copy(right);
281 TAILQ_INIT(&result->comments);
282 }
283 TAILQ_CONCAT(&result->comments, &expr->comments);
284 TAILQ_CONCAT(&result->comments, &arg->comments);
285 TAILQ_CONCAT(&result->comments, &left->comments);
286 TAILQ_CONCAT(&result->comments, &right->comments);
287 return result;
288 }
289 if (right->type == ELEMENT_BOOLEAN) {
290 *modifiedp = ISC_TRUE;
291 if (!boolValue(right))
292 result = createBool(ISC_FALSE);
293 else {
294 result = copy(left);
295 TAILQ_INIT(&result->comments);
296 }
297 TAILQ_CONCAT(&result->comments, &expr->comments);
298 TAILQ_CONCAT(&result->comments, &arg->comments);
299 TAILQ_CONCAT(&result->comments, &left->comments);
300 TAILQ_CONCAT(&result->comments, &right->comments);
301 return result;
302 }
303 return expr;
304 }
305
306 /* or */
307 if (mapContains(expr, "or")) {
308 /*
309 * syntax := { "or":
310 * { "left": <boolean_expression>,
311 * "right": <boolean_expression> }
312 * }
313 * semantics: evaluate branches, return true
314 * if any is true
315 */
316 struct element *arg;
317 struct element *left;
318 struct element *right;
319 struct element *result;
320 isc_boolean_t lmodified = ISC_FALSE;
321 isc_boolean_t rmodified = ISC_FALSE;
322
323 arg = mapGet(expr, "or");
324 if ((arg == NULL) || (arg->type != ELEMENT_MAP))
325 return expr;
326 left = mapGet(arg, "left");
327 if (left == NULL)
328 return expr;
329 right = mapGet(arg, "right");
330 if (right == NULL)
331 return expr;
332 left = eval_boolean_expression(left, &lmodified);
333 if (lmodified) {
334 mapRemove(arg, "left");
335 mapSet(arg, left, "left");
336 }
337 right = eval_boolean_expression(right, &rmodified);
338 if (rmodified) {
339 mapRemove(arg, "right");
340 mapSet(arg, right, "right");
341 }
342
343 if (left->type == ELEMENT_BOOLEAN) {
344 *modifiedp = ISC_TRUE;
345 if (boolValue(left))
346 result = createBool(ISC_TRUE);
347 else {
348 result = copy(right);
349 TAILQ_INIT(&result->comments);
350 }
351 TAILQ_CONCAT(&result->comments, &expr->comments);
352 TAILQ_CONCAT(&result->comments, &arg->comments);
353 TAILQ_CONCAT(&result->comments, &left->comments);
354 TAILQ_CONCAT(&result->comments, &right->comments);
355 return result;
356 }
357 if (right->type == ELEMENT_BOOLEAN) {
358 *modifiedp = ISC_TRUE;
359 if (boolValue(right))
360 result = createBool(ISC_TRUE);
361 else {
362 result = copy(left);
363 TAILQ_INIT(&result->comments);
364 }
365 TAILQ_CONCAT(&result->comments, &expr->comments);
366 TAILQ_CONCAT(&result->comments, &arg->comments);
367 TAILQ_CONCAT(&result->comments, &left->comments);
368 TAILQ_CONCAT(&result->comments, &right->comments);
369 return result;
370 }
371 return expr;
372 }
373
374 /* not */
375 if (mapContains(expr, "not")) {
376 /*
377 * syntax := { "not": <boolean_expression> }
378 * semantic: evaluate its branch and return its negation
379 */
380 struct element *arg;
381 struct element *result;
382 isc_boolean_t modified = ISC_FALSE;
383
384 arg = mapGet(expr, "not");
385 if (arg == NULL)
386 return expr;
387 arg = eval_boolean_expression(arg, &modified);
388 if (modified) {
389 mapRemove(expr, "not");
390 mapSet(expr, arg, "not");
391 }
392
393 /* remove double not */
394 if ((arg->type == ELEMENT_MAP) && mapContains(arg, "not")) {
395 arg = mapGet(arg, "not");
396 if (arg == NULL)
397 return expr;
398 *modifiedp = ISC_TRUE;
399 return arg;
400 }
401
402 /* compose with equal */
403 if ((arg->type == ELEMENT_MAP) &&
404 mapContains(arg, "equal")) {
405 arg = mapGet(arg, "equal");
406 if (arg == NULL)
407 return expr;
408 *modifiedp = ISC_TRUE;
409 result = createMap();
410 mapSet(result, arg, "not-equal");
411 return result;
412 }
413
414 /* compose with not-equal */
415 if ((arg->type == ELEMENT_MAP) &&
416 mapContains(arg, "not-equal")) {
417 arg = mapGet(arg, "not-equal");
418 if (arg == NULL)
419 return expr;
420 *modifiedp = ISC_TRUE;
421 result = createMap();
422 mapSet(result, arg, "equal");
423 return result;
424 }
425
426 if (arg->type != ELEMENT_BOOLEAN)
427 return expr;
428 *modifiedp = ISC_TRUE;
429 result = createBool(ISC_TF(!boolValue(arg)));
430 TAILQ_CONCAT(&result->comments, &expr->comments);
431 TAILQ_CONCAT(&result->comments, &arg->comments);
432 return result;
433 }
434
435 /* known */
436 if (mapContains(expr, "known"))
437 /*
438 * syntax := { "known": null }
439 * semantics: client is known, i.e., has a matching
440 * host declaration (aka reservation in Kea)
441 */
442 return expr;
443
444 /* static */
445 if (mapContains(expr, "static"))
446 /*
447 * syntax := { "static": null }
448 * semantics: lease is static (doesn't exist in Kea)
449 */
450 return expr;
451
452 return expr;
453}
454
455/*
456 * data_expression :== SUBSTRING LPAREN data-expression COMMA
457 * numeric-expression COMMA
458 * numeric-expression RPAREN |
459 * CONCAT LPAREN data-expression COMMA
460 * data-expression RPAREN
461 * SUFFIX LPAREN data_expression COMMA
462 * numeric-expression RPAREN |
463 * LCASE LPAREN data_expression RPAREN |
464 * UCASE LPAREN data_expression RPAREN |
465 * OPTION option_name |
466 * HARDWARE |
467 * PACKET LPAREN numeric-expression COMMA
468 * numeric-expression RPAREN |
469 * V6RELAY LPAREN numeric-expression COMMA
470 * data-expression RPAREN |
471 * STRING |
472 * colon_separated_hex_list
473 */
474
475struct element *
477{
478 /* trivial case: already done */
479 if (expr->type == ELEMENT_STRING)
480 return expr;
481
482 /*
483 * From is_data_expression
484 */
485
486 if (expr->type != ELEMENT_MAP)
487 return expr;
488
489 /* substring */
490 if (mapContains(expr, "substring")) {
491 /*
492 * syntax := { "substring":
493 * { "expression": <data_expression>,
494 * "offset": <numeric_expression>,
495 * "length": <numeric_expression> }
496 * }
497 * semantic: evaluate arguments, if the string is
498 * shorter than offset return "" else return substring
499 */
500 struct element *arg;
501 struct element *string;
502 struct element *offset;
503 struct element *length;
504 struct element *result;
505 struct string *s;
506 struct string *r;
507 int64_t off;
508 int64_t len;
509 isc_boolean_t smodified = ISC_FALSE;
510 isc_boolean_t omodified = ISC_FALSE;
511 isc_boolean_t lmodified = ISC_FALSE;
512
513 arg = mapGet(expr, "substring");
514 if ((arg == NULL) || (arg->type != ELEMENT_MAP))
515 return expr;
516 string = mapGet(arg, "expression");
517 if (string == NULL)
518 return expr;
519 offset = mapGet(arg, "offset");
520 if (offset == NULL)
521 return expr;
522 length = mapGet(arg, "length");
523 if (length == NULL)
524 return expr;
525 string = eval_data_expression(string, &smodified);
526 if (smodified) {
527 mapRemove(arg, "expression");
528 mapSet(arg, string, "expression");
529 }
530 offset = eval_numeric_expression(offset, &omodified);
531 if (omodified) {
532 mapRemove(arg, "offset");
533 mapSet(arg, offset, "offset");
534 }
536 if (lmodified) {
537 mapRemove(arg, "length");
538 mapSet(arg, length, "length");
539 }
540
541 if ((offset->type != ELEMENT_INTEGER) ||
542 (length->type != ELEMENT_INTEGER))
543 return expr;
544 off = intValue(offset);
545 len = intValue(length);
546 if ((off < 0) || (len < 0))
547 return expr;
548 /* degenerated case */
549 if (len == 0) {
550 *modifiedp = ISC_TRUE;
551 r = allocString();
552 result = createString(r);
553 return result;
554 }
555
556 /* return (part of) hw-address? */
557 if ((local_family == AF_INET) &&
558 (string->type == ELEMENT_MAP) &&
559 mapContains(string, "concat") &&
560 (off >= 1)) {
561 struct element *concat;
562 struct element *left;
563 struct element *right;
564
565 concat = mapGet(string, "concat");
566 if (concat->type != ELEMENT_MAP)
567 return expr;
568 left = mapGet(concat, "left");
569 if (left == NULL)
570 return expr;
571 right = mapGet(concat, "right");
572 if (right == NULL)
573 return expr;
574 /* from substring(hardware, ...) */
575 if ((left->type == ELEMENT_MAP) &&
576 mapContains(left, "hw-type")) {
577 *modifiedp = ISC_TRUE;
578 mapRemove(arg, "expression");
579 mapSet(arg, right, "expression");
580 mapRemove(arg, "offset");
581 mapSet(arg, createInt(off - 1), "offset");
582 return expr;
583 }
584 return expr;
585 }
586
587 /* return hw-type? */
588 if ((local_family == AF_INET) &&
589 (string->type == ELEMENT_MAP) &&
590 mapContains(string, "concat") &&
591 (off == 0) && (len == 1)) {
592 struct element *concat;
593 struct element *left;
594 struct element *right;
595
596 concat = mapGet(string, "concat");
597 if (concat->type != ELEMENT_MAP)
598 return expr;
599 left = mapGet(concat, "left");
600 if (left == NULL)
601 return expr;
602 right = mapGet(concat, "right");
603 if (right == NULL)
604 return expr;
605 /* from substring(hardware, ...) */
606 if ((left->type == ELEMENT_MAP) &&
607 mapContains(left, "hw-type")) {
608 *modifiedp = ISC_TRUE;
609 return left;
610 }
611 return expr;
612 }
613
614 if (string->type != ELEMENT_STRING)
615 return expr;
616 *modifiedp = ISC_TRUE;
617 s = stringValue(string);
618 if (s->length <= off)
619 r = allocString();
620 else {
621 r = makeString(s->length - off, s->content + off);
622 if (r->length > len)
623 r->length = len;
624 }
625 result = createString(r);
626 TAILQ_CONCAT(&result->comments, &expr->comments);
627 TAILQ_CONCAT(&result->comments, &arg->comments);
628 TAILQ_CONCAT(&result->comments, &string->comments);
629 TAILQ_CONCAT(&result->comments, &offset->comments);
630 TAILQ_CONCAT(&result->comments, &length->comments);
631 return result;
632 }
633
634 /* suffix */
635 if (mapContains(expr, "suffix")) {
636 /*
637 * syntax := { "suffix":
638 * { "expression": <data_expression>,
639 * "length": <numeric_expression> }
640 * }
641 * semantic: evaluate arguments, if the string is
642 * shorter than length return it else return suffix
643 */
644 struct element *arg;
645 struct element *string;
646 struct element *length;
647 struct element *result;
648 struct string *r;
649 int64_t len;
650 isc_boolean_t smodified = ISC_FALSE;
651 isc_boolean_t lmodified = ISC_FALSE;
652
653 arg = mapGet(expr, "suffix");
654 if ((arg == NULL) || (arg->type != ELEMENT_MAP))
655 return expr;
656 string = mapGet(arg, "expression");
657 if (string == NULL)
658 return expr;
659 length = mapGet(arg, "length");
660 if (length == NULL)
661 return expr;
662 string = eval_data_expression(string, &smodified);
663 if (smodified) {
664 mapRemove(arg, "expression");
665 mapSet(arg, string, "expression");
666 }
668 if (lmodified) {
669 mapRemove(arg, "length");
670 mapSet(arg, length, "length");
671 }
672
673 if ((string->type != ELEMENT_STRING) ||
674 (length->type != ELEMENT_INTEGER))
675 return expr;
676 len = intValue(length);
677 if (len < 0)
678 return expr;
679 *modifiedp = ISC_TRUE;
680 r = stringValue(string);
681 if (r->length > len)
682 r = makeString(r->length - len, r->content + len);
683 result = createString(r);
684 TAILQ_CONCAT(&result->comments, &expr->comments);
685 TAILQ_CONCAT(&result->comments, &arg->comments);
686 TAILQ_CONCAT(&result->comments, &string->comments);
687 TAILQ_CONCAT(&result->comments, &length->comments);
688 return result;
689 }
690
691 /* lowercase */
692 if (mapContains(expr, "lowercase")) {
693 /*
694 * syntax := { "lowercase": <data_expression> }
695 * semantic: evaluate its argument and apply tolower to
696 * its content
697 */
698 struct element *arg;
699 struct element *result;
700 struct string *r;
701 size_t i;
702 isc_boolean_t modified = ISC_FALSE;
703
704 arg = mapGet(expr, "lowercase");
705 if (arg == NULL)
706 return expr;
707 arg = eval_data_expression(arg, &modified);
708 if (modified) {
709 mapRemove(expr, "lowercase");
710 mapSet(expr, arg, "lowercase");
711 }
712
713 if (arg->type != ELEMENT_STRING)
714 return expr;
715 *modifiedp = ISC_TRUE;
716 r = allocString();
717 concatString(r, stringValue(arg));
718 for (i = 0; i < r->length; i++)
719 r->content[i] = tolower(r->content[i]);
720 result = createString(r);
721 TAILQ_CONCAT(&result->comments, &expr->comments);
722 TAILQ_CONCAT(&result->comments, &arg->comments);
723 return result;
724 }
725
726 /* uppercase */
727 if (mapContains(expr, "uppercase")) {
728 /*
729 * syntax := { "uppercase": <data_expression> }
730 * semantic: evaluate its argument and apply toupper to
731 * its content
732 */
733 struct element *arg;
734 struct element *result;
735 struct string *r;
736 size_t i;
737 isc_boolean_t modified = ISC_FALSE;
738
739 arg = mapGet(expr, "uppercase");
740 if (arg == NULL)
741 return expr;
742 arg = eval_data_expression(arg, &modified);
743 if (modified) {
744 mapRemove(expr, "lowercase");
745 mapSet(expr, arg, "lowercase");
746 }
747
748 if (arg->type != ELEMENT_STRING)
749 return expr;
750 *modifiedp = ISC_TRUE;
751 r = allocString();
752 concatString(r, stringValue(arg));
753 for (i = 0; i < r->length; i++)
754 r->content[i] = toupper(r->content[i]);
755 result = createString(r);
756 TAILQ_CONCAT(&result->comments, &expr->comments);
757 TAILQ_CONCAT(&result->comments, &arg->comments);
758 return result;
759 }
760
761 /* option */
762 if (mapContains(expr, "option"))
763 /*
764 * syntax := { "option":
765 * { "universe": <option_space_old>,
766 * "name": <option_name> }
767 * }
768 * semantic: get universe/code option from incoming packet
769 */
770 return expr;
771
772 /* hardware */
773 if (mapContains(expr, "hardware")) {
774 /*
775 * syntax := { "hardware": null }
776 * semantic: get mac type and address from incoming packet
777 */
778 struct element *left;
779 struct element *right;
780 struct element *concat;
781 struct element *result;
782
783 if (local_family != AF_INET)
784 return expr;
785 *modifiedp = ISC_TRUE;
786 left = createMap();
787 mapSet(left, createNull(), "hw-type");
788 concat = createMap();
789 mapSet(concat, left, "left");
790 right = createMap();
791 mapSet(right, createNull(), "hw-address");
792 mapSet(concat, right, "right");
793 result = createMap();
794 mapSet(result, concat, "concat");
795 return result;
796 }
797
798 /* hw-type */
799 if (mapContains(expr, "hw-type"))
800 /*
801 * syntax := { "hw-type": null }
802 * semantic: get mac type and address from incoming packet
803 */
804 return expr;
805
806 /* hw-address */
807 if (mapContains(expr, "hw-address"))
808 /*
809 * syntax := { "hw-address": null }
810 * semantic: get mac type and address from incoming packet
811 */
812 return expr;
813
814 /* const-data */
815 if (mapContains(expr, "const-data"))
816 /*
817 * syntax := { "const-data": <string> }
818 * semantic: embedded string value
819 */
820 return expr;
821
822 /* packet */
823 if (mapContains(expr, "packet"))
824 /*
825 * syntax := { "packet":
826 * { "offset": <numeric_expression>,
827 * "length": <numeric_expression> }
828 * }
829 * semantic: return the selected substring of the incoming
830 * packet content
831 */
832 return expr;
833
834 /* concat */
835 if (mapContains(expr, "concat")) {
836 /*
837 * syntax := { "concat":
838 * { "left": <data_expression>,
839 * "right": <data_expression> }
840 * }
841 * semantic: evaluate arguments and return the concatenation
842 */
843 struct element *arg;
844 struct element *left;
845 struct element *right;
846 struct element *result;
847 struct string *r;
848 isc_boolean_t lmodified = ISC_FALSE;
849 isc_boolean_t rmodified = ISC_FALSE;
850
851 arg = mapGet(expr, "concat");
852 if ((arg == NULL) || (arg->type != ELEMENT_MAP))
853 return expr;
854 left = mapGet(arg, "left");
855 if (left == NULL)
856 return expr;
857 right = mapGet(arg, "right");
858 if (right == NULL)
859 return expr;
860 left = eval_data_expression(left, &lmodified);
861 if (lmodified) {
862 mapRemove(arg, "left");
863 mapSet(arg, left, "left");
864 }
865 right = eval_data_expression(right, &rmodified);
866 if (rmodified) {
867 mapRemove(arg, "right");
868 mapSet(arg, right, "right");
869 }
870
871 /* degenerated cases */
872 if ((left->type == ELEMENT_STRING) &&
873 (stringValue(left)->length == 0)) {
874 *modifiedp = ISC_TRUE;
875 return right;
876 }
877 if ((right->type == ELEMENT_STRING) &&
878 (stringValue(right)->length == 0)) {
879 *modifiedp = ISC_TRUE;
880 return left;
881 }
882
883 if ((left->type != ELEMENT_STRING) ||
884 (right->type != ELEMENT_STRING))
885 return expr;
886 *modifiedp = ISC_TRUE;
887 r = allocString();
888 concatString(r, stringValue(left));
889 concatString(r, stringValue(right));
890 result = createString(r);
891 TAILQ_CONCAT(&result->comments, &expr->comments);
892 TAILQ_CONCAT(&result->comments, &arg->comments);
893 TAILQ_CONCAT(&result->comments, &left->comments);
894 TAILQ_CONCAT(&result->comments, &right->comments);
895 return result;
896 }
897
898 /* encapsulate */
899 if (mapContains(expr, "encapsulate"))
900 /*
901 * syntax := { "encapsulate": <encapsulated_space> }
902 * semantic: encapsulate options of the given space
903 */
904 return expr;
905
906 /* encode-int8 */
907 if (mapContains(expr, "encode-int8")) {
908 /*
909 * syntax := { "encode-int8": <numeric_expression> }
910 * semantic: return a string buffer with the evaluated
911 * number as content
912 */
913 struct element *arg;
914 struct element *result;
915 struct string *r;
916 uint8_t val;
917 isc_boolean_t modified = ISC_FALSE;
918
919 arg = mapGet(expr, "encode-int8");
920 if (arg == NULL)
921 return expr;
922 arg = eval_numeric_expression(arg, &modified);
923 if (modified) {
924 mapRemove(expr, "encode-int8");
925 mapSet(expr, arg, "encode-int8");
926 }
927
928 if (arg->type != ELEMENT_INTEGER)
929 return expr;
930 *modifiedp = ISC_TRUE;
931 val = (uint8_t)intValue(arg);
932 r = makeString(sizeof(val), (char *)&val);
933 result = createString(r);
934 TAILQ_CONCAT(&result->comments, &expr->comments);
935 TAILQ_CONCAT(&result->comments, &arg->comments);
936 return result;
937 }
938
939 /* encode-int16 */
940 if (mapContains(expr, "encode-int16")) {
941 /*
942 * syntax := { "encode-int16": <numeric_expression> }
943 * semantic: return a string buffer with the evaluated
944 * number as content
945 */
946 struct element *arg;
947 struct element *result;
948 struct string *r;
949 uint16_t val;
950 isc_boolean_t modified = ISC_FALSE;
951
952 arg = mapGet(expr, "encode-int16");
953 if (arg == NULL)
954 return expr;
955 arg = eval_numeric_expression(arg, &modified);
956 if (modified) {
957 mapRemove(expr, "encode-int16");
958 mapSet(expr, arg, "encode-int16");
959 }
960
961 if (arg->type != ELEMENT_INTEGER)
962 return expr;
963 *modifiedp = ISC_TRUE;
964 val = (uint16_t)intValue(arg);
965 val = htons(val);
966 r = makeString(sizeof(val), (char *)&val);
967 result = createString(r);
968 TAILQ_CONCAT(&result->comments, &expr->comments);
969 TAILQ_CONCAT(&result->comments, &arg->comments);
970 return result;
971 }
972
973 /* encode-int32 */
974 if (mapContains(expr, "encode-int32")) {
975 /*
976 * syntax := { "encode-int32": <numeric_expression> }
977 * semantic: return a string buffer with the evaluated
978 * number as content
979 */
980 struct element *arg;
981 struct element *result;
982 struct string *r;
983 uint32_t val;
984 isc_boolean_t modified = ISC_FALSE;
985
986 arg = mapGet(expr, "encode-int32");
987 if (arg == NULL)
988 return expr;
989 arg = eval_numeric_expression(arg, &modified);
990 if (modified) {
991 mapRemove(expr, "encode-int32");
992 mapSet(expr, arg, "encode-int32");
993 }
994
995 if (arg->type != ELEMENT_INTEGER)
996 return expr;
997 *modifiedp = ISC_TRUE;
998 val = (uint32_t)intValue(arg);
999 val = htonl(val);
1000 r = makeString(sizeof(val), (char *)&val);
1001 result = createString(r);
1002 TAILQ_CONCAT(&result->comments, &expr->comments);
1003 TAILQ_CONCAT(&result->comments, &arg->comments);
1004 return result;
1005 }
1006
1007 /* gethostbyname */
1008 if (mapContains(expr, "gethostbyname")) {
1009 /*
1010 * syntax := { "gethostbyname": <string> }
1011 * semantic: call gethostbyname and return
1012 * a binary buffer with addresses
1013 */
1014 struct element *arg;
1015 struct element *result;
1016 struct string *r;
1017 char *hostname;
1018 struct hostent *h;
1019 size_t i;
1020
1021 if (local_family != AF_INET)
1022 return expr;
1023 arg = mapGet(expr, "gethostbyname");
1024 if ((arg == NULL) || (arg->type != ELEMENT_STRING))
1025 return expr;
1026 hostname = stringValue(arg)->content;
1027 h = gethostbyname(hostname);
1028 r = allocString();
1029 if (h == NULL) {
1030 switch (h_errno) {
1031 case HOST_NOT_FOUND:
1032 debug("gethostbyname: %s: host unknown",
1033 hostname);
1034 break;
1035 case TRY_AGAIN:
1036 debug("gethostbyname: %s: temporary name "
1037 "server failure", hostname);
1038 break;
1039 case NO_RECOVERY:
1040 debug("gethostbyname: %s: name server failed",
1041 hostname);
1042 break;
1043 case NO_DATA:
1044 debug("gethostbyname: %s: no A record "
1045 "associated with address", hostname);
1046 break;
1047 }
1048 } else
1049 for (i = 0; h->h_addr_list[i] != NULL; i++) {
1050 struct string *addr;
1051
1052 addr = makeString(4, h->h_addr_list[i]);
1053 concatString(r, addr);
1054 }
1055 *modifiedp = ISC_TRUE;
1056 r = makeStringExt(r->length, r->content, 'X');
1057 result = createString(r);
1058 TAILQ_CONCAT(&result->comments, &arg->comments);
1059 return result;
1060 }
1061
1062 /* binary-to-ascii */
1063 if (mapContains(expr, "binary-to-ascii")) {
1064 /*
1065 * syntax := { "binary-to-ascii":
1066 * { "base": <numeric_expression 2..16>,
1067 * "width": <numeric_expression 8, 16 or 32>,
1068 * "separator": <data_expression>,
1069 * "buffer": <data_expression> }
1070 * }
1071 * semantic: split the input buffer into int8/16/32 numbers,
1072 * output them separated by the given string
1073 */
1074 struct element *arg;
1075 struct element *base;
1076 struct element *width;
1077 struct element *separator;
1078 struct element *buffer;
1079 struct element *result;
1080 struct string *sep;
1081 struct string *buf;
1082 struct string *r;
1083 int64_t b;
1084 int64_t w;
1085 isc_boolean_t bmodified = ISC_FALSE;
1086 isc_boolean_t wmodified = ISC_FALSE;
1087 isc_boolean_t smodified = ISC_FALSE;
1088 isc_boolean_t dmodified = ISC_FALSE;
1089
1090 arg = mapGet(expr, "binary-to-ascii");
1091 if ((arg == NULL) || (arg->type != ELEMENT_MAP))
1092 return expr;
1093 base = mapGet(arg, "base");
1094 if (base == NULL)
1095 return expr;
1096 width = mapGet(arg, "width");
1097 if (width == NULL)
1098 return expr;
1099 separator = mapGet(arg, "separator");
1100 if (separator == NULL)
1101 return expr;
1102 buffer = mapGet(arg, "buffer");
1103 if (buffer == NULL)
1104 return expr;
1105 base = eval_numeric_expression(base, &bmodified);
1106 if (bmodified) {
1107 mapRemove(arg, "base");
1108 mapSet(arg, base, "base");
1109 }
1110 width = eval_numeric_expression(width, &wmodified);
1111 if (wmodified) {
1112 mapRemove(arg, "width");
1113 mapSet(arg, width, "width");
1114 }
1115 separator = eval_data_expression(separator, &smodified);
1116 if (smodified) {
1117 mapRemove(arg, "separator");
1118 mapSet(arg, separator, "separator");
1119 }
1120 buffer = eval_data_expression(buffer, &dmodified);
1121 if (dmodified) {
1122 mapRemove(arg, "buffer");
1123 mapSet(arg, buffer, "buffer");
1124 }
1125
1126 if ((base->type != ELEMENT_INTEGER) ||
1127 (width->type != ELEMENT_INTEGER) ||
1128 (separator->type != ELEMENT_STRING) ||
1129 (buffer->type != ELEMENT_STRING))
1130 return expr;
1131 b = intValue(base);
1132 if ((b < 2) || (b > 16))
1133 return expr;
1134 if ((b != 8) && (b != 10) && (b != 16))
1135 return expr;
1136 w = intValue(width);
1137 if ((w != 8) && (w != 16) && (w != 32))
1138 return expr;
1139 sep = stringValue(separator);
1140 buf = stringValue(buffer);
1141 r = allocString();
1142 if (w == 8) {
1143 size_t i;
1144 char *fmt;
1145
1146 switch (b) {
1147 case 8:
1148 fmt = "%o";
1149 break;
1150 case 10:
1151 fmt = "%d";
1152 break;
1153 case 16:
1154 default:
1155 fmt = "%x";
1156 break;
1157 }
1158
1159 for (i = 0; i < buf->length; i++) {
1160 uint8_t val;
1161 char num[4];
1162
1163 if (i != 0)
1164 concatString(r, sep);
1165 val = (uint8_t)buf->content[i];
1166 snprintf(num, sizeof(num), fmt, (int)val);
1167 appendString(r, num);
1168 }
1169 } else if (w == 16) {
1170 size_t i;
1171 char *fmt;
1172
1173 if ((buf->length % 2) != 0)
1174 return expr;
1175
1176 switch (b) {
1177 case 8:
1178 fmt = "%o";
1179 break;
1180 case 10:
1181 fmt = "%d";
1182 break;
1183 case 16:
1184 default:
1185 fmt = "%x";
1186 break;
1187 }
1188
1189 for (i = 0; i < buf->length; i += 2) {
1190 uint16_t val;
1191 char num[8];
1192
1193 if (i != 0)
1194 concatString(r, sep);
1195 memcpy(&val, buf->content + i, 2);
1196 val = ntohs(val);
1197 snprintf(num, sizeof(num), fmt, (int)val);
1198 appendString(r, num);
1199 }
1200 } else if (w == 32) {
1201 size_t i;
1202 char *fmt;
1203
1204 if ((buf->length % 4) != 0)
1205 return expr;
1206
1207 switch (b) {
1208 case 8:
1209 fmt = "%llo";
1210 break;
1211 case 10:
1212 fmt = "%lld";
1213 break;
1214 case 16:
1215 default:
1216 fmt = "%llx";
1217 break;
1218 }
1219
1220 for (i = 0; i < buf->length; i += 4) {
1221 uint32_t val;
1222 char num[40];
1223
1224 if (i != 0)
1225 concatString(r, sep);
1226 memcpy(&val, buf->content + i, 4);
1227 val = ntohl(val);
1228 snprintf(num, sizeof(num), fmt,
1229 (long long)val);
1230 appendString(r, num);
1231 }
1232 }
1233 *modifiedp = ISC_TRUE;
1234 result = createString(r);
1235 TAILQ_CONCAT(&result->comments, &expr->comments);
1236 TAILQ_CONCAT(&result->comments, &arg->comments);
1237 TAILQ_CONCAT(&result->comments, &base->comments);
1238 TAILQ_CONCAT(&result->comments, &width->comments);
1239 TAILQ_CONCAT(&result->comments, &separator->comments);
1240 TAILQ_CONCAT(&result->comments, &buffer->comments);
1241 return result;
1242 }
1243
1244 /* filename */
1245 if (mapContains(expr, "filename"))
1246 /*
1247 * syntax := { "filename": null }
1248 * semantic: get filename field from incoming DHCPv4 packet
1249 */
1250 return expr;
1251
1252 /* server-name */
1253 if (mapContains(expr, "server-name"))
1254 /*
1255 * syntax := { "server-name": null }
1256 * semantic: get server-name field from incoming DHCPv4 packet
1257 */
1258 return expr;
1259
1260 /* reverse */
1261 if (mapContains(expr, "reverse")) {
1262 /*
1263 * syntax := { "reverse":
1264 * { "width": <numeric_expression>,
1265 * "buffer": <data_expression> }
1266 * }
1267 * semantic: reverse the input buffer by width chunks of bytes
1268 */
1269 struct element *arg;
1270 struct element *width;
1271 struct element *buffer;
1272 struct element *result;
1273 struct string *buf;
1274 struct string *r;
1275 int64_t w;
1276 size_t i;
1277 isc_boolean_t wmodified = ISC_FALSE;
1278 isc_boolean_t bmodified = ISC_FALSE;
1279
1280 arg = mapGet(expr, "reverse");
1281 if ((arg == NULL) || (arg->type != ELEMENT_MAP))
1282 return expr;
1283 width = mapGet(arg, "width");
1284 if (width == NULL)
1285 return expr;
1286 buffer = mapGet(arg, "buffer");
1287 if (buffer == NULL)
1288 return expr;
1289 width = eval_numeric_expression(width, &wmodified);
1290 if (wmodified) {
1291 mapRemove(arg, "width");
1292 mapSet(arg, width, "width");
1293 }
1294 buffer = eval_data_expression(buffer, &bmodified);
1295 if (bmodified) {
1296 mapRemove(arg, "buffer");
1297 mapSet(arg, buffer, "buffer");
1298 }
1299
1300 if ((width->type != ELEMENT_INTEGER) ||
1301 (buffer->type != ELEMENT_STRING))
1302 return expr;
1303 w = intValue(width);
1304 if (w <= 0)
1305 return expr;
1306 buf = stringValue(buffer);
1307 if ((buf->length % w) != 0)
1308 return expr;
1309 *modifiedp = ISC_TRUE;
1310 r = allocString();
1311 concatString(r, buf);
1312 for (i = 0; i < buf->length; i += w) {
1313 memcpy(r->content + i,
1314 buf->content + (buf->length - i - w),
1315 w);
1316 }
1317 result = createString(r);
1318 TAILQ_CONCAT(&result->comments, &expr->comments);
1319 TAILQ_CONCAT(&result->comments, &arg->comments);
1320 TAILQ_CONCAT(&result->comments, &width->comments);
1321 TAILQ_CONCAT(&result->comments, &buffer->comments);
1322 return result;
1323 }
1324
1325 /* pick-first-value */
1326 if (mapContains(expr, "pick-first-value")) {
1327 /*
1328 * syntax := { "pick-first-value":
1329 * [ <data_expression>, ... ]
1330 * }
1331 * semantic: evaluates expressions and return the first
1332 * not null, return null if all are null
1333 */
1334 struct element *arg;
1335 struct element *result;
1336 size_t i;
1337 isc_boolean_t modified;
1338 isc_boolean_t can_decide = ISC_TRUE;
1339
1340 arg = mapGet(expr, "pick-first-value");
1341 if ((arg == NULL) || (arg->type != ELEMENT_LIST))
1342 return expr;
1343
1344 for (i = 0; i < listSize(arg); i++) {
1345 struct element *item;
1346
1347 item = listGet(arg, i);
1348 if (item == NULL)
1349 return expr;
1350 modified = ISC_FALSE;
1351 item = eval_data_expression(item, &modified);
1352 if (modified)
1353 listRemove(arg, i);
1354 if (!can_decide)
1355 goto restore;
1356 if (item->type != ELEMENT_STRING) {
1357 can_decide = ISC_FALSE;
1358 goto restore;
1359 }
1360 if (stringValue(item)->length != 0) {
1361 *modifiedp = ISC_TRUE;
1362 TAILQ_CONCAT(&item->comments, &expr->comments);
1363 TAILQ_CONCAT(&item->comments, &arg->comments);
1364 return item;
1365 }
1366 restore:
1367 listSet(arg, item, i);
1368 }
1369 if (!can_decide)
1370 return expr;
1371 *modifiedp = ISC_TRUE;
1372 result = createString(allocString());
1373 TAILQ_CONCAT(&result->comments, &expr->comments);
1374 TAILQ_CONCAT(&result->comments, &arg->comments);
1375 return result;
1376 }
1377
1378 /* host-decl-name */
1379 if (mapContains(expr, "host-decl-name"))
1380 /*
1381 * syntax := { "host-decl-name": null }
1382 * semantic: return the name of the matching host
1383 * declaration (aka revervation in kea) or null
1384 */
1385 return expr;
1386
1387 /* leased-address */
1388 if (mapContains(expr, "leased-address"))
1389 /*
1390 * syntax := { "leased-address": null }
1391 * semantic: return the address of the assigned lease or
1392 * log a message
1393 */
1394 return expr;
1395
1396 /* config-option */
1397 if (mapContains(expr, "config-option"))
1398 /*
1399 * syntax := { "config-option":
1400 * { "universe": <option_space_old>,
1401 * "name": <option_name> }
1402 * }
1403 * semantic: get universe/code option to send
1404 */
1405 return expr;
1406
1407 /* null */
1408 if (mapContains(expr, "null")) {
1409 /*
1410 * syntax := { "null": null }
1411 * semantic: return null
1412 */
1413 struct element *result;
1414
1415 *modifiedp = ISC_TRUE;
1416 result = createString(allocString());
1417 TAILQ_CONCAT(&result->comments, &expr->comments);
1418 return result;
1419 }
1420
1421 /* gethostname */
1422 if (mapContains(expr, "gethostname")) {
1423 /*
1424 * syntax := { "gethostname": null }
1425 * semantic: return gethostname
1426 */
1427 struct element *result;
1428 char buf[300 /* >= 255 + 1 */];
1429
1430 if (gethostname(buf, sizeof(buf)) != 0) {
1431 debug("gethostname fails: %s", strerror(errno));
1432 return expr;
1433 }
1434 *modifiedp = ISC_TRUE;
1435 result = createString(makeString(-1, buf));
1436 TAILQ_CONCAT(&result->comments, &expr->comments);
1437 return result;
1438 }
1439
1440 /* v6relay */
1441 if (mapContains(expr, "v6relay")) {
1442 /*
1443 * syntax := { "v6relay":
1444 * { "relay": <numeric_expression>,
1445 * "relay-option" <data_expression> }
1446 * }
1447 * semantic: relay is a counter from client, 0 is no-op,
1448 * 1 is the relay closest to the client, etc, option
1449 * is a dhcp6 option ans is return when found
1450 */
1451 struct element *arg;
1452 struct element *relay;
1453 isc_boolean_t modified = ISC_FALSE;
1454
1455 if (local_family != AF_INET6)
1456 return expr;
1457 arg = mapGet(expr, "v6relay");
1458 if ((arg == NULL) || (arg->type != ELEMENT_MAP))
1459 return expr;
1460 relay = mapGet(arg, "relay");
1461 if (relay == NULL)
1462 return expr;
1463 relay = eval_numeric_expression(relay, &modified);
1464 if (modified) {
1465 mapRemove(arg, "relay");
1466 mapSet(arg, relay, "relay");
1467 }
1468 return expr;
1469 }
1470
1471 return expr;
1472}
1473
1474/*
1475 * numeric-expression :== EXTRACT_INT LPAREN data-expression
1476 * COMMA number RPAREN |
1477 * NUMBER
1478 */
1479
1480struct element *
1482{
1483 /* trivial case: already done */
1484 if (expr->type == ELEMENT_INTEGER)
1485 return expr;
1486
1487 /*
1488 * From is_numeric_expression
1489 */
1490
1491 if (expr->type != ELEMENT_MAP)
1492 return expr;
1493
1494 /* extract-int8 */
1495 if (mapContains(expr, "extract-int8")) {
1496 /*
1497 * syntax := { "extract-int8": <data_expression> }
1498 * semantic: extract from the evalkuated string buffer
1499 * a number
1500 */
1501 struct element *arg;
1502 struct element *result;
1503 uint8_t val = 0;
1504 isc_boolean_t modified = ISC_FALSE;
1505
1506 arg = mapGet(expr, "extract-int8");
1507 if (arg == NULL)
1508 return expr;
1509 arg = eval_data_expression(arg, &modified);
1510 if (modified) {
1511 mapRemove(expr, "extract-int8");
1512 mapSet(expr, arg, "extract-int8");
1513 }
1514
1515 if (arg->type != ELEMENT_STRING)
1516 return expr;
1517 *modifiedp = ISC_TRUE;
1518 if (stringValue(arg)->length > 0)
1519 val = (uint8_t) stringValue(arg)->content[0];
1520 result = createInt(val);
1521 TAILQ_CONCAT(&result->comments, &expr->comments);
1522 TAILQ_CONCAT(&result->comments, &arg->comments);
1523 return result;
1524 }
1525
1526 /* extract-int16 */
1527 if (mapContains(expr, "extract-int16")) {
1528 /*
1529 * syntax := { "extract-int16": <data_expression> }
1530 * semantic: extract from the evalkuated string buffer
1531 * a number
1532 */
1533 struct element *arg;
1534 struct element *result;
1535 uint16_t val;
1536 isc_boolean_t modified = ISC_FALSE;
1537
1538 arg = mapGet(expr, "extract-int16");
1539 if (arg == NULL)
1540 return expr;
1541 arg = eval_data_expression(arg, &modified);
1542 if (modified) {
1543 mapRemove(expr, "extract-int16");
1544 mapSet(expr, arg, "extract-int16");
1545 }
1546
1547 if (arg->type != ELEMENT_STRING)
1548 return expr;
1549 if (stringValue(arg)->length < 2)
1550 return expr;
1551 *modifiedp = ISC_TRUE;
1552 memcpy(&val, stringValue(arg)->content, 2);
1553 val = ntohs(val);
1554 result = createInt(val);
1555 TAILQ_CONCAT(&result->comments, &expr->comments);
1556 TAILQ_CONCAT(&result->comments, &arg->comments);
1557 return result;
1558 }
1559
1560 /* extract-int32 */
1561 if (mapContains(expr, "extract-int32")) {
1562 /*
1563 * syntax := { "extract-int32": <data_expression> }
1564 * semantic: extract from the evalkuated string buffer
1565 * a number
1566 */
1567 struct element *arg;
1568 struct element *result;
1569 uint32_t val;
1570 isc_boolean_t modified = ISC_FALSE;
1571
1572 arg = mapGet(expr, "extract-int32");
1573 if (arg == NULL)
1574 return expr;
1575 arg = eval_data_expression(arg, &modified);
1576 if (modified) {
1577 mapRemove(expr, "extract-int32");
1578 mapSet(expr, arg, "extract-int32");
1579 }
1580
1581 if (arg->type != ELEMENT_STRING)
1582 return expr;
1583 if (stringValue(arg)->length < 4)
1584 return expr;
1585 *modifiedp = ISC_TRUE;
1586 memcpy(&val, stringValue(arg)->content, 4);
1587 val = ntohl(val);
1588 result = createInt(val);
1589 TAILQ_CONCAT(&result->comments, &expr->comments);
1590 TAILQ_CONCAT(&result->comments, &arg->comments);
1591 return result;
1592 }
1593
1594 /* const-int */
1595 if (mapContains(expr, "const-int")) {
1596 /*
1597 * syntax := { "const-int": <integer> }
1598 * semantic: embedded integer value
1599 */
1600 struct element *arg;
1601 struct element *result;
1602
1603 arg = mapGet(expr, "const-int");
1604 if ((arg == NULL) || (arg->type != ELEMENT_INTEGER))
1605 return expr;
1606 *modifiedp = ISC_TRUE;
1607 result = createInt(intValue(arg));
1608 TAILQ_CONCAT(&result->comments, &expr->comments);
1609 TAILQ_CONCAT(&result->comments, &arg->comments);
1610 return result;
1611 }
1612
1613 /* lease-time */
1614 if (mapContains(expr, "lease-time"))
1615 /*
1616 * syntax := { "lease-time": null }
1617 * semantic: return duration of the current lease, i.e
1618 * the difference between expire time and now
1619 */
1620 return expr;
1621
1622 /* add */
1623 if (mapContains(expr, "add")) {
1624 /*
1625 * syntax := { "add":
1626 * { "left": <boolean_expression>,
1627 * "right": <boolean_expression> }
1628 * }
1629 * semantics: evaluate branches, return left plus right
1630 * branches
1631 */
1632 struct element *arg;
1633 struct element *left;
1634 struct element *right;
1635 struct element *result;
1636 isc_boolean_t lmodified = ISC_FALSE;
1637 isc_boolean_t rmodified = ISC_FALSE;
1638
1639 arg = mapGet(expr, "add");
1640 if ((arg == NULL) || (arg->type != ELEMENT_MAP))
1641 return expr;
1642 left = mapGet(arg, "left");
1643 if (left == NULL)
1644 return expr;
1645 right = mapGet(arg, "right");
1646 if (right == NULL)
1647 return expr;
1648 left = eval_numeric_expression(left, &lmodified);
1649 if (lmodified) {
1650 mapRemove(arg, "left");
1651 mapSet(arg, left, "left");
1652 }
1653 right = eval_numeric_expression(right, &rmodified);
1654 if (rmodified) {
1655 mapRemove(arg, "right");
1656 mapSet(arg, right, "right");
1657 }
1658
1659 if ((left->type != ELEMENT_INTEGER) ||
1660 (right->type != ELEMENT_INTEGER))
1661 return expr;
1662 *modifiedp = ISC_TRUE;
1663 result = createInt(intValue(left) + intValue(right));
1664 TAILQ_CONCAT(&result->comments, &expr->comments);
1665 TAILQ_CONCAT(&result->comments, &arg->comments);
1666 TAILQ_CONCAT(&result->comments, &left->comments);
1667 TAILQ_CONCAT(&result->comments, &right->comments);
1668 return result;
1669 }
1670
1671 /* subtract */
1672 if (mapContains(expr, "subtract")) {
1673 /*
1674 * syntax := { "subtract":
1675 * { "left": <boolean_expression>,
1676 * "right": <boolean_expression> }
1677 * }
1678 * semantics: evaluate branches, return left plus right
1679 * branches
1680 */
1681 struct element *arg;
1682 struct element *left;
1683 struct element *right;
1684 struct element *result;
1685 isc_boolean_t lmodified = ISC_FALSE;
1686 isc_boolean_t rmodified = ISC_FALSE;
1687
1688 arg = mapGet(expr, "subtract");
1689 if ((arg == NULL) || (arg->type != ELEMENT_MAP))
1690 return expr;
1691 left = mapGet(arg, "left");
1692 if (left == NULL)
1693 return expr;
1694 right = mapGet(arg, "right");
1695 if (right == NULL)
1696 return expr;
1697 left = eval_numeric_expression(left, &lmodified);
1698 if (lmodified) {
1699 mapRemove(arg, "left");
1700 mapSet(arg, left, "left");
1701 }
1702 right = eval_numeric_expression(right, &rmodified);
1703 if (rmodified) {
1704 mapRemove(arg, "right");
1705 mapSet(arg, right, "right");
1706 }
1707
1708 if ((left->type != ELEMENT_INTEGER) ||
1709 (right->type != ELEMENT_INTEGER))
1710 return expr;
1711 *modifiedp = ISC_TRUE;
1712 result = createInt(intValue(left) - intValue(right));
1713 TAILQ_CONCAT(&result->comments, &expr->comments);
1714 TAILQ_CONCAT(&result->comments, &arg->comments);
1715 TAILQ_CONCAT(&result->comments, &left->comments);
1716 TAILQ_CONCAT(&result->comments, &right->comments);
1717 return result;
1718 }
1719
1720 /* multiply */
1721 if (mapContains(expr, "multiply")) {
1722 /*
1723 * syntax := { "multiply":
1724 * { "left": <boolean_expression>,
1725 * "right": <boolean_expression> }
1726 * }
1727 * semantics: evaluate branches, return left plus right
1728 * branches
1729 */
1730 struct element *arg;
1731 struct element *left;
1732 struct element *right;
1733 struct element *result;
1734 isc_boolean_t lmodified = ISC_FALSE;
1735 isc_boolean_t rmodified = ISC_FALSE;
1736
1737 arg = mapGet(expr, "multiply");
1738 if ((arg == NULL) || (arg->type != ELEMENT_MAP))
1739 return expr;
1740 left = mapGet(arg, "left");
1741 if (left == NULL)
1742 return expr;
1743 right = mapGet(arg, "right");
1744 if (right == NULL)
1745 return expr;
1746 left = eval_numeric_expression(left, &lmodified);
1747 if (lmodified) {
1748 mapRemove(arg, "left");
1749 mapSet(arg, left, "left");
1750 }
1751 right = eval_numeric_expression(right, &rmodified);
1752 if (rmodified) {
1753 mapRemove(arg, "right");
1754 mapSet(arg, right, "right");
1755 }
1756
1757 if ((left->type != ELEMENT_INTEGER) ||
1758 (right->type != ELEMENT_INTEGER))
1759 return expr;
1760 *modifiedp = ISC_TRUE;
1761 result = createInt(intValue(left) * intValue(right));
1762 TAILQ_CONCAT(&result->comments, &expr->comments);
1763 TAILQ_CONCAT(&result->comments, &arg->comments);
1764 TAILQ_CONCAT(&result->comments, &left->comments);
1765 TAILQ_CONCAT(&result->comments, &right->comments);
1766 return result;
1767 }
1768
1769 /* divide */
1770 if (mapContains(expr, "divide")) {
1771 /*
1772 * syntax := { "divide":
1773 * { "left": <boolean_expression>,
1774 * "right": <boolean_expression> }
1775 * }
1776 * semantics: evaluate branches, return left plus right
1777 * branches
1778 */
1779 struct element *arg;
1780 struct element *left;
1781 struct element *right;
1782 struct element *result;
1783 isc_boolean_t lmodified = ISC_FALSE;
1784 isc_boolean_t rmodified = ISC_FALSE;
1785
1786 arg = mapGet(expr, "divide");
1787 if ((arg == NULL) || (arg->type != ELEMENT_MAP))
1788 return expr;
1789 left = mapGet(arg, "left");
1790 if (left == NULL)
1791 return expr;
1792 right = mapGet(arg, "right");
1793 if (right == NULL)
1794 return expr;
1795 left = eval_numeric_expression(left, &lmodified);
1796 if (lmodified) {
1797 mapRemove(arg, "left");
1798 mapSet(arg, left, "left");
1799 }
1800 right = eval_numeric_expression(right, &rmodified);
1801 if (rmodified) {
1802 mapRemove(arg, "right");
1803 mapSet(arg, right, "right");
1804 }
1805
1806 if ((left->type != ELEMENT_INTEGER) ||
1807 (right->type != ELEMENT_INTEGER))
1808 return expr;
1809 if (intValue(right) == 0)
1810 return expr;
1811 *modifiedp = ISC_TRUE;
1812 result = createInt(intValue(left) / intValue(right));
1813 TAILQ_CONCAT(&result->comments, &expr->comments);
1814 TAILQ_CONCAT(&result->comments, &arg->comments);
1815 TAILQ_CONCAT(&result->comments, &left->comments);
1816 TAILQ_CONCAT(&result->comments, &right->comments);
1817 return result;
1818 }
1819
1820 /* remainder */
1821 if (mapContains(expr, "remainder")) {
1822 /*
1823 * syntax := { "remainder":
1824 * { "left": <boolean_expression>,
1825 * "right": <boolean_expression> }
1826 * }
1827 * semantics: evaluate branches, return left plus right
1828 * branches
1829 */
1830 struct element *arg;
1831 struct element *left;
1832 struct element *right;
1833 struct element *result;
1834 isc_boolean_t lmodified = ISC_FALSE;
1835 isc_boolean_t rmodified = ISC_FALSE;
1836
1837 arg = mapGet(expr, "remainder");
1838 if ((arg == NULL) || (arg->type != ELEMENT_MAP))
1839 return expr;
1840 left = mapGet(arg, "left");
1841 if (left == NULL)
1842 return expr;
1843 right = mapGet(arg, "right");
1844 if (right == NULL)
1845 return expr;
1846 left = eval_numeric_expression(left, &lmodified);
1847 if (lmodified) {
1848 mapRemove(arg, "left");
1849 mapSet(arg, left, "left");
1850 }
1851 right = eval_numeric_expression(right, &rmodified);
1852 if (rmodified) {
1853 mapRemove(arg, "right");
1854 mapSet(arg, right, "right");
1855 }
1856
1857 if ((left->type != ELEMENT_INTEGER) ||
1858 (right->type != ELEMENT_INTEGER))
1859 return expr;
1860 if (intValue(right) == 0)
1861 return expr;
1862 *modifiedp = ISC_TRUE;
1863 result = createInt(intValue(left) % intValue(right));
1864 TAILQ_CONCAT(&result->comments, &expr->comments);
1865 TAILQ_CONCAT(&result->comments, &arg->comments);
1866 TAILQ_CONCAT(&result->comments, &left->comments);
1867 TAILQ_CONCAT(&result->comments, &right->comments);
1868 return result;
1869 }
1870
1871 /* binary-and */
1872 if (mapContains(expr, "binary-and")) {
1873 /*
1874 * syntax := { "binary-and":
1875 * { "left": <boolean_expression>,
1876 * "right": <boolean_expression> }
1877 * }
1878 * semantics: evaluate branches, return left plus right
1879 * branches
1880 */
1881 struct element *arg;
1882 struct element *left;
1883 struct element *right;
1884 struct element *result;
1885 isc_boolean_t lmodified = ISC_FALSE;
1886 isc_boolean_t rmodified = ISC_FALSE;
1887
1888 arg = mapGet(expr, "binary-and");
1889 if ((arg == NULL) || (arg->type != ELEMENT_MAP))
1890 return expr;
1891 left = mapGet(arg, "left");
1892 if (left == NULL)
1893 return expr;
1894 right = mapGet(arg, "right");
1895 if (right == NULL)
1896 return expr;
1897 left = eval_numeric_expression(left, &lmodified);
1898 if (lmodified) {
1899 mapRemove(arg, "left");
1900 mapSet(arg, left, "left");
1901 }
1902 right = eval_numeric_expression(right, &rmodified);
1903 if (rmodified) {
1904 mapRemove(arg, "right");
1905 mapSet(arg, right, "right");
1906 }
1907
1908 if ((left->type != ELEMENT_INTEGER) ||
1909 (right->type != ELEMENT_INTEGER))
1910 return expr;
1911 *modifiedp = ISC_TRUE;
1912 result = createInt(intValue(left) & intValue(right));
1913 TAILQ_CONCAT(&result->comments, &expr->comments);
1914 TAILQ_CONCAT(&result->comments, &arg->comments);
1915 TAILQ_CONCAT(&result->comments, &left->comments);
1916 TAILQ_CONCAT(&result->comments, &right->comments);
1917 return result;
1918 }
1919
1920 /* binary-or */
1921 if (mapContains(expr, "binary-or")) {
1922 /*
1923 * syntax := { "binary-or":
1924 * { "left": <boolean_expression>,
1925 * "right": <boolean_expression> }
1926 * }
1927 * semantics: evaluate branches, return left plus right
1928 * branches
1929 */
1930 struct element *arg;
1931 struct element *left;
1932 struct element *right;
1933 struct element *result;
1934 isc_boolean_t lmodified = ISC_FALSE;
1935 isc_boolean_t rmodified = ISC_FALSE;
1936
1937 arg = mapGet(expr, "binary-or");
1938 if ((arg == NULL) || (arg->type != ELEMENT_MAP))
1939 return expr;
1940 left = mapGet(arg, "left");
1941 if (left == NULL)
1942 return expr;
1943 right = mapGet(arg, "right");
1944 if (right == NULL)
1945 return expr;
1946 left = eval_numeric_expression(left, &lmodified);
1947 if (lmodified) {
1948 mapRemove(arg, "left");
1949 mapSet(arg, left, "left");
1950 }
1951 right = eval_numeric_expression(right, &rmodified);
1952 if (rmodified) {
1953 mapRemove(arg, "right");
1954 mapSet(arg, right, "right");
1955 }
1956
1957 if ((left->type != ELEMENT_INTEGER) ||
1958 (right->type != ELEMENT_INTEGER))
1959 return expr;
1960 *modifiedp = ISC_TRUE;
1961 result = createInt(intValue(left) | intValue(right));
1962 TAILQ_CONCAT(&result->comments, &expr->comments);
1963 TAILQ_CONCAT(&result->comments, &arg->comments);
1964 TAILQ_CONCAT(&result->comments, &left->comments);
1965 TAILQ_CONCAT(&result->comments, &right->comments);
1966 return result;
1967 }
1968
1969 /* binary-xor */
1970 if (mapContains(expr, "binary-xor")) {
1971 /*
1972 * syntax := { "binary-xor":
1973 * { "left": <boolean_expression>,
1974 * "right": <boolean_expression> }
1975 * }
1976 * semantics: evaluate branches, return left plus right
1977 * branches
1978 */
1979 struct element *arg;
1980 struct element *left;
1981 struct element *right;
1982 struct element *result;
1983 isc_boolean_t lmodified = ISC_FALSE;
1984 isc_boolean_t rmodified = ISC_FALSE;
1985
1986 arg = mapGet(expr, "binary-xor");
1987 if ((arg == NULL) || (arg->type != ELEMENT_MAP))
1988 return expr;
1989 left = mapGet(arg, "left");
1990 if (left == NULL)
1991 return expr;
1992 right = mapGet(arg, "right");
1993 if (right == NULL)
1994 return expr;
1995 left = eval_numeric_expression(left, &lmodified);
1996 if (lmodified) {
1997 mapRemove(arg, "left");
1998 mapSet(arg, left, "left");
1999 }
2000 right = eval_numeric_expression(right, &rmodified);
2001 if (rmodified) {
2002 mapRemove(arg, "right");
2003 mapSet(arg, right, "right");
2004 }
2005
2006 if ((left->type != ELEMENT_INTEGER) ||
2007 (right->type != ELEMENT_INTEGER))
2008 return expr;
2009 *modifiedp = ISC_TRUE;
2010 result = createInt(intValue(left) ^ intValue(right));
2011 TAILQ_CONCAT(&result->comments, &expr->comments);
2012 TAILQ_CONCAT(&result->comments, &arg->comments);
2013 TAILQ_CONCAT(&result->comments, &left->comments);
2014 TAILQ_CONCAT(&result->comments, &right->comments);
2015 return result;
2016 }
2017
2018 /* client-state */
2019 if (mapContains(expr, "client-state"))
2020 /*
2021 * syntax := { "client-state": null }
2022 * semantic: return client state
2023 */
2024 return expr;
2025
2026 return expr;
2027}
2028
2029/*
2030 * Check if the two evaluated expressions are equal, not equal,
2031 * or we can't decide.
2032 */
2033
2034static struct element *
2035eval_equal_expression(struct element *left, struct element *right)
2036{
2037 struct element *result = NULL;
2038 isc_boolean_t val;
2039
2040 /* in theory boolean is not possible */
2041 if (left->type == ELEMENT_BOOLEAN) {
2042 if (right->type == ELEMENT_BOOLEAN)
2043 val = ISC_TF(boolValue(left) == boolValue(right));
2044 else if (right->type == ELEMENT_MAP)
2045 return NULL;
2046 else
2047 val = ISC_FALSE;
2048 } else
2049 /* right is boolean */
2050 if (right->type == ELEMENT_BOOLEAN) {
2051 if (left->type == ELEMENT_MAP)
2052 return NULL;
2053 else
2054 val = ISC_FALSE;
2055 } else
2056 /* left is numeric literal */
2057 if (left->type == ELEMENT_INTEGER) {
2058 if (right->type == ELEMENT_INTEGER)
2059 val = ISC_TF(intValue(left) == intValue(right));
2060 else if ((right->type == ELEMENT_MAP) &&
2061 mapContains(right, "const-int")) {
2062 struct element *ci;
2063
2064 ci = mapGet(right, "const-int");
2065 if ((ci == NULL) || (ci->type != ELEMENT_INTEGER)) {
2066 debug("bad const-int");
2067 return NULL;
2068 }
2069 val = ISC_TF(intValue(left) == intValue(ci));
2070 } else if (right->type == ELEMENT_MAP)
2071 return NULL;
2072 else
2073 val = ISC_FALSE;
2074 } else
2075 /* left is const-int */
2076 if ((left->type == ELEMENT_MAP) && mapContains(left, "const-int")) {
2077 if (right->type == ELEMENT_INTEGER) {
2078 struct element *ci;
2079
2080 ci = mapGet(left, "const-int");
2081 if ((ci == NULL) || (ci->type != ELEMENT_INTEGER)) {
2082 debug("bad const-int");
2083 return NULL;
2084 }
2085 val = ISC_TF(intValue(ci) == intValue(right));
2086 } else if ((right->type == ELEMENT_MAP) &&
2087 mapContains(right, "const-int")) {
2088 struct element *lci;
2089 struct element *rci;
2090
2091 lci = mapGet(left, "const-int");
2092 rci = mapGet(right, "const-int");
2093 if ((lci == NULL) || (lci->type != ELEMENT_INTEGER) ||
2094 (rci == NULL) || (rci->type != ELEMENT_INTEGER)) {
2095 debug("bad const-int");
2096 return NULL;
2097 }
2098 val = ISC_TF(intValue(lci) == intValue(rci));
2099 } else if (right->type == ELEMENT_MAP)
2100 return NULL;
2101 else
2102 val = ISC_FALSE;
2103 } else
2104 /* right is numeric literal */
2105 if (right->type == ELEMENT_INTEGER) {
2106 if (left->type == ELEMENT_MAP)
2107 return NULL;
2108 else
2109 val = ISC_FALSE;
2110 } else
2111 /* right is const-int */
2112 if ((right->type == ELEMENT_MAP) && mapContains(right, "const-int")) {
2113 if (left->type == ELEMENT_MAP)
2114 return NULL;
2115 else
2116 val = ISC_FALSE;
2117 } else
2118 /* left is data literal */
2119 if (left->type == ELEMENT_STRING) {
2120 if (right->type == ELEMENT_STRING)
2121 val = cmp_hexa(left, ISC_FALSE, right, ISC_FALSE);
2122 else if ((right->type == ELEMENT_MAP) &&
2123 mapContains(right, "const-data")) {
2124 struct element *cd;
2125
2126 cd = mapGet(right, "const-data");
2127 if ((cd == NULL) || (cd->type != ELEMENT_STRING)) {
2128 debug("bad const-data");
2129 return NULL;
2130 }
2131 val = cmp_hexa(left, ISC_FALSE, cd, ISC_TRUE);
2132 } else if (right->type == ELEMENT_MAP)
2133 return NULL;
2134 else
2135 val = ISC_FALSE;
2136 } else
2137 /* left is const-data */
2138 if ((left->type == ELEMENT_MAP) && mapContains(left, "const-data")) {
2139 if (right->type == ELEMENT_STRING) {
2140 struct element *cd;
2141
2142 cd = mapGet(left, "const-data");
2143 if ((cd == NULL) || (cd->type != ELEMENT_STRING)) {
2144 debug("bad const-data");
2145 return NULL;
2146 }
2147 val = cmp_hexa(cd, ISC_TRUE, right, ISC_FALSE);
2148 } else if ((right->type == ELEMENT_MAP) &&
2149 mapContains(right, "const-data")) {
2150 struct element *lcd;
2151 struct element *rcd;
2152
2153 lcd = mapGet(left, "const-data");
2154 rcd = mapGet(right, "const-data");
2155 if ((lcd == NULL) || (lcd->type != ELEMENT_STRING) ||
2156 (rcd == NULL) || (rcd->type != ELEMENT_STRING)) {
2157 debug("bad const-data");
2158 return NULL;
2159 }
2160 val = cmp_hexa(lcd, ISC_TRUE, rcd, ISC_TRUE);
2161 } else if (right->type == ELEMENT_MAP)
2162 return NULL;
2163 else
2164 val = ISC_FALSE;
2165 } else
2166 /* right is data literal */
2167 if (right->type == ELEMENT_STRING) {
2168 if (left->type == ELEMENT_MAP)
2169 return NULL;
2170 else
2171 val = ISC_FALSE;
2172 } else
2173 /* right is const-data */
2174 if ((right->type == ELEMENT_MAP) && mapContains(right, "const-data")) {
2175 if (left->type == ELEMENT_MAP)
2176 return NULL;
2177 else
2178 val = ISC_FALSE;
2179 } else
2180 /* impossible cases */
2181 if ((left->type != ELEMENT_MAP) || (right->type != ELEMENT_MAP)) {
2182 debug("equal between unexpected %s and %s",
2183 type2name(left->type), type2name(right->type));
2184 val = ISC_FALSE;
2185 } else
2186 /* can't decide */
2187 return NULL;
2188
2189 result = createBool(val);
2190 TAILQ_CONCAT(&result->comments, &left->comments);
2191 TAILQ_CONCAT(&result->comments, &right->comments);
2192 return result;
2193}
2194
2195static isc_boolean_t
2196cmp_hexa(struct element *left, isc_boolean_t left_is_hexa,
2197 struct element *right, isc_boolean_t right_is_hexa)
2198{
2199 struct string *sleft;
2200 struct string *sright;
2201
2202 /* both are not hexa */
2203 if (!left_is_hexa && !right_is_hexa) {
2204 sleft = stringValue(left);
2205 sright = stringValue(right);
2206 /* eqString() compares lengths them use memcmp() */
2207 return eqString(sleft, sright);
2208 }
2209
2210 /* both are hexa */
2211 if (left_is_hexa && right_is_hexa) {
2212 sleft = stringValue(left);
2213 sright = stringValue(right);
2214 if (sleft->length != sright->length)
2215 return ISC_FALSE;
2216 if (sleft->length == 0) {
2217 debug("empty const-data");
2218 return ISC_TRUE;
2219 }
2220 return ISC_TF(strcasecmp(sleft->content,
2221 sright->content) == 0);
2222 }
2223
2224 /* put the hexa at left */
2225 if (left_is_hexa) {
2226 sleft = hexaValue(left);
2227 sright = stringValue(right);
2228 } else {
2229 sleft = hexaValue(right);
2230 sright = stringValue(left);
2231 }
2232
2233 /* hexa is double length */
2234 if (sleft->length != 2 * sright->length)
2235 return ISC_FALSE;
2236
2237 /* build the hexa representation */
2238 makeStringExt(sright->length, sright->content, 'X');
2239
2240 return ISC_TF(strcasecmp(sleft->content, sright->content) == 0);
2241}
2242
2243static void
2244debug(const char* fmt, ...)
2245{
2246 va_list list;
2247
2248 va_start(list, fmt);
2249 vfprintf(stderr, fmt, list);
2250 fprintf(stderr, "\n");
2251 va_end(list);
2252}
void concatString(struct string *s, const struct string *a)
Definition data.c:330
isc_boolean_t eqString(const struct string *s, const struct string *o)
Definition data.c:343
struct string * makeString(int l, const char *s)
Definition data.c:44
isc_boolean_t boolValue(const struct element *e)
Definition data.c:399
struct element * copy(struct element *e)
Definition data.c:1115
void listRemove(struct element *l, int i)
Definition data.c:707
struct element * createBool(isc_boolean_t b)
Definition data.c:469
struct string * allocString(void)
Definition data.c:32
void appendString(struct string *s, const char *a)
Definition data.c:311
struct element * listGet(struct element *l, int i)
Definition data.c:646
struct string * stringValue(struct element *e)
Definition data.c:408
struct element * createNull(void)
Definition data.c:481
void concat(struct element *l, struct element *o)
Definition data.c:748
isc_boolean_t mapContains(const struct element *m, const char *k)
Definition data.c:811
struct string * hexaValue(struct element *s)
Definition data.c:1234
struct element * createInt(int64_t i)
Definition data.c:445
void mapSet(struct element *m, struct element *e, const char *k)
Definition data.c:777
void listSet(struct element *l, struct element *e, int i)
Definition data.c:669
size_t listSize(const struct element *l)
Definition data.c:730
struct element * createMap(void)
Definition data.c:516
struct element * createString(const struct string *s)
Definition data.c:492
void mapRemove(struct element *m, const char *k)
Definition data.c:792
struct element * mapGet(struct element *m, const char *k)
Definition data.c:759
int64_t intValue(const struct element *e)
Definition data.c:383
const char * type2name(int t)
Definition data.c:867
struct string * makeStringExt(int l, const char *s, char fmt)
Definition data.c:64
#define ELEMENT_INTEGER
Definition data.h:162
#define ELEMENT_LIST
Definition data.h:167
#define TAILQ_INIT(head)
Definition data.h:72
#define TAILQ_CONCAT(head1, head2)
Definition data.h:49
isc_boolean_t
Definition data.h:150
#define ELEMENT_STRING
Definition data.h:166
#define ISC_TF(x)
Definition data.h:154
#define ELEMENT_BOOLEAN
Definition data.h:164
#define ISC_TRUE
Definition data.h:153
#define ISC_FALSE
Definition data.h:152
#define ELEMENT_MAP
Definition data.h:168
int local_family
Definition discover.c:59
struct element * eval_boolean_expression(struct element *expr, isc_boolean_t *modifiedp)
Definition eval.c:72
struct element * eval_expression(struct element *expr, isc_boolean_t *modifiedp)
Definition eval.c:43
struct element * eval_data_expression(struct element *expr, isc_boolean_t *modifiedp)
Definition eval.c:476
struct element * eval_numeric_expression(struct element *expr, isc_boolean_t *modifiedp)
Definition eval.c:1481
Definition tree.h:60
int type
Definition data.h:217
struct comments comments
Definition data.h:222
Definition data.h:171
char * content
Definition data.h:173
size_t length
Definition data.h:172
int is_boolean_expression(struct expression *expr)
Definition tree.c:3031
int is_numeric_expression(struct expression *expr)
Definition tree.c:3078
int is_data_expression(struct expression *expr)
Definition tree.c:3048