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: 281706eb41d5c550202d5b77ce2d457c137fc564 $
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: 281706eb41d5c550202d5b77ce2d457c137fc564 $")
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, *p;
906 size_t i, 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 if (op == T_MUL) {
922
924
925 } else {
926 COERCE_B(FR_TYPE_OCTETS, dst->enumv);
927 }
928
929 len = a->vb_length + b->vb_length;
930
931 switch (op) {
932 case T_ADD: /* dst = a . b */
933 buf = talloc_array(ctx, uint8_t, len);
934 if (!buf) {
935 oom:
936 fr_strerror_const("Out of memory");
937 return -1;
938 }
939
940 memcpy(buf, a->vb_octets, a->vb_length);
941 memcpy(buf + a->vb_length, b->vb_octets, b->vb_length);
942
943 fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, false);
946 break;
947
948 case T_SUB:
949 /*
950 * The inverse of add!
951 */
952 if (a->vb_length < b->vb_length) {
953 fr_strerror_const("Suffix to remove is longer than input string.");
954 return -1;
955 }
956
957 if (memcmp(a->vb_octets + a->vb_length - b->vb_length, b->vb_strvalue, b->vb_length) != 0) {
958 fr_strerror_const("Suffix to remove is not a suffix of the input string.");
959 return -1;
960 }
961
962 len = a->vb_length - b->vb_length;
963 buf = talloc_array(ctx, uint8_t, len);
964 if (!buf) goto oom;
965
966 memcpy(buf, a->vb_strvalue, len);
967
968 fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, false);
970 break;
971
972 case T_AND:
973 if (a->vb_length != b->vb_length) {
974 length_error:
975 fr_strerror_const("Cannot perform operation on strings of different length");
976 return -1;
977 }
978
979 buf = talloc_array(ctx, uint8_t, a->vb_length);
980 if (!buf) goto oom;
981
982 for (len = 0; len < a->vb_length; len++) {
983 buf[len] = a->vb_octets[len] & b->vb_octets[len];
984 }
985
986 set_result:
987 fr_value_box_memdup_shallow(dst, dst->enumv, buf, a->vb_length, false);
990 break;
991
992 case T_OR:
993 if (a->vb_length != b->vb_length) goto length_error;
994
995 buf = talloc_array(ctx, uint8_t, a->vb_length);
996 if (!buf) goto oom;
997
998 for (len = 0; len < a->vb_length; len++) {
999 buf[len] = a->vb_octets[len] | b->vb_octets[len];
1000 }
1001 goto set_result;
1002
1003 case T_XOR:
1004 if (a->vb_length != b->vb_length) goto length_error;
1005
1006 buf = talloc_array(ctx, uint8_t, a->vb_length);
1007 if (!buf) goto oom;
1008
1009 for (len = 0; len < a->vb_length; len++) {
1010 buf[len] = a->vb_octets[len] ^ b->vb_octets[len];
1011 }
1012
1013 goto set_result;
1014
1015 case T_RSHIFT:
1016 if (b->vb_uint32 > a->vb_length) return ERR_UNDERFLOW;
1017
1018 len = a->vb_length - b->vb_uint32;
1019 buf = talloc_array(ctx, uint8_t, len);
1020 if (!buf) goto oom;
1021
1022 memcpy(buf, a->vb_octets, len);
1023
1024 fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, false);
1026 break;
1027
1028 case T_LSHIFT:
1029 if (b->vb_uint32 > a->vb_length) return ERR_OVERFLOW;
1030
1031 len = a->vb_length - b->vb_uint32;
1032
1033 buf = talloc_array(ctx, uint8_t, len);
1034 if (!buf) goto oom;
1035
1036 memcpy(buf, a->vb_octets + b->vb_uint32, len);
1037
1038 fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, false);
1040 break;
1041
1042 case T_MUL:
1043 /*
1044 * 0 * 0 = 0
1045 */
1046 if (!b->vb_uint64 || !a->vb_length) {
1047 fr_value_box_memdup(ctx, dst, dst->enumv, (const uint8_t *) "", 0, false);
1049 break;
1050 }
1051
1052 if (b->vb_uint64 > 256) return ERR_OVERFLOW;
1053 if (a->vb_length > 16) return ERR_OVERFLOW;
1054
1055 len = a->vb_length * b->vb_uint64;
1056
1057 buf = talloc_array(ctx, uint8_t, len);
1058 if (!buf) goto oom;
1059
1060 for (i = 0, p = buf; i < b->vb_uint64; i++, p += a->vb_length) {
1061 memcpy(p, a->vb_octets, a->vb_length);
1062 }
1063
1064 fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, false);
1066 break;
1067
1068 default:
1069 return ERR_INVALID; /* invalid operator */
1070 }
1071
1072 if (a == &one) fr_value_box_clear_value(&one);
1073 if (b == &two) fr_value_box_clear_value(&two);
1074
1075 return 0;
1076}
1077
1078static 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)
1079{
1080 char *buf, *p;
1081 size_t i, len;
1082 fr_value_box_t one = {};
1083 fr_value_box_t two = {};
1084
1085 fr_assert(dst->type == FR_TYPE_STRING);
1086
1087 COERCE_A(FR_TYPE_STRING, dst->enumv);
1088
1089 if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
1090 /*
1091 * Don't touch the RHS.
1092 */
1093 fr_assert(b->type == FR_TYPE_UINT32);
1094
1095 } else if (op == T_MUL) {
1097
1098 COERCE_B(FR_TYPE_UINT64, NULL);
1099
1100 } else {
1101 COERCE_B(FR_TYPE_STRING, dst->enumv);
1102 }
1103
1104 len = a->vb_length + b->vb_length;
1105
1106 switch (op) {
1107 case T_ADD:
1108 buf = talloc_array(ctx, char, len + 1);
1109 if (!buf) {
1110 oom:
1111 fr_strerror_const("Out of memory");
1112 return -1;
1113 }
1114
1115 len = a->vb_length + b->vb_length;
1116 memcpy(buf, a->vb_strvalue, a->vb_length);
1117 memcpy(buf + a->vb_length, b->vb_strvalue, b->vb_length);
1118 buf[len] = '\0';
1119
1120 fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1123 break;
1124
1125 case T_XOR: /* is prepend for strings */
1126 buf = talloc_array(ctx, char, len + 1);
1127 if (!buf) goto oom;
1128
1129 len = a->vb_length + b->vb_length;
1130 memcpy(buf, b->vb_strvalue, b->vb_length);
1131 memcpy(buf + b->vb_length, a->vb_strvalue, a->vb_length);
1132 buf[len] = '\0';
1133
1134 fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1137 break;
1138
1139 case T_SUB:
1140 /*
1141 * The inverse of add!
1142 */
1143 if (a->vb_length < b->vb_length) {
1144 fr_strerror_const("Suffix to remove is longer than input string");
1145 return -1;
1146 }
1147
1148 if (memcmp(a->vb_strvalue + a->vb_length - b->vb_length, b->vb_strvalue, b->vb_length) != 0) {
1149 fr_strerror_const("Right side of substract is not a suffix of the input string");
1150 return -1;
1151 }
1152
1153 len = a->vb_length - b->vb_length;
1154 buf = talloc_array(ctx, char, len + 1);
1155 if (!buf) goto oom;
1156
1157 memcpy(buf, a->vb_strvalue, len);
1158 buf[len] = '\0';
1159
1160 fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1162 break;
1163
1164 case T_RSHIFT:
1165 if (b->vb_uint32 > a->vb_length) return ERR_UNDERFLOW;
1166
1167 len = a->vb_length - b->vb_uint32;
1168 buf = talloc_array(ctx, char, len + 1);
1169 if (!buf) goto oom;
1170
1171 memcpy(buf, a->vb_strvalue, len);
1172 buf[len] = '\0';
1173
1174 fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1176 break;
1177
1178 case T_LSHIFT:
1179 if (b->vb_uint32 > a->vb_length) return ERR_OVERFLOW;
1180
1181 len = a->vb_length - b->vb_uint32;
1182
1183 buf = talloc_array(ctx, char, len + 1);
1184 if (!buf) goto oom;
1185
1186 memcpy(buf, a->vb_strvalue + b->vb_uint32, len);
1187 buf[len] = '\0';
1188
1189 fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1191 break;
1192
1193 case T_MUL:
1194 /*
1195 * 0 * 0 = 0
1196 */
1197 if (!b->vb_uint64 || !a->vb_length) {
1198 fr_value_box_strdup(ctx, dst, dst->enumv, "", false);
1200 break;
1201 }
1202
1203 if (b->vb_uint64 > 256) return ERR_OVERFLOW;
1204 if (a->vb_length > 16) return ERR_OVERFLOW;
1205
1206 len = a->vb_length * b->vb_uint64;
1207
1208 buf = talloc_array(ctx, char, len + 1);
1209 if (!buf) goto oom;
1210
1211 for (i = 0, p = buf; i < b->vb_uint64; i++, p += a->vb_length) {
1212 memcpy(p, a->vb_strvalue, a->vb_length);
1213 }
1214 *p = '\0';
1215
1216 fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1218 break;
1219
1220 default:
1221 return ERR_INVALID; /* invalid operator */
1222 }
1223
1224 if (a == &one) fr_value_box_clear_value(&one);
1225 if (b == &two) fr_value_box_clear_value(&two);
1226
1227 return 0;
1228}
1229
1231{
1232 switch (in->type) {
1233 default:
1234 fr_strerror_printf("Cannot operate on ipaddr and %s",
1235 fr_type_to_str(in->type));
1236 return -1;
1237
1239 if (in->vb_ip.af == AF_INET6) goto cast_ipv6_addr;
1240
1241 fr_value_box_init(out, FR_TYPE_IPV4_ADDR, NULL, in->tainted);
1242 out->vb_ip = in->vb_ip;
1243 break;
1244
1246 if (in->vb_ip.af == AF_INET6) goto cast_ipv6_prefix;
1247
1248 fr_value_box_init(out, FR_TYPE_IPV4_PREFIX, NULL, in->tainted);
1249 out->vb_ip = in->vb_ip;
1250 break;
1251
1253 case FR_TYPE_IPV4_ADDR:
1254 if (unlikely(fr_value_box_copy(NULL, out, in) < 0)) return -1;
1255 break;
1256
1257 case FR_TYPE_IPV6_ADDR:
1259 if (fr_value_box_cast(NULL, out, FR_TYPE_IPV4_ADDR, NULL, in) < 0) return -1;
1260 break;
1261
1263 cast_ipv6_prefix:
1264 if (fr_value_box_cast(NULL, out, FR_TYPE_IPV4_PREFIX, NULL, in) < 0) return -1;
1265 break;
1266
1267 /*
1268 * All of these get mashed to 32-bits. The cast
1269 * operation will check bounds (both negative and
1270 * positive) on the run-time values.
1271 */
1272 case FR_TYPE_BOOL:
1273
1274 case FR_TYPE_UINT8:
1275 case FR_TYPE_UINT16:
1276 case FR_TYPE_UINT32:
1277 case FR_TYPE_UINT64:
1278
1279 case FR_TYPE_SIZE:
1280
1281 case FR_TYPE_INT8:
1282 case FR_TYPE_INT16:
1283 case FR_TYPE_INT32:
1284 case FR_TYPE_INT64:
1285
1286 case FR_TYPE_FLOAT32:
1287 case FR_TYPE_FLOAT64:
1288 if (fr_value_box_cast(NULL, out, FR_TYPE_UINT32, NULL, in) < 0) return -1;
1289 break;
1290 }
1291
1292 return 0;
1293}
1294
1295static 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)
1296{
1297 fr_value_box_t one, two;
1298 fr_value_box_t *a, *b;
1299
1300 fr_assert((dst->type == FR_TYPE_IPV4_ADDR) || (dst->type == FR_TYPE_COMBO_IP_ADDR));
1301
1302 if (cast_ipv4_addr(&one, in1) < 0) return -1;
1303 a = &one;
1304
1305 if (cast_ipv4_addr(&two, in2) < 0) return -1;
1306 b = &two;
1307
1308 switch (op) {
1309 case T_ADD:
1310 case T_OR:
1311 /*
1312 * For simplicity, make sure that the prefix is first.
1313 */
1314 if (b->type == FR_TYPE_IPV4_PREFIX) swap(a,b);
1315
1316 /*
1317 * We can only add something to a prefix, and
1318 * that something has to be a number. The cast
1319 * operation already ensured that the number is
1320 * uint32, and is at least vaguely within the
1321 * allowed range.
1322 */
1323 if (a->type != FR_TYPE_IPV4_PREFIX) return ERR_INVALID;
1324
1325 if (b->type != FR_TYPE_UINT32) return ERR_INVALID;
1326
1327 /*
1328 * Trying to add a number outside of the given prefix. That's not allowed.
1329 */
1330 if (b->vb_uint32 >= (((uint32_t) 1) << (32 - a->vb_ip.prefix))) return ERR_OVERFLOW;
1331
1332 dst->vb_ip.af = AF_INET;
1333 dst->vb_ipv4addr = htonl(ntohl(a->vb_ipv4addr) | b->vb_uint32);
1334 dst->vb_ip.prefix = 32;
1337 break;
1338
1339 default:
1340 return ERR_INVALID;
1341 }
1342
1343 return 0;
1344}
1345
1346static 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)
1347{
1348 int prefix;
1349 fr_value_box_t one, two, tmp;
1350
1351 fr_assert((dst->type == FR_TYPE_IPV4_PREFIX) || (dst->type == FR_TYPE_COMBO_IP_PREFIX));
1352
1353 switch (op) {
1354 case T_AND:
1355 if (fr_type_is_integer(a->type)) {
1356 if (fr_value_box_cast(NULL, &one, FR_TYPE_UINT32, NULL, a) < 0) return -1;
1357
1358 a = &one;
1359 swap(a, b);
1360
1361 } else if (fr_type_is_integer(b->type)) {
1362 if (fr_value_box_cast(NULL, &two, FR_TYPE_UINT32, NULL, b) < 0) return -1;
1363 b = &two;
1364
1365 } else {
1366 fr_strerror_const("Invalid input types for ipv4prefix");
1367 return -1;
1368 }
1369
1370 switch (a->type) {
1371 case FR_TYPE_IPV6_ADDR:
1372 if (fr_value_box_cast(NULL, &tmp, FR_TYPE_IPV4_ADDR, NULL, a) < 0) return -1;
1373 a = &tmp;
1374 break;
1375
1376 case FR_TYPE_IPV4_ADDR:
1378 break;
1379
1380 default:
1381 fr_strerror_printf("Invalid input data type '%s' for logical 'and'",
1382 fr_type_to_str(a->type));
1383
1384 return -1;
1385 }
1386
1387 if (b->vb_uint32 == 0) { /* set everything to zero */
1388 dst->vb_ipv4addr = 0;
1389 prefix = 0;
1390
1391 } else if ((~b->vb_uint32) == 0) { /* all 1's */
1392 dst->vb_ipv4addr = a->vb_ipv4addr;
1393 prefix = 32;
1394
1395 } else {
1396 uint32_t mask;
1397
1398 mask = ~b->vb_uint32; /* 0xff00 -> 0x00ff */
1399 mask++; /* 0x00ff -> 0x0100 */
1400 if ((mask & b->vb_uint32) != mask) {
1401 fr_strerror_printf("Invalid network mask '0x%08x'", b->vb_uint32);
1402 return -1;
1403 }
1404
1405 mask = 0xfffffffe;
1406 prefix = 31;
1407
1408 while (prefix > 0) {
1409 if (mask == b->vb_uint32) break;
1410
1411 prefix--;
1412 /* coverity[overflow_const] */
1413 mask <<= 1;
1414 }
1415 fr_assert(prefix > 0);
1416
1417 dst->vb_ipv4addr = htonl(ntohl(a->vb_ipv4addr) & b->vb_uint32);
1418 }
1419
1420 dst->vb_ip.af = AF_INET;
1421 dst->vb_ip.prefix = prefix;
1422 break;
1423
1424 default:
1425 return ERR_INVALID;
1426 }
1427
1428 return 0;
1429}
1430
1432{
1433 switch (in->type) {
1434 default:
1435 fr_strerror_printf("Cannot operate on ipv6addr and %s",
1436 fr_type_to_str(in->type));
1437 return -1;
1438
1440 if (in->vb_ip.af == AF_INET) goto cast_ipv4_addr;
1441
1442 fr_assert(in->vb_ip.af == AF_INET6);
1443 fr_value_box_init(out, FR_TYPE_IPV6_ADDR, NULL, in->tainted);
1444 out->vb_ip = in->vb_ip;
1445 break;
1446
1448 if (in->vb_ip.af == AF_INET) goto cast_ipv4_prefix;
1449
1450 fr_assert(in->vb_ip.af == AF_INET6);
1451 fr_value_box_init(out, FR_TYPE_IPV6_PREFIX, NULL, in->tainted);
1452 out->vb_ip = in->vb_ip;
1453 break;
1454
1455
1457 case FR_TYPE_IPV6_ADDR:
1458 if (unlikely(fr_value_box_copy(NULL, out, in) < 0)) return -1;
1459 break;
1460
1461 case FR_TYPE_IPV4_ADDR:
1463 if (fr_value_box_cast(NULL, out, FR_TYPE_IPV6_ADDR, NULL, in) < 0) return -1;
1464 break;
1465
1467 cast_ipv4_prefix:
1468 if (fr_value_box_cast(NULL, out, FR_TYPE_IPV6_PREFIX, NULL, in) < 0) return -1;
1469 break;
1470
1471 /*
1472 * All of these get mashed to 64-bits. The cast
1473 * operation will check bounds (both negative and
1474 * positive) on the run-time values.
1475 */
1476 case FR_TYPE_BOOL:
1477
1478 case FR_TYPE_UINT8:
1479 case FR_TYPE_UINT16:
1480 case FR_TYPE_UINT32:
1481 case FR_TYPE_UINT64:
1482
1483 case FR_TYPE_SIZE:
1484
1485 case FR_TYPE_INT8:
1486 case FR_TYPE_INT16:
1487 case FR_TYPE_INT32:
1488 case FR_TYPE_INT64:
1489
1490 case FR_TYPE_FLOAT32:
1491 case FR_TYPE_FLOAT64:
1492 if (fr_value_box_cast(NULL, out, FR_TYPE_UINT64, NULL, in) < 0) return -1;
1493 break;
1494 }
1495
1496 return 0;
1497}
1498
1499static 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)
1500{
1501 fr_value_box_t one, two;
1502 fr_value_box_t *a, *b;
1503 int i;
1504 uint64_t mask;
1505
1506 fr_assert((dst->type == FR_TYPE_IPV6_ADDR) || (dst->type == FR_TYPE_COMBO_IP_ADDR));
1507
1508 if (cast_ipv6_addr(&one, in1) < 0) return -1;
1509 a = &one;
1510
1511 if (cast_ipv6_addr(&two, in2) < 0) return -1;
1512 b = &two;
1513
1514 switch (op) {
1515 case T_ADD:
1516 case T_OR:
1517 /*
1518 * For simplicity, make sure that the prefix is first.
1519 */
1520 if (b->type == FR_TYPE_IPV6_PREFIX) swap(a, b);
1521
1522 /*
1523 * We can only add something to a prefix, and
1524 * that something has to be a number. The cast
1525 * operation already ensured that the number is
1526 * uint64, and is at least vaguely within the
1527 * allowed range.
1528 */
1529 if (a->type != FR_TYPE_IPV6_PREFIX) return ERR_INVALID;
1530
1531 if (b->type != FR_TYPE_UINT64) return ERR_INVALID;
1532
1533 /*
1534 * If we're adding a UINT64, the prefix can't be shorter than 64.
1535 */
1536 if (a->vb_ip.prefix <= 64) return ERR_OVERFLOW;
1537
1538 /*
1539 * Trying to add a number outside of the given prefix. That's not allowed.
1540 */
1541 if (b->vb_uint64 >= (((uint64_t) 1) << (128 - a->vb_ip.prefix))) return ERR_OVERFLOW;
1542
1543 /*
1544 * Add in the relevant low bits.
1545 */
1546 memcpy(&dst->vb_ipv6addr, a->vb_ipv6addr, sizeof(dst->vb_ipv6addr));
1547 mask = b->vb_uint64;
1548 for (i = 15; i >= ((a->vb_ip.prefix + 7) >> 3); i--) {
1549 dst->vb_ipv6addr[i] |= mask & 0xff;
1550 mask >>= 8;
1551 }
1552
1553 dst->vb_ip.af = AF_INET6;
1554 dst->vb_ip.prefix = 128;
1555 dst->vb_ip.scope_id = a->vb_ip.scope_id;
1557 break;
1558
1559 default:
1560 return ERR_INVALID;
1561 }
1562
1563 return 0;
1564}
1565
1566static int get_ipv6_prefix(uint8_t const *in)
1567{
1568 int i, j, prefix;
1569
1570 prefix = 128;
1571 for (i = 15; i >= 0; i--) {
1572 if (!in[i]) {
1573 prefix -= 8;
1574 continue;
1575 }
1576
1577 for (j = 0; j < 8; j++) {
1578 if ((in[i] & (1 << j)) == 0) {
1579 prefix--;
1580 continue;
1581 }
1582 return prefix;
1583 }
1584 }
1585
1586 return prefix;
1587}
1588
1589static 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)
1590{
1591 int i, prefix = 128;
1592 uint8_t const *pa, *pb;
1593 uint8_t *pdst;
1594
1595 fr_assert((dst->type == FR_TYPE_IPV6_PREFIX) || (dst->type == FR_TYPE_COMBO_IP_PREFIX));
1596
1597 if (a->type == FR_TYPE_OCTETS) {
1598 if (a->vb_length != (128 / 8)) {
1599 fr_strerror_printf("Invalid length %zu for octets network mask", a->vb_length);
1600 return -1;
1601 }
1602 pa = a->vb_octets;
1603 prefix = get_ipv6_prefix(pa);
1604
1605 } else if (a->type == FR_TYPE_IPV6_ADDR) {
1606 pa = (const uint8_t *) &a->vb_ipv6addr;
1607
1608 } else {
1609 return ERR_INVALID;
1610 }
1611
1612 if (b->type == FR_TYPE_OCTETS) {
1613 if (b->vb_length != (128 / 8)) {
1614 fr_strerror_printf("Invalid length %zu for octets network mask", b->vb_length);
1615 return -1;
1616 }
1617 pb = b->vb_octets;
1618 prefix = get_ipv6_prefix(pb);
1619
1620 } else if (b->type == FR_TYPE_IPV6_ADDR) {
1621 pb = (const uint8_t *) &b->vb_ip.addr.v6;
1622
1623 } else {
1624 return ERR_INVALID;
1625 }
1626
1627 switch (op) {
1628 case T_AND:
1629 fr_value_box_init(dst, FR_TYPE_IPV6_PREFIX, NULL, false);
1630 pdst = (uint8_t *) &dst->vb_ip.addr.v6;
1631
1632 for (i = 0; i < 16; i++) {
1633 pdst[i] = pa[i] & pb[i];
1634 }
1635
1636 dst->vb_ip.af = AF_INET6;
1637 dst->vb_ip.prefix = prefix;
1640 break;
1641
1642 default:
1643 return ERR_INVALID;
1644 }
1645
1646 return 0;
1647}
1648
1649#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)))
1650
1651static 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)
1652{
1653 /*
1654 * IPv6 is better than IPv4!
1655 */
1656 if (is_ipv6(in1) || is_ipv6(in2)) {
1657 return calc_ipv6_addr(ctx, dst, in1, op, in2);
1658 }
1659
1660 return calc_ipv4_addr(ctx, dst, in1, op, in2);
1661}
1662
1663static 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)
1664{
1665 if (is_ipv6(in1) || is_ipv6(in2)) {
1666 return calc_ipv6_prefix(ctx, dst, in1, op, in2);
1667 }
1668
1669 return calc_ipv4_prefix(ctx, dst, in1, op, in2);
1670}
1671
1672
1673static 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)
1674{
1675 fr_value_box_t one, two;
1676 fr_value_box_t const *a = in1;
1677 fr_value_box_t const *b = in2;
1678
1679 fr_assert(dst->type == FR_TYPE_FLOAT32);
1680
1681 /*
1682 * Intermediate calculations are done using increased precision.
1683 */
1686
1687 switch (op) {
1688 case T_ADD:
1689 dst->vb_float32 = a->vb_float64 + b->vb_float64;
1690 break;
1691
1692 case T_SUB:
1693 dst->vb_float32 = a->vb_float64 - b->vb_float64;
1694 break;
1695
1696 case T_MUL:
1697 dst->vb_float32 = a->vb_float64 * b->vb_float64;
1698 break;
1699
1700 case T_DIV:
1701 if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
1702
1703 dst->vb_float32 = a->vb_float64 / b->vb_float64;
1704 break;
1705
1706 case T_MOD:
1707 if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
1708
1709 dst->vb_float32 = fmod(a->vb_float64, b->vb_float64);
1710 break;
1711
1712 default:
1713 return ERR_INVALID;
1714 }
1715
1718
1719 return 0;
1720
1721}
1722
1723static 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)
1724{
1725 fr_value_box_t one, two;
1726 fr_value_box_t const *a = in1;
1727 fr_value_box_t const *b = in2;
1728
1729 fr_assert(dst->type == FR_TYPE_FLOAT64);
1730
1733
1734 switch (op) {
1735 case T_ADD:
1736 dst->vb_float64 = a->vb_float64 + b->vb_float64;
1737 break;
1738
1739 case T_SUB:
1740 dst->vb_float64 = a->vb_float64 - b->vb_float64;
1741 break;
1742
1743 case T_MUL:
1744 dst->vb_float64 = a->vb_float64 * b->vb_float64;
1745 break;
1746
1747 case T_DIV:
1748 if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
1749
1750 dst->vb_float64 = a->vb_float64 / b->vb_float64;
1751 break;
1752
1753 case T_MOD:
1754 if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
1755
1756 dst->vb_float64 = fmod(a->vb_float64, b->vb_float64);
1757 break;
1758
1759 default:
1760 return ERR_INVALID;
1761 }
1762
1765
1766 return 0;
1767}
1768
1769/*
1770 * Do all intermediate operations on 64-bit numbers.
1771 */
1772static 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)
1773{
1774 fr_value_box_t one, two, result;
1775 fr_value_box_t const *a = in1;
1776 fr_value_box_t const *b = in2;
1777
1778 fr_value_box_init(&result, FR_TYPE_UINT64, NULL, a->tainted | b->tainted);
1779
1780 COERCE_A(FR_TYPE_UINT64, NULL);
1781
1782 if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
1783 /*
1784 * Don't touch the RHS.
1785 */
1786 fr_assert(b->type == FR_TYPE_UINT32);
1787
1788 } else {
1789 COERCE_B(FR_TYPE_UINT64, dst->enumv);
1790 }
1791
1792 switch (op) {
1793 case T_ADD:
1794 if (!fr_add(&result.vb_uint64, a->vb_uint64, b->vb_uint64)) return ERR_OVERFLOW;
1795 break;
1796
1797 case T_SUB:
1798 if (!fr_sub(&result.vb_uint64, a->vb_uint64, b->vb_uint64)) return ERR_UNDERFLOW;
1799 break;
1800
1801 case T_MUL:
1802 if (!fr_multiply(&result.vb_uint64, a->vb_uint64, b->vb_uint64)) return ERR_OVERFLOW;
1803 break;
1804
1805 case T_DIV:
1806 if (b->vb_uint64 == 0) return ERR_ZERO;
1807
1808 result.vb_uint64 = a->vb_uint64 / b->vb_uint64;
1809 break;
1810
1811 case T_MOD:
1812 if (b->vb_uint64 == 0) return ERR_ZERO;
1813
1814 result.vb_uint64 = a->vb_uint64 % b->vb_uint64;
1815 break;
1816
1817 case T_AND:
1818 result.vb_uint64 = a->vb_uint64 & b->vb_uint64;
1819 break;
1820
1821 case T_OR:
1822 result.vb_uint64 = a->vb_uint64 | b->vb_uint64;
1823 break;
1824
1825 case T_XOR:
1826 result.vb_uint64 = a->vb_uint64 ^ b->vb_uint64;
1827 break;
1828
1829 case T_RSHIFT:
1830 if (b->vb_uint32 >= (8 * sizeof(a->vb_uint64))) return ERR_UNDERFLOW;
1831
1832 result.vb_uint64 = a->vb_uint64 >> b->vb_uint32;
1833 break;
1834
1835 case T_LSHIFT:
1836 if (b->vb_uint32 >= (8 * sizeof(a->vb_uint64))) return ERR_OVERFLOW;
1837
1838 result.vb_uint64 = a->vb_uint64 << b->vb_uint32;
1839 break;
1840
1841 default:
1842 return ERR_INVALID;
1843 }
1844
1845 /*
1846 * Once we're done, cast the result to the final data type.
1847 */
1848 if (fr_value_box_cast(ctx, dst, dst->type, dst->enumv, &result) < 0) return -1;
1849
1852
1853 return 0;
1854}
1855
1856/*
1857 * Same as above, except uint64 -> int64. These functions should be kept in sync!
1858 */
1859static 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)
1860{
1861 fr_value_box_t one, two, result;
1862 fr_value_box_t const *a = in1;
1863 fr_value_box_t const *b = in2;
1864
1865 fr_value_box_init(&result, FR_TYPE_INT64, NULL, a->tainted | b->tainted);
1866
1867 COERCE_A(FR_TYPE_INT64, NULL);
1868
1869 if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
1870 /*
1871 * Don't touch the RHS.
1872 */
1873 fr_assert(b->type == FR_TYPE_UINT32);
1874
1875 } else {
1876 COERCE_B(FR_TYPE_INT64, dst->enumv);
1877 }
1878
1879 switch (op) {
1880 case T_ADD:
1881 if (!fr_add(&result.vb_int64, a->vb_int64, b->vb_int64)) return ERR_OVERFLOW;
1882 break;
1883
1884 case T_SUB:
1885 if (!fr_sub(&result.vb_int64, a->vb_int64, b->vb_int64)) return ERR_UNDERFLOW;
1886 break;
1887
1888 case T_MUL:
1889 if (!fr_multiply(&result.vb_int64, a->vb_int64, b->vb_int64)) return ERR_OVERFLOW;
1890 break;
1891
1892 case T_DIV:
1893 if (b->vb_int64 == 0) return ERR_ZERO;
1894
1895 result.vb_int64 = a->vb_int64 / b->vb_int64;
1896 break;
1897
1898 case T_MOD:
1899 if (b->vb_int64 == 0) return ERR_ZERO;
1900
1901 result.vb_int64 = a->vb_int64 % b->vb_int64;
1902 break;
1903
1904 case T_AND:
1905 result.vb_int64 = a->vb_int64 & b->vb_int64;
1906 break;
1907
1908 case T_OR:
1909 result.vb_int64 = a->vb_int64 | b->vb_int64;
1910 break;
1911
1912 case T_XOR:
1913 result.vb_int64 = a->vb_int64 ^ b->vb_int64;
1914 break;
1915
1916 case T_RSHIFT:
1917 if (b->vb_uint32 >= (8 * sizeof(a->vb_int64))) return ERR_UNDERFLOW;
1918
1919 result.vb_int64 = a->vb_int64 >> b->vb_uint32;
1920 break;
1921
1922 case T_LSHIFT:
1923 if (b->vb_uint32 >= (8 * sizeof(a->vb_int64))) return ERR_OVERFLOW;
1924
1925 result.vb_int64 = a->vb_int64 << b->vb_uint32;
1926 break;
1927
1928 default:
1929 return ERR_INVALID;
1930 }
1931
1932 /*
1933 * Once we're done, cast the result to the final data type.
1934 */
1935 if (fr_value_box_cast(ctx, dst, dst->type, dst->enumv, &result) < 0) return -1;
1936
1939
1940 return 0;
1941}
1942
1943typedef 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);
1944
1945/** Map output type to its associated function
1946 *
1947 */
1981
1982/** Calculate DST = A OP B
1983 *
1984 * The result is written to DST only *after* it has been calculated.
1985 * So it's safe to pass DST as either A or B. DST should already exist.
1986 *
1987 * This function should arguably not take comparison operators, but
1988 * whatever. The "promote types" code is the same for all of the
1989 * binary operations, so we might as well just have one function.
1990 */
1991int 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)
1992{
1993 int rcode = -1;
1994 fr_value_box_t one, two;
1996 fr_binary_op_t func;
1997
1998 if ((hint != FR_TYPE_NULL) && !fr_type_is_leaf(hint)) return invalid_type(hint);
1999
2000 /*
2001 * Casting to structural types should be a parse error,
2002 * and not a run-time calculation error.
2003 */
2004 if (!fr_type_is_leaf(a->type)) return invalid_type(a->type);
2005 if (!fr_type_is_leaf(b->type)) return invalid_type(b->type);
2006
2007 /*
2008 * === and !== also check types. If the types are
2009 * different, it's a failure. Otherwise they revert to == and !=.
2010 */
2011 switch (op) {
2012 case T_OP_CMP_EQ_TYPE:
2013 if (a->type != b->type) {
2014 mismatch_type:
2015 fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false); /* @todo - enum */
2016 dst->vb_bool = false;
2017 return 0;
2018 }
2019 op = T_OP_CMP_EQ;
2020 break;
2021
2022 case T_OP_CMP_NE_TYPE:
2023 if (a->type != b->type) goto mismatch_type;
2024
2025 op = T_OP_NE;
2026 break;
2027
2028 case T_OP_REG_EQ:
2029 case T_OP_REG_NE:
2030 if (b->type != FR_TYPE_STRING) {
2031 fr_strerror_const("Invalid type for regular expression");
2032 return -1;
2033 }
2034
2035 rcode = fr_regex_cmp_op(op, a, b);
2036 if (rcode < 0) return rcode;
2037
2038 fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false); /* @todo - enum */
2039 dst->vb_bool = (rcode != 0);
2040 return 0;
2041
2042 default:
2043 break;
2044 }
2045
2048
2049 /*
2050 * We don't know what the output type should be. Try to
2051 * guess based on a variety of factors.
2052 */
2053 if (hint == FR_TYPE_NULL) do {
2054 /*
2055 * All kinds of special cases :(
2056 *
2057 * date1 - date2 --> time_delta
2058 *
2059 * time_delta * FOO --> float64, because time_delta is _printed_ as a floating point
2060 * number. And this is the least surprising thing to do.
2061 */
2062 if ((op == T_SUB) && (a->type == b->type) && (a->type == FR_TYPE_DATE)) {
2063 hint = FR_TYPE_TIME_DELTA;
2064 break;
2065 }
2066
2067 if (op == T_MUL) {
2068 if (a->type == FR_TYPE_TIME_DELTA) {
2069 hint = upcast_op[FR_TYPE_FLOAT64][b->type];
2070 if (hint == FR_TYPE_NULL) hint = upcast_op[b->type][FR_TYPE_FLOAT64];
2071
2072 } else if (b->type == FR_TYPE_TIME_DELTA) {
2073 hint = upcast_op[a->type][FR_TYPE_FLOAT64];
2074 if (hint == FR_TYPE_NULL) hint = upcast_op[FR_TYPE_FLOAT64][a->type];
2075 }
2076
2077 if ((a->type == FR_TYPE_STRING) &&
2078 (fr_type_is_integer_except_bool(b->type))) {
2079 hint = FR_TYPE_STRING;
2080 }
2081
2082 if ((a->type == FR_TYPE_OCTETS) &&
2083 (fr_type_is_integer_except_bool(b->type))) {
2084 hint = FR_TYPE_OCTETS;
2085 }
2086
2087 if (hint != FR_TYPE_NULL) break;
2088 }
2089
2090 /*
2091 * date % time_delta --> time_delta
2092 */
2093 if ((op == T_MOD) && (a->type == FR_TYPE_DATE)) {
2094 hint = FR_TYPE_TIME_DELTA;
2095 break;
2096 }
2097
2098 switch (op) {
2099 case T_OP_CMP_EQ:
2100 case T_OP_NE:
2101 case T_OP_GE:
2102 case T_OP_GT:
2103 case T_OP_LE:
2104 case T_OP_LT:
2105 /*
2106 * Comparison operators always return
2107 * "bool".
2108 */
2109 hint = FR_TYPE_BOOL;
2110 break;
2111
2112 case T_AND:
2113 /*
2114 * Get mask from IP + number
2115 */
2116 if ((a->type == FR_TYPE_IPV4_ADDR) || (b->type == FR_TYPE_IPV4_ADDR)) {
2117 hint = FR_TYPE_IPV4_PREFIX;
2118 break;
2119 }
2120
2121 if ((a->type == FR_TYPE_IPV6_ADDR) || (b->type == FR_TYPE_IPV6_ADDR)) {
2122 hint = FR_TYPE_IPV6_PREFIX;
2123 break;
2124 }
2126
2127 case T_OR:
2128 case T_ADD:
2129 case T_SUB:
2130 case T_MUL:
2131 case T_DIV:
2132 case T_MOD:
2133 case T_XOR:
2134 /*
2135 * Try to "up-cast" the types. This is
2136 * so that we can take (for example)
2137 * uint8 + uint16, and have the output as
2138 * uint16.
2139 *
2140 * There must be only one entry per [a,b]
2141 * pairing. That way we're sure that [a,b]==[b,a]
2142 */
2143 hint = upcast_op[a->type][b->type];
2144 if (hint == FR_TYPE_NULL) {
2145 hint = upcast_op[b->type][a->type];
2146 } else if (a->type != b->type) {
2147 fr_assert(upcast_op[b->type][a->type] == FR_TYPE_NULL);
2148 }
2149
2150 /*
2151 * No idea what to do. :(
2152 */
2153 if (hint == FR_TYPE_NULL) {
2154 fr_strerror_printf("Invalid operation on data types - '%s' %s '%s'",
2155 fr_type_to_str(a->type), fr_tokens[op], fr_type_to_str(b->type));
2156 goto done;
2157 }
2158
2159 break;
2160
2161 /*
2162 * The RHS MUST be a numerical type. We don't need to do any upcasting here.
2163 *
2164 * @todo - the output type could be larger than the input type, if the shift is
2165 * more than the input type can handle. e.g. uint8 << 4 could result in uint16
2166 */
2167 case T_LSHIFT:
2168 if (!fr_type_is_integer(a->type)) {
2169 return handle_result(a->type, T_LSHIFT, ERR_INVALID);
2170 }
2171
2172 if (fr_type_is_signed(a->type)) {
2173 hint = FR_TYPE_INT64;
2174 break;
2175 }
2176 hint = FR_TYPE_UINT64;
2177 break;
2178
2179 case T_RSHIFT:
2180 hint = a->type;
2181 break;
2182
2183 default:
2184 return handle_result(a->type, op, ERR_INVALID);
2185 }
2186 } while (0);
2187
2188 /*
2189 * Now that we've figured out the correct types, perform the operation.
2190 */
2191 switch (op) {
2192 case T_OP_CMP_EQ:
2193 case T_OP_NE:
2194 case T_OP_GE:
2195 case T_OP_GT:
2196 case T_OP_LE:
2197 case T_OP_LT:
2198 if (hint != FR_TYPE_BOOL) {
2199 fr_strerror_printf("Invalid destination type '%s' for comparison operator",
2200 fr_type_to_str(hint));
2201 goto done;
2202 }
2203
2204 /*
2205 * Convert the types to ones which are comparable.
2206 */
2207 if (a->type != b->type) {
2208 fr_dict_attr_t const *enumv = NULL;
2209
2210 /*
2211 * If we're doing comparisons and one of them has an enum, and the other is an
2212 * enum name, then use the enum name to convert the string to the other type.
2213 *
2214 * We can then do type-specific comparisons.
2215 */
2216 if ((a->type == FR_TYPE_STRING) && b->enumv) {
2217 enumv = b->enumv;
2218 hint = b->type;
2219
2220 } else if ((b->type == FR_TYPE_STRING) && a->enumv) {
2221 enumv = a->enumv;
2222 hint = a->type;
2223
2224 } else {
2225 /*
2226 * Try to "up-cast" the types. This is so that we can take (for example)
2227 * uint8 < uint16, and have it make sense.
2228 *
2229 * There must be only one entry per [a,b] pairing. That way we're sure
2230 * that [a,b]==[b,a]
2231 */
2232 hint = upcast_cmp[a->type][b->type];
2233 if (hint == FR_TYPE_NULL) {
2234 hint = upcast_cmp[b->type][a->type];
2235 } else {
2236 fr_assert(upcast_cmp[b->type][a->type] == FR_TYPE_NULL);
2237 }
2238
2239 /*
2240 * time_deltas have a scale in the enumv, but default to "seconds" if
2241 * there's no scale. As a result, if we compare time_delta(ms) to integer,
2242 * then the integer is interpreted as seconds, and the scale is wrong.
2243 *
2244 * The solution is to use the appropriate scale.
2245 */
2246 if (hint == a->type) enumv = a->enumv;
2247 if (hint == b->type) enumv = b->enumv;
2248
2249 if (hint == FR_TYPE_NULL) {
2250 fr_strerror_printf("Cannot compare incompatible types (%s)... %s (%s)...",
2251 fr_type_to_str(a->type),
2252 fr_tokens[op],
2253 fr_type_to_str(b->type));
2254 goto done;
2255 }
2256 }
2257
2258 /*
2259 * Cast them to the appropriate type, which may be different from either of the
2260 * inputs.
2261 */
2262 if (a->type != hint) {
2263 if (fr_value_box_cast(NULL, &one, hint, enumv, a) < 0) goto done;
2264 a = &one;
2265 }
2266
2267 if (b->type != hint) {
2268 if (fr_value_box_cast(NULL, &two, hint, enumv, b) < 0) goto done;
2269 b = &two;
2270 }
2271 }
2272
2273 rcode = fr_value_box_cmp_op(op, a, b);
2274 if (rcode < 0) goto done;
2275
2276 fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false);
2277 dst->vb_bool = (rcode > 0);
2278 break;
2279
2280 /*
2281 * For shifts, the RHS value MUST be an integer. There's no reason to have it as
2282 * anything other than an 8-bit field.
2283 */
2284 case T_LSHIFT:
2285 case T_RSHIFT:
2286 if (b->type != FR_TYPE_UINT32) {
2287 if (fr_value_box_cast(ctx, &two, FR_TYPE_UINT32, NULL, b) < 0) {
2288 fr_strerror_printf("Cannot parse shift value as integer - %s",
2289 fr_strerror());
2290 goto done;
2291 }
2292 b = &two;
2293 }
2295
2296 case T_ADD:
2297 case T_SUB:
2298 case T_MUL:
2299 case T_DIV:
2300 case T_MOD:
2301 case T_AND:
2302 case T_OR:
2303 case T_XOR:
2304 fr_assert(hint != FR_TYPE_NULL);
2305
2306 func = calc_type[hint];
2307 if (!func) {
2308 fr_strerror_printf("Cannot perform any operations for destination type %s",
2309 fr_type_to_str(hint));
2310 rcode = -1;
2311 break;
2312 }
2313
2314 /*
2315 * It's OK to use one of the inputs as the
2316 * output. In order to ensure that nothing bad
2317 * happens, we use an intermediate value-box.
2318 */
2319 fr_value_box_init(&out, hint, NULL, false);
2320
2321 rcode = func(ctx, &out, a, op, b); /* not calc_type[hint], to shut up clang */
2322 if (rcode < 0) goto done;
2323
2324 fr_value_box_copy_shallow(NULL, dst, &out);
2325 dst->tainted = a->tainted | b->tainted;
2326 break;
2327
2328 default:
2329 rcode = ERR_INVALID;
2330 break;
2331 }
2332
2333done:
2336
2337 return handle_result(hint, op, rcode);
2338}
2339
2340/** Calculate DST = OP { A, B, C, ... }
2341 *
2342 * The result is written to DST only *after* it has been calculated.
2343 * So it's safe to pass DST as one of the inputs. DST should already
2344 * exist.
2345 */
2347{
2348 fr_value_box_t out, *vb;
2349 fr_binary_op_t calc;
2350
2351 if (group->type != FR_TYPE_GROUP) {
2352 fr_strerror_const("Invalid type passed to multivalue calculation");
2353 return -1;
2354 }
2355
2358 fr_strerror_printf("Invalid operation %s for data type %s", fr_tokens[op], fr_type_to_str(type));
2359 return -1;
2360 }
2361
2362 if (type == FR_TYPE_STRING) {
2363 fr_sbuff_t *sbuff;
2364
2365 if (op != T_ADD) goto invalid_type;
2366
2367 FR_SBUFF_TALLOC_THREAD_LOCAL(&sbuff, 1024, (1 << 16));
2368
2369 if (fr_value_box_list_concat_as_string(dst, sbuff, UNCONST(fr_value_box_list_t *, &group->vb_group),
2370 NULL, 0, NULL, FR_VALUE_BOX_LIST_NONE, FR_VALUE_BOX_SAFE_FOR_ANY, false) < 0) return -1;
2371
2372 if (fr_value_box_bstrndup(ctx, dst, NULL, fr_sbuff_start(sbuff), fr_sbuff_used(sbuff), false) < 0) return -1;
2373 return 0;
2374 }
2375
2376 if (type == FR_TYPE_OCTETS) {
2377 fr_dbuff_t *dbuff;
2378
2379 if (op != T_ADD) goto invalid_type;
2380
2381 FR_DBUFF_TALLOC_THREAD_LOCAL(&dbuff, 1024, (1 << 16));
2382
2383 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;
2384
2385 if (fr_value_box_memdup(ctx, dst, NULL, fr_dbuff_start(dbuff), fr_dbuff_used(dbuff), false) < 0) return -1;
2386
2387 return 0;
2388 }
2389
2390 /*
2391 * Can't add or multiply booleans.
2392 */
2393 if ((type == FR_TYPE_BOOL) && !((op == T_AND) || (op == T_OR) || (op == T_XOR))) goto unsupported;
2394
2395 switch (op) {
2396 case T_ADD:
2397 case T_MUL:
2398 case T_AND:
2399 case T_OR:
2400 case T_XOR:
2401 break;
2402
2403 default:
2404 goto invalid_type;
2405 }
2406
2407 /*
2408 * Strings and octets are different.
2409 */
2410 if (!fr_type_is_numeric(type)) {
2411 unsupported:
2412 fr_strerror_printf("Not yet supported operation %s for data type %s", fr_tokens[op], fr_type_to_str(type));
2413 return -1;
2414 }
2415
2416 switch (type) {
2417 case FR_TYPE_UINT8:
2418 case FR_TYPE_UINT16:
2419 case FR_TYPE_UINT32:
2420 case FR_TYPE_UINT64:
2421 calc = calc_uint64;
2422 break;
2423
2424 case FR_TYPE_INT8:
2425 case FR_TYPE_INT16:
2426 case FR_TYPE_INT32:
2427 case FR_TYPE_INT64:
2428 calc = calc_int64;
2429 break;
2430
2431 case FR_TYPE_TIME_DELTA:
2432 if ((op != T_ADD) && (op != T_SUB)) goto invalid_type;
2433 calc = calc_time_delta;
2434 break;
2435
2436 case FR_TYPE_FLOAT32:
2437 calc = calc_float32;
2438 break;
2439
2440 case FR_TYPE_FLOAT64:
2441 calc = calc_float64;
2442 break;
2443
2444 default:
2445 goto unsupported;
2446 }
2447
2448 vb = fr_value_box_list_head(&group->vb_group);
2449 if (!vb) {
2450 fr_strerror_printf("Empty input is invalid");
2451 return -1;
2452 }
2453
2454 if (fr_value_box_cast(ctx, &out, type, NULL, vb) < 0) return -1;
2455
2456 while ((vb = fr_value_box_list_next(&group->vb_group, vb)) != NULL) {
2457 int rcode;
2458 fr_value_box_t box;
2459
2460 if (vb->type == type) {
2461 rcode = calc(ctx, &out, &out, op, vb);
2462 if (rcode < 0) return rcode;
2463
2464 } else {
2465 if (fr_value_box_cast(ctx, &box, type, NULL, vb) < 0) return -1;
2466
2467 rcode = calc(ctx, &out, &out, op, &box);
2468 if (rcode < 0) return rcode;
2469 }
2470 }
2471
2472 return fr_value_box_copy(ctx, dst, &out);
2473}
2474
2475
2476#define T(_x) [T_OP_ ## _x ## _EQ] = T_ ## _x
2477
2479 T(ADD),
2480 T(SUB),
2481 T(MUL),
2482 T(DIV),
2483 T(AND),
2484 T(OR),
2485 T(XOR),
2486 T(RSHIFT),
2487 T(LSHIFT),
2488};
2489
2490/** Calculate DST OP SRC
2491 *
2492 * e.g. "foo += bar".
2493 *
2494 * This is done by doing some sanity checks, and then just calling
2495 * the "binary operation" function.
2496 */
2498{
2499 int rcode;
2500
2501 if (!fr_type_is_leaf(dst->type)) return invalid_type(dst->type);
2502 if (!fr_type_is_leaf(src->type)) return invalid_type(src->type);
2503
2504 if (dst->immutable) {
2505 fr_strerror_printf("Cannot modify immutable value");
2506 return -1;
2507 }
2508
2509 /*
2510 * These operators are included here for testing and completeness. But see comments in
2511 * fr_edit_list_apply_pair_assignment() for what the caller should be doing.
2512 */
2513 if ((op == T_OP_EQ) || (op == T_OP_SET)) {
2514 /*
2515 * Allow for unintentional mistakes.
2516 */
2517 if (src == dst) return 0;
2518
2520 return fr_value_box_cast(ctx, dst, dst->type, dst->enumv, src); /* cast, as the RHS might not (yet) be the same! */
2521 }
2522
2523 if (assignment2op[op] == T_INVALID) {
2524 return handle_result(dst->type, op, ERR_INVALID);
2525 }
2526 op = assignment2op[op];
2527
2528 /*
2529 * Just call the binary op function. It already ensures that (a) the inputs are "const", and (b)
2530 * the output is over-written only at the final step.
2531 */
2532 if (src->type != FR_TYPE_GROUP) {
2533 rcode = fr_value_calc_binary_op(ctx, dst, dst->type, dst, op, src);
2534
2535 } else {
2536 fr_value_box_t *vb = NULL;
2537
2538 /*
2539 * If the RHS is a group, then we loop over the group recursively, doing the operation.
2540 */
2541 rcode = 0; /* in case group is empty */
2542
2543 while ((vb = fr_value_box_list_next(&src->vb_group, vb)) != NULL) {
2544 rcode = fr_value_calc_binary_op(ctx, dst, dst->type, dst, op, vb);
2545 if (rcode < 0) break;
2546 }
2547 }
2548
2549 if (rcode < 0) return handle_result(dst->type, op, rcode);
2550
2551 return 0;
2552}
2553
2554/** Calculate unary operations
2555 *
2556 * e.g. "foo++", or "-foo".
2557 */
2558int fr_value_calc_unary_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_token_t op, fr_value_box_t const *src)
2559{
2560 int rcode = -1;
2561 fr_value_box_t one;
2562
2563 if (!fr_type_is_numeric(src->type)) return invalid_type(src->type);
2564
2565 if (dst->immutable) {
2566 fr_strerror_printf("Cannot modify immutable value");
2567 return -1;
2568 }
2569
2570 if (op == T_OP_INCRM) {
2571 /*
2572 * Add 1 or subtract 1 means RHS is always 1.
2573 */
2574 fr_value_box_init(&one, src->type, NULL, false);
2575 switch (src->type) {
2576 case FR_TYPE_UINT8:
2577 one.vb_uint8 = 1;
2578 break;
2579
2580 case FR_TYPE_UINT16:
2581 one.vb_uint16 = 1;
2582 break;
2583
2584 case FR_TYPE_UINT32:
2585 one.vb_uint32 = 1;
2586 break;
2587
2588 case FR_TYPE_UINT64:
2589 one.vb_uint64 = 1;
2590 break;
2591
2592 case FR_TYPE_SIZE:
2593 one.vb_size = 1;
2594 break;
2595
2596 case FR_TYPE_INT8:
2597 one.vb_int8 = 1;
2598 break;
2599
2600 case FR_TYPE_INT16:
2601 one.vb_int16 = 1;
2602 break;
2603
2604 case FR_TYPE_INT32:
2605 one.vb_int32 = 1;
2606 break;
2607
2608 case FR_TYPE_INT64:
2609 one.vb_int64 = 1;
2610 break;
2611
2612 case FR_TYPE_FLOAT32:
2613 one.vb_float32 = 1;
2614 break;
2615
2616 case FR_TYPE_FLOAT64:
2617 one.vb_float64 = 1;
2618 break;
2619
2620 default:
2621 fr_assert(0);
2622 return -1;
2623 }
2624
2625 rcode = fr_value_calc_binary_op(ctx, dst, src->type, src, T_ADD, &one);
2626 return handle_result(dst->type, op, rcode);
2627
2628 } else if (op == T_COMPLEMENT) {
2629 if (dst != src) {
2630 fr_value_box_init(dst, src->type, src->enumv, false);
2631 fr_value_box_safety_copy(dst, src);
2632 }
2633
2634#undef COMP
2635#define COMP(_type, _field) case FR_TYPE_ ## _type: dst->vb_ ##_field = (_field ## _t) ~src->vb_ ##_field; break
2636 switch (src->type) {
2637 COMP(UINT8, uint8);
2638 COMP(UINT16, uint16);
2639 COMP(UINT32, uint32);
2640 COMP(UINT64, uint64);
2641 COMP(SIZE, size);
2642
2643 COMP(INT8, int8);
2644 COMP(INT16, int16);
2645 COMP(INT32, int32);
2646 COMP(INT64, int64);
2647
2648 default:
2649 goto invalid;
2650 }
2651
2652 return 0;
2653
2654 } else if (op == T_SUB) {
2655 fr_type_t type = src->type;
2656
2657 if ((dst != src) && !fr_type_is_signed(src->type)) {
2658 type = upcast_unsigned[src->type];
2659
2660 if (type == FR_TYPE_NULL) {
2661 type = src->type; /* hope for the best */
2662 }
2663 }
2664
2665 fr_value_box_init(&one, type, NULL, src->tainted); /* init to zero */
2666 rcode = fr_value_calc_binary_op(ctx, dst, type, &one, T_SUB, src);
2667
2668 return handle_result(dst->type, op, rcode);
2669
2670 } else if (op == T_NOT) {
2671 bool value = fr_value_box_is_truthy(src);
2672
2673 fr_value_box_clear(dst);
2674 fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false); // @todo - add enum!
2675 dst->vb_bool = !value;
2676
2677 return 0;
2678
2679 } else {
2680 invalid:
2681 return handle_result(src->type, op, ERR_INVALID);
2682 }
2683
2684}
2685
2686/*
2687 * Empty lists are empty:
2688 *
2689 * {}
2690 * {{}}
2691 * {''}
2692 * {{},''}
2693 *
2694 * etc.
2695 */
2696static bool fr_value_calc_list_empty(fr_value_box_list_t const *list)
2697{
2699 switch (item->type) {
2700 default:
2701 return false;
2702
2703 case FR_TYPE_GROUP:
2704 if (!fr_value_calc_list_empty(&item->vb_group)) return false;
2705 break;
2706
2707 case FR_TYPE_STRING:
2708 case FR_TYPE_OCTETS:
2709 if (item->vb_length != 0) return false;
2710 break;
2711 }
2712 }
2713
2714 return true;
2715}
2716
2717
2718/*
2719 * Loop over input lists, calling fr_value_calc_binary_op()
2720 *
2721 * This implementation is arguably wrong... it should be checking individual entries in list1 against individual entries in list2.
2722 * Instead, it checks if ANY entry in list1 matches ANY entry in list2.
2723 */
2724int 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)
2725{
2726 int rcode;
2727 bool invert = false;
2728 bool a_empty, b_empty;
2729
2730 if (!fr_comparison_op[op]) {
2731 fr_strerror_printf("Invalid operator '%s' passed to list comparison", fr_tokens[op]);
2732 return -1;
2733 }
2734
2735 /*
2736 * v3 hack. != really means !( ... == ... )
2737 */
2738 if (op == T_OP_NE) {
2739 invert = true;
2740 op = T_OP_CMP_EQ;
2741 }
2742
2743 /*
2744 * It's annoying when the debug prints out cmp({},{}) and says "not equal".
2745 *
2746 * What's happening behind the scenes is that one side is an empty value-box group, such as when
2747 * an xlat expansion fails. And the other side is an empty string. If we believe that strings
2748 * are actually sets of characters, then {}=='', and we're all OK
2749 */
2750 a_empty = fr_value_box_list_empty(list1) || fr_value_calc_list_empty(list1);
2751 b_empty = fr_value_box_list_empty(list2) || fr_value_calc_list_empty(list2);
2752
2753 /*
2754 * Both lists are empty, they should be equal when checked for equality.
2755 */
2756 if (a_empty && b_empty) {
2757 switch (op) {
2758 case T_OP_CMP_EQ:
2759 case T_OP_LE:
2760 case T_OP_GE:
2761 invert = !invert;
2762 break;
2763
2764 default:
2765 break;
2766 }
2767
2768 goto done;
2769 }
2770
2771 /*
2772 * Emulate v3. :(
2773 */
2774 fr_value_box_list_foreach(list1, a) {
2775 fr_value_box_list_foreach(list2, b) {
2776 rcode = fr_value_calc_binary_op(ctx, dst, FR_TYPE_BOOL, a, op, b);
2777 if (rcode < 0) return rcode;
2778
2779 /*
2780 * No match: keep looking for a match.
2781 */
2782 fr_assert(dst->type == FR_TYPE_BOOL);
2783 if (!dst->vb_bool) continue;
2784
2785 /*
2786 * Found a match, we're done.
2787 */
2788 dst->vb_bool = !invert;
2789 return 0;
2790 }
2791 }
2792
2793 /*
2794 * No match,
2795 */
2796done:
2797 fr_value_box_clear(dst);
2798 fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false); // @todo - add enum!
2799 dst->vb_bool = invert;
2800 return 0;
2801}
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:186
#define RCSID(id)
Definition build.h:506
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition build.h:343
#define unlikely(_x)
Definition build.h:402
#define UNUSED
Definition build.h:336
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:1295
static int get_ipv6_prefix(uint8_t const *in)
Definition calc.c:1566
static const fr_binary_op_t calc_type[FR_TYPE_MAX+1]
Map output type to its associated function.
Definition calc.c:1948
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:1499
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:1673
#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:1346
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:1772
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:1651
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:1589
static int cast_ipv6_addr(fr_value_box_t *out, fr_value_box_t const *in)
Definition calc.c:1431
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:1859
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:1078
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:2724
#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:1663
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:1943
static int cast_ipv4_addr(fr_value_box_t *out, fr_value_box_t const *in)
Definition calc.c:1230
static bool fr_value_calc_list_empty(fr_value_box_list_t const *list)
Definition calc.c:2696
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:1723
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:2346
#define is_ipv6(_x)
Definition calc.c:1649
#define COERCE_B(_type, _enumv)
Definition calc.c:48
static const fr_token_t assignment2op[T_TOKEN_LAST]
Definition calc.c:2478
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:2497
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:1991
#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:2558
#define T(_x)
Definition calc.c:2476
#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:775
#define fr_dbuff_start(_dbuff_or_marker)
Return the 'start' position of a dbuff or marker.
Definition dbuff.h:906
#define FR_DBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
Create a function local and thread local extensible dbuff.
Definition dbuff.h:564
static fr_slen_t in
Definition dict.h:882
Test enumeration values.
Definition dict_test.h:92
static void * item(fr_lst_t const *lst, fr_lst_index_t idx)
Definition lst.c:121
#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:37
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:80
const bool fr_comparison_op[T_TOKEN_LAST]
Definition token.c:200
enum fr_token fr_token_t
@ T_AND
Definition token.h:53
@ T_INVALID
Definition token.h:37
@ T_SUB
Definition token.h:50
@ T_RSHIFT
Definition token.h:60
@ T_NOT
Definition token.h:55
@ T_XOR
Definition token.h:56
@ T_DIV
Definition token.h:52
@ T_MOD
Definition token.h:58
@ T_OP_EQ
Definition token.h:81
@ T_COMPLEMENT
Definition token.h:57
@ T_ADD
Definition token.h:49
@ T_OP_SET
Definition token.h:82
@ T_OP_NE
Definition token.h:95
@ T_LSHIFT
Definition token.h:61
@ T_OP_REG_EQ
Definition token.h:100
@ T_OP_CMP_EQ_TYPE
Definition token.h:105
@ T_OP_CMP_EQ
Definition token.h:104
@ T_OP_INCRM
Definition token.h:111
@ T_MUL
Definition token.h:51
@ T_OP_LE
Definition token.h:98
@ T_OP_CMP_NE_TYPE
Definition token.h:106
@ T_OP_GE
Definition token.h:96
@ T_OP_GT
Definition token.h:97
@ T_OP_LT
Definition token.h:99
@ T_OP_REG_NE
Definition token.h:101
@ T_OR
Definition token.h:54
#define T_TOKEN_LAST
Definition token.h:127
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:1024
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:392
#define fr_type_is_integer_except_bool(_x)
Definition types.h:380
#define fr_type_is_numeric(_x)
Definition types.h:382
#define fr_type_is_signed(_x)
Definition types.h:383
#define fr_type_is_leaf(_x)
Definition types.h:393
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:454
#define fr_type_is_integer(_x)
Definition types.h:381
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:6373
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:3931
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:4379
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:993
bool fr_value_box_is_truthy(fr_value_box_t const *in)
Check truthiness of values.
Definition value.c:7375
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:5148
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:4503
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:6489
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
Definition value.c:4316
int fr_value_box_strdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Copy a nul terminated string to a fr_value_box_t.
Definition value.c:4604
void fr_value_box_safety_merge(fr_value_box_t *out, fr_value_box_t const *in)
Merge safety results.
Definition value.c:7337
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:7315
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition value.c:4362
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:4823
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:4910
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:5064
@ 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:1030
#define FR_VALUE_BOX_SAFE_FOR_ANY
Definition value.h:173