The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
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: 69fdca482b509f6bc5cd24ace25f6f075f1aeb96 $
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: 69fdca482b509f6bc5cd24ace25f6f075f1aeb96 $")
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 fr_value_box_safety_copy(&_box, _vb); \
44 _vb = &_box; \
45 } \
46 } while (0)
47
48#define COERCE_A(_type, _enumv) COERCE(a, one, _type, _enumv)
49#define COERCE_B(_type, _enumv) COERCE(b, two, _type, _enumv)
50
51/** Updates type (a,b) -> c
52 *
53 * Note that we MUST have a less than b here. Otherwise there will
54 * be two entries for the same upcast, and the entries may get out of
55 * sync.
56 *
57 * These upcasts are for operations.
58 *
59 *
60 * If one side is a string and the other isn't, then we try to parse
61 * the string as the type of the other side.
62 *
63 * If one side is an octets type and the other isn't, then we try to
64 * parse the octets as the type of the other side.
65 */
66static const fr_type_t upcast_op[FR_TYPE_MAX + 1][FR_TYPE_MAX + 1] = {
67 /*
68 * string / octets -> octets
69 */
70 [FR_TYPE_STRING] = {
73 },
74
75 [FR_TYPE_OCTETS] = {
77 },
78
80 /*
81 * ipaddr + int --> prefix (generally only "and")
82 */
84
85 /*
86 * 192.168.0.255 - 192.168.0.1 -> int64
87 */
89 },
90
91 /*
92 * IPv6 mod IPv6 -> ????
93 */
96 },
97
98 /*
99 * Prefix + int --> ipaddr
100 */
105
107
112
114
119
122 },
123
127
129
134
136
141
144 },
145
149
151
156
158
163
166 },
167
170
175
177
182
185 },
186
187 /*
188 * Bools and to pretty much any numerical type result in
189 * the other integer.
190 */
191 [FR_TYPE_BOOL] = {
193
196
201
203
205
210
212
215 },
216
217 /*
218 * Various ints get cast to the next highest size which
219 * can hold their values.
220 */
221 [FR_TYPE_UINT8] = {
224
229
231
233
238
240
243 },
244
245 [FR_TYPE_UINT16] = {
248
252
254
256
261
263
266 },
267
268 [FR_TYPE_UINT32] = {
271
274
276
278
283
285
288 },
289
290 [FR_TYPE_UINT64] = {
293
296
298
300
302
305 },
306
307 [FR_TYPE_SIZE] = {
309
314
316
319 },
320
321 [FR_TYPE_DATE] = {
323
328
331
334 },
335
336 /*
337 * Signed ints
338 */
339 [FR_TYPE_INT8] = {
342
347
349
352 },
353
354 [FR_TYPE_INT16] = {
357
361
364 },
365
366 [FR_TYPE_INT32] = {
369
371
374 },
375
376 [FR_TYPE_INT64] = {
379
381
385 },
386
389
391
394 },
395
396 [FR_TYPE_FLOAT32] = {
398
401 },
402
403 [FR_TYPE_FLOAT64] = {
406 },
407};
408
409/** Updates type (a,b) -> c
410 *
411 * Note that we MUST have a less than b here. Otherwise there will
412 * be two entries for the same upcast, and the entries may get out of
413 * sync.
414 *
415 * These upcasts are for comparisons. In some cases, we can promote
416 * one data type to another, and then compare them. However, this is
417 * not always possible.
418 *
419 * If one side is a string and the other isn't, then we try to parse
420 * the string as the type of the other side.
421 *
422 * If one side is an octets type and the other isn't, then we try to
423 * parse the octets as the type of the other side.
424 *
425 * @todo - check this table against fr_type_promote()
426 */
427static const fr_type_t upcast_cmp[FR_TYPE_MAX + 1][FR_TYPE_MAX + 1] = {
428 [FR_TYPE_STRING] = {
430 },
431
435
437
440
443
445 },
446
450
452
454 },
455
459
461
464 },
465
469
471 },
472
473 [FR_TYPE_IFID] = {
476 },
477
480 },
481
482 [FR_TYPE_ETHERNET] = {
485 },
486
487 /*
488 * Bools compared to pretty much any numerical type
489 * result in the other integer.
490 */
491 [FR_TYPE_BOOL] = {
494
499
501
503
508
510
513 },
514
515 /*
516 * Integers of the same sign get cast to the larger of
517 * the data type. Integers of different signs get cast
518 * to a *different* data type which can hold all values
519 * from both sides.
520 */
521 [FR_TYPE_UINT8] = {
524
528
530
532
537
539
542 },
543
544 [FR_TYPE_UINT16] = {
547
550
552
554
559
561
564 },
565
566 [FR_TYPE_UINT32] = {
569
571
573
575
580
582
585 },
586
587 [FR_TYPE_UINT64] = {
590
592
594
596
599 },
600
601 [FR_TYPE_SIZE] = {
603
608
611 },
612
613 [FR_TYPE_DATE] = {
615
620
622
625 },
626
627 /*
628 * Signed ints
629 */
630 [FR_TYPE_INT8] = {
633
637
639
642 },
643
644 [FR_TYPE_INT16] = {
647
650
653 },
654
655 [FR_TYPE_INT32] = {
658
660
663 },
664
665 [FR_TYPE_INT64] = {
668
670 },
671
674
677 },
678
679 [FR_TYPE_FLOAT32] = {
681
683 },
684
685 [FR_TYPE_FLOAT64] = {
687 },
688};
689
698
700{
701 fr_strerror_printf("Cannot perform mathematical operations on data type %s",
703 return -1;
704}
705
706static int handle_result(fr_type_t type, fr_token_t op, int rcode)
707{
708 if (rcode == ERR_ZERO) {
709 fr_strerror_const("Cannot divide by zero.");
710
711 } else if (rcode == ERR_UNDERFLOW) {
712 fr_strerror_printf("Value underflows '%s' when calculating result.",
714
715 } else if (rcode == ERR_OVERFLOW) {
716 fr_strerror_printf("Value overflows '%s' when calculating result.",
718
719 } else if (rcode == ERR_INVALID) {
720 fr_strerror_printf("Invalid assignment operator '%s' for result type '%s'.",
721 fr_tokens[op],
723 }
724
725 return rcode;
726}
727
728static 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)
729{
730 fr_value_box_t one, two;
731
732 fr_assert(dst->type == FR_TYPE_BOOL);
733
734 COERCE_A(FR_TYPE_BOOL, NULL);
735 COERCE_B(FR_TYPE_BOOL, NULL);
736
737 switch (op) {
738 case T_ADD:
739 /*
740 * 1+1 = 2, which isn't a valid boolean value.
741 */
742 if (a->vb_bool & b->vb_bool) return ERR_OVERFLOW;
743
744 dst->vb_bool = a->vb_bool | b->vb_bool;
745 break;
746
747 case T_SUB:
748 /*
749 * 0-1 = -1, which isn't a valid boolean value.
750 */
751 if (a->vb_bool < b->vb_bool) return ERR_UNDERFLOW;
752
753 dst->vb_bool = a->vb_bool - b->vb_bool;
754 break;
755
756 case T_MUL: /* MUL is just AND here! */
757 case T_AND:
758 dst->vb_bool = a->vb_bool & b->vb_bool;
759 break;
760
761 case T_OR:
762 dst->vb_bool = a->vb_bool | b->vb_bool;
763 break;
764
765 case T_XOR:
766 dst->vb_bool = a->vb_bool ^ b->vb_bool;
767 break;
768
769 default:
770 return ERR_INVALID;
771 }
772
773 return 0;
774}
775
776static 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)
777{
778 fr_value_box_t one, two;
779 bool overflow;
780 int64_t when;
781
782 fr_assert(dst->type == FR_TYPE_DATE);
783
784 if ((a->type == FR_TYPE_DATE) && (b->type == FR_TYPE_DATE)) {
785 fr_strerror_const("Cannot perform operation on two values of type 'date'. One value must be a number.");
786 return -1;
787 }
788
789 fr_assert(!dst->enumv); /* unix time is always seconds */
790
791 /*
792 * Cast dates to time delta, do the conversions.
793 */
796
797 switch (op) {
798 case T_ADD:
799 if (!fr_add(&when, fr_time_delta_unwrap(a->vb_time_delta), fr_time_delta_unwrap(b->vb_time_delta))) return ERR_OVERFLOW;
800
801 dst->vb_date = fr_unix_time_from_integer(&overflow, when, FR_TIME_RES_NSEC);
802 if (overflow) return ERR_OVERFLOW;
803 break;
804
805 case T_SUB:
806 if (!fr_sub(&when, fr_time_delta_unwrap(a->vb_time_delta), fr_time_delta_unwrap(b->vb_time_delta))) return ERR_UNDERFLOW;
807
808 dst->vb_date = fr_unix_time_from_integer(&overflow, when, FR_TIME_RES_NSEC);
809 if (overflow) return ERR_UNDERFLOW;
810 break;
811
812 default:
813 return ERR_INVALID; /* invalid operator */
814 }
815
816 return 0;
817}
818
819static 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)
820{
821 fr_value_box_t one, two;
822 int64_t when;
823
824 fr_assert(dst->type == FR_TYPE_TIME_DELTA);
825
826 /*
827 * We can subtract two dates to get a time delta, but we
828 * cannot add two dates to get a time delta.
829 */
830 if ((a->type == FR_TYPE_DATE) && (b->type == FR_TYPE_DATE)) {
831 if (op != T_SUB) {
832 fr_strerror_const("Cannot perform operation on two values of type 'date'.");
833 return -1;
834 }
835 }
836
837 /*
838 * date % (time_delta) 1d --> time_delta
839 */
840 if (op == T_MOD) {
841 /*
842 * We MUST specify date ranges as a time delta, not as an integer. And it must be a
843 * positive time delta.
844 */
845 if ((b->type != FR_TYPE_TIME_DELTA) || !fr_time_delta_ispos(b->vb_time_delta)) {
846 return ERR_INVALID;
847 }
848
849 dst->vb_time_delta = fr_time_delta_wrap(fr_unix_time_unwrap(a->vb_date) % fr_time_delta_unwrap(b->vb_time_delta));
850 return 0;
851 }
852
853 /*
854 * Unix times are always converted 1-1 to our internal
855 * TIME_DELTA.
856 *
857 * We cast the inputs based on the destination time resolution. So "5ms + 5" = "10ms".
858 */
859 COERCE_A(FR_TYPE_TIME_DELTA, dst->enumv);
860
861 if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
862 /*
863 * Don't touch the RHS.
864 */
865 fr_assert(b->type == FR_TYPE_UINT32);
866
867 } else {
868 COERCE_B(FR_TYPE_TIME_DELTA, dst->enumv);
869 }
870
871 switch (op) {
872 case T_ADD:
873 if (!fr_add(&when, fr_time_delta_unwrap(a->vb_time_delta), fr_time_delta_unwrap(b->vb_time_delta))) return ERR_OVERFLOW;
874 dst->vb_time_delta = fr_time_delta_wrap(when);
875 break;
876
877 case T_SUB:
878 if (!fr_sub(&when, fr_time_delta_unwrap(a->vb_time_delta), fr_time_delta_unwrap(b->vb_time_delta))) return ERR_UNDERFLOW;
879 dst->vb_time_delta = fr_time_delta_wrap(when);
880 break;
881
882 case T_RSHIFT:
883 if (b->vb_uint32 >= 64) return ERR_UNDERFLOW;
884
885 when = fr_time_delta_unwrap(a->vb_time_delta) >> b->vb_uint32;
886 dst->vb_time_delta = fr_time_delta_wrap(when);
887 break;
888
889 case T_LSHIFT:
890 if (b->vb_uint32 >= 64) return ERR_OVERFLOW;
891
892 when = fr_time_delta_unwrap(a->vb_time_delta) << b->vb_uint32;
893 dst->vb_time_delta = fr_time_delta_wrap(when);
894 break;
895
896 default:
897 return ERR_INVALID; /* invalid operator */
898 }
899
900 return 0;
901
902}
903
904static 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)
905{
906 uint8_t *buf, *p;
907 size_t i, len;
908 fr_value_box_t one = {};
909 fr_value_box_t two = {};
910
911 fr_assert(dst->type == FR_TYPE_OCTETS);
912
913 COERCE_A(FR_TYPE_OCTETS, dst->enumv);
914
915 if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
916 /*
917 * Don't touch the RHS.
918 */
919 fr_assert(b->type == FR_TYPE_UINT32);
920
921 } else if (op == T_MUL) {
923
925
926 } else {
927 COERCE_B(FR_TYPE_OCTETS, dst->enumv);
928 }
929
930 len = a->vb_length + b->vb_length;
931
932 switch (op) {
933 case T_ADD: /* dst = a . b */
934 buf = talloc_array(ctx, uint8_t, len);
935 if (!buf) {
936 oom:
937 fr_strerror_const("Out of memory");
938 return -1;
939 }
940
941 memcpy(buf, a->vb_octets, a->vb_length);
942 memcpy(buf + a->vb_length, b->vb_octets, b->vb_length);
943
944 fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, false);
947 break;
948
949 case T_SUB:
950 /*
951 * The inverse of add!
952 */
953 if (a->vb_length < b->vb_length) {
954 fr_strerror_const("Suffix to remove is longer than input string.");
955 return -1;
956 }
957
958 if (memcmp(a->vb_octets + a->vb_length - b->vb_length, b->vb_strvalue, b->vb_length) != 0) {
959 fr_strerror_const("Suffix to remove is not a suffix of the input string.");
960 return -1;
961 }
962
963 len = a->vb_length - b->vb_length;
964 buf = talloc_array(ctx, uint8_t, len);
965 if (!buf) goto oom;
966
967 memcpy(buf, a->vb_strvalue, len);
968
969 fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, false);
971 break;
972
973 case T_AND:
974 if (a->vb_length != b->vb_length) {
975 length_error:
976 fr_strerror_const("Cannot perform operation on strings of different length");
977 return -1;
978 }
979
980 buf = talloc_array(ctx, uint8_t, a->vb_length);
981 if (!buf) goto oom;
982
983 for (len = 0; len < a->vb_length; len++) {
984 buf[len] = a->vb_octets[len] & b->vb_octets[len];
985 }
986
987 set_result:
988 fr_value_box_memdup_shallow(dst, dst->enumv, buf, a->vb_length, false);
991 break;
992
993 case T_OR:
994 if (a->vb_length != b->vb_length) goto length_error;
995
996 buf = talloc_array(ctx, uint8_t, a->vb_length);
997 if (!buf) goto oom;
998
999 for (len = 0; len < a->vb_length; len++) {
1000 buf[len] = a->vb_octets[len] | b->vb_octets[len];
1001 }
1002 goto set_result;
1003
1004 case T_XOR:
1005 if (a->vb_length != b->vb_length) goto length_error;
1006
1007 buf = talloc_array(ctx, uint8_t, a->vb_length);
1008 if (!buf) goto oom;
1009
1010 for (len = 0; len < a->vb_length; len++) {
1011 buf[len] = a->vb_octets[len] ^ b->vb_octets[len];
1012 }
1013
1014 goto set_result;
1015
1016 case T_RSHIFT:
1017 if (b->vb_uint32 > a->vb_length) return ERR_UNDERFLOW;
1018
1019 len = a->vb_length - b->vb_uint32;
1020 buf = talloc_array(ctx, uint8_t, len);
1021 if (!buf) goto oom;
1022
1023 memcpy(buf, a->vb_octets, len);
1024
1025 fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, false);
1027 break;
1028
1029 case T_LSHIFT:
1030 if (b->vb_uint32 > a->vb_length) return ERR_OVERFLOW;
1031
1032 len = a->vb_length - b->vb_uint32;
1033
1034 buf = talloc_array(ctx, uint8_t, len);
1035 if (!buf) goto oom;
1036
1037 memcpy(buf, a->vb_octets + b->vb_uint32, len);
1038
1039 fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, false);
1041 break;
1042
1043 case T_MUL:
1044 /*
1045 * 0 * 0 = 0
1046 */
1047 if (!b->vb_uint64 || !a->vb_length) {
1048 fr_value_box_memdup(ctx, dst, dst->enumv, (const uint8_t *) "", 0, false);
1050 break;
1051 }
1052
1053 if (b->vb_uint64 > 256) return ERR_OVERFLOW;
1054 if (a->vb_length > 16) return ERR_OVERFLOW;
1055
1056 len = a->vb_length * b->vb_uint64;
1057
1058 buf = talloc_array(ctx, uint8_t, len);
1059 if (!buf) goto oom;
1060
1061 for (i = 0, p = buf; i < b->vb_uint64; i++, p += a->vb_length) {
1062 memcpy(p, a->vb_octets, a->vb_length);
1063 }
1064
1065 fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, false);
1067 break;
1068
1069 default:
1070 return ERR_INVALID; /* invalid operator */
1071 }
1072
1073 if (a == &one) fr_value_box_clear_value(&one);
1074 if (b == &two) fr_value_box_clear_value(&two);
1075
1076 return 0;
1077}
1078
1079static 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)
1080{
1081 char *buf, *p;
1082 size_t i, len;
1083 fr_value_box_t one = {};
1084 fr_value_box_t two = {};
1085
1086 fr_assert(dst->type == FR_TYPE_STRING);
1087
1088 COERCE_A(FR_TYPE_STRING, dst->enumv);
1089
1090 if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
1091 /*
1092 * Don't touch the RHS.
1093 */
1094 fr_assert(b->type == FR_TYPE_UINT32);
1095
1096 } else if (op == T_MUL) {
1098
1099 COERCE_B(FR_TYPE_UINT64, NULL);
1100
1101 } else {
1102 COERCE_B(FR_TYPE_STRING, dst->enumv);
1103 }
1104
1105 len = a->vb_length + b->vb_length;
1106
1107 switch (op) {
1108 case T_ADD:
1109 buf = talloc_array(ctx, char, len + 1);
1110 if (!buf) {
1111 oom:
1112 fr_strerror_const("Out of memory");
1113 return -1;
1114 }
1115
1116 len = a->vb_length + b->vb_length;
1117 memcpy(buf, a->vb_strvalue, a->vb_length);
1118 memcpy(buf + a->vb_length, b->vb_strvalue, b->vb_length);
1119 buf[len] = '\0';
1120
1121 fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1124 break;
1125
1126 case T_XOR: /* is prepend for strings */
1127 buf = talloc_array(ctx, char, len + 1);
1128 if (!buf) goto oom;
1129
1130 len = a->vb_length + b->vb_length;
1131 memcpy(buf, b->vb_strvalue, b->vb_length);
1132 memcpy(buf + b->vb_length, a->vb_strvalue, a->vb_length);
1133 buf[len] = '\0';
1134
1135 fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1138 break;
1139
1140 case T_SUB:
1141 /*
1142 * The inverse of add!
1143 */
1144 if (a->vb_length < b->vb_length) {
1145 fr_strerror_const("Suffix to remove is longer than input string");
1146 return -1;
1147 }
1148
1149 if (memcmp(a->vb_strvalue + a->vb_length - b->vb_length, b->vb_strvalue, b->vb_length) != 0) {
1150 fr_strerror_const("Right side of substract is not a suffix of the input string");
1151 return -1;
1152 }
1153
1154 len = a->vb_length - b->vb_length;
1155 buf = talloc_array(ctx, char, len + 1);
1156 if (!buf) goto oom;
1157
1158 memcpy(buf, a->vb_strvalue, len);
1159 buf[len] = '\0';
1160
1161 fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1163 break;
1164
1165 case T_RSHIFT:
1166 if (b->vb_uint32 > a->vb_length) return ERR_UNDERFLOW;
1167
1168 len = a->vb_length - b->vb_uint32;
1169 buf = talloc_array(ctx, char, len + 1);
1170 if (!buf) goto oom;
1171
1172 memcpy(buf, a->vb_strvalue, len);
1173 buf[len] = '\0';
1174
1175 fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1177 break;
1178
1179 case T_LSHIFT:
1180 if (b->vb_uint32 > a->vb_length) return ERR_OVERFLOW;
1181
1182 len = a->vb_length - b->vb_uint32;
1183
1184 buf = talloc_array(ctx, char, len + 1);
1185 if (!buf) goto oom;
1186
1187 memcpy(buf, a->vb_strvalue + b->vb_uint32, len);
1188 buf[len] = '\0';
1189
1190 fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1192 break;
1193
1194 case T_MUL:
1195 /*
1196 * 0 * 0 = 0
1197 */
1198 if (!b->vb_uint64 || !a->vb_length) {
1199 fr_value_box_strdup(ctx, dst, dst->enumv, "", false);
1201 break;
1202 }
1203
1204 if (b->vb_uint64 > 256) return ERR_OVERFLOW;
1205 if (a->vb_length > 16) return ERR_OVERFLOW;
1206
1207 len = a->vb_length * b->vb_uint64;
1208
1209 buf = talloc_array(ctx, char, len + 1);
1210 if (!buf) goto oom;
1211
1212 for (i = 0, p = buf; i < b->vb_uint64; i++, p += a->vb_length) {
1213 memcpy(p, a->vb_strvalue, a->vb_length);
1214 }
1215 *p = '\0';
1216
1217 fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1219 break;
1220
1221 default:
1222 return ERR_INVALID; /* invalid operator */
1223 }
1224
1225 if (a == &one) fr_value_box_clear_value(&one);
1226 if (b == &two) fr_value_box_clear_value(&two);
1227
1228 return 0;
1229}
1230
1232{
1233 switch (in->type) {
1234 default:
1235 fr_strerror_printf("Cannot operate on ipaddr and %s",
1236 fr_type_to_str(in->type));
1237 return -1;
1238
1240 if (in->vb_ip.af == AF_INET6) goto cast_ipv6_addr;
1241
1242 fr_value_box_init(out, FR_TYPE_IPV4_ADDR, NULL, in->tainted);
1243 out->vb_ip = in->vb_ip;
1244 break;
1245
1247 if (in->vb_ip.af == AF_INET6) goto cast_ipv6_prefix;
1248
1249 fr_value_box_init(out, FR_TYPE_IPV4_PREFIX, NULL, in->tainted);
1250 out->vb_ip = in->vb_ip;
1251 break;
1252
1254 case FR_TYPE_IPV4_ADDR:
1255 if (unlikely(fr_value_box_copy(NULL, out, in) < 0)) return -1;
1256 break;
1257
1258 case FR_TYPE_IPV6_ADDR:
1260 if (fr_value_box_cast(NULL, out, FR_TYPE_IPV4_ADDR, NULL, in) < 0) return -1;
1261 break;
1262
1264 cast_ipv6_prefix:
1265 if (fr_value_box_cast(NULL, out, FR_TYPE_IPV4_PREFIX, NULL, in) < 0) return -1;
1266 break;
1267
1268 /*
1269 * All of these get mashed to 32-bits. The cast
1270 * operation will check bounds (both negative and
1271 * positive) on the run-time values.
1272 */
1273 case FR_TYPE_BOOL:
1274
1275 case FR_TYPE_UINT8:
1276 case FR_TYPE_UINT16:
1277 case FR_TYPE_UINT32:
1278 case FR_TYPE_UINT64:
1279
1280 case FR_TYPE_SIZE:
1281
1282 case FR_TYPE_INT8:
1283 case FR_TYPE_INT16:
1284 case FR_TYPE_INT32:
1285 case FR_TYPE_INT64:
1286
1287 case FR_TYPE_FLOAT32:
1288 case FR_TYPE_FLOAT64:
1289 if (fr_value_box_cast(NULL, out, FR_TYPE_UINT32, NULL, in) < 0) return -1;
1290 break;
1291 }
1292
1293 return 0;
1294}
1295
1296static 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)
1297{
1298 fr_value_box_t one, two;
1299 fr_value_box_t *a, *b;
1300
1301 fr_assert((dst->type == FR_TYPE_IPV4_ADDR) || (dst->type == FR_TYPE_COMBO_IP_ADDR));
1302
1303 if (cast_ipv4_addr(&one, in1) < 0) return -1;
1304 a = &one;
1305
1306 if (cast_ipv4_addr(&two, in2) < 0) return -1;
1307 b = &two;
1308
1309 switch (op) {
1310 case T_ADD:
1311 case T_OR:
1312 /*
1313 * For simplicity, make sure that the prefix is first.
1314 */
1315 if (b->type == FR_TYPE_IPV4_PREFIX) swap(a,b);
1316
1317 /*
1318 * We can only add something to a prefix, and
1319 * that something has to be a number. The cast
1320 * operation already ensured that the number is
1321 * uint32, and is at least vaguely within the
1322 * allowed range.
1323 */
1324 if (a->type != FR_TYPE_IPV4_PREFIX) return ERR_INVALID;
1325
1326 if (b->type != FR_TYPE_UINT32) return ERR_INVALID;
1327
1328 /*
1329 * Trying to add a number outside of the given prefix. That's not allowed.
1330 */
1331 if (b->vb_uint32 >= (((uint32_t) 1) << (32 - a->vb_ip.prefix))) return ERR_OVERFLOW;
1332
1333 dst->vb_ip.af = AF_INET;
1334 dst->vb_ipv4addr = htonl(ntohl(a->vb_ipv4addr) | b->vb_uint32);
1335 dst->vb_ip.prefix = 32;
1338 break;
1339
1340 default:
1341 return ERR_INVALID;
1342 }
1343
1344 return 0;
1345}
1346
1347static 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)
1348{
1349 int prefix;
1350 fr_value_box_t one, two, tmp;
1351
1352 fr_assert((dst->type == FR_TYPE_IPV4_PREFIX) || (dst->type == FR_TYPE_COMBO_IP_PREFIX));
1353
1354 switch (op) {
1355 case T_AND:
1356 if (fr_type_is_integer(a->type)) {
1357 if (fr_value_box_cast(NULL, &one, FR_TYPE_UINT32, NULL, a) < 0) return -1;
1358
1359 a = &one;
1360 swap(a, b);
1361
1362 } else if (fr_type_is_integer(b->type)) {
1363 if (fr_value_box_cast(NULL, &two, FR_TYPE_UINT32, NULL, b) < 0) return -1;
1364 b = &two;
1365
1366 } else {
1367 fr_strerror_const("Invalid input types for ipv4prefix");
1368 return -1;
1369 }
1370
1371 switch (a->type) {
1372 case FR_TYPE_IPV6_ADDR:
1373 if (fr_value_box_cast(NULL, &tmp, FR_TYPE_IPV4_ADDR, NULL, a) < 0) return -1;
1374 a = &tmp;
1375 break;
1376
1377 case FR_TYPE_IPV4_ADDR:
1379 break;
1380
1381 default:
1382 fr_strerror_printf("Invalid input data type '%s' for logical 'and'",
1383 fr_type_to_str(a->type));
1384
1385 return -1;
1386 }
1387
1388 if (b->vb_uint32 == 0) { /* set everything to zero */
1389 dst->vb_ipv4addr = 0;
1390 prefix = 0;
1391
1392 } else if ((~b->vb_uint32) == 0) { /* all 1's */
1393 dst->vb_ipv4addr = a->vb_ipv4addr;
1394 prefix = 32;
1395
1396 } else {
1397 uint32_t mask;
1398
1399 mask = ~b->vb_uint32; /* 0xff00 -> 0x00ff */
1400 mask++; /* 0x00ff -> 0x0100 */
1401 if ((mask & b->vb_uint32) != mask) {
1402 fr_strerror_printf("Invalid network mask '0x%08x'", b->vb_uint32);
1403 return -1;
1404 }
1405
1406 mask = 0xfffffffe;
1407 prefix = 31;
1408
1409 while (prefix > 0) {
1410 if (mask == b->vb_uint32) break;
1411
1412 prefix--;
1413 /* coverity[overflow_const] */
1414 mask <<= 1;
1415 }
1416 fr_assert(prefix > 0);
1417
1418 dst->vb_ipv4addr = htonl(ntohl(a->vb_ipv4addr) & b->vb_uint32);
1419 }
1420
1421 dst->vb_ip.af = AF_INET;
1422 dst->vb_ip.prefix = prefix;
1423 break;
1424
1425 default:
1426 return ERR_INVALID;
1427 }
1428
1429 return 0;
1430}
1431
1433{
1434 switch (in->type) {
1435 default:
1436 fr_strerror_printf("Cannot operate on ipv6addr and %s",
1437 fr_type_to_str(in->type));
1438 return -1;
1439
1441 if (in->vb_ip.af == AF_INET) goto cast_ipv4_addr;
1442
1443 fr_assert(in->vb_ip.af == AF_INET6);
1444 fr_value_box_init(out, FR_TYPE_IPV6_ADDR, NULL, in->tainted);
1445 out->vb_ip = in->vb_ip;
1446 break;
1447
1449 if (in->vb_ip.af == AF_INET) goto cast_ipv4_prefix;
1450
1451 fr_assert(in->vb_ip.af == AF_INET6);
1452 fr_value_box_init(out, FR_TYPE_IPV6_PREFIX, NULL, in->tainted);
1453 out->vb_ip = in->vb_ip;
1454 break;
1455
1456
1458 case FR_TYPE_IPV6_ADDR:
1459 if (unlikely(fr_value_box_copy(NULL, out, in) < 0)) return -1;
1460 break;
1461
1462 case FR_TYPE_IPV4_ADDR:
1464 if (fr_value_box_cast(NULL, out, FR_TYPE_IPV6_ADDR, NULL, in) < 0) return -1;
1465 break;
1466
1468 cast_ipv4_prefix:
1469 if (fr_value_box_cast(NULL, out, FR_TYPE_IPV6_PREFIX, NULL, in) < 0) return -1;
1470 break;
1471
1472 /*
1473 * All of these get mashed to 64-bits. The cast
1474 * operation will check bounds (both negative and
1475 * positive) on the run-time values.
1476 */
1477 case FR_TYPE_BOOL:
1478
1479 case FR_TYPE_UINT8:
1480 case FR_TYPE_UINT16:
1481 case FR_TYPE_UINT32:
1482 case FR_TYPE_UINT64:
1483
1484 case FR_TYPE_SIZE:
1485
1486 case FR_TYPE_INT8:
1487 case FR_TYPE_INT16:
1488 case FR_TYPE_INT32:
1489 case FR_TYPE_INT64:
1490
1491 case FR_TYPE_FLOAT32:
1492 case FR_TYPE_FLOAT64:
1493 if (fr_value_box_cast(NULL, out, FR_TYPE_UINT64, NULL, in) < 0) return -1;
1494 break;
1495 }
1496
1497 return 0;
1498}
1499
1500static 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)
1501{
1502 fr_value_box_t one, two;
1503 fr_value_box_t *a, *b;
1504 int i;
1505 uint64_t mask;
1506
1507 fr_assert((dst->type == FR_TYPE_IPV6_ADDR) || (dst->type == FR_TYPE_COMBO_IP_ADDR));
1508
1509 if (cast_ipv6_addr(&one, in1) < 0) return -1;
1510 a = &one;
1511
1512 if (cast_ipv6_addr(&two, in2) < 0) return -1;
1513 b = &two;
1514
1515 switch (op) {
1516 case T_ADD:
1517 case T_OR:
1518 /*
1519 * For simplicity, make sure that the prefix is first.
1520 */
1521 if (b->type == FR_TYPE_IPV6_PREFIX) swap(a, b);
1522
1523 /*
1524 * We can only add something to a prefix, and
1525 * that something has to be a number. The cast
1526 * operation already ensured that the number is
1527 * uint64, and is at least vaguely within the
1528 * allowed range.
1529 */
1530 if (a->type != FR_TYPE_IPV6_PREFIX) return ERR_INVALID;
1531
1532 if (b->type != FR_TYPE_UINT64) return ERR_INVALID;
1533
1534 /*
1535 * If we're adding a UINT64, the prefix can't be shorter than 64.
1536 */
1537 if (a->vb_ip.prefix <= 64) return ERR_OVERFLOW;
1538
1539 /*
1540 * Trying to add a number outside of the given prefix. That's not allowed.
1541 */
1542 if (b->vb_uint64 >= (((uint64_t) 1) << (128 - a->vb_ip.prefix))) return ERR_OVERFLOW;
1543
1544 /*
1545 * Add in the relevant low bits.
1546 */
1547 memcpy(&dst->vb_ipv6addr, a->vb_ipv6addr, sizeof(dst->vb_ipv6addr));
1548 mask = b->vb_uint64;
1549 for (i = 15; i >= ((a->vb_ip.prefix + 7) >> 3); i--) {
1550 dst->vb_ipv6addr[i] |= mask & 0xff;
1551 mask >>= 8;
1552 }
1553
1554 dst->vb_ip.af = AF_INET6;
1555 dst->vb_ip.prefix = 128;
1556 dst->vb_ip.scope_id = a->vb_ip.scope_id;
1558 break;
1559
1560 default:
1561 return ERR_INVALID;
1562 }
1563
1564 return 0;
1565}
1566
1567static int get_ipv6_prefix(uint8_t const *in)
1568{
1569 int i, j, prefix;
1570
1571 prefix = 128;
1572 for (i = 15; i >= 0; i--) {
1573 if (!in[i]) {
1574 prefix -= 8;
1575 continue;
1576 }
1577
1578 for (j = 0; j < 8; j++) {
1579 if ((in[i] & (1 << j)) == 0) {
1580 prefix--;
1581 continue;
1582 }
1583 return prefix;
1584 }
1585 }
1586
1587 return prefix;
1588}
1589
1590static 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)
1591{
1592 int i, prefix = 128;
1593 uint8_t const *pa, *pb;
1594 uint8_t *pdst;
1595
1596 fr_assert((dst->type == FR_TYPE_IPV6_PREFIX) || (dst->type == FR_TYPE_COMBO_IP_PREFIX));
1597
1598 if (a->type == FR_TYPE_OCTETS) {
1599 if (a->vb_length != (128 / 8)) {
1600 fr_strerror_printf("Invalid length %zu for octets network mask", a->vb_length);
1601 return -1;
1602 }
1603 pa = a->vb_octets;
1604 prefix = get_ipv6_prefix(pa);
1605
1606 } else if (a->type == FR_TYPE_IPV6_ADDR) {
1607 pa = (const uint8_t *) &a->vb_ipv6addr;
1608
1609 } else {
1610 return ERR_INVALID;
1611 }
1612
1613 if (b->type == FR_TYPE_OCTETS) {
1614 if (b->vb_length != (128 / 8)) {
1615 fr_strerror_printf("Invalid length %zu for octets network mask", b->vb_length);
1616 return -1;
1617 }
1618 pb = b->vb_octets;
1619 prefix = get_ipv6_prefix(pb);
1620
1621 } else if (b->type == FR_TYPE_IPV6_ADDR) {
1622 pb = (const uint8_t *) &b->vb_ip.addr.v6;
1623
1624 } else {
1625 return ERR_INVALID;
1626 }
1627
1628 switch (op) {
1629 case T_AND:
1630 fr_value_box_init(dst, FR_TYPE_IPV6_PREFIX, NULL, false);
1631 pdst = (uint8_t *) &dst->vb_ip.addr.v6;
1632
1633 for (i = 0; i < 16; i++) {
1634 pdst[i] = pa[i] & pb[i];
1635 }
1636
1637 dst->vb_ip.af = AF_INET6;
1638 dst->vb_ip.prefix = prefix;
1641 break;
1642
1643 default:
1644 return ERR_INVALID;
1645 }
1646
1647 return 0;
1648}
1649
1650#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)))
1651
1652static 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)
1653{
1654 /*
1655 * IPv6 is better than IPv4!
1656 */
1657 if (is_ipv6(in1) || is_ipv6(in2)) {
1658 return calc_ipv6_addr(ctx, dst, in1, op, in2);
1659 }
1660
1661 return calc_ipv4_addr(ctx, dst, in1, op, in2);
1662}
1663
1664static 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)
1665{
1666 if (is_ipv6(in1) || is_ipv6(in2)) {
1667 return calc_ipv6_prefix(ctx, dst, in1, op, in2);
1668 }
1669
1670 return calc_ipv4_prefix(ctx, dst, in1, op, in2);
1671}
1672
1673
1674static 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)
1675{
1676 fr_value_box_t one, two;
1677 fr_value_box_t const *a = in1;
1678 fr_value_box_t const *b = in2;
1679
1680 fr_assert(dst->type == FR_TYPE_FLOAT32);
1681
1682 /*
1683 * Intermediate calculations are done using increased precision.
1684 */
1687
1688 switch (op) {
1689 case T_ADD:
1690 dst->vb_float32 = a->vb_float64 + b->vb_float64;
1691 break;
1692
1693 case T_SUB:
1694 dst->vb_float32 = a->vb_float64 - b->vb_float64;
1695 break;
1696
1697 case T_MUL:
1698 dst->vb_float32 = a->vb_float64 * b->vb_float64;
1699 break;
1700
1701 case T_DIV:
1702 if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
1703
1704 dst->vb_float32 = a->vb_float64 / b->vb_float64;
1705 break;
1706
1707 case T_MOD:
1708 if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
1709
1710 dst->vb_float32 = fmod(a->vb_float64, b->vb_float64);
1711 break;
1712
1713 default:
1714 return ERR_INVALID;
1715 }
1716
1719
1720 return 0;
1721
1722}
1723
1724static 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)
1725{
1726 fr_value_box_t one, two;
1727 fr_value_box_t const *a = in1;
1728 fr_value_box_t const *b = in2;
1729
1730 fr_assert(dst->type == FR_TYPE_FLOAT64);
1731
1734
1735 switch (op) {
1736 case T_ADD:
1737 dst->vb_float64 = a->vb_float64 + b->vb_float64;
1738 break;
1739
1740 case T_SUB:
1741 dst->vb_float64 = a->vb_float64 - b->vb_float64;
1742 break;
1743
1744 case T_MUL:
1745 dst->vb_float64 = a->vb_float64 * b->vb_float64;
1746 break;
1747
1748 case T_DIV:
1749 if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
1750
1751 dst->vb_float64 = a->vb_float64 / b->vb_float64;
1752 break;
1753
1754 case T_MOD:
1755 if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
1756
1757 dst->vb_float64 = fmod(a->vb_float64, b->vb_float64);
1758 break;
1759
1760 default:
1761 return ERR_INVALID;
1762 }
1763
1766
1767 return 0;
1768}
1769
1770/*
1771 * Do all intermediate operations on 64-bit numbers.
1772 */
1773static 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)
1774{
1775 fr_value_box_t one, two, result;
1776 fr_value_box_t const *a = in1;
1777 fr_value_box_t const *b = in2;
1778
1779 fr_value_box_init(&result, FR_TYPE_UINT64, NULL, a->tainted | b->tainted);
1780
1781 COERCE_A(FR_TYPE_UINT64, NULL);
1782
1783 if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
1784 /*
1785 * Don't touch the RHS.
1786 */
1787 fr_assert(b->type == FR_TYPE_UINT32);
1788
1789 } else {
1790 COERCE_B(FR_TYPE_UINT64, dst->enumv);
1791 }
1792
1793 switch (op) {
1794 case T_ADD:
1795 if (!fr_add(&result.vb_uint64, a->vb_uint64, b->vb_uint64)) return ERR_OVERFLOW;
1796 break;
1797
1798 case T_SUB:
1799 if (!fr_sub(&result.vb_uint64, a->vb_uint64, b->vb_uint64)) return ERR_UNDERFLOW;
1800 break;
1801
1802 case T_MUL:
1803 if (!fr_multiply(&result.vb_uint64, a->vb_uint64, b->vb_uint64)) return ERR_OVERFLOW;
1804 break;
1805
1806 case T_DIV:
1807 if (b->vb_uint64 == 0) return ERR_ZERO;
1808
1809 result.vb_uint64 = a->vb_uint64 / b->vb_uint64;
1810 break;
1811
1812 case T_MOD:
1813 if (b->vb_uint64 == 0) return ERR_ZERO;
1814
1815 result.vb_uint64 = a->vb_uint64 % b->vb_uint64;
1816 break;
1817
1818 case T_AND:
1819 result.vb_uint64 = a->vb_uint64 & b->vb_uint64;
1820 break;
1821
1822 case T_OR:
1823 result.vb_uint64 = a->vb_uint64 | b->vb_uint64;
1824 break;
1825
1826 case T_XOR:
1827 result.vb_uint64 = a->vb_uint64 ^ b->vb_uint64;
1828 break;
1829
1830 case T_RSHIFT:
1831 if (b->vb_uint32 >= (8 * sizeof(a->vb_uint64))) return ERR_UNDERFLOW;
1832
1833 result.vb_uint64 = a->vb_uint64 >> b->vb_uint32;
1834 break;
1835
1836 case T_LSHIFT:
1837 if (b->vb_uint32 >= (8 * sizeof(a->vb_uint64))) return ERR_OVERFLOW;
1838
1839 result.vb_uint64 = a->vb_uint64 << b->vb_uint32;
1840 break;
1841
1842 default:
1843 return ERR_INVALID;
1844 }
1845
1846 /*
1847 * Once we're done, cast the result to the final data type.
1848 */
1849 if (fr_value_box_cast(ctx, dst, dst->type, dst->enumv, &result) < 0) return -1;
1850
1853
1854 return 0;
1855}
1856
1857/*
1858 * Same as above, except uint64 -> int64. These functions should be kept in sync!
1859 */
1860static 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)
1861{
1862 fr_value_box_t one, two, result;
1863 fr_value_box_t const *a = in1;
1864 fr_value_box_t const *b = in2;
1865
1866 fr_value_box_init(&result, FR_TYPE_INT64, NULL, a->tainted | b->tainted);
1867
1868 COERCE_A(FR_TYPE_INT64, NULL);
1869
1870 if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
1871 /*
1872 * Don't touch the RHS.
1873 */
1874 fr_assert(b->type == FR_TYPE_UINT32);
1875
1876 } else {
1877 COERCE_B(FR_TYPE_INT64, dst->enumv);
1878 }
1879
1880 switch (op) {
1881 case T_ADD:
1882 if (!fr_add(&result.vb_int64, a->vb_int64, b->vb_int64)) return ERR_OVERFLOW;
1883 break;
1884
1885 case T_SUB:
1886 if (!fr_sub(&result.vb_int64, a->vb_int64, b->vb_int64)) return ERR_UNDERFLOW;
1887 break;
1888
1889 case T_MUL:
1890 if (!fr_multiply(&result.vb_int64, a->vb_int64, b->vb_int64)) return ERR_OVERFLOW;
1891 break;
1892
1893 case T_DIV:
1894 if (b->vb_int64 == 0) return ERR_ZERO;
1895
1896 result.vb_int64 = a->vb_int64 / b->vb_int64;
1897 break;
1898
1899 case T_MOD:
1900 if (b->vb_int64 == 0) return ERR_ZERO;
1901
1902 result.vb_int64 = a->vb_int64 % b->vb_int64;
1903 break;
1904
1905 case T_AND:
1906 result.vb_int64 = a->vb_int64 & b->vb_int64;
1907 break;
1908
1909 case T_OR:
1910 result.vb_int64 = a->vb_int64 | b->vb_int64;
1911 break;
1912
1913 case T_XOR:
1914 result.vb_int64 = a->vb_int64 ^ b->vb_int64;
1915 break;
1916
1917 case T_RSHIFT:
1918 if (b->vb_uint32 >= (8 * sizeof(a->vb_int64))) return ERR_UNDERFLOW;
1919
1920 result.vb_int64 = a->vb_int64 >> b->vb_uint32;
1921 break;
1922
1923 case T_LSHIFT:
1924 if (b->vb_uint32 >= (8 * sizeof(a->vb_int64))) return ERR_OVERFLOW;
1925
1926 result.vb_int64 = a->vb_int64 << b->vb_uint32;
1927 break;
1928
1929 default:
1930 return ERR_INVALID;
1931 }
1932
1933 /*
1934 * Once we're done, cast the result to the final data type.
1935 */
1936 if (fr_value_box_cast(ctx, dst, dst->type, dst->enumv, &result) < 0) return -1;
1937
1940
1941 return 0;
1942}
1943
1944typedef 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);
1945
1946/** Map output type to its associated function
1947 *
1948 */
1982
1983/** Calculate DST = A OP B
1984 *
1985 * The result is written to DST only *after* it has been calculated.
1986 * So it's safe to pass DST as either A or B. DST should already exist.
1987 *
1988 * This function should arguably not take comparison operators, but
1989 * whatever. The "promote types" code is the same for all of the
1990 * binary operations, so we might as well just have one function.
1991 */
1992int 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)
1993{
1994 int rcode = -1;
1995 fr_value_box_t one, two;
1997 fr_binary_op_t func;
1998
1999 if ((hint != FR_TYPE_NULL) && !fr_type_is_leaf(hint)) return invalid_type(hint);
2000
2001 /*
2002 * Casting to structural types should be a parse error,
2003 * and not a run-time calculation error.
2004 */
2005 if (!fr_type_is_leaf(a->type)) return invalid_type(a->type);
2006 if (!fr_type_is_leaf(b->type)) return invalid_type(b->type);
2007
2010
2011 /*
2012 * === and !== also check types. If the types are
2013 * different, it's a failure. Otherwise they revert to == and !=.
2014 */
2015 switch (op) {
2016 case T_OP_CMP_EQ_TYPE:
2017 if (a->type != b->type) {
2018 mismatch_type:
2019 fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false); /* @todo - enum */
2020 dst->vb_bool = false;
2021 return 0;
2022 }
2023 op = T_OP_CMP_EQ;
2024 break;
2025
2026 case T_OP_CMP_NE_TYPE:
2027 if (a->type != b->type) goto mismatch_type;
2028
2029 op = T_OP_NE;
2030 break;
2031
2032 case T_OP_REG_EQ:
2033 case T_OP_REG_NE:
2034 if (b->type != FR_TYPE_STRING) {
2035 fr_strerror_const("Invalid type for regular expression");
2036 return -1;
2037 }
2038
2039 rcode = fr_regex_cmp_op(op, a, b);
2040 if (rcode < 0) return rcode;
2041
2042 fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false); /* @todo - enum */
2043 dst->vb_bool = (rcode != 0);
2044 return 0;
2045
2046 default:
2047 break;
2048 }
2049
2052
2053 /*
2054 * We don't know what the output type should be. Try to
2055 * guess based on a variety of factors.
2056 */
2057 if (hint == FR_TYPE_NULL) do {
2058 /*
2059 * All kinds of special cases :(
2060 *
2061 * date1 - date2 --> time_delta
2062 *
2063 * time_delta * FOO --> float64, because time_delta is _printed_ as a floating point
2064 * number. And this is the least surprising thing to do.
2065 */
2066 if ((op == T_SUB) && (a->type == b->type) && (a->type == FR_TYPE_DATE)) {
2067 hint = FR_TYPE_TIME_DELTA;
2068 break;
2069 }
2070
2071 if (op == T_MUL) {
2072 if (a->type == FR_TYPE_TIME_DELTA) {
2073 hint = upcast_op[FR_TYPE_FLOAT64][b->type];
2074 if (hint == FR_TYPE_NULL) hint = upcast_op[b->type][FR_TYPE_FLOAT64];
2075
2076 } else if (b->type == FR_TYPE_TIME_DELTA) {
2077 hint = upcast_op[a->type][FR_TYPE_FLOAT64];
2078 if (hint == FR_TYPE_NULL) hint = upcast_op[FR_TYPE_FLOAT64][a->type];
2079 }
2080
2081 if ((a->type == FR_TYPE_STRING) &&
2082 (fr_type_is_integer_except_bool(b->type))) {
2083 hint = FR_TYPE_STRING;
2084 }
2085
2086 if ((a->type == FR_TYPE_OCTETS) &&
2087 (fr_type_is_integer_except_bool(b->type))) {
2088 hint = FR_TYPE_OCTETS;
2089 }
2090
2091 if (hint != FR_TYPE_NULL) break;
2092 }
2093
2094 /*
2095 * date % time_delta --> time_delta
2096 */
2097 if ((op == T_MOD) && (a->type == FR_TYPE_DATE)) {
2098 hint = FR_TYPE_TIME_DELTA;
2099 break;
2100 }
2101
2102 switch (op) {
2103 case T_OP_CMP_EQ:
2104 case T_OP_NE:
2105 case T_OP_GE:
2106 case T_OP_GT:
2107 case T_OP_LE:
2108 case T_OP_LT:
2109 /*
2110 * Comparison operators always return
2111 * "bool".
2112 */
2113 hint = FR_TYPE_BOOL;
2114 break;
2115
2116 case T_AND:
2117 /*
2118 * Get mask from IP + number
2119 */
2120 if ((a->type == FR_TYPE_IPV4_ADDR) || (b->type == FR_TYPE_IPV4_ADDR)) {
2121 hint = FR_TYPE_IPV4_PREFIX;
2122 break;
2123 }
2124
2125 if ((a->type == FR_TYPE_IPV6_ADDR) || (b->type == FR_TYPE_IPV6_ADDR)) {
2126 hint = FR_TYPE_IPV6_PREFIX;
2127 break;
2128 }
2130
2131 case T_OR:
2132 case T_ADD:
2133 case T_SUB:
2134 case T_MUL:
2135 case T_DIV:
2136 case T_MOD:
2137 case T_XOR:
2138 /*
2139 * Try to "up-cast" the types. This is
2140 * so that we can take (for example)
2141 * uint8 + uint16, and have the output as
2142 * uint16.
2143 *
2144 * There must be only one entry per [a,b]
2145 * pairing. That way we're sure that [a,b]==[b,a]
2146 */
2147 hint = upcast_op[a->type][b->type];
2148 if (hint == FR_TYPE_NULL) {
2149 hint = upcast_op[b->type][a->type];
2150 } else if (a->type != b->type) {
2151 fr_assert(upcast_op[b->type][a->type] == FR_TYPE_NULL);
2152 }
2153
2154 /*
2155 * No idea what to do. :(
2156 */
2157 if (hint == FR_TYPE_NULL) {
2158 fr_strerror_printf("Invalid operation on data types - '%s' %s '%s'",
2159 fr_type_to_str(a->type), fr_tokens[op], fr_type_to_str(b->type));
2160 goto done;
2161 }
2162
2163 break;
2164
2165 /*
2166 * The RHS MUST be a numerical type. We don't need to do any upcasting here.
2167 *
2168 * @todo - the output type could be larger than the input type, if the shift is
2169 * more than the input type can handle. e.g. uint8 << 4 could result in uint16
2170 */
2171 case T_LSHIFT:
2172 if (!fr_type_is_integer(a->type)) {
2173 return handle_result(a->type, T_LSHIFT, ERR_INVALID);
2174 }
2175
2176 if (fr_type_is_signed(a->type)) {
2177 hint = FR_TYPE_INT64;
2178 break;
2179 }
2180 hint = FR_TYPE_UINT64;
2181 break;
2182
2183 case T_RSHIFT:
2184 hint = a->type;
2185 break;
2186
2187 default:
2188 return handle_result(a->type, op, ERR_INVALID);
2189 }
2190 } while (0);
2191
2192 /*
2193 * Now that we've figured out the correct types, perform the operation.
2194 */
2195 switch (op) {
2196 case T_OP_CMP_EQ:
2197 case T_OP_NE:
2198 case T_OP_GE:
2199 case T_OP_GT:
2200 case T_OP_LE:
2201 case T_OP_LT:
2202 if (hint != FR_TYPE_BOOL) {
2203 fr_strerror_printf("Invalid destination type '%s' for comparison operator",
2204 fr_type_to_str(hint));
2205 goto done;
2206 }
2207
2208 /*
2209 * Convert the types to ones which are comparable.
2210 */
2211 if (a->type != b->type) {
2212 fr_dict_attr_t const *enumv = NULL;
2213
2214 /*
2215 * If we're doing comparisons and one of them has an enum, and the other is an
2216 * enum name, then use the enum name to convert the string to the other type.
2217 *
2218 * We can then do type-specific comparisons.
2219 */
2220 if ((a->type == FR_TYPE_STRING) && b->enumv) {
2221 enumv = b->enumv;
2222 hint = b->type;
2223
2224 } else if ((b->type == FR_TYPE_STRING) && a->enumv) {
2225 enumv = a->enumv;
2226 hint = a->type;
2227
2228 } else {
2229 /*
2230 * Try to "up-cast" the types. This is so that we can take (for example)
2231 * uint8 < uint16, and have it make sense.
2232 *
2233 * There must be only one entry per [a,b] pairing. That way we're sure
2234 * that [a,b]==[b,a]
2235 */
2236 hint = upcast_cmp[a->type][b->type];
2237 if (hint == FR_TYPE_NULL) {
2238 hint = upcast_cmp[b->type][a->type];
2239 } else {
2240 fr_assert(upcast_cmp[b->type][a->type] == FR_TYPE_NULL);
2241 }
2242
2243 /*
2244 * time_deltas have a scale in the enumv, but default to "seconds" if
2245 * there's no scale. As a result, if we compare time_delta(ms) to integer,
2246 * then the integer is interpreted as seconds, and the scale is wrong.
2247 *
2248 * The solution is to use the appropriate scale.
2249 */
2250 if (hint == a->type) enumv = a->enumv;
2251 if (hint == b->type) enumv = b->enumv;
2252
2253 if (hint == FR_TYPE_NULL) {
2254 fr_strerror_printf("Cannot compare incompatible types (%s)... %s (%s)...",
2255 fr_type_to_str(a->type),
2256 fr_tokens[op],
2257 fr_type_to_str(b->type));
2258 goto done;
2259 }
2260 }
2261
2262 /*
2263 * Cast them to the appropriate type, which may be different from either of the
2264 * inputs.
2265 */
2266 if (a->type != hint) {
2267 if (fr_value_box_cast(NULL, &one, hint, enumv, a) < 0) goto done;
2268 a = &one;
2270 }
2271
2272 if (b->type != hint) {
2273 if (fr_value_box_cast(NULL, &two, hint, enumv, b) < 0) goto done;
2274 b = &two;
2276 }
2277 }
2278
2279 rcode = fr_value_box_cmp_op(op, a, b);
2280 if (rcode < 0) goto done;
2281
2282 fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false);
2283 dst->vb_bool = (rcode > 0);
2284 break;
2285
2286 /*
2287 * For shifts, the RHS value MUST be an integer. There's no reason to have it as
2288 * anything other than an 8-bit field.
2289 */
2290 case T_LSHIFT:
2291 case T_RSHIFT:
2292 if (b->type != FR_TYPE_UINT32) {
2293 if (fr_value_box_cast(ctx, &two, FR_TYPE_UINT32, NULL, b) < 0) {
2294 fr_strerror_const_push("Cannot parse shift value as integer");
2295 goto done;
2296 }
2297 b = &two;
2298 }
2300
2301 case T_ADD:
2302 case T_SUB:
2303 case T_MUL:
2304 case T_DIV:
2305 case T_MOD:
2306 case T_AND:
2307 case T_OR:
2308 case T_XOR:
2309 fr_assert(hint != FR_TYPE_NULL);
2310
2311 func = calc_type[hint];
2312 if (!func) {
2313 fr_strerror_printf("Cannot perform any operations for destination type %s",
2314 fr_type_to_str(hint));
2315 rcode = -1;
2316 break;
2317 }
2318
2319 /*
2320 * It's OK to use one of the inputs as the
2321 * output. In order to ensure that nothing bad
2322 * happens, we use an intermediate value-box.
2323 */
2324 fr_value_box_init(&out, hint, NULL, false);
2325
2326 rcode = func(ctx, &out, a, op, b); /* not calc_type[hint], to shut up clang */
2327 if (rcode < 0) goto done;
2328
2329 fr_value_box_copy_shallow(NULL, dst, &out);
2330 dst->tainted = a->tainted | b->tainted;
2331 break;
2332
2333 default:
2334 rcode = ERR_INVALID;
2335 break;
2336 }
2337
2338done:
2341
2342 return handle_result(hint, op, rcode);
2343}
2344
2345/** Calculate DST = OP { A, B, C, ... }
2346 *
2347 * The result is written to DST only *after* it has been calculated.
2348 * So it's safe to pass DST as one of the inputs. DST should already
2349 * exist.
2350 */
2352{
2353 fr_value_box_t out, *vb;
2354 fr_binary_op_t calc;
2355
2356 if (group->type != FR_TYPE_GROUP) {
2357 fr_strerror_const("Invalid type passed to multivalue calculation");
2358 return -1;
2359 }
2360
2363 fr_strerror_printf("Invalid operation %s for data type %s", fr_tokens[op], fr_type_to_str(type));
2364 return -1;
2365 }
2366
2367 if (type == FR_TYPE_STRING) {
2368 fr_sbuff_t *sbuff;
2370
2371 if (op != T_ADD) goto invalid_type;
2372
2373 FR_SBUFF_TALLOC_THREAD_LOCAL(&sbuff, 1024, (1 << 16));
2374
2375 if (fr_value_box_list_concat_as_string(&safety, sbuff, UNCONST(fr_value_box_list_t *, &group->vb_group),
2376 NULL, 0, NULL, FR_VALUE_BOX_LIST_NONE, FR_VALUE_BOX_SAFE_FOR_ANY, false) < 0) return -1;
2377
2378 if (fr_value_box_bstrndup(ctx, dst, NULL, fr_sbuff_start(sbuff), fr_sbuff_used(sbuff), false) < 0) return -1;
2379 fr_value_box_safety_set(dst, &safety);
2380 return 0;
2381 }
2382
2383 if (type == FR_TYPE_OCTETS) {
2384 fr_dbuff_t *dbuff;
2386
2387 if (op != T_ADD) goto invalid_type;
2388
2389 FR_DBUFF_TALLOC_THREAD_LOCAL(&dbuff, 1024, (1 << 16));
2390
2391 if (fr_value_box_list_concat_as_octets(&safety, dbuff, UNCONST(fr_value_box_list_t *, &group->vb_group), NULL, 0, FR_VALUE_BOX_LIST_NONE, false) < 0) return -1;
2392
2393 if (fr_value_box_memdup(ctx, dst, NULL, fr_dbuff_start(dbuff), fr_dbuff_used(dbuff), false) < 0) return -1;
2394 fr_value_box_safety_set(dst, &safety);
2395
2396 return 0;
2397 }
2398
2399 /*
2400 * Can't add or multiply booleans.
2401 */
2402 if ((type == FR_TYPE_BOOL) && !((op == T_AND) || (op == T_OR) || (op == T_XOR))) goto unsupported;
2403
2404 switch (op) {
2405 case T_ADD:
2406 case T_MUL:
2407 case T_AND:
2408 case T_OR:
2409 case T_XOR:
2410 break;
2411
2412 default:
2413 goto invalid_type;
2414 }
2415
2416 /*
2417 * Strings and octets are different.
2418 */
2419 if (!fr_type_is_numeric(type)) {
2420 unsupported:
2421 fr_strerror_printf("Not yet supported operation %s for data type %s", fr_tokens[op], fr_type_to_str(type));
2422 return -1;
2423 }
2424
2425 switch (type) {
2426 case FR_TYPE_UINT8:
2427 case FR_TYPE_UINT16:
2428 case FR_TYPE_UINT32:
2429 case FR_TYPE_UINT64:
2430 calc = calc_uint64;
2431 break;
2432
2433 case FR_TYPE_INT8:
2434 case FR_TYPE_INT16:
2435 case FR_TYPE_INT32:
2436 case FR_TYPE_INT64:
2437 calc = calc_int64;
2438 break;
2439
2440 case FR_TYPE_TIME_DELTA:
2441 if ((op != T_ADD) && (op != T_SUB)) goto invalid_type;
2442 calc = calc_time_delta;
2443 break;
2444
2445 case FR_TYPE_FLOAT32:
2446 calc = calc_float32;
2447 break;
2448
2449 case FR_TYPE_FLOAT64:
2450 calc = calc_float64;
2451 break;
2452
2453 default:
2454 goto unsupported;
2455 }
2456
2457 vb = fr_value_box_list_head(&group->vb_group);
2458 if (!vb) {
2459 fr_strerror_printf("Empty input is invalid");
2460 return -1;
2461 }
2462
2463 if (fr_value_box_cast(ctx, &out, type, NULL, vb) < 0) return -1;
2464
2465 while ((vb = fr_value_box_list_next(&group->vb_group, vb)) != NULL) {
2466 int rcode;
2467 fr_value_box_t box;
2468
2469 if (vb->type == type) {
2470 rcode = calc(ctx, &out, &out, op, vb);
2471 if (rcode < 0) return rcode;
2472
2473 } else {
2474 if (fr_value_box_cast(ctx, &box, type, NULL, vb) < 0) return -1;
2475
2476 rcode = calc(ctx, &out, &out, op, &box);
2477 if (rcode < 0) return rcode;
2478 }
2479 }
2480
2481 return fr_value_box_copy(ctx, dst, &out);
2482}
2483
2484
2485#define T(_x) [T_OP_ ## _x ## _EQ] = T_ ## _x
2486
2488 T(ADD),
2489 T(SUB),
2490 T(MUL),
2491 T(DIV),
2492 T(AND),
2493 T(OR),
2494 T(XOR),
2495 T(RSHIFT),
2496 T(LSHIFT),
2497};
2498
2499/** Calculate DST OP SRC
2500 *
2501 * e.g. "foo += bar".
2502 *
2503 * This is done by doing some sanity checks, and then just calling
2504 * the "binary operation" function.
2505 */
2507{
2508 int rcode;
2509
2510 if (!fr_type_is_leaf(dst->type)) return invalid_type(dst->type);
2511 if (!fr_type_is_leaf(src->type)) return invalid_type(src->type);
2512
2513 if (dst->immutable) {
2514 fr_strerror_printf("Cannot modify immutable value");
2515 return -1;
2516 }
2517
2518 /*
2519 * These operators are included here for testing and completeness. But see comments in
2520 * fr_edit_list_apply_pair_assignment() for what the caller should be doing.
2521 */
2522 if ((op == T_OP_EQ) || (op == T_OP_SET)) {
2523 /*
2524 * Allow for unintentional mistakes.
2525 */
2526 if (src == dst) return 0;
2527
2529 return fr_value_box_cast(ctx, dst, dst->type, dst->enumv, src); /* cast, as the RHS might not (yet) be the same! */
2530 }
2531
2532 if (assignment2op[op] == T_INVALID) {
2533 return handle_result(dst->type, op, ERR_INVALID);
2534 }
2535 op = assignment2op[op];
2536
2537 /*
2538 * Just call the binary op function. It already ensures that (a) the inputs are "const", and (b)
2539 * the output is over-written only at the final step.
2540 */
2541 if (src->type != FR_TYPE_GROUP) {
2542 rcode = fr_value_calc_binary_op(ctx, dst, dst->type, dst, op, src);
2543
2544 } else {
2545 fr_value_box_t *vb = NULL;
2546
2547 /*
2548 * If the RHS is a group, then we loop over the group recursively, doing the operation.
2549 */
2550 rcode = 0; /* in case group is empty */
2551
2552 while ((vb = fr_value_box_list_next(&src->vb_group, vb)) != NULL) {
2553 rcode = fr_value_calc_binary_op(ctx, dst, dst->type, dst, op, vb);
2554 if (rcode < 0) break;
2555 }
2556 }
2557
2558 if (rcode < 0) return handle_result(dst->type, op, rcode);
2559
2560 return 0;
2561}
2562
2563/** Calculate unary operations
2564 *
2565 * e.g. "foo++", or "-foo".
2566 */
2567int fr_value_calc_unary_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_token_t op, fr_value_box_t const *src)
2568{
2569 int rcode = -1;
2570 fr_value_box_t one;
2571
2572 if (!fr_type_is_numeric(src->type)) return invalid_type(src->type);
2573
2574 if (dst->immutable) {
2575 fr_strerror_printf("Cannot modify immutable value");
2576 return -1;
2577 }
2578
2579 if (op == T_OP_INCRM) {
2580 /*
2581 * Add 1 or subtract 1 means RHS is always 1.
2582 */
2583 fr_value_box_init(&one, src->type, NULL, false);
2584 switch (src->type) {
2585 case FR_TYPE_UINT8:
2586 one.vb_uint8 = 1;
2587 break;
2588
2589 case FR_TYPE_UINT16:
2590 one.vb_uint16 = 1;
2591 break;
2592
2593 case FR_TYPE_UINT32:
2594 one.vb_uint32 = 1;
2595 break;
2596
2597 case FR_TYPE_UINT64:
2598 one.vb_uint64 = 1;
2599 break;
2600
2601 case FR_TYPE_SIZE:
2602 one.vb_size = 1;
2603 break;
2604
2605 case FR_TYPE_INT8:
2606 one.vb_int8 = 1;
2607 break;
2608
2609 case FR_TYPE_INT16:
2610 one.vb_int16 = 1;
2611 break;
2612
2613 case FR_TYPE_INT32:
2614 one.vb_int32 = 1;
2615 break;
2616
2617 case FR_TYPE_INT64:
2618 one.vb_int64 = 1;
2619 break;
2620
2621 case FR_TYPE_FLOAT32:
2622 one.vb_float32 = 1;
2623 break;
2624
2625 case FR_TYPE_FLOAT64:
2626 one.vb_float64 = 1;
2627 break;
2628
2629 default:
2630 fr_assert(0);
2631 return -1;
2632 }
2633
2634 rcode = fr_value_calc_binary_op(ctx, dst, src->type, src, T_ADD, &one);
2635 return handle_result(dst->type, op, rcode);
2636
2637 } else if (op == T_COMPLEMENT) {
2638 if (dst != src) {
2639 fr_value_box_init(dst, src->type, src->enumv, false);
2640 fr_value_box_safety_copy(dst, src);
2641 }
2642
2643#undef COMP
2644#define COMP(_type, _field) case FR_TYPE_ ## _type: dst->vb_ ##_field = (_field ## _t) ~src->vb_ ##_field; break
2645 switch (src->type) {
2646 COMP(UINT8, uint8);
2647 COMP(UINT16, uint16);
2648 COMP(UINT32, uint32);
2649 COMP(UINT64, uint64);
2650 COMP(SIZE, size);
2651
2652 COMP(INT8, int8);
2653 COMP(INT16, int16);
2654 COMP(INT32, int32);
2655 COMP(INT64, int64);
2656
2657 default:
2658 goto invalid;
2659 }
2660
2661 return 0;
2662
2663 } else if (op == T_SUB) {
2664 fr_type_t type = src->type;
2665
2666 if ((dst != src) && !fr_type_is_signed(src->type)) {
2667 type = upcast_unsigned[src->type];
2668
2669 if (type == FR_TYPE_NULL) {
2670 type = src->type; /* hope for the best */
2671 }
2672 }
2673
2674 fr_value_box_init(&one, type, NULL, src->tainted); /* init to zero */
2675 rcode = fr_value_calc_binary_op(ctx, dst, type, &one, T_SUB, src);
2676
2677 return handle_result(dst->type, op, rcode);
2678
2679 } else if (op == T_NOT) {
2680 bool value = fr_value_box_is_truthy(src);
2681
2682 fr_value_box_clear(dst);
2683 fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false); // @todo - add enum!
2684 dst->vb_bool = !value;
2685
2686 return 0;
2687
2688 } else {
2689 invalid:
2690 return handle_result(src->type, op, ERR_INVALID);
2691 }
2692
2693}
2694
2695/*
2696 * Empty lists are empty:
2697 *
2698 * {}
2699 * {{}}
2700 * {''}
2701 * {{},''}
2702 *
2703 * etc.
2704 */
2705static bool fr_value_calc_list_empty(fr_value_box_list_t const *list)
2706{
2708 switch (item->type) {
2709 default:
2710 return false;
2711
2712 case FR_TYPE_GROUP:
2713 if (!fr_value_calc_list_empty(&item->vb_group)) return false;
2714 break;
2715
2716 case FR_TYPE_STRING:
2717 case FR_TYPE_OCTETS:
2718 if (item->vb_length != 0) return false;
2719 break;
2720 }
2721 }
2722
2723 return true;
2724}
2725
2726
2727/*
2728 * Loop over input lists, calling fr_value_calc_binary_op()
2729 *
2730 * This implementation is arguably wrong... it should be checking individual entries in list1 against individual entries in list2.
2731 * Instead, it checks if ANY entry in list1 matches ANY entry in list2.
2732 */
2733int 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)
2734{
2735 int rcode;
2736 bool invert = false;
2737 bool a_empty, b_empty;
2738
2739 if (!fr_comparison_op[op]) {
2740 fr_strerror_printf("Invalid operator '%s' passed to list comparison", fr_tokens[op]);
2741 return -1;
2742 }
2743
2744 /*
2745 * v3 hack. != really means !( ... == ... )
2746 */
2747 if (op == T_OP_NE) {
2748 invert = true;
2749 op = T_OP_CMP_EQ;
2750 }
2751
2752 /*
2753 * It's annoying when the debug prints out cmp({},{}) and says "not equal".
2754 *
2755 * What's happening behind the scenes is that one side is an empty value-box group, such as when
2756 * an xlat expansion fails. And the other side is an empty string. If we believe that strings
2757 * are actually sets of characters, then {}=='', and we're all OK
2758 */
2759 a_empty = fr_value_box_list_empty(list1) || fr_value_calc_list_empty(list1);
2760 b_empty = fr_value_box_list_empty(list2) || fr_value_calc_list_empty(list2);
2761
2762 /*
2763 * Both lists are empty, they should be equal when checked for equality.
2764 */
2765 if (a_empty && b_empty) {
2766 switch (op) {
2767 case T_OP_CMP_EQ:
2768 case T_OP_LE:
2769 case T_OP_GE:
2770 invert = !invert;
2771 break;
2772
2773 default:
2774 break;
2775 }
2776
2777 goto done;
2778 }
2779
2780 /*
2781 * Emulate v3. :(
2782 */
2783 fr_value_box_list_foreach(list1, a) {
2784 fr_value_box_list_foreach(list2, b) {
2785 rcode = fr_value_calc_binary_op(ctx, dst, FR_TYPE_BOOL, a, op, b);
2786 if (rcode < 0) return rcode;
2787
2788 /*
2789 * No match: keep looking for a match.
2790 */
2791 fr_assert(dst->type == FR_TYPE_BOOL);
2792 if (!dst->vb_bool) continue;
2793
2794 /*
2795 * Found a match, we're done.
2796 */
2797 dst->vb_bool = !invert;
2798 return 0;
2799 }
2800 }
2801
2802 /*
2803 * No match,
2804 */
2805done:
2806 fr_value_box_clear(dst);
2807 fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false); // @todo - add enum!
2808 dst->vb_bool = invert;
2809 return 0;
2810}
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:186
#define RCSID(id)
Definition build.h:560
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition build.h:391
#define unlikely(_x)
Definition build.h:455
#define UNUSED
Definition build.h:384
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:776
static const fr_type_t upcast_cmp[FR_TYPE_MAX+1][FR_TYPE_MAX+1]
Updates type (a,b) -> c.
Definition calc.c:427
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:1296
static int get_ipv6_prefix(uint8_t const *in)
Definition calc.c:1567
static const fr_binary_op_t calc_type[FR_TYPE_MAX+1]
Map output type to its associated function.
Definition calc.c:1949
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:1500
static int invalid_type(fr_type_t type)
Definition calc.c:699
#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:66
#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:1674
#define COERCE_A(_type, _enumv)
Definition calc.c:48
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:1347
static const fr_type_t upcast_unsigned[FR_TYPE_MAX+1]
Definition calc.c:690
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:1773
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:904
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:1652
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:1590
static int cast_ipv6_addr(fr_value_box_t *out, fr_value_box_t const *in)
Definition calc.c:1432
static int handle_result(fr_type_t type, fr_token_t op, int rcode)
Definition calc.c:706
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:1860
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:728
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:1079
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:2733
#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:1664
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:819
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:1944
static int cast_ipv4_addr(fr_value_box_t *out, fr_value_box_t const *in)
Definition calc.c:1231
static bool fr_value_calc_list_empty(fr_value_box_list_t const *list)
Definition calc.c:2705
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:1724
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:2351
#define is_ipv6(_x)
Definition calc.c:1650
#define COERCE_B(_type, _enumv)
Definition calc.c:49
static const fr_token_t assignment2op[T_TOKEN_LAST]
Definition calc.c:2487
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:2506
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:1992
#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:2567
#define T(_x)
Definition calc.c:2485
#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:906
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:146
const bool fr_comparison_op[T_TOKEN_LAST]
Definition token.c:266
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:1028
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_const_push(_msg)
Definition strerror.h:227
#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
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:3974
ssize_t fr_value_box_list_concat_as_octets(fr_value_box_safety_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:6569
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:4422
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:1008
bool fr_value_box_is_truthy(fr_value_box_t const *in)
Check truthiness of values.
Definition value.c:7560
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:5225
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:4546
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
Definition value.c:4359
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:4649
void fr_value_box_safety_set(fr_value_box_t *box, fr_value_box_safety_t const *safety)
Replace the safety of a box.
Definition value.c:7499
ssize_t fr_value_box_list_concat_as_string(fr_value_box_safety_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:6452
void fr_value_box_safety_merge(fr_value_box_t *out, fr_value_box_t const *in)
Merge safety results.
Definition value.c:7488
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:7430
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition value.c:4405
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:4900
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:4987
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:5141
@ FR_VALUE_BOX_LIST_NONE
Do nothing to processed boxes.
Definition value.h:256
fr_value_box_safe_for_t safe_for
A unique value to indicate if that value box is safe for consumption by a particular module for a par...
Definition value.h:182
#define fr_value_box_init_null(_vb)
Initialise an empty/null box that will be filled later.
Definition value.h:641
#define VALUE_BOX_VERIFY(_x)
Definition value.h:1389
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
Definition value.h:635
#define fr_value_box_list_foreach(_list_head, _iter)
Definition value.h:247
static size_t char ** out
Definition value.h:1062
#define FR_VALUE_BOX_SAFE_FOR_ANY
Definition value.h:173
The safety of a value.
Definition value.h:181