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: 968a9943dc5719068696c50d981290b54a3e8a50 $
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: 968a9943dc5719068696c50d981290b54a3e8a50 $")
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 fr_value_box_copy(NULL, out, in);
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_ip.addr.v4.s_addr = htonl(ntohl(a->vb_ip.addr.v4.s_addr) | 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_ip.addr.v4.s_addr = 0;
1326 prefix = 0;
1327
1328 } else if ((~b->vb_uint32) == 0) { /* all 1's */
1329 dst->vb_ip.addr.v4.s_addr = a->vb_ip.addr.v4.s_addr;
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_ip.addr.v4.s_addr = htonl(ntohl(a->vb_ip.addr.v4.s_addr) & 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_value_box_init(out, FR_TYPE_IPV4_ADDR, NULL, in->tainted);
1380 out->vb_ip = in->vb_ip;
1381 break;
1382
1384 if (in->vb_ip.af == AF_INET) goto cast_ipv4_prefix;
1385
1386 fr_value_box_init(out, FR_TYPE_IPV4_PREFIX, NULL, in->tainted);
1387 out->vb_ip = in->vb_ip;
1388 break;
1389
1390
1392 case FR_TYPE_IPV6_ADDR:
1393 fr_value_box_copy(NULL, out, in);
1394 break;
1395
1396 case FR_TYPE_IPV4_ADDR:
1398 if (fr_value_box_cast(NULL, out, FR_TYPE_IPV6_ADDR, NULL, in) < 0) return -1;
1399 break;
1400
1402 cast_ipv4_prefix:
1403 if (fr_value_box_cast(NULL, out, FR_TYPE_IPV6_PREFIX, NULL, in) < 0) return -1;
1404 break;
1405
1406 /*
1407 * All of these get mashed to 64-bits. The cast
1408 * operation will check bounds (both negative and
1409 * positive) on the run-time values.
1410 */
1411 case FR_TYPE_BOOL:
1412
1413 case FR_TYPE_UINT8:
1414 case FR_TYPE_UINT16:
1415 case FR_TYPE_UINT32:
1416 case FR_TYPE_UINT64:
1417
1418 case FR_TYPE_SIZE:
1419
1420 case FR_TYPE_INT8:
1421 case FR_TYPE_INT16:
1422 case FR_TYPE_INT32:
1423 case FR_TYPE_INT64:
1424
1425 case FR_TYPE_FLOAT32:
1426 case FR_TYPE_FLOAT64:
1427 if (fr_value_box_cast(NULL, out, FR_TYPE_UINT64, NULL, in) < 0) return -1;
1428 break;
1429 }
1430
1431 return 0;
1432}
1433
1434static 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)
1435{
1436 fr_value_box_t one, two;
1437 fr_value_box_t *a, *b;
1438 int i;
1439 uint64_t mask;
1440
1441 fr_assert((dst->type == FR_TYPE_IPV6_ADDR) || (dst->type == FR_TYPE_COMBO_IP_ADDR));
1442
1443 if (cast_ipv6_addr(&one, in1) < 0) return -1;
1444 a = &one;
1445
1446 if (cast_ipv6_addr(&two, in2) < 0) return -1;
1447 b = &two;
1448
1449 switch (op) {
1450 case T_ADD:
1451 /*
1452 * For simplicity, make sure that the prefix is first.
1453 */
1454 if (b->type == FR_TYPE_IPV6_PREFIX) swap(a, b);
1455
1456 /*
1457 * We can only add something to a prefix, and
1458 * that something has to be a number. The cast
1459 * operation already ensured that the number is
1460 * uint32, and is at least vaguely within the
1461 * allowed range.
1462 */
1463 if (a->type != FR_TYPE_IPV6_PREFIX) return ERR_INVALID;
1464
1465 if (b->type != FR_TYPE_UINT64) return ERR_INVALID;
1466
1467 /*
1468 * If we're adding a UINT64, the prefix can't be shorter than 64.
1469 */
1470 if (a->vb_ip.prefix <= 64) return ERR_OVERFLOW;
1471
1472 /*
1473 * Trying to add a number outside of the given prefix. That's not allowed.
1474 */
1475 if (b->vb_uint64 >= (((uint64_t) 1) << (128 - a->vb_ip.prefix))) return ERR_OVERFLOW;
1476
1477 /*
1478 * Add in the relevant low bits.
1479 */
1480 mask = b->vb_uint64;
1481 for (i = 15; i >= ((a->vb_ip.prefix + 7) >> 3); i--) {
1482 dst->vb_ip.addr.v6.s6_addr[i] |= mask & 0xff;
1483 mask >>= 8;
1484 }
1485
1486 dst->vb_ip.af = AF_INET6;
1487 dst->vb_ip.prefix = 0;
1488 dst->vb_ip.scope_id = a->vb_ip.scope_id;
1490 break;
1491
1492 default:
1493 return ERR_INVALID;
1494 }
1495
1496 return 0;
1497}
1498
1499static int get_ipv6_prefix(uint8_t const *in)
1500{
1501 int i, j, prefix;
1502
1503 prefix = 128;
1504 for (i = 15; i >= 0; i--) {
1505 if (!in[i]) {
1506 prefix -= 8;
1507 continue;
1508 }
1509
1510 for (j = 0; j < 8; j++) {
1511 if ((in[i] & (1 << j)) == 0) {
1512 prefix--;
1513 continue;
1514 }
1515 return prefix;
1516 }
1517 }
1518
1519 return prefix;
1520}
1521
1522static 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)
1523{
1524 int i, prefix = 128;
1525 uint8_t const *pa, *pb;
1526 uint8_t *pdst;
1527
1528 fr_assert((dst->type == FR_TYPE_IPV6_PREFIX) || (dst->type == FR_TYPE_COMBO_IP_PREFIX));
1529
1530 if (a->type == FR_TYPE_OCTETS) {
1531 if (a->vb_length != (128 / 8)) {
1532 fr_strerror_printf("Invalid length %zu for octets network mask", a->vb_length);
1533 return -1;
1534 }
1535 pa = a->vb_octets;
1536 prefix = get_ipv6_prefix(pa);
1537
1538 } else if (a->type == FR_TYPE_IPV6_ADDR) {
1539 pa = (const uint8_t *) &a->vb_ip.addr.v6.s6_addr;
1540
1541 } else {
1542 return ERR_INVALID;
1543 }
1544
1545 if (b->type == FR_TYPE_OCTETS) {
1546 if (b->vb_length != (128 / 8)) {
1547 fr_strerror_printf("Invalid length %zu for octets network mask", b->vb_length);
1548 return -1;
1549 }
1550 pb = b->vb_octets;
1551 prefix = get_ipv6_prefix(pb);
1552
1553 } else if (a->type == FR_TYPE_IPV6_ADDR) {
1554 pb = (const uint8_t *) &b->vb_ip.addr.v6;
1555
1556 } else {
1557 return ERR_INVALID;
1558 }
1559
1560 switch (op) {
1561 case T_AND:
1562 fr_value_box_init(dst, FR_TYPE_IPV6_PREFIX, NULL, false);
1563 pdst = (uint8_t *) &dst->vb_ip.addr.v6;
1564
1565 for (i = 0; i < 16; i++) {
1566 pdst[i] = pa[i] & pb[i];
1567 }
1568
1569 dst->vb_ip.af = AF_INET6;
1570 dst->vb_ip.prefix = prefix;
1573 break;
1574
1575 default:
1576 return ERR_INVALID;
1577 }
1578
1579 return 0;
1580}
1581
1582#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)))
1583
1584static 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)
1585{
1586 /*
1587 * IPv6 is better than IPv4!
1588 */
1589 if (is_ipv6(in1) || is_ipv6(in2)) {
1590 return calc_ipv6_addr(ctx, dst, in1, op, in2);
1591 }
1592
1593 return calc_ipv4_addr(ctx, dst, in1, op, in2);
1594}
1595
1596static 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)
1597{
1598 if (is_ipv6(in1) || is_ipv6(in2)) {
1599 return calc_ipv6_prefix(ctx, dst, in1, op, in2);
1600 }
1601
1602 return calc_ipv4_prefix(ctx, dst, in1, op, in2);
1603}
1604
1605
1606static 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)
1607{
1608 fr_value_box_t one, two;
1609 fr_value_box_t const *a = in1;
1610 fr_value_box_t const *b = in2;
1611
1612 fr_assert(dst->type == FR_TYPE_FLOAT32);
1613
1614 /*
1615 * Intermediate calculations are done using increased precision.
1616 */
1619
1620 switch (op) {
1621 case T_ADD:
1622 dst->vb_float32 = a->vb_float64 + b->vb_float64;
1623 break;
1624
1625 case T_SUB:
1626 dst->vb_float32 = a->vb_float64 - b->vb_float64;
1627 break;
1628
1629 case T_MUL:
1630 dst->vb_float32 = a->vb_float64 * b->vb_float64;
1631 break;
1632
1633 case T_DIV:
1634 if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
1635
1636 dst->vb_float32 = a->vb_float64 / b->vb_float64;
1637 break;
1638
1639 case T_MOD:
1640 if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
1641
1642 dst->vb_float32 = fmod(a->vb_float64, b->vb_float64);
1643 break;
1644
1645 default:
1646 return ERR_INVALID;
1647 }
1648
1651
1652 return 0;
1653
1654}
1655
1656static 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)
1657{
1658 fr_value_box_t one, two;
1659 fr_value_box_t const *a = in1;
1660 fr_value_box_t const *b = in2;
1661
1662 fr_assert(dst->type == FR_TYPE_FLOAT64);
1663
1666
1667 switch (op) {
1668 case T_ADD:
1669 dst->vb_float64 = a->vb_float64 + b->vb_float64;
1670 break;
1671
1672 case T_SUB:
1673 dst->vb_float64 = a->vb_float64 - b->vb_float64;
1674 break;
1675
1676 case T_MUL:
1677 dst->vb_float64 = a->vb_float64 * b->vb_float64;
1678 break;
1679
1680 case T_DIV:
1681 if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
1682
1683 dst->vb_float64 = a->vb_float64 / b->vb_float64;
1684 break;
1685
1686 case T_MOD:
1687 if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
1688
1689 dst->vb_float64 = fmod(a->vb_float64, b->vb_float64);
1690 break;
1691
1692 default:
1693 return ERR_INVALID;
1694 }
1695
1698
1699 return 0;
1700}
1701
1702/*
1703 * Do all intermediate operations on 64-bit numbers.
1704 */
1705static 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)
1706{
1707 fr_value_box_t one, two, result;
1708 fr_value_box_t const *a = in1;
1709 fr_value_box_t const *b = in2;
1710
1711 fr_value_box_init(&result, FR_TYPE_UINT64, NULL, a->tainted | b->tainted);
1712
1713 COERCE_A(FR_TYPE_UINT64, NULL);
1714
1715 if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
1716 /*
1717 * Don't touch the RHS.
1718 */
1719 fr_assert(b->type == FR_TYPE_UINT32);
1720
1721 } else {
1722 COERCE_B(FR_TYPE_UINT64, dst->enumv);
1723 }
1724
1725 switch (op) {
1726 case T_ADD:
1727 if (!fr_add(&result.vb_uint64, a->vb_uint64, b->vb_uint64)) return ERR_OVERFLOW;
1728 break;
1729
1730 case T_SUB:
1731 if (!fr_sub(&result.vb_uint64, a->vb_uint64, b->vb_uint64)) return ERR_UNDERFLOW;
1732 break;
1733
1734 case T_MUL:
1735 if (!fr_multiply(&result.vb_uint64, a->vb_uint64, b->vb_uint64)) return ERR_OVERFLOW;
1736 break;
1737
1738 case T_DIV:
1739 if (b->vb_uint64 == 0) return ERR_ZERO;
1740
1741 result.vb_uint64 = a->vb_uint64 / b->vb_uint64;
1742 break;
1743
1744 case T_MOD:
1745 if (b->vb_uint64 == 0) return ERR_ZERO;
1746
1747 result.vb_uint64 = a->vb_uint64 % in2->vb_uint64;
1748 break;
1749
1750 case T_AND:
1751 result.vb_uint64 = a->vb_uint64 & b->vb_uint64;
1752 break;
1753
1754 case T_OR:
1755 result.vb_uint64 = a->vb_uint64 | b->vb_uint64;
1756 break;
1757
1758 case T_XOR:
1759 result.vb_uint64 = a->vb_uint64 ^ b->vb_uint64;
1760 break;
1761
1762 case T_RSHIFT:
1763 if (b->vb_uint32 >= (8 * sizeof(a->vb_uint64))) return ERR_UNDERFLOW;
1764
1765 result.vb_uint64 = a->vb_uint64 >> b->vb_uint32;
1766 break;
1767
1768 case T_LSHIFT:
1769 if (b->vb_uint32 >= (8 * sizeof(a->vb_uint64))) return ERR_OVERFLOW;
1770
1771 result.vb_uint64 = a->vb_uint64 << b->vb_uint32;
1772 break;
1773
1774 default:
1775 return ERR_INVALID;
1776 }
1777
1778 /*
1779 * Once we're done, cast the result to the final data type.
1780 */
1781 if (fr_value_box_cast(ctx, dst, dst->type, dst->enumv, &result) < 0) return -1;
1782
1785
1786 return 0;
1787}
1788
1789/*
1790 * Same as above, except uint64 -> int64. These functions should be kept in sync!
1791 */
1792static 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)
1793{
1794 fr_value_box_t one, two, result;
1795 fr_value_box_t const *a = in1;
1796 fr_value_box_t const *b = in2;
1797
1798 fr_value_box_init(&result, FR_TYPE_INT64, NULL, a->tainted | b->tainted);
1799
1800 COERCE_A(FR_TYPE_INT64, NULL);
1801
1802 if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
1803 /*
1804 * Don't touch the RHS.
1805 */
1806 fr_assert(b->type == FR_TYPE_UINT32);
1807
1808 } else {
1809 COERCE_B(FR_TYPE_INT64, dst->enumv);
1810 }
1811
1812 switch (op) {
1813 case T_ADD:
1814 if (!fr_add(&result.vb_int64, a->vb_int64, b->vb_int64)) return ERR_OVERFLOW;
1815 break;
1816
1817 case T_SUB:
1818 if (!fr_sub(&result.vb_int64, a->vb_int64, b->vb_int64)) return ERR_UNDERFLOW;
1819 break;
1820
1821 case T_MUL:
1822 if (!fr_multiply(&result.vb_int64, a->vb_int64, b->vb_int64)) return ERR_OVERFLOW;
1823 break;
1824
1825 case T_DIV:
1826 if (b->vb_int64 == 0) return ERR_ZERO;
1827
1828 result.vb_int64 = a->vb_int64 / b->vb_int64;
1829 break;
1830
1831 case T_MOD:
1832 if (b->vb_int64 == 0) return ERR_ZERO;
1833
1834 result.vb_int64 = a->vb_int64 % in2->vb_int64;
1835 break;
1836
1837 case T_AND:
1838 result.vb_int64 = a->vb_int64 & b->vb_int64;
1839 break;
1840
1841 case T_OR:
1842 result.vb_int64 = a->vb_int64 | b->vb_int64;
1843 break;
1844
1845 case T_XOR:
1846 result.vb_int64 = a->vb_int64 ^ b->vb_int64;
1847 break;
1848
1849 case T_RSHIFT:
1850 if (b->vb_uint32 >= (8 * sizeof(a->vb_int64))) return ERR_UNDERFLOW;
1851
1852 result.vb_int64 = a->vb_int64 >> b->vb_uint32;
1853 break;
1854
1855 case T_LSHIFT:
1856 if (b->vb_uint32 >= (8 * sizeof(a->vb_int64))) return ERR_OVERFLOW;
1857
1858 result.vb_int64 = a->vb_int64 << b->vb_uint32;
1859 break;
1860
1861 default:
1862 return ERR_INVALID;
1863 }
1864
1865 /*
1866 * Once we're done, cast the result to the final data type.
1867 */
1868 if (fr_value_box_cast(ctx, dst, dst->type, dst->enumv, &result) < 0) return -1;
1869
1872
1873 return 0;
1874}
1875
1876typedef 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);
1877
1878/** Map output type to its associated function
1879 *
1880 */
1914
1915/** Calculate DST = A OP B
1916 *
1917 * The result is written to DST only *after* it has been calculated.
1918 * So it's safe to pass DST as either A or B. DST should already exist.
1919 *
1920 * This function should arguably not take comparison operators, but
1921 * whatever. The "promote types" code is the same for all of the
1922 * binary operations, so we might as well just have one function.
1923 */
1924int 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)
1925{
1926 int rcode = -1;
1927 fr_value_box_t one, two;
1929 fr_binary_op_t func;
1930
1931 if ((hint != FR_TYPE_NULL) && !fr_type_is_leaf(hint)) return invalid_type(hint);
1932
1933 /*
1934 * Casting to structural types should be a parse error,
1935 * and not a run-time calculation error.
1936 */
1937 if (!fr_type_is_leaf(a->type)) return invalid_type(a->type);
1938 if (!fr_type_is_leaf(b->type)) return invalid_type(b->type);
1939
1940 /*
1941 * === and !== also check types. If the types are
1942 * different, it's a failure. Otherwise they revert to == and !=.
1943 */
1944 switch (op) {
1945 case T_OP_CMP_EQ_TYPE:
1946 if (a->type != b->type) {
1947 mismatch_type:
1948 fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false); /* @todo - enum */
1949 dst->vb_bool = false;
1950 return 0;
1951 }
1952 op = T_OP_CMP_EQ;
1953 break;
1954
1955 case T_OP_CMP_NE_TYPE:
1956 if (a->type != b->type) goto mismatch_type;
1957
1958 op = T_OP_NE;
1959 break;
1960
1961 case T_OP_REG_EQ:
1962 case T_OP_REG_NE:
1963 if (b->type != FR_TYPE_STRING) {
1964 fr_strerror_const("Invalid type for regular expression");
1965 return -1;
1966 }
1967
1968 rcode = fr_regex_cmp_op(op, a, b);
1969 if (rcode < 0) return rcode;
1970
1971 fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false); /* @todo - enum */
1972 dst->vb_bool = (rcode != 0);
1973 return 0;
1974
1975 default:
1976 break;
1977 }
1978
1981
1982 /*
1983 * We don't know what the output type should be. Try to
1984 * guess based on a variety of factors.
1985 */
1986 if (hint == FR_TYPE_NULL) do {
1987 /*
1988 * All kinds of special cases :(
1989 *
1990 * date1 - date2 --> time_delta
1991 *
1992 * time_delta * FOO --> float64, because time_delta is _printed_ as a floating point
1993 * number. And this is the least surprising thing to do.
1994 */
1995 if ((op == T_SUB) && (a->type == b->type) && (a->type == FR_TYPE_DATE)) {
1996 hint = FR_TYPE_TIME_DELTA;
1997 break;
1998 }
1999
2000 if (op == T_MUL) {
2001 if (a->type == FR_TYPE_TIME_DELTA) {
2002 hint = upcast_op[FR_TYPE_FLOAT64][b->type];
2003 if (hint == FR_TYPE_NULL) hint = upcast_op[b->type][FR_TYPE_FLOAT64];
2004
2005 } else if (b->type == FR_TYPE_TIME_DELTA) {
2006 hint = upcast_op[a->type][FR_TYPE_FLOAT64];
2007 if (hint == FR_TYPE_NULL) hint = upcast_op[FR_TYPE_FLOAT64][a->type];
2008 }
2009
2010 if (hint != FR_TYPE_NULL) break;
2011 }
2012
2013 /*
2014 * date % time_delta --> time_delta
2015 */
2016 if ((op == T_MOD) && (a->type == FR_TYPE_DATE)) {
2017 hint = FR_TYPE_TIME_DELTA;
2018 break;
2019 }
2020
2021 switch (op) {
2022 case T_OP_CMP_EQ:
2023 case T_OP_NE:
2024 case T_OP_GE:
2025 case T_OP_GT:
2026 case T_OP_LE:
2027 case T_OP_LT:
2028 /*
2029 * Comparison operators always return
2030 * "bool".
2031 */
2032 hint = FR_TYPE_BOOL;
2033 break;
2034
2035 case T_AND:
2036 /*
2037 * Get mask from IP + number
2038 */
2039 if ((a->type == FR_TYPE_IPV4_ADDR) || (b->type == FR_TYPE_IPV4_ADDR)) {
2040 hint = FR_TYPE_IPV4_PREFIX;
2041 break;
2042 }
2043
2044 if ((a->type == FR_TYPE_IPV6_ADDR) || (b->type == FR_TYPE_IPV6_ADDR)) {
2045 hint = FR_TYPE_IPV6_PREFIX;
2046 break;
2047 }
2049
2050 case T_OR:
2051 case T_ADD:
2052 case T_SUB:
2053 case T_MUL:
2054 case T_DIV:
2055 case T_MOD:
2056 case T_XOR:
2057 /*
2058 * Try to "up-cast" the types. This is
2059 * so that we can take (for example)
2060 * uint8 + uint16, and have the output as
2061 * uint16.
2062 *
2063 * There must be only one entry per [a,b]
2064 * pairing. That way we're sure that [a,b]==[b,a]
2065 */
2066 hint = upcast_op[a->type][b->type];
2067 if (hint == FR_TYPE_NULL) {
2068 hint = upcast_op[b->type][a->type];
2069 } else if (a->type != b->type) {
2070 fr_assert(upcast_op[b->type][a->type] == FR_TYPE_NULL);
2071 }
2072
2073 /*
2074 * No idea what to do. :(
2075 */
2076 if (hint == FR_TYPE_NULL) {
2077 fr_strerror_printf("Invalid operation on data types - '%s' %s '%s'",
2078 fr_type_to_str(a->type), fr_tokens[op], fr_type_to_str(b->type));
2079 goto done;
2080 }
2081
2082 break;
2083
2084 /*
2085 * The RHS MUST be a numerical type. We don't need to do any upcasting here.
2086 *
2087 * @todo - the output type could be larger than the input type, if the shift is
2088 * more than the input type can handle. e.g. uint8 << 4 could result in uint16
2089 */
2090 case T_LSHIFT:
2091 if (!fr_type_is_integer(a->type)) {
2092 return handle_result(a->type, T_LSHIFT, ERR_INVALID);
2093 }
2094
2095 if (fr_type_is_signed(a->type)) {
2096 hint = FR_TYPE_INT64;
2097 break;
2098 }
2099 hint = FR_TYPE_UINT64;
2100 break;
2101
2102 case T_RSHIFT:
2103 hint = a->type;
2104 break;
2105
2106 default:
2107 return handle_result(a->type, op, ERR_INVALID);
2108 }
2109 } while (0);
2110
2111 /*
2112 * Now that we've figured out the correct types, perform the operation.
2113 */
2114 switch (op) {
2115 case T_OP_CMP_EQ:
2116 case T_OP_NE:
2117 case T_OP_GE:
2118 case T_OP_GT:
2119 case T_OP_LE:
2120 case T_OP_LT:
2121 if (hint != FR_TYPE_BOOL) {
2122 fr_strerror_printf("Invalid destination type '%s' for comparison operator",
2123 fr_type_to_str(hint));
2124 goto done;
2125 }
2126
2127 /*
2128 * Convert the types to ones which are comparable.
2129 */
2130 if (a->type != b->type) {
2131 fr_dict_attr_t const *enumv = NULL;
2132
2133 /*
2134 * If we're doing comparisons and one of them has an enum, and the other is an
2135 * enum name, then use the enum name to convert the string to the other type.
2136 *
2137 * We can then do type-specific comparisons.
2138 */
2139 if ((a->type == FR_TYPE_STRING) && b->enumv) {
2140 enumv = b->enumv;
2141 hint = b->type;
2142
2143 } else if ((b->type == FR_TYPE_STRING) && a->enumv) {
2144 enumv = a->enumv;
2145 hint = a->type;
2146
2147 } else {
2148 /*
2149 * Try to "up-cast" the types. This is so that we can take (for example)
2150 * uint8 < uint16, and have it make sense.
2151 *
2152 * There must be only one entry per [a,b] pairing. That way we're sure
2153 * that [a,b]==[b,a]
2154 */
2155 hint = upcast_cmp[a->type][b->type];
2156 if (hint == FR_TYPE_NULL) {
2157 hint = upcast_cmp[b->type][a->type];
2158 } else {
2159 fr_assert(upcast_cmp[b->type][a->type] == FR_TYPE_NULL);
2160 }
2161
2162 /*
2163 * time_deltas have a scale in the enumv, but default to "seconds" if
2164 * there's no scale. As a result, if we compare time_delta(ms) to integer,
2165 * then the integer is interpreted as seconds, and the scale is wrong.
2166 *
2167 * The solution is to use the appropriate scale.
2168 */
2169 if (hint == a->type) enumv = a->enumv;
2170 if (hint == b->type) enumv = b->enumv;
2171
2172 if (hint == FR_TYPE_NULL) {
2173 fr_strerror_printf("Cannot compare incompatible types (%s)... %s (%s)...",
2174 fr_type_to_str(a->type),
2175 fr_tokens[op],
2176 fr_type_to_str(b->type));
2177 goto done;
2178 }
2179 }
2180
2181 /*
2182 * Cast them to the appropriate type, which may be different from either of the
2183 * inputs.
2184 */
2185 if (a->type != hint) {
2186 if (fr_value_box_cast(NULL, &one, hint, enumv, a) < 0) goto done;
2187 a = &one;
2188 }
2189
2190 if (b->type != hint) {
2191 if (fr_value_box_cast(NULL, &two, hint, enumv, b) < 0) goto done;
2192 b = &two;
2193 }
2194 }
2195
2196 rcode = fr_value_box_cmp_op(op, a, b);
2197 if (rcode < 0) goto done;
2198
2199 fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false);
2200 dst->vb_bool = (rcode > 0);
2201 break;
2202
2203 /*
2204 * For shifts, the RHS value MUST be an integer. There's no reason to have it as
2205 * anything other than an 8-bit field.
2206 */
2207 case T_LSHIFT:
2208 case T_RSHIFT:
2209 if (b->type != FR_TYPE_UINT32) {
2210 if (fr_value_box_cast(ctx, &two, FR_TYPE_UINT32, NULL, b) < 0) {
2211 fr_strerror_printf("Cannot parse shift value as integer - %s",
2212 fr_strerror());
2213 goto done;
2214 }
2215 b = &two;
2216 }
2218
2219 case T_ADD:
2220 case T_SUB:
2221 case T_MUL:
2222 case T_DIV:
2223 case T_MOD:
2224 case T_AND:
2225 case T_OR:
2226 case T_XOR:
2227 fr_assert(hint != FR_TYPE_NULL);
2228
2229 func = calc_type[hint];
2230 if (!func) {
2231 fr_strerror_printf("Cannot perform any operations for destination type %s",
2232 fr_type_to_str(hint));
2233 rcode = -1;
2234 break;
2235 }
2236
2237 /*
2238 * It's OK to use one of the inputs as the
2239 * output. In order to ensure that nothing bad
2240 * happens, we use an intermediate value-box.
2241 */
2242 fr_value_box_init(&out, hint, NULL, false);
2243
2244 rcode = func(ctx, &out, a, op, b); /* not calc_type[hint], to shut up clang */
2245 if (rcode < 0) goto done;
2246
2247 fr_value_box_copy_shallow(NULL, dst, &out);
2248 dst->tainted = a->tainted | b->tainted;
2249 break;
2250
2251 default:
2252 rcode = ERR_INVALID;
2253 break;
2254 }
2255
2256done:
2259
2260 return handle_result(hint, op, rcode);
2261}
2262
2263/** Calculate DST = OP { A, B, C, ... }
2264 *
2265 * The result is written to DST only *after* it has been calculated.
2266 * So it's safe to pass DST as one of the inputs. DST should already
2267 * exist.
2268 */
2270{
2271 fr_value_box_t out, *vb;
2272 fr_binary_op_t calc;
2273
2274 if (group->type != FR_TYPE_GROUP) {
2275 fr_strerror_const("Invalid type passed to multivalue calculation");
2276 return -1;
2277 }
2278
2281 fr_strerror_printf("Invalid operation %s for data type %s", fr_tokens[op], fr_type_to_str(type));
2282 return -1;
2283 }
2284
2285 if (type == FR_TYPE_STRING) {
2286 fr_sbuff_t *sbuff;
2287
2288 if (op != T_ADD) goto invalid_type;
2289
2290 FR_SBUFF_TALLOC_THREAD_LOCAL(&sbuff, 1024, (1 << 16));
2291
2292 if (fr_value_box_list_concat_as_string(dst, sbuff, UNCONST(fr_value_box_list_t *, &group->vb_group),
2293 NULL, 0, NULL, FR_VALUE_BOX_LIST_NONE, FR_VALUE_BOX_SAFE_FOR_ANY, false) < 0) return -1;
2294
2295 if (fr_value_box_bstrndup(ctx, dst, NULL, fr_sbuff_start(sbuff), fr_sbuff_used(sbuff), false) < 0) return -1;
2296 return 0;
2297 }
2298
2299 if (type == FR_TYPE_OCTETS) {
2300 fr_dbuff_t *dbuff;
2301
2302 if (op != T_ADD) goto invalid_type;
2303
2304 FR_DBUFF_TALLOC_THREAD_LOCAL(&dbuff, 1024, (1 << 16));
2305
2306 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;
2307
2308 if (fr_value_box_memdup(ctx, dst, NULL, fr_dbuff_start(dbuff), fr_dbuff_used(dbuff), false) < 0) return -1;
2309
2310 return 0;
2311 }
2312
2313 /*
2314 * Can't add or multiply booleans.
2315 */
2316 if ((type == FR_TYPE_BOOL) && !((op == T_AND) || (op == T_OR) || (op == T_XOR))) goto unsupported;
2317
2318 switch (op) {
2319 case T_ADD:
2320 case T_MUL:
2321 case T_AND:
2322 case T_OR:
2323 case T_XOR:
2324 break;
2325
2326 default:
2327 goto invalid_type;
2328 }
2329
2330 /*
2331 * Strings and octets are different.
2332 */
2333 if (!fr_type_is_numeric(type)) {
2334 unsupported:
2335 fr_strerror_printf("Not yet supported operation %s for data type %s", fr_tokens[op], fr_type_to_str(type));
2336 return -1;
2337 }
2338
2339 switch (type) {
2340 case FR_TYPE_UINT8:
2341 case FR_TYPE_UINT16:
2342 case FR_TYPE_UINT32:
2343 case FR_TYPE_UINT64:
2344 calc = calc_uint64;
2345 break;
2346
2347 case FR_TYPE_INT8:
2348 case FR_TYPE_INT16:
2349 case FR_TYPE_INT32:
2350 case FR_TYPE_INT64:
2351 calc = calc_int64;
2352 break;
2353
2354 case FR_TYPE_TIME_DELTA:
2355 if ((op != T_ADD) && (op != T_SUB)) goto invalid_type;
2356 calc = calc_time_delta;
2357 break;
2358
2359 case FR_TYPE_FLOAT32:
2360 calc = calc_float32;
2361 break;
2362
2363 case FR_TYPE_FLOAT64:
2364 calc = calc_float64;
2365 break;
2366
2367 default:
2368 goto unsupported;
2369 }
2370
2371 vb = fr_value_box_list_head(&group->vb_group);
2372 if (!vb) {
2373 fr_strerror_printf("Empty input is invalid");
2374 return -1;
2375 }
2376
2377 if (fr_value_box_cast(ctx, &out, type, NULL, vb) < 0) return -1;
2378
2379 while ((vb = fr_value_box_list_next(&group->vb_group, vb)) != NULL) {
2380 int rcode;
2381 fr_value_box_t box;
2382
2383 if (vb->type == type) {
2384 rcode = calc(ctx, &out, &out, op, vb);
2385 if (rcode < 0) return rcode;
2386
2387 } else {
2388 if (fr_value_box_cast(ctx, &box, type, NULL, vb) < 0) return -1;
2389
2390 rcode = calc(ctx, &out, &out, op, &box);
2391 if (rcode < 0) return rcode;
2392 }
2393 }
2394
2395 return fr_value_box_copy(ctx, dst, &out);
2396}
2397
2398
2399#define T(_x) [T_OP_ ## _x ## _EQ] = T_ ## _x
2400
2402 T(ADD),
2403 T(SUB),
2404 T(MUL),
2405 T(DIV),
2406 T(AND),
2407 T(OR),
2408 T(XOR),
2409 T(RSHIFT),
2410 T(LSHIFT),
2411};
2412
2413/** Calculate DST OP SRC
2414 *
2415 * e.g. "foo += bar".
2416 *
2417 * This is done by doing some sanity checks, and then just calling
2418 * the "binary operation" function.
2419 */
2421{
2422 int rcode;
2423
2424 if (!fr_type_is_leaf(dst->type)) return invalid_type(dst->type);
2425 if (!fr_type_is_leaf(src->type)) return invalid_type(src->type);
2426
2427 if (dst->immutable) {
2428 fr_strerror_printf("Cannot modify immutable value");
2429 return -1;
2430 }
2431
2432 /*
2433 * These operators are included here for testing and completeness. But see comments in
2434 * fr_edit_list_apply_pair_assignment() for what the caller should be doing.
2435 */
2436 if ((op == T_OP_EQ) || (op == T_OP_SET)) {
2437 /*
2438 * Allow for unintentional mistakes.
2439 */
2440 if (src == dst) return 0;
2441
2443 return fr_value_box_cast(ctx, dst, dst->type, dst->enumv, src); /* cast, as the RHS might not (yet) be the same! */
2444 }
2445
2446 if (assignment2op[op] == T_INVALID) {
2447 return handle_result(dst->type, op, ERR_INVALID);
2448 }
2449 op = assignment2op[op];
2450
2451 /*
2452 * Just call the binary op function. It already ensures that (a) the inputs are "const", and (b)
2453 * the output is over-written only at the final step.
2454 */
2455 if (src->type != FR_TYPE_GROUP) {
2456 rcode = fr_value_calc_binary_op(ctx, dst, dst->type, dst, op, src);
2457
2458 } else {
2459 fr_value_box_t *vb = NULL;
2460
2461 /*
2462 * If the RHS is a group, then we loop over the group recursively, doing the operation.
2463 */
2464 rcode = 0; /* in case group is empty */
2465
2466 while ((vb = fr_value_box_list_next(&src->vb_group, vb)) != NULL) {
2467 rcode = fr_value_calc_binary_op(ctx, dst, dst->type, dst, op, vb);
2468 if (rcode < 0) break;
2469 }
2470 }
2471
2472 if (rcode < 0) return handle_result(dst->type, op, rcode);
2473
2474 return 0;
2475}
2476
2477/** Calculate unary operations
2478 *
2479 * e.g. "foo++", or "-foo".
2480 */
2481int fr_value_calc_unary_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_token_t op, fr_value_box_t const *src)
2482{
2483 int rcode = -1;
2484 fr_value_box_t one;
2485
2486 if (!fr_type_is_numeric(src->type)) return invalid_type(src->type);
2487
2488 if (dst->immutable) {
2489 fr_strerror_printf("Cannot modify immutable value");
2490 return -1;
2491 }
2492
2493 if (op == T_OP_INCRM) {
2494 /*
2495 * Add 1 or subtract 1 means RHS is always 1.
2496 */
2497 fr_value_box_init(&one, src->type, NULL, false);
2498 switch (src->type) {
2499 case FR_TYPE_UINT8:
2500 one.vb_uint8 = 1;
2501 break;
2502
2503 case FR_TYPE_UINT16:
2504 one.vb_uint16 = 1;
2505 break;
2506
2507 case FR_TYPE_UINT32:
2508 one.vb_uint32 = 1;
2509 break;
2510
2511 case FR_TYPE_UINT64:
2512 one.vb_uint64 = 1;
2513 break;
2514
2515 case FR_TYPE_SIZE:
2516 one.vb_size = 1;
2517 break;
2518
2519 case FR_TYPE_INT8:
2520 one.vb_int8 = 1;
2521 break;
2522
2523 case FR_TYPE_INT16:
2524 one.vb_int16 = 1;
2525 break;
2526
2527 case FR_TYPE_INT32:
2528 one.vb_int32 = 1;
2529 break;
2530
2531 case FR_TYPE_INT64:
2532 one.vb_int64 = 1;
2533 break;
2534
2535 case FR_TYPE_FLOAT32:
2536 one.vb_float32 = 1;
2537 break;
2538
2539 case FR_TYPE_FLOAT64:
2540 one.vb_float64 = 1;
2541 break;
2542
2543 default:
2544 fr_assert(0);
2545 return -1;
2546 }
2547
2548 rcode = fr_value_calc_binary_op(ctx, dst, src->type, src, T_ADD, &one);
2549 return handle_result(dst->type, op, rcode);
2550
2551 } else if (op == T_COMPLEMENT) {
2552 if (dst != src) {
2553 fr_value_box_init(dst, src->type, src->enumv, false);
2554 fr_value_box_safety_copy(dst, src);
2555 }
2556
2557#undef COMP
2558#define COMP(_type, _field) case FR_TYPE_ ## _type: dst->vb_ ##_field = (_field ## _t) ~src->vb_ ##_field; break
2559 switch (src->type) {
2560 COMP(UINT8, uint8);
2561 COMP(UINT16, uint16);
2562 COMP(UINT32, uint32);
2563 COMP(UINT64, uint64);
2564 COMP(SIZE, size);
2565
2566 COMP(INT8, int8);
2567 COMP(INT16, int16);
2568 COMP(INT32, int32);
2569 COMP(INT64, int64);
2570
2571 default:
2572 goto invalid;
2573 }
2574
2575 return 0;
2576
2577 } else if (op == T_SUB) {
2578 fr_type_t type = src->type;
2579
2580 if ((dst != src) && !fr_type_is_signed(src->type)) {
2581 type = upcast_unsigned[src->type];
2582
2583 if (type == FR_TYPE_NULL) {
2584 type = src->type; /* hope for the best */
2585 }
2586 }
2587
2588 fr_value_box_init(&one, type, NULL, src->tainted); /* init to zero */
2589 rcode = fr_value_calc_binary_op(ctx, dst, type, &one, T_SUB, src);
2590
2591 return handle_result(dst->type, op, rcode);
2592
2593 } else if (op == T_NOT) {
2594 bool value = fr_value_box_is_truthy(src);
2595
2596 fr_value_box_clear(dst);
2597 fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false); // @todo - add enum!
2598 dst->vb_bool = !value;
2599
2600 return 0;
2601
2602 } else {
2603 invalid:
2604 return handle_result(src->type, op, ERR_INVALID);
2605 }
2606
2607}
2608
2609/*
2610 * Empty lists are empty:
2611 *
2612 * {}
2613 * {{}}
2614 * {''}
2615 * {{},''}
2616 *
2617 * etc.
2618 */
2619static bool fr_value_calc_list_empty(fr_value_box_list_t const *list)
2620{
2622 switch (item->type) {
2623 default:
2624 return false;
2625
2626 case FR_TYPE_GROUP:
2627 if (!fr_value_calc_list_empty(&item->vb_group)) return false;
2628 break;
2629
2630 case FR_TYPE_STRING:
2631 case FR_TYPE_OCTETS:
2632 if (item->vb_length != 0) return false;
2633 break;
2634 }
2635 }
2636
2637 return true;
2638}
2639
2640
2641/*
2642 * Loop over input lists, calling fr_value_calc_binary_op()
2643 *
2644 * This implementation is arguably wrong... it should be checking individual entries in list1 against individual entries in list2.
2645 * Instead, it checks if ANY entry in list1 matches ANY entry in list2.
2646 */
2647int 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)
2648{
2649 int rcode;
2650 bool invert = false;
2651 bool a_empty, b_empty;
2652
2653 if (!fr_comparison_op[op]) {
2654 fr_strerror_printf("Invalid operator '%s' passed to list comparison", fr_tokens[op]);
2655 return -1;
2656 }
2657
2658 /*
2659 * v3 hack. != really means !( ... == ... )
2660 */
2661 if (op == T_OP_NE) {
2662 invert = true;
2663 op = T_OP_CMP_EQ;
2664 }
2665
2666 /*
2667 * It's annoying when the debug prints out cmp({},{}) and says "not equal".
2668 *
2669 * What's happening behind the scenes is that one side is an empty value-box group, such as when
2670 * an xlat expansion fails. And the other side is an empty string. If we believe that strings
2671 * are actually sets of characters, then {}=='', and we're all OK
2672 */
2673 a_empty = fr_value_box_list_empty(list1) || fr_value_calc_list_empty(list1);
2674 b_empty = fr_value_box_list_empty(list2) || fr_value_calc_list_empty(list2);
2675
2676 /*
2677 * Both lists are empty, they should be equal when checked for equality.
2678 */
2679 if (a_empty && b_empty) {
2680 switch (op) {
2681 case T_OP_CMP_EQ:
2682 case T_OP_LE:
2683 case T_OP_GE:
2684 invert = !invert;
2685 break;
2686
2687 default:
2688 break;
2689 }
2690
2691 goto done;
2692 }
2693
2694 /*
2695 * Emulate v3. :(
2696 */
2697 fr_value_box_list_foreach(list1, a) {
2698 fr_value_box_list_foreach(list2, b) {
2699 rcode = fr_value_calc_binary_op(ctx, dst, FR_TYPE_BOOL, a, op, b);
2700 if (rcode < 0) return rcode;
2701
2702 /*
2703 * No match: keep looking for a match.
2704 */
2705 fr_assert(dst->type == FR_TYPE_BOOL);
2706 if (!dst->vb_bool) continue;
2707
2708 /*
2709 * Found a match, we're done.
2710 */
2711 dst->vb_bool = !invert;
2712 return 0;
2713 }
2714 }
2715
2716 /*
2717 * No match,
2718 */
2719done:
2720 fr_value_box_clear(dst);
2721 fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false); // @todo - add enum!
2722 dst->vb_bool = invert;
2723 return 0;
2724}
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:167
#define RCSID(id)
Definition build.h:485
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition build.h:324
#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:1499
static const fr_binary_op_t calc_type[FR_TYPE_MAX+1]
Map output type to its associated function.
Definition calc.c:1881
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:1434
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:1606
#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:1705
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:1584
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:1522
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:1792
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:2647
#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:1596
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:1876
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:2619
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:1656
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:2269
#define is_ipv6(_x)
Definition calc.c:1582
#define COERCE_B(_type, _enumv)
Definition calc.c:48
static const fr_token_t assignment2op[T_TOKEN_LAST]
Definition calc.c:2401
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:2420
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:1924
#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:2481
#define T(_x)
Definition calc.c:2399
#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:767
#define fr_dbuff_start(_dbuff_or_marker)
Return the 'start' position of a dbuff or marker.
Definition dbuff.h:898
#define FR_DBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
Create a function local and thread local extensible dbuff.
Definition dbuff.h:556
static fr_slen_t in
Definition dict.h:831
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:140
#define fr_add(_out, _a, _b)
Adds two integers.
Definition math.h:129
#define fr_multiply(_out, _a, _b)
Multiplies two integers together.
Definition math.h:118
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:80
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:78
const bool fr_comparison_op[T_TOKEN_LAST]
Definition token.c:198
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:1392
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:554
#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:371
#define fr_type_is_numeric(_x)
Definition types.h:361
#define fr_type_is_signed(_x)
Definition types.h:362
#define fr_type_is_leaf(_x)
Definition types.h:372
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:433
#define fr_type_is_integer(_x)
Definition types.h:360
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:5514
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:3370
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:3759
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:929
bool fr_value_box_is_truthy(fr_value_box_t const *in)
Check truthiness of values.
Definition value.c:6370
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:4499
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:3864
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:5630
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
Definition value.c:3700
void fr_value_box_safety_merge(fr_value_box_t *out, fr_value_box_t const *in)
Merge safety results.
Definition value.c:6332
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:6310
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition value.c:3742
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:4178
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:4262
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:4419
@ FR_VALUE_BOX_LIST_NONE
Do nothing to processed boxes.
Definition value.h:227
#define fr_value_box_init_null(_vb)
Initialise an empty/null box that will be filled later.
Definition value.h:604
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
Definition value.h:598
#define fr_value_box_list_foreach(_list_head, _iter)
Definition value.h:217
static size_t char ** out
Definition value.h:1012
#define FR_VALUE_BOX_SAFE_FOR_ANY
Definition value.h:166