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