The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
calc.c
Go to the documentation of this file.
1/*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: 0e71073d4e67a85fe40bacab85c7b7e09eee555e $
19 *
20 * @file src/lib/util/calc.c
21 * @brief Functions to perform calculations on leaf values
22 *
23 * @copyright 2021 Network RADIUS SAS (legal@networkradius.com)
24 */
25
26RCSID("$Id: 0e71073d4e67a85fe40bacab85c7b7e09eee555e $")
27
28#include <freeradius-devel/util/strerror.h>
29#include <freeradius-devel/util/regex.h>
30#include <math.h>
31#include "calc.h"
32
33#define swap(_a, _b) do { __typeof__ (_a) _tmp = _a; _a = _b; _b = _tmp; } while (0)
34
35#define ERR_ZERO (-5)
36#define ERR_UNDERFLOW (-4)
37#define ERR_OVERFLOW (-3)
38#define ERR_INVALID (-2)
39
40#define COERCE(_vb, _box, _type, _enumv) do { \
41 if (_vb->type != _type) { \
42 if (fr_value_box_cast(NULL, &_box, _type, _enumv, _vb) < 0) return -1; \
43 _vb = &_box; \
44 } \
45 } while (0)
46
47#define COERCE_A(_type, _enumv) COERCE(a, one, _type, _enumv)
48#define COERCE_B(_type, _enumv) COERCE(b, two, _type, _enumv)
49
50/** Updates type (a,b) -> c
51 *
52 * Note that we MUST have a less than b here. Otherwise there will
53 * be two entries for the same upcast, and the entries may get out of
54 * sync.
55 *
56 * These upcasts are for operations.
57 *
58 *
59 * If one side is a string and the other isn't, then we try to parse
60 * the string as the type of the other side.
61 *
62 * If one side is an octets type and the other isn't, then we try to
63 * parse the octets as the type of the other side.
64 */
65static const fr_type_t upcast_op[FR_TYPE_MAX + 1][FR_TYPE_MAX + 1] = {
66 /*
67 * string / octets -> octets
68 */
69 [FR_TYPE_STRING] = {
72 },
73
74 [FR_TYPE_OCTETS] = {
76 },
77
79 /*
80 * ipaddr + int --> prefix (generally only "and")
81 */
83
84 /*
85 * 192.168.0.255 - 192.168.0.1 -> int64
86 */
88 },
89
90 /*
91 * IPv6 mod IPv6 -> ????
92 */
95 },
96
97 /*
98 * Prefix + int --> ipaddr
99 */
104
106
111
113
118
121 },
122
126
128
133
135
140
143 },
144
148
150
155
157
162
165 },
166
169
174
176
181
184 },
185
186 /*
187 * Bools and to pretty much any numerical type result in
188 * the other integer.
189 */
190 [FR_TYPE_BOOL] = {
192
195
200
202
204
209
211
214 },
215
216 /*
217 * Various ints get cast to the next highest size which
218 * can hold their values.
219 */
220 [FR_TYPE_UINT8] = {
223
228
230
232
237
239
242 },
243
244 [FR_TYPE_UINT16] = {
247
251
253
255
260
262
265 },
266
267 [FR_TYPE_UINT32] = {
270
273
275
277
282
284
287 },
288
289 [FR_TYPE_UINT64] = {
292
295
297
299
301
304 },
305
306 [FR_TYPE_SIZE] = {
308
313
315
318 },
319
320 [FR_TYPE_DATE] = {
322
327
330
333 },
334
335 /*
336 * Signed ints
337 */
338 [FR_TYPE_INT8] = {
341
346
348
351 },
352
353 [FR_TYPE_INT16] = {
356
360
363 },
364
365 [FR_TYPE_INT32] = {
368
370
373 },
374
375 [FR_TYPE_INT64] = {
378
380
384 },
385
388
390
393 },
394
395 [FR_TYPE_FLOAT32] = {
397
400 },
401
402 [FR_TYPE_FLOAT64] = {
405 },
406};
407
408/** Updates type (a,b) -> c
409 *
410 * Note that we MUST have a less than b here. Otherwise there will
411 * be two entries for the same upcast, and the entries may get out of
412 * sync.
413 *
414 * These upcasts are for comparisons. In some cases, we can promote
415 * one data type to another, and then compare them. However, this is
416 * not always possible.
417 *
418 * If one side is a string and the other isn't, then we try to parse
419 * the string as the type of the other side.
420 *
421 * If one side is an octets type and the other isn't, then we try to
422 * parse the octets as the type of the other side.
423 *
424 * @todo - check this table against fr_type_promote()
425 */
426static const fr_type_t upcast_cmp[FR_TYPE_MAX + 1][FR_TYPE_MAX + 1] = {
427 [FR_TYPE_STRING] = {
429 },
430
434
436
439
442
444 },
445
449
451
453 },
454
458
460
463 },
464
468
470 },
471
472 [FR_TYPE_IFID] = {
475 },
476
479 },
480
481 [FR_TYPE_ETHERNET] = {
484 },
485
486 /*
487 * Bools compared to pretty much any numerical type
488 * result in the other integer.
489 */
490 [FR_TYPE_BOOL] = {
493
498
500
502
507
509
512 },
513
514 /*
515 * Integers of the same sign get cast to the larger of
516 * the data type. Integers of different signs get cast
517 * to a *different* data type which can hold all values
518 * from both sides.
519 */
520 [FR_TYPE_UINT8] = {
523
527
529
531
536
538
541 },
542
543 [FR_TYPE_UINT16] = {
546
549
551
553
558
560
563 },
564
565 [FR_TYPE_UINT32] = {
568
570
572
574
579
581
584 },
585
586 [FR_TYPE_UINT64] = {
589
591
593
595
598 },
599
600 [FR_TYPE_SIZE] = {
602
607
610 },
611
612 [FR_TYPE_DATE] = {
614
619
621
624 },
625
626 /*
627 * Signed ints
628 */
629 [FR_TYPE_INT8] = {
632
636
638
641 },
642
643 [FR_TYPE_INT16] = {
646
649
652 },
653
654 [FR_TYPE_INT32] = {
657
659
662 },
663
664 [FR_TYPE_INT64] = {
667
669 },
670
673
676 },
677
678 [FR_TYPE_FLOAT32] = {
680
682 },
683
684 [FR_TYPE_FLOAT64] = {
686 },
687};
688
697
699{
700 fr_strerror_printf("Cannot perform mathematical operations on data type %s",
702 return -1;
703}
704
705static int handle_result(fr_type_t type, fr_token_t op, int rcode)
706{
707 if (rcode == ERR_ZERO) {
708 fr_strerror_const("Cannot divide by zero.");
709
710 } else if (rcode == ERR_UNDERFLOW) {
711 fr_strerror_printf("Value underflows '%s' when calculating result.",
713
714 } else if (rcode == ERR_OVERFLOW) {
715 fr_strerror_printf("Value overflows '%s' when calculating result.",
717
718 } else if (rcode == ERR_INVALID) {
719 fr_strerror_printf("Invalid assignment operator '%s' for result type '%s'.",
720 fr_tokens[op],
722 }
723
724 return rcode;
725}
726
727static int calc_bool(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b)
728{
729 fr_value_box_t one, two;
730
731 fr_assert(dst->type == FR_TYPE_BOOL);
732
733 COERCE_A(FR_TYPE_BOOL, NULL);
734 COERCE_B(FR_TYPE_BOOL, NULL);
735
736 switch (op) {
737 case T_ADD:
738 /*
739 * 1+1 = 2, which isn't a valid boolean value.
740 */
741 if (a->vb_bool & b->vb_bool) return ERR_OVERFLOW;
742
743 dst->vb_bool = a->vb_bool | b->vb_bool;
744 break;
745
746 case T_SUB:
747 /*
748 * 0-1 = -1, which isn't a valid boolean value.
749 */
750 if (a->vb_bool < b->vb_bool) return ERR_UNDERFLOW;
751
752 dst->vb_bool = a->vb_bool - b->vb_bool;
753 break;
754
755 case T_MUL: /* MUL is just AND here! */
756 case T_AND:
757 dst->vb_bool = a->vb_bool & b->vb_bool;
758 break;
759
760 case T_OR:
761 dst->vb_bool = a->vb_bool | b->vb_bool;
762 break;
763
764 case T_XOR:
765 dst->vb_bool = a->vb_bool ^ b->vb_bool;
766 break;
767
768 default:
769 return ERR_INVALID;
770 }
771
772 return 0;
773}
774
775static int calc_date(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b)
776{
777 fr_value_box_t one, two;
778 bool overflow;
779 int64_t when;
780
781 fr_assert(dst->type == FR_TYPE_DATE);
782
783 if ((a->type == FR_TYPE_DATE) && (b->type == FR_TYPE_DATE)) {
784 fr_strerror_const("Cannot perform operation on two values of type 'date'. One value must be a number.");
785 return -1;
786 }
787
788 fr_assert(!dst->enumv); /* unix time is always seconds */
789
790 /*
791 * Cast dates to time delta, do the conversions.
792 */
795
796 switch (op) {
797 case T_ADD:
798 if (!fr_add(&when, fr_time_delta_unwrap(a->vb_time_delta), fr_time_delta_unwrap(b->vb_time_delta))) return ERR_OVERFLOW;
799
800 dst->vb_date = fr_unix_time_from_integer(&overflow, when, FR_TIME_RES_NSEC);
801 if (overflow) return ERR_OVERFLOW;
802 break;
803
804 case T_SUB:
805 if (!fr_sub(&when, fr_time_delta_unwrap(a->vb_time_delta), fr_time_delta_unwrap(b->vb_time_delta))) return ERR_UNDERFLOW;
806
807 dst->vb_date = fr_unix_time_from_integer(&overflow, when, FR_TIME_RES_NSEC);
808 if (overflow) return ERR_UNDERFLOW;
809 break;
810
811 default:
812 return ERR_INVALID; /* invalid operator */
813 }
814
815 return 0;
816}
817
818static int calc_time_delta(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b)
819{
820 fr_value_box_t one, two;
821 int64_t when;
822
823 fr_assert(dst->type == FR_TYPE_TIME_DELTA);
824
825 /*
826 * We can subtract two dates to get a time delta, but we
827 * cannot add two dates to get a time delta.
828 */
829 if ((a->type == FR_TYPE_DATE) && (b->type == FR_TYPE_DATE)) {
830 if (op != T_SUB) {
831 fr_strerror_const("Cannot perform operation on two values of type 'date'.");
832 return -1;
833 }
834 }
835
836 /*
837 * date % (time_delta) 1d --> time_delta
838 */
839 if (op == T_MOD) {
840 /*
841 * We MUST specify date ranges as a time delta, not as an integer. And it must be a
842 * positive time delta.
843 */
844 if ((b->type != FR_TYPE_TIME_DELTA) || !fr_time_delta_ispos(b->vb_time_delta)) {
845 return ERR_INVALID;
846 }
847
848 dst->vb_time_delta = fr_time_delta_wrap(fr_unix_time_unwrap(a->vb_date) % fr_time_delta_unwrap(b->vb_time_delta));
849 return 0;
850 }
851
852 /*
853 * Unix times are always converted 1-1 to our internal
854 * TIME_DELTA.
855 *
856 * We cast the inputs based on the destination time resolution. So "5ms + 5" = "10ms".
857 */
858 COERCE_A(FR_TYPE_TIME_DELTA, dst->enumv);
859
860 if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
861 /*
862 * Don't touch the RHS.
863 */
864 fr_assert(b->type == FR_TYPE_UINT32);
865
866 } else {
867 COERCE_B(FR_TYPE_TIME_DELTA, dst->enumv);
868 }
869
870 switch (op) {
871 case T_ADD:
872 if (!fr_add(&when, fr_time_delta_unwrap(a->vb_time_delta), fr_time_delta_unwrap(b->vb_time_delta))) return ERR_OVERFLOW;
873 dst->vb_time_delta = fr_time_delta_wrap(when);
874 break;
875
876 case T_SUB:
877 if (!fr_sub(&when, fr_time_delta_unwrap(a->vb_time_delta), fr_time_delta_unwrap(b->vb_time_delta))) return ERR_UNDERFLOW;
878 dst->vb_time_delta = fr_time_delta_wrap(when);
879 break;
880
881 case T_RSHIFT:
882 if (b->vb_uint32 >= 64) return ERR_UNDERFLOW;
883
884 when = fr_time_delta_unwrap(a->vb_time_delta) >> b->vb_uint32;
885 dst->vb_time_delta = fr_time_delta_wrap(when);
886 break;
887
888 case T_LSHIFT:
889 if (b->vb_uint32 >= 64) return ERR_OVERFLOW;
890
891 when = fr_time_delta_unwrap(a->vb_time_delta) << b->vb_uint32;
892 dst->vb_time_delta = fr_time_delta_wrap(when);
893 break;
894
895 default:
896 return ERR_INVALID; /* invalid operator */
897 }
898
899 return 0;
900
901}
902
903static int calc_octets(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b)
904{
905 uint8_t *buf;
906 size_t len;
907 fr_value_box_t one = {};
908 fr_value_box_t two = {};
909
910 fr_assert(dst->type == FR_TYPE_OCTETS);
911
912 COERCE_A(FR_TYPE_OCTETS, dst->enumv);
913
914 if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
915 /*
916 * Don't touch the RHS.
917 */
918 fr_assert(b->type == FR_TYPE_UINT32);
919
920 } else {
921 COERCE_B(FR_TYPE_OCTETS, dst->enumv);
922 }
923
924 len = a->vb_length + b->vb_length;
925
926 switch (op) {
927 case T_ADD: /* dst = a . b */
928 buf = talloc_array(ctx, uint8_t, len);
929 if (!buf) {
930 oom:
931 fr_strerror_const("Out of memory");
932 return -1;
933 }
934
935 memcpy(buf, a->vb_octets, a->vb_length);
936 memcpy(buf + a->vb_length, b->vb_octets, b->vb_length);
937
938 fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, false);
941 break;
942
943 case T_SUB:
944 /*
945 * The inverse of add!
946 */
947 if (a->vb_length < b->vb_length) {
948 fr_strerror_const("Suffix to remove is longer than input string.");
949 return -1;
950 }
951
952 if (memcmp(a->vb_octets + a->vb_length - b->vb_length, b->vb_strvalue, b->vb_length) != 0) {
953 fr_strerror_const("Suffix to remove is not a suffix of the input string.");
954 return -1;
955 }
956
957 len = a->vb_length - b->vb_length;
958 buf = talloc_array(ctx, uint8_t, len);
959 if (!buf) goto oom;
960
961 memcpy(buf, a->vb_strvalue, len);
962
963 fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, false);
965 break;
966
967 case T_AND:
968 if (a->vb_length != b->vb_length) {
969 length_error:
970 fr_strerror_const("Cannot perform operation on strings of different length");
971 return -1;
972 }
973
974 buf = talloc_array(ctx, uint8_t, a->vb_length);
975 if (!buf) goto oom;
976
977 for (len = 0; len < a->vb_length; len++) {
978 buf[len] = a->vb_octets[len] & b->vb_octets[len];
979 }
980
981 set_result:
982 fr_value_box_memdup_shallow(dst, dst->enumv, buf, a->vb_length, false);
985 break;
986
987 case T_OR:
988 if (a->vb_length != b->vb_length) goto length_error;
989
990 buf = talloc_array(ctx, uint8_t, a->vb_length);
991 if (!buf) goto oom;
992
993 for (len = 0; len < a->vb_length; len++) {
994 buf[len] = a->vb_octets[len] | b->vb_octets[len];
995 }
996 goto set_result;
997
998 case T_XOR:
999 if (a->vb_length != b->vb_length) goto length_error;
1000
1001 buf = talloc_array(ctx, uint8_t, a->vb_length);
1002 if (!buf) goto oom;
1003
1004 for (len = 0; len < a->vb_length; len++) {
1005 buf[len] = a->vb_octets[len] ^ b->vb_octets[len];
1006 }
1007
1008 goto set_result;
1009
1010 case T_RSHIFT:
1011 if (b->vb_uint32 > a->vb_length) return ERR_UNDERFLOW;
1012
1013 len = a->vb_length - b->vb_uint32;
1014 buf = talloc_array(ctx, uint8_t, len);
1015 if (!buf) goto oom;
1016
1017 memcpy(buf, a->vb_octets, len);
1018
1019 fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, false);
1021 break;
1022
1023 case T_LSHIFT:
1024 if (b->vb_uint32 > a->vb_length) return ERR_OVERFLOW;
1025
1026 len = a->vb_length - b->vb_uint32;
1027
1028 buf = talloc_array(ctx, uint8_t, len);
1029 if (!buf) goto oom;
1030
1031 memcpy(buf, a->vb_octets + b->vb_uint32, len);
1032
1033 fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, false);
1035 break;
1036
1037 default:
1038 return ERR_INVALID; /* invalid operator */
1039 }
1040
1041 if (a == &one) fr_value_box_clear_value(&one);
1042 if (b == &two) fr_value_box_clear_value(&two);
1043
1044 return 0;
1045}
1046
1047static int calc_string(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b)
1048{
1049 char *buf;
1050 size_t len;
1051 fr_value_box_t one = {};
1052 fr_value_box_t two = {};
1053
1054 fr_assert(dst->type == FR_TYPE_STRING);
1055
1056 COERCE_A(FR_TYPE_STRING, dst->enumv);
1057
1058 if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
1059 /*
1060 * Don't touch the RHS.
1061 */
1062 fr_assert(b->type == FR_TYPE_UINT32);
1063
1064 } else {
1065 COERCE_B(FR_TYPE_STRING, dst->enumv);
1066 }
1067
1068 len = a->vb_length + b->vb_length;
1069
1070 switch (op) {
1071 case T_ADD:
1072 buf = talloc_array(ctx, char, len + 1);
1073 if (!buf) {
1074 oom:
1075 fr_strerror_const("Out of memory");
1076 return -1;
1077 }
1078
1079 len = a->vb_length + b->vb_length;
1080 memcpy(buf, a->vb_strvalue, a->vb_length);
1081 memcpy(buf + a->vb_length, b->vb_strvalue, b->vb_length);
1082 buf[len] = '\0';
1083
1084 fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1087 break;
1088
1089 case T_XOR: /* is prepend for strings */
1090 buf = talloc_array(ctx, char, len + 1);
1091 if (!buf) goto oom;
1092
1093 len = a->vb_length + b->vb_length;
1094 memcpy(buf, b->vb_strvalue, b->vb_length);
1095 memcpy(buf + b->vb_length, a->vb_strvalue, a->vb_length);
1096 buf[len] = '\0';
1097
1098 fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1101 break;
1102
1103 case T_SUB:
1104 /*
1105 * The inverse of add!
1106 */
1107 if (a->vb_length < b->vb_length) {
1108 fr_strerror_const("Suffix to remove is longer than input string");
1109 return -1;
1110 }
1111
1112 if (memcmp(a->vb_strvalue + a->vb_length - b->vb_length, b->vb_strvalue, b->vb_length) != 0) {
1113 fr_strerror_const("Right side of substract is not a suffix of the input string");
1114 return -1;
1115 }
1116
1117 len = a->vb_length - b->vb_length;
1118 buf = talloc_array(ctx, char, len + 1);
1119 if (!buf) goto oom;
1120
1121 memcpy(buf, a->vb_strvalue, len);
1122 buf[len] = '\0';
1123
1124 fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1126 break;
1127
1128 case T_RSHIFT:
1129 if (b->vb_uint32 > a->vb_length) return ERR_UNDERFLOW;
1130
1131 len = a->vb_length - b->vb_uint32;
1132 buf = talloc_array(ctx, char, len + 1);
1133 if (!buf) goto oom;
1134
1135 memcpy(buf, a->vb_strvalue, len);
1136 buf[len] = '\0';
1137
1138 fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1140 break;
1141
1142 case T_LSHIFT:
1143 if (b->vb_uint32 > a->vb_length) return ERR_OVERFLOW;
1144
1145 len = a->vb_length - b->vb_uint32;
1146
1147 buf = talloc_array(ctx, char, len + 1);
1148 if (!buf) goto oom;
1149
1150 memcpy(buf, a->vb_strvalue + b->vb_uint32, len);
1151 buf[len] = '\0';
1152
1153 fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1155 break;
1156
1157 default:
1158 return ERR_INVALID; /* invalid operator */
1159 }
1160
1161 if (a == &one) fr_value_box_clear_value(&one);
1162 if (b == &two) fr_value_box_clear_value(&two);
1163
1164 return 0;
1165}
1166
1168{
1169 switch (in->type) {
1170 default:
1171 fr_strerror_printf("Cannot operate on ipaddr and %s",
1172 fr_type_to_str(in->type));
1173 return -1;
1174
1176 if (in->vb_ip.af == AF_INET6) goto cast_ipv6_addr;
1177
1178 fr_value_box_init(out, FR_TYPE_IPV4_ADDR, NULL, in->tainted);
1179 out->vb_ip = in->vb_ip;
1180 break;
1181
1183 if (in->vb_ip.af == AF_INET6) goto cast_ipv6_prefix;
1184
1185 fr_value_box_init(out, FR_TYPE_IPV4_PREFIX, NULL, in->tainted);
1186 out->vb_ip = in->vb_ip;
1187 break;
1188
1190 case FR_TYPE_IPV4_ADDR:
1191 if (unlikely(fr_value_box_copy(NULL, out, in) < 0)) return -1;
1192 break;
1193
1194 case FR_TYPE_IPV6_ADDR:
1196 if (fr_value_box_cast(NULL, out, FR_TYPE_IPV4_ADDR, NULL, in) < 0) return -1;
1197 break;
1198
1200 cast_ipv6_prefix:
1201 if (fr_value_box_cast(NULL, out, FR_TYPE_IPV4_PREFIX, NULL, in) < 0) return -1;
1202 break;
1203
1204 /*
1205 * All of these get mashed to 32-bits. The cast
1206 * operation will check bounds (both negative and
1207 * positive) on the run-time values.
1208 */
1209 case FR_TYPE_BOOL:
1210
1211 case FR_TYPE_UINT8:
1212 case FR_TYPE_UINT16:
1213 case FR_TYPE_UINT32:
1214 case FR_TYPE_UINT64:
1215
1216 case FR_TYPE_SIZE:
1217
1218 case FR_TYPE_INT8:
1219 case FR_TYPE_INT16:
1220 case FR_TYPE_INT32:
1221 case FR_TYPE_INT64:
1222
1223 case FR_TYPE_FLOAT32:
1224 case FR_TYPE_FLOAT64:
1225 if (fr_value_box_cast(NULL, out, FR_TYPE_UINT32, NULL, in) < 0) return -1;
1226 break;
1227 }
1228
1229 return 0;
1230}
1231
1232static int calc_ipv4_addr(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *in1, fr_token_t op, fr_value_box_t const *in2)
1233{
1234 fr_value_box_t one, two;
1235 fr_value_box_t *a, *b;
1236
1237 fr_assert((dst->type == FR_TYPE_IPV4_ADDR) || (dst->type == FR_TYPE_COMBO_IP_ADDR));
1238
1239 if (cast_ipv4_addr(&one, in1) < 0) return -1;
1240 a = &one;
1241
1242 if (cast_ipv4_addr(&two, in2) < 0) return -1;
1243 b = &two;
1244
1245 switch (op) {
1246 case T_ADD:
1247 case T_OR:
1248 /*
1249 * For simplicity, make sure that the prefix is first.
1250 */
1251 if (b->type == FR_TYPE_IPV4_PREFIX) swap(a,b);
1252
1253 /*
1254 * We can only add something to a prefix, and
1255 * that something has to be a number. The cast
1256 * operation already ensured that the number is
1257 * uint32, and is at least vaguely within the
1258 * allowed range.
1259 */
1260 if (a->type != FR_TYPE_IPV4_PREFIX) return ERR_INVALID;
1261
1262 if (b->type != FR_TYPE_UINT32) return ERR_INVALID;
1263
1264 /*
1265 * Trying to add a number outside of the given prefix. That's not allowed.
1266 */
1267 if (b->vb_uint32 >= (((uint32_t) 1) << (32 - a->vb_ip.prefix))) return ERR_OVERFLOW;
1268
1269 dst->vb_ip.af = AF_INET;
1270 dst->vb_ipv4addr = htonl(ntohl(a->vb_ipv4addr) | b->vb_uint32);
1271 dst->vb_ip.prefix = 32;
1274 break;
1275
1276 default:
1277 return ERR_INVALID;
1278 }
1279
1280 return 0;
1281}
1282
1283static int calc_ipv4_prefix(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b)
1284{
1285 int prefix;
1286 fr_value_box_t one, two, tmp;
1287
1288 fr_assert((dst->type == FR_TYPE_IPV4_PREFIX) || (dst->type == FR_TYPE_COMBO_IP_PREFIX));
1289
1290 switch (op) {
1291 case T_AND:
1292 if (fr_type_is_integer(a->type)) {
1293 if (fr_value_box_cast(NULL, &one, FR_TYPE_UINT32, NULL, a) < 0) return -1;
1294
1295 a = &one;
1296 swap(a, b);
1297
1298 } else if (fr_type_is_integer(b->type)) {
1299 if (fr_value_box_cast(NULL, &two, FR_TYPE_UINT32, NULL, b) < 0) return -1;
1300 b = &two;
1301
1302 } else {
1303 fr_strerror_const("Invalid input types for ipv4prefix");
1304 return -1;
1305 }
1306
1307 switch (a->type) {
1308 case FR_TYPE_IPV6_ADDR:
1309 if (fr_value_box_cast(NULL, &tmp, FR_TYPE_IPV4_ADDR, NULL, a) < 0) return -1;
1310 a = &tmp;
1311 break;
1312
1313 case FR_TYPE_IPV4_ADDR:
1315 break;
1316
1317 default:
1318 fr_strerror_printf("Invalid input data type '%s' for logical 'and'",
1319 fr_type_to_str(a->type));
1320
1321 return -1;
1322 }
1323
1324 if (b->vb_uint32 == 0) { /* set everything to zero */
1325 dst->vb_ipv4addr = 0;
1326 prefix = 0;
1327
1328 } else if ((~b->vb_uint32) == 0) { /* all 1's */
1329 dst->vb_ipv4addr = a->vb_ipv4addr;
1330 prefix = 32;
1331
1332 } else {
1333 uint32_t mask;
1334
1335 mask = ~b->vb_uint32; /* 0xff00 -> 0x00ff */
1336 mask++; /* 0x00ff -> 0x0100 */
1337 if ((mask & b->vb_uint32) != mask) {
1338 fr_strerror_printf("Invalid network mask '0x%08x'", b->vb_uint32);
1339 return -1;
1340 }
1341
1342 mask = 0xfffffffe;
1343 prefix = 31;
1344
1345 while (prefix > 0) {
1346 if (mask == b->vb_uint32) break;
1347
1348 prefix--;
1349 /* coverity[overflow_const] */
1350 mask <<= 1;
1351 }
1352 fr_assert(prefix > 0);
1353
1354 dst->vb_ipv4addr = htonl(ntohl(a->vb_ipv4addr) & b->vb_uint32);
1355 }
1356
1357 dst->vb_ip.af = AF_INET;
1358 dst->vb_ip.prefix = prefix;
1359 break;
1360
1361 default:
1362 return ERR_INVALID;
1363 }
1364
1365 return 0;
1366}
1367
1369{
1370 switch (in->type) {
1371 default:
1372 fr_strerror_printf("Cannot operate on ipv6addr and %s",
1373 fr_type_to_str(in->type));
1374 return -1;
1375
1377 if (in->vb_ip.af == AF_INET) goto cast_ipv4_addr;
1378
1379 fr_assert(in->vb_ip.af == AF_INET6);
1380 fr_value_box_init(out, FR_TYPE_IPV6_ADDR, NULL, in->tainted);
1381 out->vb_ip = in->vb_ip;
1382 break;
1383
1385 if (in->vb_ip.af == AF_INET) goto cast_ipv4_prefix;
1386
1387 fr_assert(in->vb_ip.af == AF_INET6);
1388 fr_value_box_init(out, FR_TYPE_IPV6_PREFIX, NULL, in->tainted);
1389 out->vb_ip = in->vb_ip;
1390 break;
1391
1392
1394 case FR_TYPE_IPV6_ADDR:
1395 if (unlikely(fr_value_box_copy(NULL, out, in) < 0)) return -1;
1396 break;
1397
1398 case FR_TYPE_IPV4_ADDR:
1400 if (fr_value_box_cast(NULL, out, FR_TYPE_IPV6_ADDR, NULL, in) < 0) return -1;
1401 break;
1402
1404 cast_ipv4_prefix:
1405 if (fr_value_box_cast(NULL, out, FR_TYPE_IPV6_PREFIX, NULL, in) < 0) return -1;
1406 break;
1407
1408 /*
1409 * All of these get mashed to 64-bits. The cast
1410 * operation will check bounds (both negative and
1411 * positive) on the run-time values.
1412 */
1413 case FR_TYPE_BOOL:
1414
1415 case FR_TYPE_UINT8:
1416 case FR_TYPE_UINT16:
1417 case FR_TYPE_UINT32:
1418 case FR_TYPE_UINT64:
1419
1420 case FR_TYPE_SIZE:
1421
1422 case FR_TYPE_INT8:
1423 case FR_TYPE_INT16:
1424 case FR_TYPE_INT32:
1425 case FR_TYPE_INT64:
1426
1427 case FR_TYPE_FLOAT32:
1428 case FR_TYPE_FLOAT64:
1429 if (fr_value_box_cast(NULL, out, FR_TYPE_UINT64, NULL, in) < 0) return -1;
1430 break;
1431 }
1432
1433 return 0;
1434}
1435
1436static int calc_ipv6_addr(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *in1, fr_token_t op, fr_value_box_t const *in2)
1437{
1438 fr_value_box_t one, two;
1439 fr_value_box_t *a, *b;
1440 int i;
1441 uint64_t mask;
1442
1443 fr_assert((dst->type == FR_TYPE_IPV6_ADDR) || (dst->type == FR_TYPE_COMBO_IP_ADDR));
1444
1445 if (cast_ipv6_addr(&one, in1) < 0) return -1;
1446 a = &one;
1447
1448 if (cast_ipv6_addr(&two, in2) < 0) return -1;
1449 b = &two;
1450
1451 switch (op) {
1452 case T_ADD:
1453 case T_OR:
1454 /*
1455 * For simplicity, make sure that the prefix is first.
1456 */
1457 if (b->type == FR_TYPE_IPV6_PREFIX) swap(a, b);
1458
1459 /*
1460 * We can only add something to a prefix, and
1461 * that something has to be a number. The cast
1462 * operation already ensured that the number is
1463 * uint64, and is at least vaguely within the
1464 * allowed range.
1465 */
1466 if (a->type != FR_TYPE_IPV6_PREFIX) return ERR_INVALID;
1467
1468 if (b->type != FR_TYPE_UINT64) return ERR_INVALID;
1469
1470 /*
1471 * If we're adding a UINT64, the prefix can't be shorter than 64.
1472 */
1473 if (a->vb_ip.prefix <= 64) return ERR_OVERFLOW;
1474
1475 /*
1476 * Trying to add a number outside of the given prefix. That's not allowed.
1477 */
1478 if (b->vb_uint64 >= (((uint64_t) 1) << (128 - a->vb_ip.prefix))) return ERR_OVERFLOW;
1479
1480 /*
1481 * Add in the relevant low bits.
1482 */
1483 memcpy(&dst->vb_ipv6addr, a->vb_ipv6addr, sizeof(dst->vb_ipv6addr));
1484 mask = b->vb_uint64;
1485 for (i = 15; i >= ((a->vb_ip.prefix + 7) >> 3); i--) {
1486 dst->vb_ipv6addr[i] |= mask & 0xff;
1487 mask >>= 8;
1488 }
1489
1490 dst->vb_ip.af = AF_INET6;
1491 dst->vb_ip.prefix = 128;
1492 dst->vb_ip.scope_id = a->vb_ip.scope_id;
1494 break;
1495
1496 default:
1497 return ERR_INVALID;
1498 }
1499
1500 return 0;
1501}
1502
1503static int get_ipv6_prefix(uint8_t const *in)
1504{
1505 int i, j, prefix;
1506
1507 prefix = 128;
1508 for (i = 15; i >= 0; i--) {
1509 if (!in[i]) {
1510 prefix -= 8;
1511 continue;
1512 }
1513
1514 for (j = 0; j < 8; j++) {
1515 if ((in[i] & (1 << j)) == 0) {
1516 prefix--;
1517 continue;
1518 }
1519 return prefix;
1520 }
1521 }
1522
1523 return prefix;
1524}
1525
1526static int calc_ipv6_prefix(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b)
1527{
1528 int i, prefix = 128;
1529 uint8_t const *pa, *pb;
1530 uint8_t *pdst;
1531
1532 fr_assert((dst->type == FR_TYPE_IPV6_PREFIX) || (dst->type == FR_TYPE_COMBO_IP_PREFIX));
1533
1534 if (a->type == FR_TYPE_OCTETS) {
1535 if (a->vb_length != (128 / 8)) {
1536 fr_strerror_printf("Invalid length %zu for octets network mask", a->vb_length);
1537 return -1;
1538 }
1539 pa = a->vb_octets;
1540 prefix = get_ipv6_prefix(pa);
1541
1542 } else if (a->type == FR_TYPE_IPV6_ADDR) {
1543 pa = (const uint8_t *) &a->vb_ipv6addr;
1544
1545 } else {
1546 return ERR_INVALID;
1547 }
1548
1549 if (b->type == FR_TYPE_OCTETS) {
1550 if (b->vb_length != (128 / 8)) {
1551 fr_strerror_printf("Invalid length %zu for octets network mask", b->vb_length);
1552 return -1;
1553 }
1554 pb = b->vb_octets;
1555 prefix = get_ipv6_prefix(pb);
1556
1557 } else if (b->type == FR_TYPE_IPV6_ADDR) {
1558 pb = (const uint8_t *) &b->vb_ip.addr.v6;
1559
1560 } else {
1561 return ERR_INVALID;
1562 }
1563
1564 switch (op) {
1565 case T_AND:
1566 fr_value_box_init(dst, FR_TYPE_IPV6_PREFIX, NULL, false);
1567 pdst = (uint8_t *) &dst->vb_ip.addr.v6;
1568
1569 for (i = 0; i < 16; i++) {
1570 pdst[i] = pa[i] & pb[i];
1571 }
1572
1573 dst->vb_ip.af = AF_INET6;
1574 dst->vb_ip.prefix = prefix;
1577 break;
1578
1579 default:
1580 return ERR_INVALID;
1581 }
1582
1583 return 0;
1584}
1585
1586#define is_ipv6(_x) (((_x)->type == FR_TYPE_IPV6_ADDR) || ((_x)->type == FR_TYPE_IPV6_PREFIX) || ((((_x)->type == FR_TYPE_COMBO_IP_ADDR) || ((_x)->type == FR_TYPE_COMBO_IP_PREFIX)) && ((_x)->vb_ip.af == AF_INET6)))
1587
1588static int calc_combo_ip_addr(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *in1, fr_token_t op, fr_value_box_t const *in2)
1589{
1590 /*
1591 * IPv6 is better than IPv4!
1592 */
1593 if (is_ipv6(in1) || is_ipv6(in2)) {
1594 return calc_ipv6_addr(ctx, dst, in1, op, in2);
1595 }
1596
1597 return calc_ipv4_addr(ctx, dst, in1, op, in2);
1598}
1599
1600static int calc_combo_ip_prefix(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *in1, fr_token_t op, fr_value_box_t const *in2)
1601{
1602 if (is_ipv6(in1) || is_ipv6(in2)) {
1603 return calc_ipv6_prefix(ctx, dst, in1, op, in2);
1604 }
1605
1606 return calc_ipv4_prefix(ctx, dst, in1, op, in2);
1607}
1608
1609
1610static int calc_float32(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *in1, fr_token_t op, fr_value_box_t const *in2)
1611{
1612 fr_value_box_t one, two;
1613 fr_value_box_t const *a = in1;
1614 fr_value_box_t const *b = in2;
1615
1616 fr_assert(dst->type == FR_TYPE_FLOAT32);
1617
1618 /*
1619 * Intermediate calculations are done using increased precision.
1620 */
1623
1624 switch (op) {
1625 case T_ADD:
1626 dst->vb_float32 = a->vb_float64 + b->vb_float64;
1627 break;
1628
1629 case T_SUB:
1630 dst->vb_float32 = a->vb_float64 - b->vb_float64;
1631 break;
1632
1633 case T_MUL:
1634 dst->vb_float32 = a->vb_float64 * b->vb_float64;
1635 break;
1636
1637 case T_DIV:
1638 if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
1639
1640 dst->vb_float32 = a->vb_float64 / b->vb_float64;
1641 break;
1642
1643 case T_MOD:
1644 if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
1645
1646 dst->vb_float32 = fmod(a->vb_float64, b->vb_float64);
1647 break;
1648
1649 default:
1650 return ERR_INVALID;
1651 }
1652
1655
1656 return 0;
1657
1658}
1659
1660static int calc_float64(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *in1, fr_token_t op, fr_value_box_t const *in2)
1661{
1662 fr_value_box_t one, two;
1663 fr_value_box_t const *a = in1;
1664 fr_value_box_t const *b = in2;
1665
1666 fr_assert(dst->type == FR_TYPE_FLOAT64);
1667
1670
1671 switch (op) {
1672 case T_ADD:
1673 dst->vb_float64 = a->vb_float64 + b->vb_float64;
1674 break;
1675
1676 case T_SUB:
1677 dst->vb_float64 = a->vb_float64 - b->vb_float64;
1678 break;
1679
1680 case T_MUL:
1681 dst->vb_float64 = a->vb_float64 * b->vb_float64;
1682 break;
1683
1684 case T_DIV:
1685 if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
1686
1687 dst->vb_float64 = a->vb_float64 / b->vb_float64;
1688 break;
1689
1690 case T_MOD:
1691 if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
1692
1693 dst->vb_float64 = fmod(a->vb_float64, b->vb_float64);
1694 break;
1695
1696 default:
1697 return ERR_INVALID;
1698 }
1699
1702
1703 return 0;
1704}
1705
1706/*
1707 * Do all intermediate operations on 64-bit numbers.
1708 */
1709static int calc_uint64(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *in1, fr_token_t op, fr_value_box_t const *in2)
1710{
1711 fr_value_box_t one, two, result;
1712 fr_value_box_t const *a = in1;
1713 fr_value_box_t const *b = in2;
1714
1715 fr_value_box_init(&result, FR_TYPE_UINT64, NULL, a->tainted | b->tainted);
1716
1717 COERCE_A(FR_TYPE_UINT64, NULL);
1718
1719 if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
1720 /*
1721 * Don't touch the RHS.
1722 */
1723 fr_assert(b->type == FR_TYPE_UINT32);
1724
1725 } else {
1726 COERCE_B(FR_TYPE_UINT64, dst->enumv);
1727 }
1728
1729 switch (op) {
1730 case T_ADD:
1731 if (!fr_add(&result.vb_uint64, a->vb_uint64, b->vb_uint64)) return ERR_OVERFLOW;
1732 break;
1733
1734 case T_SUB:
1735 if (!fr_sub(&result.vb_uint64, a->vb_uint64, b->vb_uint64)) return ERR_UNDERFLOW;
1736 break;
1737
1738 case T_MUL:
1739 if (!fr_multiply(&result.vb_uint64, a->vb_uint64, b->vb_uint64)) return ERR_OVERFLOW;
1740 break;
1741
1742 case T_DIV:
1743 if (b->vb_uint64 == 0) return ERR_ZERO;
1744
1745 result.vb_uint64 = a->vb_uint64 / b->vb_uint64;
1746 break;
1747
1748 case T_MOD:
1749 if (b->vb_uint64 == 0) return ERR_ZERO;
1750
1751 result.vb_uint64 = a->vb_uint64 % in2->vb_uint64;
1752 break;
1753
1754 case T_AND:
1755 result.vb_uint64 = a->vb_uint64 & b->vb_uint64;
1756 break;
1757
1758 case T_OR:
1759 result.vb_uint64 = a->vb_uint64 | b->vb_uint64;
1760 break;
1761
1762 case T_XOR:
1763 result.vb_uint64 = a->vb_uint64 ^ b->vb_uint64;
1764 break;
1765
1766 case T_RSHIFT:
1767 if (b->vb_uint32 >= (8 * sizeof(a->vb_uint64))) return ERR_UNDERFLOW;
1768
1769 result.vb_uint64 = a->vb_uint64 >> b->vb_uint32;
1770 break;
1771
1772 case T_LSHIFT:
1773 if (b->vb_uint32 >= (8 * sizeof(a->vb_uint64))) return ERR_OVERFLOW;
1774
1775 result.vb_uint64 = a->vb_uint64 << b->vb_uint32;
1776 break;
1777
1778 default:
1779 return ERR_INVALID;
1780 }
1781
1782 /*
1783 * Once we're done, cast the result to the final data type.
1784 */
1785 if (fr_value_box_cast(ctx, dst, dst->type, dst->enumv, &result) < 0) return -1;
1786
1789
1790 return 0;
1791}
1792
1793/*
1794 * Same as above, except uint64 -> int64. These functions should be kept in sync!
1795 */
1796static int calc_int64(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *in1, fr_token_t op, fr_value_box_t const *in2)
1797{
1798 fr_value_box_t one, two, result;
1799 fr_value_box_t const *a = in1;
1800 fr_value_box_t const *b = in2;
1801
1802 fr_value_box_init(&result, FR_TYPE_INT64, NULL, a->tainted | b->tainted);
1803
1804 COERCE_A(FR_TYPE_INT64, NULL);
1805
1806 if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
1807 /*
1808 * Don't touch the RHS.
1809 */
1810 fr_assert(b->type == FR_TYPE_UINT32);
1811
1812 } else {
1813 COERCE_B(FR_TYPE_INT64, dst->enumv);
1814 }
1815
1816 switch (op) {
1817 case T_ADD:
1818 if (!fr_add(&result.vb_int64, a->vb_int64, b->vb_int64)) return ERR_OVERFLOW;
1819 break;
1820
1821 case T_SUB:
1822 if (!fr_sub(&result.vb_int64, a->vb_int64, b->vb_int64)) return ERR_UNDERFLOW;
1823 break;
1824
1825 case T_MUL:
1826 if (!fr_multiply(&result.vb_int64, a->vb_int64, b->vb_int64)) return ERR_OVERFLOW;
1827 break;
1828
1829 case T_DIV:
1830 if (b->vb_int64 == 0) return ERR_ZERO;
1831
1832 result.vb_int64 = a->vb_int64 / b->vb_int64;
1833 break;
1834
1835 case T_MOD:
1836 if (b->vb_int64 == 0) return ERR_ZERO;
1837
1838 result.vb_int64 = a->vb_int64 % in2->vb_int64;
1839 break;
1840
1841 case T_AND:
1842 result.vb_int64 = a->vb_int64 & b->vb_int64;
1843 break;
1844
1845 case T_OR:
1846 result.vb_int64 = a->vb_int64 | b->vb_int64;
1847 break;
1848
1849 case T_XOR:
1850 result.vb_int64 = a->vb_int64 ^ b->vb_int64;
1851 break;
1852
1853 case T_RSHIFT:
1854 if (b->vb_uint32 >= (8 * sizeof(a->vb_int64))) return ERR_UNDERFLOW;
1855
1856 result.vb_int64 = a->vb_int64 >> b->vb_uint32;
1857 break;
1858
1859 case T_LSHIFT:
1860 if (b->vb_uint32 >= (8 * sizeof(a->vb_int64))) return ERR_OVERFLOW;
1861
1862 result.vb_int64 = a->vb_int64 << b->vb_uint32;
1863 break;
1864
1865 default:
1866 return ERR_INVALID;
1867 }
1868
1869 /*
1870 * Once we're done, cast the result to the final data type.
1871 */
1872 if (fr_value_box_cast(ctx, dst, dst->type, dst->enumv, &result) < 0) return -1;
1873
1876
1877 return 0;
1878}
1879
1880typedef int (*fr_binary_op_t)(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b);
1881
1882/** Map output type to its associated function
1883 *
1884 */
1918
1919/** Calculate DST = A OP B
1920 *
1921 * The result is written to DST only *after* it has been calculated.
1922 * So it's safe to pass DST as either A or B. DST should already exist.
1923 *
1924 * This function should arguably not take comparison operators, but
1925 * whatever. The "promote types" code is the same for all of the
1926 * binary operations, so we might as well just have one function.
1927 */
1928int fr_value_calc_binary_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t hint, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b)
1929{
1930 int rcode = -1;
1931 fr_value_box_t one, two;
1933 fr_binary_op_t func;
1934
1935 if ((hint != FR_TYPE_NULL) && !fr_type_is_leaf(hint)) return invalid_type(hint);
1936
1937 /*
1938 * Casting to structural types should be a parse error,
1939 * and not a run-time calculation error.
1940 */
1941 if (!fr_type_is_leaf(a->type)) return invalid_type(a->type);
1942 if (!fr_type_is_leaf(b->type)) return invalid_type(b->type);
1943
1944 /*
1945 * === and !== also check types. If the types are
1946 * different, it's a failure. Otherwise they revert to == and !=.
1947 */
1948 switch (op) {
1949 case T_OP_CMP_EQ_TYPE:
1950 if (a->type != b->type) {
1951 mismatch_type:
1952 fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false); /* @todo - enum */
1953 dst->vb_bool = false;
1954 return 0;
1955 }
1956 op = T_OP_CMP_EQ;
1957 break;
1958
1959 case T_OP_CMP_NE_TYPE:
1960 if (a->type != b->type) goto mismatch_type;
1961
1962 op = T_OP_NE;
1963 break;
1964
1965 case T_OP_REG_EQ:
1966 case T_OP_REG_NE:
1967 if (b->type != FR_TYPE_STRING) {
1968 fr_strerror_const("Invalid type for regular expression");
1969 return -1;
1970 }
1971
1972 rcode = fr_regex_cmp_op(op, a, b);
1973 if (rcode < 0) return rcode;
1974
1975 fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false); /* @todo - enum */
1976 dst->vb_bool = (rcode != 0);
1977 return 0;
1978
1979 default:
1980 break;
1981 }
1982
1985
1986 /*
1987 * We don't know what the output type should be. Try to
1988 * guess based on a variety of factors.
1989 */
1990 if (hint == FR_TYPE_NULL) do {
1991 /*
1992 * All kinds of special cases :(
1993 *
1994 * date1 - date2 --> time_delta
1995 *
1996 * time_delta * FOO --> float64, because time_delta is _printed_ as a floating point
1997 * number. And this is the least surprising thing to do.
1998 */
1999 if ((op == T_SUB) && (a->type == b->type) && (a->type == FR_TYPE_DATE)) {
2000 hint = FR_TYPE_TIME_DELTA;
2001 break;
2002 }
2003
2004 if (op == T_MUL) {
2005 if (a->type == FR_TYPE_TIME_DELTA) {
2006 hint = upcast_op[FR_TYPE_FLOAT64][b->type];
2007 if (hint == FR_TYPE_NULL) hint = upcast_op[b->type][FR_TYPE_FLOAT64];
2008
2009 } else if (b->type == FR_TYPE_TIME_DELTA) {
2010 hint = upcast_op[a->type][FR_TYPE_FLOAT64];
2011 if (hint == FR_TYPE_NULL) hint = upcast_op[FR_TYPE_FLOAT64][a->type];
2012 }
2013
2014 if (hint != FR_TYPE_NULL) break;
2015 }
2016
2017 /*
2018 * date % time_delta --> time_delta
2019 */
2020 if ((op == T_MOD) && (a->type == FR_TYPE_DATE)) {
2021 hint = FR_TYPE_TIME_DELTA;
2022 break;
2023 }
2024
2025 switch (op) {
2026 case T_OP_CMP_EQ:
2027 case T_OP_NE:
2028 case T_OP_GE:
2029 case T_OP_GT:
2030 case T_OP_LE:
2031 case T_OP_LT:
2032 /*
2033 * Comparison operators always return
2034 * "bool".
2035 */
2036 hint = FR_TYPE_BOOL;
2037 break;
2038
2039 case T_AND:
2040 /*
2041 * Get mask from IP + number
2042 */
2043 if ((a->type == FR_TYPE_IPV4_ADDR) || (b->type == FR_TYPE_IPV4_ADDR)) {
2044 hint = FR_TYPE_IPV4_PREFIX;
2045 break;
2046 }
2047
2048 if ((a->type == FR_TYPE_IPV6_ADDR) || (b->type == FR_TYPE_IPV6_ADDR)) {
2049 hint = FR_TYPE_IPV6_PREFIX;
2050 break;
2051 }
2053
2054 case T_OR:
2055 case T_ADD:
2056 case T_SUB:
2057 case T_MUL:
2058 case T_DIV:
2059 case T_MOD:
2060 case T_XOR:
2061 /*
2062 * Try to "up-cast" the types. This is
2063 * so that we can take (for example)
2064 * uint8 + uint16, and have the output as
2065 * uint16.
2066 *
2067 * There must be only one entry per [a,b]
2068 * pairing. That way we're sure that [a,b]==[b,a]
2069 */
2070 hint = upcast_op[a->type][b->type];
2071 if (hint == FR_TYPE_NULL) {
2072 hint = upcast_op[b->type][a->type];
2073 } else if (a->type != b->type) {
2074 fr_assert(upcast_op[b->type][a->type] == FR_TYPE_NULL);
2075 }
2076
2077 /*
2078 * No idea what to do. :(
2079 */
2080 if (hint == FR_TYPE_NULL) {
2081 fr_strerror_printf("Invalid operation on data types - '%s' %s '%s'",
2082 fr_type_to_str(a->type), fr_tokens[op], fr_type_to_str(b->type));
2083 goto done;
2084 }
2085
2086 break;
2087
2088 /*
2089 * The RHS MUST be a numerical type. We don't need to do any upcasting here.
2090 *
2091 * @todo - the output type could be larger than the input type, if the shift is
2092 * more than the input type can handle. e.g. uint8 << 4 could result in uint16
2093 */
2094 case T_LSHIFT:
2095 if (!fr_type_is_integer(a->type)) {
2096 return handle_result(a->type, T_LSHIFT, ERR_INVALID);
2097 }
2098
2099 if (fr_type_is_signed(a->type)) {
2100 hint = FR_TYPE_INT64;
2101 break;
2102 }
2103 hint = FR_TYPE_UINT64;
2104 break;
2105
2106 case T_RSHIFT:
2107 hint = a->type;
2108 break;
2109
2110 default:
2111 return handle_result(a->type, op, ERR_INVALID);
2112 }
2113 } while (0);
2114
2115 /*
2116 * Now that we've figured out the correct types, perform the operation.
2117 */
2118 switch (op) {
2119 case T_OP_CMP_EQ:
2120 case T_OP_NE:
2121 case T_OP_GE:
2122 case T_OP_GT:
2123 case T_OP_LE:
2124 case T_OP_LT:
2125 if (hint != FR_TYPE_BOOL) {
2126 fr_strerror_printf("Invalid destination type '%s' for comparison operator",
2127 fr_type_to_str(hint));
2128 goto done;
2129 }
2130
2131 /*
2132 * Convert the types to ones which are comparable.
2133 */
2134 if (a->type != b->type) {
2135 fr_dict_attr_t const *enumv = NULL;
2136
2137 /*
2138 * If we're doing comparisons and one of them has an enum, and the other is an
2139 * enum name, then use the enum name to convert the string to the other type.
2140 *
2141 * We can then do type-specific comparisons.
2142 */
2143 if ((a->type == FR_TYPE_STRING) && b->enumv) {
2144 enumv = b->enumv;
2145 hint = b->type;
2146
2147 } else if ((b->type == FR_TYPE_STRING) && a->enumv) {
2148 enumv = a->enumv;
2149 hint = a->type;
2150
2151 } else {
2152 /*
2153 * Try to "up-cast" the types. This is so that we can take (for example)
2154 * uint8 < uint16, and have it make sense.
2155 *
2156 * There must be only one entry per [a,b] pairing. That way we're sure
2157 * that [a,b]==[b,a]
2158 */
2159 hint = upcast_cmp[a->type][b->type];
2160 if (hint == FR_TYPE_NULL) {
2161 hint = upcast_cmp[b->type][a->type];
2162 } else {
2163 fr_assert(upcast_cmp[b->type][a->type] == FR_TYPE_NULL);
2164 }
2165
2166 /*
2167 * time_deltas have a scale in the enumv, but default to "seconds" if
2168 * there's no scale. As a result, if we compare time_delta(ms) to integer,
2169 * then the integer is interpreted as seconds, and the scale is wrong.
2170 *
2171 * The solution is to use the appropriate scale.
2172 */
2173 if (hint == a->type) enumv = a->enumv;
2174 if (hint == b->type) enumv = b->enumv;
2175
2176 if (hint == FR_TYPE_NULL) {
2177 fr_strerror_printf("Cannot compare incompatible types (%s)... %s (%s)...",
2178 fr_type_to_str(a->type),
2179 fr_tokens[op],
2180 fr_type_to_str(b->type));
2181 goto done;
2182 }
2183 }
2184
2185 /*
2186 * Cast them to the appropriate type, which may be different from either of the
2187 * inputs.
2188 */
2189 if (a->type != hint) {
2190 if (fr_value_box_cast(NULL, &one, hint, enumv, a) < 0) goto done;
2191 a = &one;
2192 }
2193
2194 if (b->type != hint) {
2195 if (fr_value_box_cast(NULL, &two, hint, enumv, b) < 0) goto done;
2196 b = &two;
2197 }
2198 }
2199
2200 rcode = fr_value_box_cmp_op(op, a, b);
2201 if (rcode < 0) goto done;
2202
2203 fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false);
2204 dst->vb_bool = (rcode > 0);
2205 break;
2206
2207 /*
2208 * For shifts, the RHS value MUST be an integer. There's no reason to have it as
2209 * anything other than an 8-bit field.
2210 */
2211 case T_LSHIFT:
2212 case T_RSHIFT:
2213 if (b->type != FR_TYPE_UINT32) {
2214 if (fr_value_box_cast(ctx, &two, FR_TYPE_UINT32, NULL, b) < 0) {
2215 fr_strerror_printf("Cannot parse shift value as integer - %s",
2216 fr_strerror());
2217 goto done;
2218 }
2219 b = &two;
2220 }
2222
2223 case T_ADD:
2224 case T_SUB:
2225 case T_MUL:
2226 case T_DIV:
2227 case T_MOD:
2228 case T_AND:
2229 case T_OR:
2230 case T_XOR:
2231 fr_assert(hint != FR_TYPE_NULL);
2232
2233 func = calc_type[hint];
2234 if (!func) {
2235 fr_strerror_printf("Cannot perform any operations for destination type %s",
2236 fr_type_to_str(hint));
2237 rcode = -1;
2238 break;
2239 }
2240
2241 /*
2242 * It's OK to use one of the inputs as the
2243 * output. In order to ensure that nothing bad
2244 * happens, we use an intermediate value-box.
2245 */
2246 fr_value_box_init(&out, hint, NULL, false);
2247
2248 rcode = func(ctx, &out, a, op, b); /* not calc_type[hint], to shut up clang */
2249 if (rcode < 0) goto done;
2250
2251 fr_value_box_copy_shallow(NULL, dst, &out);
2252 dst->tainted = a->tainted | b->tainted;
2253 break;
2254
2255 default:
2256 rcode = ERR_INVALID;
2257 break;
2258 }
2259
2260done:
2263
2264 return handle_result(hint, op, rcode);
2265}
2266
2267/** Calculate DST = OP { A, B, C, ... }
2268 *
2269 * The result is written to DST only *after* it has been calculated.
2270 * So it's safe to pass DST as one of the inputs. DST should already
2271 * exist.
2272 */
2274{
2275 fr_value_box_t out, *vb;
2276 fr_binary_op_t calc;
2277
2278 if (group->type != FR_TYPE_GROUP) {
2279 fr_strerror_const("Invalid type passed to multivalue calculation");
2280 return -1;
2281 }
2282
2285 fr_strerror_printf("Invalid operation %s for data type %s", fr_tokens[op], fr_type_to_str(type));
2286 return -1;
2287 }
2288
2289 if (type == FR_TYPE_STRING) {
2290 fr_sbuff_t *sbuff;
2291
2292 if (op != T_ADD) goto invalid_type;
2293
2294 FR_SBUFF_TALLOC_THREAD_LOCAL(&sbuff, 1024, (1 << 16));
2295
2296 if (fr_value_box_list_concat_as_string(dst, sbuff, UNCONST(fr_value_box_list_t *, &group->vb_group),
2297 NULL, 0, NULL, FR_VALUE_BOX_LIST_NONE, FR_VALUE_BOX_SAFE_FOR_ANY, false) < 0) return -1;
2298
2299 if (fr_value_box_bstrndup(ctx, dst, NULL, fr_sbuff_start(sbuff), fr_sbuff_used(sbuff), false) < 0) return -1;
2300 return 0;
2301 }
2302
2303 if (type == FR_TYPE_OCTETS) {
2304 fr_dbuff_t *dbuff;
2305
2306 if (op != T_ADD) goto invalid_type;
2307
2308 FR_DBUFF_TALLOC_THREAD_LOCAL(&dbuff, 1024, (1 << 16));
2309
2310 if (fr_value_box_list_concat_as_octets(dst, dbuff, UNCONST(fr_value_box_list_t *, &group->vb_group), NULL, 0, FR_VALUE_BOX_LIST_NONE, false) < 0) return -1;
2311
2312 if (fr_value_box_memdup(ctx, dst, NULL, fr_dbuff_start(dbuff), fr_dbuff_used(dbuff), false) < 0) return -1;
2313
2314 return 0;
2315 }
2316
2317 /*
2318 * Can't add or multiply booleans.
2319 */
2320 if ((type == FR_TYPE_BOOL) && !((op == T_AND) || (op == T_OR) || (op == T_XOR))) goto unsupported;
2321
2322 switch (op) {
2323 case T_ADD:
2324 case T_MUL:
2325 case T_AND:
2326 case T_OR:
2327 case T_XOR:
2328 break;
2329
2330 default:
2331 goto invalid_type;
2332 }
2333
2334 /*
2335 * Strings and octets are different.
2336 */
2337 if (!fr_type_is_numeric(type)) {
2338 unsupported:
2339 fr_strerror_printf("Not yet supported operation %s for data type %s", fr_tokens[op], fr_type_to_str(type));
2340 return -1;
2341 }
2342
2343 switch (type) {
2344 case FR_TYPE_UINT8:
2345 case FR_TYPE_UINT16:
2346 case FR_TYPE_UINT32:
2347 case FR_TYPE_UINT64:
2348 calc = calc_uint64;
2349 break;
2350
2351 case FR_TYPE_INT8:
2352 case FR_TYPE_INT16:
2353 case FR_TYPE_INT32:
2354 case FR_TYPE_INT64:
2355 calc = calc_int64;
2356 break;
2357
2358 case FR_TYPE_TIME_DELTA:
2359 if ((op != T_ADD) && (op != T_SUB)) goto invalid_type;
2360 calc = calc_time_delta;
2361 break;
2362
2363 case FR_TYPE_FLOAT32:
2364 calc = calc_float32;
2365 break;
2366
2367 case FR_TYPE_FLOAT64:
2368 calc = calc_float64;
2369 break;
2370
2371 default:
2372 goto unsupported;
2373 }
2374
2375 vb = fr_value_box_list_head(&group->vb_group);
2376 if (!vb) {
2377 fr_strerror_printf("Empty input is invalid");
2378 return -1;
2379 }
2380
2381 if (fr_value_box_cast(ctx, &out, type, NULL, vb) < 0) return -1;
2382
2383 while ((vb = fr_value_box_list_next(&group->vb_group, vb)) != NULL) {
2384 int rcode;
2385 fr_value_box_t box;
2386
2387 if (vb->type == type) {
2388 rcode = calc(ctx, &out, &out, op, vb);
2389 if (rcode < 0) return rcode;
2390
2391 } else {
2392 if (fr_value_box_cast(ctx, &box, type, NULL, vb) < 0) return -1;
2393
2394 rcode = calc(ctx, &out, &out, op, &box);
2395 if (rcode < 0) return rcode;
2396 }
2397 }
2398
2399 return fr_value_box_copy(ctx, dst, &out);
2400}
2401
2402
2403#define T(_x) [T_OP_ ## _x ## _EQ] = T_ ## _x
2404
2406 T(ADD),
2407 T(SUB),
2408 T(MUL),
2409 T(DIV),
2410 T(AND),
2411 T(OR),
2412 T(XOR),
2413 T(RSHIFT),
2414 T(LSHIFT),
2415};
2416
2417/** Calculate DST OP SRC
2418 *
2419 * e.g. "foo += bar".
2420 *
2421 * This is done by doing some sanity checks, and then just calling
2422 * the "binary operation" function.
2423 */
2425{
2426 int rcode;
2427
2428 if (!fr_type_is_leaf(dst->type)) return invalid_type(dst->type);
2429 if (!fr_type_is_leaf(src->type)) return invalid_type(src->type);
2430
2431 if (dst->immutable) {
2432 fr_strerror_printf("Cannot modify immutable value");
2433 return -1;
2434 }
2435
2436 /*
2437 * These operators are included here for testing and completeness. But see comments in
2438 * fr_edit_list_apply_pair_assignment() for what the caller should be doing.
2439 */
2440 if ((op == T_OP_EQ) || (op == T_OP_SET)) {
2441 /*
2442 * Allow for unintentional mistakes.
2443 */
2444 if (src == dst) return 0;
2445
2447 return fr_value_box_cast(ctx, dst, dst->type, dst->enumv, src); /* cast, as the RHS might not (yet) be the same! */
2448 }
2449
2450 if (assignment2op[op] == T_INVALID) {
2451 return handle_result(dst->type, op, ERR_INVALID);
2452 }
2453 op = assignment2op[op];
2454
2455 /*
2456 * Just call the binary op function. It already ensures that (a) the inputs are "const", and (b)
2457 * the output is over-written only at the final step.
2458 */
2459 if (src->type != FR_TYPE_GROUP) {
2460 rcode = fr_value_calc_binary_op(ctx, dst, dst->type, dst, op, src);
2461
2462 } else {
2463 fr_value_box_t *vb = NULL;
2464
2465 /*
2466 * If the RHS is a group, then we loop over the group recursively, doing the operation.
2467 */
2468 rcode = 0; /* in case group is empty */
2469
2470 while ((vb = fr_value_box_list_next(&src->vb_group, vb)) != NULL) {
2471 rcode = fr_value_calc_binary_op(ctx, dst, dst->type, dst, op, vb);
2472 if (rcode < 0) break;
2473 }
2474 }
2475
2476 if (rcode < 0) return handle_result(dst->type, op, rcode);
2477
2478 return 0;
2479}
2480
2481/** Calculate unary operations
2482 *
2483 * e.g. "foo++", or "-foo".
2484 */
2485int fr_value_calc_unary_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_token_t op, fr_value_box_t const *src)
2486{
2487 int rcode = -1;
2488 fr_value_box_t one;
2489
2490 if (!fr_type_is_numeric(src->type)) return invalid_type(src->type);
2491
2492 if (dst->immutable) {
2493 fr_strerror_printf("Cannot modify immutable value");
2494 return -1;
2495 }
2496
2497 if (op == T_OP_INCRM) {
2498 /*
2499 * Add 1 or subtract 1 means RHS is always 1.
2500 */
2501 fr_value_box_init(&one, src->type, NULL, false);
2502 switch (src->type) {
2503 case FR_TYPE_UINT8:
2504 one.vb_uint8 = 1;
2505 break;
2506
2507 case FR_TYPE_UINT16:
2508 one.vb_uint16 = 1;
2509 break;
2510
2511 case FR_TYPE_UINT32:
2512 one.vb_uint32 = 1;
2513 break;
2514
2515 case FR_TYPE_UINT64:
2516 one.vb_uint64 = 1;
2517 break;
2518
2519 case FR_TYPE_SIZE:
2520 one.vb_size = 1;
2521 break;
2522
2523 case FR_TYPE_INT8:
2524 one.vb_int8 = 1;
2525 break;
2526
2527 case FR_TYPE_INT16:
2528 one.vb_int16 = 1;
2529 break;
2530
2531 case FR_TYPE_INT32:
2532 one.vb_int32 = 1;
2533 break;
2534
2535 case FR_TYPE_INT64:
2536 one.vb_int64 = 1;
2537 break;
2538
2539 case FR_TYPE_FLOAT32:
2540 one.vb_float32 = 1;
2541 break;
2542
2543 case FR_TYPE_FLOAT64:
2544 one.vb_float64 = 1;
2545 break;
2546
2547 default:
2548 fr_assert(0);
2549 return -1;
2550 }
2551
2552 rcode = fr_value_calc_binary_op(ctx, dst, src->type, src, T_ADD, &one);
2553 return handle_result(dst->type, op, rcode);
2554
2555 } else if (op == T_COMPLEMENT) {
2556 if (dst != src) {
2557 fr_value_box_init(dst, src->type, src->enumv, false);
2558 fr_value_box_safety_copy(dst, src);
2559 }
2560
2561#undef COMP
2562#define COMP(_type, _field) case FR_TYPE_ ## _type: dst->vb_ ##_field = (_field ## _t) ~src->vb_ ##_field; break
2563 switch (src->type) {
2564 COMP(UINT8, uint8);
2565 COMP(UINT16, uint16);
2566 COMP(UINT32, uint32);
2567 COMP(UINT64, uint64);
2568 COMP(SIZE, size);
2569
2570 COMP(INT8, int8);
2571 COMP(INT16, int16);
2572 COMP(INT32, int32);
2573 COMP(INT64, int64);
2574
2575 default:
2576 goto invalid;
2577 }
2578
2579 return 0;
2580
2581 } else if (op == T_SUB) {
2582 fr_type_t type = src->type;
2583
2584 if ((dst != src) && !fr_type_is_signed(src->type)) {
2585 type = upcast_unsigned[src->type];
2586
2587 if (type == FR_TYPE_NULL) {
2588 type = src->type; /* hope for the best */
2589 }
2590 }
2591
2592 fr_value_box_init(&one, type, NULL, src->tainted); /* init to zero */
2593 rcode = fr_value_calc_binary_op(ctx, dst, type, &one, T_SUB, src);
2594
2595 return handle_result(dst->type, op, rcode);
2596
2597 } else if (op == T_NOT) {
2598 bool value = fr_value_box_is_truthy(src);
2599
2600 fr_value_box_clear(dst);
2601 fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false); // @todo - add enum!
2602 dst->vb_bool = !value;
2603
2604 return 0;
2605
2606 } else {
2607 invalid:
2608 return handle_result(src->type, op, ERR_INVALID);
2609 }
2610
2611}
2612
2613/*
2614 * Empty lists are empty:
2615 *
2616 * {}
2617 * {{}}
2618 * {''}
2619 * {{},''}
2620 *
2621 * etc.
2622 */
2623static bool fr_value_calc_list_empty(fr_value_box_list_t const *list)
2624{
2626 switch (item->type) {
2627 default:
2628 return false;
2629
2630 case FR_TYPE_GROUP:
2631 if (!fr_value_calc_list_empty(&item->vb_group)) return false;
2632 break;
2633
2634 case FR_TYPE_STRING:
2635 case FR_TYPE_OCTETS:
2636 if (item->vb_length != 0) return false;
2637 break;
2638 }
2639 }
2640
2641 return true;
2642}
2643
2644
2645/*
2646 * Loop over input lists, calling fr_value_calc_binary_op()
2647 *
2648 * This implementation is arguably wrong... it should be checking individual entries in list1 against individual entries in list2.
2649 * Instead, it checks if ANY entry in list1 matches ANY entry in list2.
2650 */
2651int fr_value_calc_list_cmp(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_list_t const *list1, fr_token_t op, fr_value_box_list_t const *list2)
2652{
2653 int rcode;
2654 bool invert = false;
2655 bool a_empty, b_empty;
2656
2657 if (!fr_comparison_op[op]) {
2658 fr_strerror_printf("Invalid operator '%s' passed to list comparison", fr_tokens[op]);
2659 return -1;
2660 }
2661
2662 /*
2663 * v3 hack. != really means !( ... == ... )
2664 */
2665 if (op == T_OP_NE) {
2666 invert = true;
2667 op = T_OP_CMP_EQ;
2668 }
2669
2670 /*
2671 * It's annoying when the debug prints out cmp({},{}) and says "not equal".
2672 *
2673 * What's happening behind the scenes is that one side is an empty value-box group, such as when
2674 * an xlat expansion fails. And the other side is an empty string. If we believe that strings
2675 * are actually sets of characters, then {}=='', and we're all OK
2676 */
2677 a_empty = fr_value_box_list_empty(list1) || fr_value_calc_list_empty(list1);
2678 b_empty = fr_value_box_list_empty(list2) || fr_value_calc_list_empty(list2);
2679
2680 /*
2681 * Both lists are empty, they should be equal when checked for equality.
2682 */
2683 if (a_empty && b_empty) {
2684 switch (op) {
2685 case T_OP_CMP_EQ:
2686 case T_OP_LE:
2687 case T_OP_GE:
2688 invert = !invert;
2689 break;
2690
2691 default:
2692 break;
2693 }
2694
2695 goto done;
2696 }
2697
2698 /*
2699 * Emulate v3. :(
2700 */
2701 fr_value_box_list_foreach(list1, a) {
2702 fr_value_box_list_foreach(list2, b) {
2703 rcode = fr_value_calc_binary_op(ctx, dst, FR_TYPE_BOOL, a, op, b);
2704 if (rcode < 0) return rcode;
2705
2706 /*
2707 * No match: keep looking for a match.
2708 */
2709 fr_assert(dst->type == FR_TYPE_BOOL);
2710 if (!dst->vb_bool) continue;
2711
2712 /*
2713 * Found a match, we're done.
2714 */
2715 dst->vb_bool = !invert;
2716 return 0;
2717 }
2718 }
2719
2720 /*
2721 * No match,
2722 */
2723done:
2724 fr_value_box_clear(dst);
2725 fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false); // @todo - add enum!
2726 dst->vb_bool = invert;
2727 return 0;
2728}
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:167
#define RCSID(id)
Definition build.h:487
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition build.h:324
#define unlikely(_x)
Definition build.h:383
#define UNUSED
Definition build.h:317
static int calc_date(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b)
Definition calc.c:775
static const fr_type_t upcast_cmp[FR_TYPE_MAX+1][FR_TYPE_MAX+1]
Updates type (a,b) -> c.
Definition calc.c:426
static int calc_ipv4_addr(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *in1, fr_token_t op, fr_value_box_t const *in2)
Definition calc.c:1232
static int get_ipv6_prefix(uint8_t const *in)
Definition calc.c:1503
static const fr_binary_op_t calc_type[FR_TYPE_MAX+1]
Map output type to its associated function.
Definition calc.c:1885
static int calc_ipv6_addr(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *in1, fr_token_t op, fr_value_box_t const *in2)
Definition calc.c:1436
static int invalid_type(fr_type_t type)
Definition calc.c:698
#define ERR_UNDERFLOW
Definition calc.c:36
static const fr_type_t upcast_op[FR_TYPE_MAX+1][FR_TYPE_MAX+1]
Updates type (a,b) -> c.
Definition calc.c:65
#define ERR_ZERO
Definition calc.c:35
static int calc_float32(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *in1, fr_token_t op, fr_value_box_t const *in2)
Definition calc.c:1610
#define COERCE_A(_type, _enumv)
Definition calc.c:47
static int calc_ipv4_prefix(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b)
Definition calc.c:1283
static const fr_type_t upcast_unsigned[FR_TYPE_MAX+1]
Definition calc.c:689
static int calc_uint64(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *in1, fr_token_t op, fr_value_box_t const *in2)
Definition calc.c:1709
static int calc_octets(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b)
Definition calc.c:903
static int calc_combo_ip_addr(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *in1, fr_token_t op, fr_value_box_t const *in2)
Definition calc.c:1588
static int calc_ipv6_prefix(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b)
Definition calc.c:1526
static int cast_ipv6_addr(fr_value_box_t *out, fr_value_box_t const *in)
Definition calc.c:1368
static int handle_result(fr_type_t type, fr_token_t op, int rcode)
Definition calc.c:705
static int calc_int64(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *in1, fr_token_t op, fr_value_box_t const *in2)
Definition calc.c:1796
static int calc_bool(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b)
Definition calc.c:727
static int calc_string(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b)
Definition calc.c:1047
int fr_value_calc_list_cmp(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_list_t const *list1, fr_token_t op, fr_value_box_list_t const *list2)
Definition calc.c:2651
#define ERR_INVALID
Definition calc.c:38
#define swap(_a, _b)
Definition calc.c:33
static int calc_combo_ip_prefix(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *in1, fr_token_t op, fr_value_box_t const *in2)
Definition calc.c:1600
static int calc_time_delta(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b)
Definition calc.c:818
int(* fr_binary_op_t)(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b)
Definition calc.c:1880
static int cast_ipv4_addr(fr_value_box_t *out, fr_value_box_t const *in)
Definition calc.c:1167
static bool fr_value_calc_list_empty(fr_value_box_list_t const *list)
Definition calc.c:2623
static int calc_float64(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *in1, fr_token_t op, fr_value_box_t const *in2)
Definition calc.c:1660
int fr_value_calc_nary_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t type, fr_token_t op, fr_value_box_t const *group)
Calculate DST = OP { A, B, C, ... }.
Definition calc.c:2273
#define is_ipv6(_x)
Definition calc.c:1586
#define COERCE_B(_type, _enumv)
Definition calc.c:48
static const fr_token_t assignment2op[T_TOKEN_LAST]
Definition calc.c:2405
int fr_value_calc_assignment_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_token_t op, fr_value_box_t const *src)
Calculate DST OP SRC.
Definition calc.c:2424
int fr_value_calc_binary_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t hint, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b)
Calculate DST = A OP B.
Definition calc.c:1928
#define ERR_OVERFLOW
Definition calc.c:37
#define COMP(_type, _field)
int fr_value_calc_unary_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_token_t op, fr_value_box_t const *src)
Calculate unary operations.
Definition calc.c:2485
#define T(_x)
Definition calc.c:2403
#define fr_dbuff_used(_dbuff_or_marker)
Return the number of bytes remaining between the start of the dbuff or marker and the current positio...
Definition dbuff.h:777
#define fr_dbuff_start(_dbuff_or_marker)
Return the 'start' position of a dbuff or marker.
Definition dbuff.h:908
#define FR_DBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
Create a function local and thread local extensible dbuff.
Definition dbuff.h:566
static fr_slen_t in
Definition dict.h:884
Test enumeration values.
Definition dict_test.h:92
static void * item(fr_lst_t const *lst, fr_lst_index_t idx)
Definition lst.c:122
#define fr_sub(_out, _a, _b)
Subtracts two integers.
Definition math.h:198
#define fr_add(_out, _a, _b)
Adds two integers.
Definition math.h:187
#define fr_multiply(_out, _a, _b)
Multiplies two integers together.
Definition math.h:176
fr_type_t
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_FLOAT32
Single precision floating point.
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_INT8
8 Bit signed integer.
@ FR_TYPE_ETHERNET
48 Bit Mac-Address.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_MAX
Number of defined data types.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_INT64
64 Bit signed integer.
@ FR_TYPE_INT16
16 Bit signed integer.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_COMBO_IP_PREFIX
IPv4 or IPv6 address prefix depending on length.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_INT32
32 Bit signed integer.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
@ FR_TYPE_IFID
Interface ID.
@ FR_TYPE_OCTETS
Raw octets.
@ FR_TYPE_GROUP
A grouping of other attributes.
@ FR_TYPE_FLOAT64
Double precision floating point.
unsigned int uint32_t
unsigned char uint8_t
#define fr_assert(_expr)
Definition rad_assert.h:38
static bool done
Definition radclient.c:83
static uint32_t mask
Definition rbmonkey.c:39
#define fr_sbuff_start(_sbuff_or_marker)
#define fr_sbuff_used(_sbuff_or_marker)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
fr_aka_sim_id_type_t type
static int64_t fr_time_delta_unwrap(fr_time_delta_t time)
Definition time.h:154
#define fr_time_delta_wrap(_time)
Definition time.h:152
#define fr_time_delta_ispos(_a)
Definition time.h:290
@ FR_TIME_RES_NSEC
Definition time.h:60
static fr_unix_time_t fr_unix_time_from_integer(bool *overflow, int64_t integer, fr_time_res_t res)
Definition time.h:411
static uint64_t fr_unix_time_unwrap(fr_unix_time_t time)
Definition time.h:161
char const * fr_tokens[T_TOKEN_LAST]
Definition token.c:79
const bool fr_comparison_op[T_TOKEN_LAST]
Definition token.c:199
enum fr_token fr_token_t
@ T_AND
Definition token.h:55
@ T_INVALID
Definition token.h:39
@ T_SUB
Definition token.h:52
@ T_RSHIFT
Definition token.h:62
@ T_NOT
Definition token.h:57
@ T_XOR
Definition token.h:58
@ T_DIV
Definition token.h:54
@ T_MOD
Definition token.h:60
@ T_OP_EQ
Definition token.h:83
@ T_COMPLEMENT
Definition token.h:59
@ T_ADD
Definition token.h:51
@ T_OP_SET
Definition token.h:84
@ T_OP_NE
Definition token.h:97
@ T_LSHIFT
Definition token.h:63
@ T_OP_REG_EQ
Definition token.h:102
@ T_OP_CMP_EQ_TYPE
Definition token.h:107
@ T_OP_CMP_EQ
Definition token.h:106
@ T_OP_INCRM
Definition token.h:113
@ T_MUL
Definition token.h:53
@ T_OP_LE
Definition token.h:100
@ T_OP_CMP_NE_TYPE
Definition token.h:108
@ T_OP_GE
Definition token.h:98
@ T_OP_GT
Definition token.h:99
@ T_OP_LT
Definition token.h:101
@ T_OP_REG_NE
Definition token.h:103
@ T_OR
Definition token.h:56
#define T_TOKEN_LAST
Definition token.h:129
int fr_regex_cmp_op(fr_token_t op, fr_value_box_t const *a, fr_value_box_t const *b)
Compare two boxes using an operator.
Definition regex.c:1025
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:553
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_const(_msg)
Definition strerror.h:223
#define fr_type_is_structural(_x)
Definition types.h:393
#define fr_type_is_numeric(_x)
Definition types.h:383
#define fr_type_is_signed(_x)
Definition types.h:384
#define fr_type_is_leaf(_x)
Definition types.h:394
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:455
#define fr_type_is_integer(_x)
Definition types.h:382
ssize_t fr_value_box_list_concat_as_string(fr_value_box_t *safety, fr_sbuff_t *sbuff, fr_value_box_list_t *list, char const *sep, size_t sep_len, fr_sbuff_escape_rules_t const *e_rules, fr_value_box_list_action_t proc_action, fr_value_box_safe_for_t safe_for, bool flatten)
Concatenate a list of value boxes together.
Definition value.c:6396
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
Definition value.c:3961
int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
Copy value data verbatim duplicating any buffers.
Definition value.c:4409
int fr_value_box_cmp_op(fr_token_t op, fr_value_box_t const *a, fr_value_box_t const *b)
Compare two attributes using an operator.
Definition value.c:1023
bool fr_value_box_is_truthy(fr_value_box_t const *in)
Check truthiness of values.
Definition value.c:7284
void fr_value_box_memdup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Assign a buffer to a box, but don't copy it.
Definition value.c:5178
void fr_value_box_copy_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *src)
Perform a shallow copy of a value_box.
Definition value.c:4533
ssize_t fr_value_box_list_concat_as_octets(fr_value_box_t *safety, fr_dbuff_t *dbuff, fr_value_box_list_t *list, uint8_t const *sep, size_t sep_len, fr_value_box_list_action_t proc_action, bool flatten)
Concatenate a list of value boxes together.
Definition value.c:6512
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
Definition value.c:4346
void fr_value_box_safety_merge(fr_value_box_t *out, fr_value_box_t const *in)
Merge safety results.
Definition value.c:7246
void fr_value_box_safety_copy(fr_value_box_t *out, fr_value_box_t const *in)
Copy the safety values from one box to another.
Definition value.c:7224
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition value.c:4392
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
Definition value.c:4853
void fr_value_box_bstrndup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Assign a string to to a fr_value_box_t.
Definition value.c:4940
int fr_value_box_memdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Copy a buffer to a fr_value_box_t.
Definition value.c:5094
@ FR_VALUE_BOX_LIST_NONE
Do nothing to processed boxes.
Definition value.h:233
#define fr_value_box_init_null(_vb)
Initialise an empty/null box that will be filled later.
Definition value.h:616
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
Definition value.h:610
#define fr_value_box_list_foreach(_list_head, _iter)
Definition value.h:224
static size_t char ** out
Definition value.h:1024
#define FR_VALUE_BOX_SAFE_FOR_ANY
Definition value.h:173