Coverage Report

Created: 2025-12-14 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/freeradius-server/src/lib/util/calc.c
Line
Count
Source
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: 145b1597afaffb297e3f3dc1841ad81de686af8c $
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: 145b1597afaffb297e3f3dc1841ad81de686af8c $")
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
0
#define swap(_a, _b) do { __typeof__ (_a) _tmp = _a; _a = _b; _b = _tmp; } while (0)
34
35
0
#define ERR_ZERO (-5)
36
0
#define ERR_UNDERFLOW (-4)
37
0
#define ERR_OVERFLOW (-3)
38
0
#define ERR_INVALID  (-2)
39
40
0
#define COERCE(_vb, _box, _type, _enumv) do { \
41
0
    if (_vb->type != _type) { \
42
0
      if (fr_value_box_cast(NULL, &_box, _type, _enumv, _vb) < 0) return -1; \
43
0
      _vb = &_box; \
44
0
    } \
45
0
  } while (0)
46
47
0
#define COERCE_A(_type, _enumv) COERCE(a, one, _type, _enumv)
48
0
#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] = {
70
    [FR_TYPE_STRING] = FR_TYPE_STRING,
71
    [FR_TYPE_OCTETS] = FR_TYPE_OCTETS,
72
  },
73
74
  [FR_TYPE_OCTETS] = {
75
    [FR_TYPE_OCTETS] = FR_TYPE_OCTETS,
76
  },
77
78
  [FR_TYPE_IPV4_ADDR] = {
79
    /*
80
     *  ipaddr + int --> prefix (generally only "and")
81
     */
82
    [FR_TYPE_UINT32] =  FR_TYPE_IPV4_PREFIX,
83
84
    /*
85
     *  192.168.0.255 - 192.168.0.1 -> int64
86
     */
87
    [FR_TYPE_IPV4_ADDR] =  FR_TYPE_INT64,
88
  },
89
90
  /*
91
   *  IPv6 mod IPv6 -> ????
92
   */
93
  [FR_TYPE_IPV6_ADDR] = {
94
    [FR_TYPE_IPV6_ADDR] = FR_TYPE_OCTETS,
95
  },
96
97
  /*
98
   *  Prefix + int --> ipaddr
99
   */
100
  [FR_TYPE_IPV4_PREFIX] = {
101
    [FR_TYPE_IPV4_PREFIX] = FR_TYPE_IPV4_PREFIX,
102
    [FR_TYPE_IPV6_PREFIX] = FR_TYPE_IPV6_PREFIX,
103
    [FR_TYPE_COMBO_IP_PREFIX] = FR_TYPE_COMBO_IP_PREFIX,
104
105
    [FR_TYPE_BOOL] =   FR_TYPE_IPV4_ADDR,
106
107
    [FR_TYPE_UINT8] =   FR_TYPE_IPV4_ADDR,
108
    [FR_TYPE_UINT16] =  FR_TYPE_IPV4_ADDR,
109
    [FR_TYPE_UINT32] =  FR_TYPE_IPV4_ADDR,
110
    [FR_TYPE_UINT64] =  FR_TYPE_IPV4_ADDR,
111
112
    [FR_TYPE_SIZE] =    FR_TYPE_IPV4_ADDR,
113
114
    [FR_TYPE_INT8] =    FR_TYPE_IPV4_ADDR,
115
    [FR_TYPE_INT16] =   FR_TYPE_IPV4_ADDR,
116
    [FR_TYPE_INT32] =   FR_TYPE_IPV4_ADDR,
117
    [FR_TYPE_INT64] =   FR_TYPE_IPV4_ADDR,
118
119
    [FR_TYPE_FLOAT32] = FR_TYPE_IPV4_ADDR,
120
    [FR_TYPE_FLOAT64] = FR_TYPE_IPV4_ADDR,
121
  },
122
123
  [FR_TYPE_IPV6_PREFIX] = {
124
    [FR_TYPE_IPV6_PREFIX] = FR_TYPE_IPV6_PREFIX,
125
    [FR_TYPE_COMBO_IP_PREFIX] = FR_TYPE_COMBO_IP_PREFIX,
126
127
    [FR_TYPE_BOOL] =   FR_TYPE_IPV6_ADDR,
128
129
    [FR_TYPE_UINT8] =   FR_TYPE_IPV6_ADDR,
130
    [FR_TYPE_UINT16] =  FR_TYPE_IPV6_ADDR,
131
    [FR_TYPE_UINT32] =  FR_TYPE_IPV6_ADDR,
132
    [FR_TYPE_UINT64] =  FR_TYPE_IPV6_ADDR,
133
134
    [FR_TYPE_SIZE] =    FR_TYPE_IPV6_ADDR,
135
136
    [FR_TYPE_INT8] =    FR_TYPE_IPV6_ADDR,
137
    [FR_TYPE_INT16] =   FR_TYPE_IPV6_ADDR,
138
    [FR_TYPE_INT32] =   FR_TYPE_IPV6_ADDR,
139
    [FR_TYPE_INT64] =   FR_TYPE_IPV6_ADDR,
140
141
    [FR_TYPE_FLOAT32] = FR_TYPE_IPV6_ADDR,
142
    [FR_TYPE_FLOAT64] = FR_TYPE_IPV6_ADDR,
143
  },
144
145
  [FR_TYPE_COMBO_IP_ADDR] = {
146
    [FR_TYPE_IPV6_PREFIX] = FR_TYPE_COMBO_IP_PREFIX,
147
    [FR_TYPE_COMBO_IP_PREFIX] = FR_TYPE_COMBO_IP_PREFIX,
148
149
    [FR_TYPE_BOOL] =   FR_TYPE_COMBO_IP_ADDR,
150
151
    [FR_TYPE_UINT8] =   FR_TYPE_COMBO_IP_ADDR,
152
    [FR_TYPE_UINT16] =  FR_TYPE_COMBO_IP_ADDR,
153
    [FR_TYPE_UINT32] =  FR_TYPE_COMBO_IP_ADDR,
154
    [FR_TYPE_UINT64] =  FR_TYPE_COMBO_IP_ADDR,
155
156
    [FR_TYPE_SIZE] =    FR_TYPE_COMBO_IP_ADDR,
157
158
    [FR_TYPE_INT8] =    FR_TYPE_COMBO_IP_ADDR,
159
    [FR_TYPE_INT16] =   FR_TYPE_COMBO_IP_ADDR,
160
    [FR_TYPE_INT32] =   FR_TYPE_COMBO_IP_ADDR,
161
    [FR_TYPE_INT64] =   FR_TYPE_COMBO_IP_ADDR,
162
163
    [FR_TYPE_FLOAT32] = FR_TYPE_COMBO_IP_ADDR,
164
    [FR_TYPE_FLOAT64] = FR_TYPE_COMBO_IP_ADDR,
165
  },
166
167
  [FR_TYPE_COMBO_IP_PREFIX] = {
168
    [FR_TYPE_BOOL] =   FR_TYPE_COMBO_IP_ADDR,
169
170
    [FR_TYPE_UINT8] =   FR_TYPE_COMBO_IP_ADDR,
171
    [FR_TYPE_UINT16] =  FR_TYPE_COMBO_IP_ADDR,
172
    [FR_TYPE_UINT32] =  FR_TYPE_COMBO_IP_ADDR,
173
    [FR_TYPE_UINT64] =  FR_TYPE_COMBO_IP_ADDR,
174
175
    [FR_TYPE_SIZE] =    FR_TYPE_COMBO_IP_ADDR,
176
177
    [FR_TYPE_INT8] =    FR_TYPE_COMBO_IP_ADDR,
178
    [FR_TYPE_INT16] =   FR_TYPE_COMBO_IP_ADDR,
179
    [FR_TYPE_INT32] =   FR_TYPE_COMBO_IP_ADDR,
180
    [FR_TYPE_INT64] =   FR_TYPE_COMBO_IP_ADDR,
181
182
    [FR_TYPE_FLOAT32] = FR_TYPE_COMBO_IP_ADDR,
183
    [FR_TYPE_FLOAT64] = FR_TYPE_COMBO_IP_ADDR,
184
  },
185
186
  /*
187
   *  Bools and to pretty much any numerical type result in
188
   *  the other integer.
189
   */
190
  [FR_TYPE_BOOL] = {
191
    [FR_TYPE_BOOL] = FR_TYPE_BOOL,
192
193
    [FR_TYPE_STRING] = FR_TYPE_BOOL,
194
    [FR_TYPE_OCTETS] = FR_TYPE_BOOL,
195
196
    [FR_TYPE_UINT8] = FR_TYPE_UINT8,
197
    [FR_TYPE_UINT16] = FR_TYPE_UINT16,
198
    [FR_TYPE_UINT32] = FR_TYPE_UINT32,
199
    [FR_TYPE_UINT64] = FR_TYPE_UINT64,
200
201
    [FR_TYPE_SIZE] =   FR_TYPE_SIZE,
202
203
    [FR_TYPE_DATE]  = FR_TYPE_DATE,
204
205
    [FR_TYPE_INT8]   = FR_TYPE_INT16,
206
    [FR_TYPE_INT16]  = FR_TYPE_INT16,
207
    [FR_TYPE_INT32]  = FR_TYPE_INT32,
208
    [FR_TYPE_INT64]  = FR_TYPE_INT64,
209
210
    [FR_TYPE_TIME_DELTA] = FR_TYPE_TIME_DELTA,
211
212
    [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT32,
213
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
214
  },
215
216
  /*
217
   *  Various ints get cast to the next highest size which
218
   *  can hold their values.
219
   */
220
  [FR_TYPE_UINT8] = {
221
    [FR_TYPE_STRING] = FR_TYPE_UINT8,
222
    [FR_TYPE_OCTETS] = FR_TYPE_UINT8,
223
224
    [FR_TYPE_UINT8] = FR_TYPE_UINT64,
225
    [FR_TYPE_UINT16] = FR_TYPE_UINT64,
226
    [FR_TYPE_UINT32] = FR_TYPE_UINT64,
227
    [FR_TYPE_UINT64] = FR_TYPE_UINT64,
228
229
    [FR_TYPE_SIZE] =   FR_TYPE_UINT64,
230
231
    [FR_TYPE_DATE]  = FR_TYPE_DATE,
232
233
    [FR_TYPE_INT8]   = FR_TYPE_INT64,
234
    [FR_TYPE_INT16]  = FR_TYPE_INT64,
235
    [FR_TYPE_INT32]  = FR_TYPE_INT64,
236
    [FR_TYPE_INT64]  = FR_TYPE_INT64,
237
238
    [FR_TYPE_TIME_DELTA] = FR_TYPE_TIME_DELTA,
239
240
    [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT32,
241
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
242
  },
243
244
  [FR_TYPE_UINT16] = {
245
    [FR_TYPE_STRING] = FR_TYPE_UINT16,
246
    [FR_TYPE_OCTETS] = FR_TYPE_UINT16,
247
248
    [FR_TYPE_UINT16] = FR_TYPE_UINT64,
249
    [FR_TYPE_UINT32] = FR_TYPE_UINT64,
250
    [FR_TYPE_UINT64] = FR_TYPE_UINT64,
251
252
    [FR_TYPE_SIZE] =   FR_TYPE_UINT64,
253
254
    [FR_TYPE_DATE]  = FR_TYPE_DATE,
255
256
    [FR_TYPE_INT8]   = FR_TYPE_INT64,
257
    [FR_TYPE_INT16]  = FR_TYPE_INT64,
258
    [FR_TYPE_INT32]  = FR_TYPE_INT64,
259
    [FR_TYPE_INT64]  = FR_TYPE_INT64,
260
261
    [FR_TYPE_TIME_DELTA]  = FR_TYPE_TIME_DELTA,
262
263
    [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT32,
264
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
265
  },
266
267
  [FR_TYPE_UINT32] = {
268
    [FR_TYPE_STRING] = FR_TYPE_UINT32,
269
    [FR_TYPE_OCTETS] = FR_TYPE_UINT32,
270
271
    [FR_TYPE_UINT32] = FR_TYPE_UINT64,
272
    [FR_TYPE_UINT64] = FR_TYPE_UINT64,
273
274
    [FR_TYPE_SIZE]   = FR_TYPE_UINT64,
275
276
    [FR_TYPE_DATE]   = FR_TYPE_DATE,
277
278
    [FR_TYPE_INT8]   = FR_TYPE_INT64,
279
    [FR_TYPE_INT16]  = FR_TYPE_INT64,
280
    [FR_TYPE_INT32]  = FR_TYPE_INT64,
281
    [FR_TYPE_INT64]  = FR_TYPE_INT64,
282
283
    [FR_TYPE_TIME_DELTA]  = FR_TYPE_TIME_DELTA,
284
285
    [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT32,
286
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
287
  },
288
289
  [FR_TYPE_UINT64] = {
290
    [FR_TYPE_STRING] = FR_TYPE_UINT64,
291
    [FR_TYPE_OCTETS] = FR_TYPE_UINT64,
292
293
    [FR_TYPE_UINT64]  = FR_TYPE_UINT64,
294
    [FR_TYPE_INT64]  = FR_TYPE_INT64,
295
296
    [FR_TYPE_SIZE]  = FR_TYPE_UINT64,
297
298
    [FR_TYPE_DATE]  = FR_TYPE_DATE,
299
300
    [FR_TYPE_TIME_DELTA]  = FR_TYPE_TIME_DELTA,
301
302
    [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT32,
303
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
304
  },
305
306
  [FR_TYPE_SIZE] = {
307
    [FR_TYPE_STRING] = FR_TYPE_SIZE,
308
309
    [FR_TYPE_INT8]    = FR_TYPE_INT64,
310
    [FR_TYPE_INT16]   = FR_TYPE_INT64,
311
    [FR_TYPE_INT32]   = FR_TYPE_INT64,
312
    [FR_TYPE_INT64]   = FR_TYPE_INT64,
313
314
    [FR_TYPE_SIZE]   = FR_TYPE_INT64,
315
316
    [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT32,
317
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
318
  },
319
320
  [FR_TYPE_DATE] = {
321
    [FR_TYPE_STRING] = FR_TYPE_DATE,
322
323
    [FR_TYPE_INT8]  = FR_TYPE_DATE,
324
    [FR_TYPE_INT16] = FR_TYPE_DATE,
325
    [FR_TYPE_INT32] = FR_TYPE_DATE,
326
    [FR_TYPE_INT64] = FR_TYPE_DATE,
327
328
    [FR_TYPE_DATE] = FR_TYPE_DATE,
329
    [FR_TYPE_TIME_DELTA]  = FR_TYPE_DATE,
330
331
    [FR_TYPE_FLOAT32] = FR_TYPE_DATE,
332
    [FR_TYPE_FLOAT64] = FR_TYPE_DATE,
333
  },
334
335
  /*
336
   *  Signed ints
337
   */
338
  [FR_TYPE_INT8] = {
339
    [FR_TYPE_STRING] = FR_TYPE_INT8,
340
    [FR_TYPE_OCTETS] = FR_TYPE_INT8,
341
342
    [FR_TYPE_INT8] = FR_TYPE_INT64,
343
    [FR_TYPE_INT16] = FR_TYPE_INT64,
344
    [FR_TYPE_INT32] = FR_TYPE_INT64,
345
    [FR_TYPE_INT64] = FR_TYPE_INT64,
346
347
    [FR_TYPE_TIME_DELTA] = FR_TYPE_TIME_DELTA,
348
349
    [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT32,
350
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
351
  },
352
353
  [FR_TYPE_INT16] = {
354
    [FR_TYPE_STRING] = FR_TYPE_INT16,
355
    [FR_TYPE_OCTETS] = FR_TYPE_INT16,
356
357
    [FR_TYPE_INT16] = FR_TYPE_INT64,
358
    [FR_TYPE_INT32] = FR_TYPE_INT64,
359
    [FR_TYPE_INT64] = FR_TYPE_INT64,
360
361
    [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT32,
362
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
363
  },
364
365
  [FR_TYPE_INT32] = {
366
    [FR_TYPE_STRING] = FR_TYPE_INT32,
367
    [FR_TYPE_OCTETS] = FR_TYPE_INT32,
368
369
    [FR_TYPE_INT64] = FR_TYPE_INT64,
370
371
    [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT32,
372
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
373
  },
374
375
  [FR_TYPE_INT64] = {
376
    [FR_TYPE_STRING] = FR_TYPE_INT64,
377
    [FR_TYPE_OCTETS] = FR_TYPE_INT64,
378
379
    [FR_TYPE_INT64] = FR_TYPE_INT64,
380
381
    [FR_TYPE_TIME_DELTA] = FR_TYPE_TIME_DELTA,
382
    [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT32,
383
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
384
  },
385
386
  [FR_TYPE_TIME_DELTA] = {
387
    [FR_TYPE_STRING] = FR_TYPE_TIME_DELTA,
388
389
    [FR_TYPE_TIME_DELTA] = FR_TYPE_TIME_DELTA,
390
391
    [FR_TYPE_FLOAT32] = FR_TYPE_TIME_DELTA,
392
    [FR_TYPE_FLOAT64] = FR_TYPE_TIME_DELTA,
393
  },
394
395
  [FR_TYPE_FLOAT32] = {
396
    [FR_TYPE_STRING] = FR_TYPE_FLOAT32,
397
398
    [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT32,
399
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
400
  },
401
402
  [FR_TYPE_FLOAT64] = {
403
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
404
    [FR_TYPE_STRING] = 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] = {
428
    [FR_TYPE_OCTETS] = FR_TYPE_OCTETS,
429
  },
430
431
  [FR_TYPE_IPV4_ADDR] = {
432
    [FR_TYPE_STRING] = FR_TYPE_IPV4_ADDR,
433
    [FR_TYPE_OCTETS] = FR_TYPE_IPV4_ADDR,
434
435
    [FR_TYPE_IPV4_PREFIX] = FR_TYPE_IPV4_PREFIX,
436
437
    [FR_TYPE_IPV6_ADDR] = FR_TYPE_IPV6_ADDR,
438
    [FR_TYPE_IPV6_PREFIX] = FR_TYPE_IPV6_PREFIX,
439
440
    [FR_TYPE_COMBO_IP_ADDR] = FR_TYPE_COMBO_IP_ADDR,
441
    [FR_TYPE_COMBO_IP_PREFIX] = FR_TYPE_COMBO_IP_PREFIX,
442
443
    [FR_TYPE_UINT32] =  FR_TYPE_IPV4_ADDR,
444
  },
445
446
  [FR_TYPE_IPV4_PREFIX] = {
447
    [FR_TYPE_STRING] = FR_TYPE_IPV4_PREFIX,
448
    [FR_TYPE_OCTETS] = FR_TYPE_IPV4_PREFIX,
449
450
    [FR_TYPE_IPV6_PREFIX] = FR_TYPE_IPV6_PREFIX,
451
452
    [FR_TYPE_COMBO_IP_PREFIX] = FR_TYPE_COMBO_IP_PREFIX,
453
  },
454
455
  [FR_TYPE_IPV6_ADDR] = {
456
    [FR_TYPE_STRING] = FR_TYPE_IPV6_ADDR,
457
    [FR_TYPE_OCTETS] = FR_TYPE_IPV6_ADDR,
458
459
    [FR_TYPE_IPV6_PREFIX] = FR_TYPE_IPV6_PREFIX,
460
461
    [FR_TYPE_COMBO_IP_ADDR] = FR_TYPE_COMBO_IP_ADDR,
462
    [FR_TYPE_COMBO_IP_PREFIX] = FR_TYPE_COMBO_IP_PREFIX,
463
  },
464
465
  [FR_TYPE_IPV6_PREFIX] = {
466
    [FR_TYPE_STRING] = FR_TYPE_IPV6_PREFIX,
467
    [FR_TYPE_OCTETS] = FR_TYPE_IPV6_PREFIX,
468
469
    [FR_TYPE_COMBO_IP_PREFIX] = FR_TYPE_COMBO_IP_PREFIX,
470
  },
471
472
  [FR_TYPE_IFID] = {
473
    [FR_TYPE_STRING] = FR_TYPE_IFID,
474
    [FR_TYPE_OCTETS] = FR_TYPE_IFID,
475
  },
476
477
  [FR_TYPE_COMBO_IP_ADDR] = {
478
    [FR_TYPE_COMBO_IP_PREFIX] = FR_TYPE_COMBO_IP_PREFIX,
479
  },
480
481
  [FR_TYPE_ETHERNET] = {
482
    [FR_TYPE_STRING] = FR_TYPE_ETHERNET,
483
    [FR_TYPE_OCTETS] = 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] = {
491
    [FR_TYPE_STRING] = FR_TYPE_BOOL,
492
    [FR_TYPE_OCTETS] = FR_TYPE_BOOL,
493
494
    [FR_TYPE_UINT8] = FR_TYPE_UINT8,
495
    [FR_TYPE_UINT16] = FR_TYPE_UINT16,
496
    [FR_TYPE_UINT32] = FR_TYPE_UINT32,
497
    [FR_TYPE_UINT64] = FR_TYPE_UINT64,
498
499
    [FR_TYPE_SIZE] =   FR_TYPE_SIZE,
500
501
    [FR_TYPE_DATE]  = FR_TYPE_DATE,
502
503
    [FR_TYPE_INT8]   = FR_TYPE_INT16,
504
    [FR_TYPE_INT16]  = FR_TYPE_INT16,
505
    [FR_TYPE_INT32]  = FR_TYPE_INT32,
506
    [FR_TYPE_INT64]  = FR_TYPE_INT64,
507
508
    [FR_TYPE_TIME_DELTA] = FR_TYPE_TIME_DELTA,
509
510
    [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT32,
511
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
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] = {
521
    [FR_TYPE_STRING] = FR_TYPE_UINT8,
522
    [FR_TYPE_OCTETS] = FR_TYPE_UINT8,
523
524
    [FR_TYPE_UINT16] = FR_TYPE_UINT16,
525
    [FR_TYPE_UINT32] = FR_TYPE_UINT32,
526
    [FR_TYPE_UINT64] = FR_TYPE_UINT64,
527
528
    [FR_TYPE_SIZE] =   FR_TYPE_SIZE,
529
530
    [FR_TYPE_DATE]  = FR_TYPE_DATE,
531
532
    [FR_TYPE_INT8]   = FR_TYPE_INT16,
533
    [FR_TYPE_INT16]  = FR_TYPE_INT16,
534
    [FR_TYPE_INT32]  = FR_TYPE_INT32,
535
    [FR_TYPE_INT64]  = FR_TYPE_INT64,
536
537
    [FR_TYPE_TIME_DELTA] = FR_TYPE_TIME_DELTA,
538
539
    [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT32,
540
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
541
  },
542
543
  [FR_TYPE_UINT16] = {
544
    [FR_TYPE_STRING] = FR_TYPE_UINT16,
545
    [FR_TYPE_OCTETS] = FR_TYPE_UINT16,
546
547
    [FR_TYPE_UINT32] = FR_TYPE_UINT32,
548
    [FR_TYPE_UINT64] = FR_TYPE_UINT64,
549
550
    [FR_TYPE_SIZE] =   FR_TYPE_SIZE,
551
552
    [FR_TYPE_DATE]  = FR_TYPE_DATE,
553
554
    [FR_TYPE_INT8]   = FR_TYPE_INT32,
555
    [FR_TYPE_INT16]  = FR_TYPE_INT32,
556
    [FR_TYPE_INT32]  = FR_TYPE_INT32,
557
    [FR_TYPE_INT64]  = FR_TYPE_INT64,
558
559
    [FR_TYPE_TIME_DELTA]  = FR_TYPE_TIME_DELTA,
560
561
    [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT32,
562
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
563
  },
564
565
  [FR_TYPE_UINT32] = {
566
    [FR_TYPE_STRING] = FR_TYPE_UINT32,
567
    [FR_TYPE_OCTETS] = FR_TYPE_UINT32,
568
569
    [FR_TYPE_UINT64] = FR_TYPE_UINT64,
570
571
    [FR_TYPE_SIZE]   = FR_TYPE_SIZE,
572
573
    [FR_TYPE_DATE]   = FR_TYPE_DATE,
574
575
    [FR_TYPE_INT8]   = FR_TYPE_INT64,
576
    [FR_TYPE_INT16]  = FR_TYPE_INT64,
577
    [FR_TYPE_INT32]  = FR_TYPE_INT64,
578
    [FR_TYPE_INT64]  = FR_TYPE_INT64,
579
580
    [FR_TYPE_TIME_DELTA]  = FR_TYPE_TIME_DELTA,
581
582
    [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT32,
583
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
584
  },
585
586
  [FR_TYPE_UINT64] = {
587
    [FR_TYPE_STRING] = FR_TYPE_UINT64,
588
    [FR_TYPE_OCTETS] = FR_TYPE_UINT64,
589
590
    [FR_TYPE_SIZE]  = FR_TYPE_SIZE,
591
592
    [FR_TYPE_DATE]  = FR_TYPE_DATE,
593
594
    [FR_TYPE_TIME_DELTA]  = FR_TYPE_TIME_DELTA,
595
596
    [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT32,
597
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
598
  },
599
600
  [FR_TYPE_SIZE] = {
601
    [FR_TYPE_STRING] = FR_TYPE_SIZE,
602
603
    [FR_TYPE_INT8]    = FR_TYPE_INT64,
604
    [FR_TYPE_INT16]   = FR_TYPE_INT64,
605
    [FR_TYPE_INT32]   = FR_TYPE_INT64,
606
    [FR_TYPE_INT64]   = FR_TYPE_INT64,
607
608
    [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT32,
609
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
610
  },
611
612
  [FR_TYPE_DATE] = {
613
    [FR_TYPE_STRING] = FR_TYPE_DATE,
614
615
    [FR_TYPE_INT8]  = FR_TYPE_DATE,
616
    [FR_TYPE_INT16] = FR_TYPE_DATE,
617
    [FR_TYPE_INT32] = FR_TYPE_DATE,
618
    [FR_TYPE_INT64] = FR_TYPE_DATE,
619
620
    [FR_TYPE_TIME_DELTA]  = FR_TYPE_DATE,
621
622
    [FR_TYPE_FLOAT32] = FR_TYPE_DATE,
623
    [FR_TYPE_FLOAT64] = FR_TYPE_DATE,
624
  },
625
626
  /*
627
   *  Signed ints
628
   */
629
  [FR_TYPE_INT8] = {
630
    [FR_TYPE_STRING] = FR_TYPE_INT8,
631
    [FR_TYPE_OCTETS] = FR_TYPE_INT8,
632
633
    [FR_TYPE_INT16] = FR_TYPE_INT32,
634
    [FR_TYPE_INT32] = FR_TYPE_INT32,
635
    [FR_TYPE_INT64] = FR_TYPE_INT64,
636
637
    [FR_TYPE_TIME_DELTA] = FR_TYPE_TIME_DELTA,
638
639
    [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT32,
640
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
641
  },
642
643
  [FR_TYPE_INT16] = {
644
    [FR_TYPE_STRING] = FR_TYPE_INT16,
645
    [FR_TYPE_OCTETS] = FR_TYPE_INT16,
646
647
    [FR_TYPE_INT32] = FR_TYPE_INT64,
648
    [FR_TYPE_INT64] = FR_TYPE_INT64,
649
650
    [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT32,
651
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
652
  },
653
654
  [FR_TYPE_INT32] = {
655
    [FR_TYPE_STRING] = FR_TYPE_INT32,
656
    [FR_TYPE_OCTETS] = FR_TYPE_INT32,
657
658
    [FR_TYPE_INT64] = FR_TYPE_INT64,
659
660
    [FR_TYPE_FLOAT32] = FR_TYPE_FLOAT32,
661
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
662
  },
663
664
  [FR_TYPE_INT64] = {
665
    [FR_TYPE_STRING] = FR_TYPE_INT64,
666
    [FR_TYPE_OCTETS] = FR_TYPE_INT64,
667
668
    [FR_TYPE_TIME_DELTA] = FR_TYPE_TIME_DELTA,
669
  },
670
671
  [FR_TYPE_TIME_DELTA] = {
672
    [FR_TYPE_STRING] = FR_TYPE_TIME_DELTA,
673
674
    [FR_TYPE_FLOAT32] = FR_TYPE_TIME_DELTA,
675
    [FR_TYPE_FLOAT64] = FR_TYPE_TIME_DELTA,
676
  },
677
678
  [FR_TYPE_FLOAT32] = {
679
    [FR_TYPE_STRING] = FR_TYPE_FLOAT32,
680
681
    [FR_TYPE_FLOAT64] = FR_TYPE_FLOAT64,
682
  },
683
684
  [FR_TYPE_FLOAT64] = {
685
    [FR_TYPE_STRING] = FR_TYPE_FLOAT64,
686
  },
687
};
688
689
static const fr_type_t upcast_unsigned[FR_TYPE_MAX + 1] = {
690
  [FR_TYPE_BOOL] = FR_TYPE_INT8,
691
  [FR_TYPE_UINT8] = FR_TYPE_INT16,
692
  [FR_TYPE_UINT16] = FR_TYPE_INT32,
693
  [FR_TYPE_UINT32] = FR_TYPE_INT64,
694
  [FR_TYPE_UINT64] = FR_TYPE_INT64,
695
  [FR_TYPE_SIZE] = FR_TYPE_INT64,
696
};
697
698
static int invalid_type(fr_type_t type)
699
0
{
700
0
  fr_strerror_printf("Cannot perform mathematical operations on data type %s",
701
0
         fr_type_to_str(type));
702
0
  return -1;
703
0
}
704
705
static int handle_result(fr_type_t type, fr_token_t op, int rcode)
706
0
{
707
0
  if (rcode == ERR_ZERO) {
708
0
    fr_strerror_const("Cannot divide by zero.");
709
710
0
  } else if (rcode == ERR_UNDERFLOW) {
711
0
    fr_strerror_printf("Value underflows '%s' when calculating result.",
712
0
           fr_type_to_str(type));
713
714
0
  } else if (rcode == ERR_OVERFLOW) {
715
0
    fr_strerror_printf("Value overflows '%s' when calculating result.",
716
0
           fr_type_to_str(type));
717
718
0
  } else if (rcode == ERR_INVALID) {
719
0
    fr_strerror_printf("Invalid assignment operator '%s' for result type '%s'.",
720
0
           fr_tokens[op],
721
0
           fr_type_to_str(type));
722
0
  }
723
724
0
  return rcode;
725
0
}
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
0
{
729
0
  fr_value_box_t one, two;
730
731
0
  fr_assert(dst->type == FR_TYPE_BOOL);
732
733
0
  COERCE_A(FR_TYPE_BOOL, NULL);
734
0
  COERCE_B(FR_TYPE_BOOL, NULL);
735
736
0
  switch (op) {
737
0
  case T_ADD:
738
    /*
739
     *  1+1 = 2, which isn't a valid boolean value.
740
     */
741
0
    if (a->vb_bool & b->vb_bool) return ERR_OVERFLOW;
742
743
0
    dst->vb_bool = a->vb_bool | b->vb_bool;
744
0
    break;
745
746
0
  case T_SUB:
747
    /*
748
     *  0-1 = -1, which isn't a valid boolean value.
749
     */
750
0
    if (a->vb_bool < b->vb_bool) return ERR_UNDERFLOW;
751
752
0
    dst->vb_bool = a->vb_bool - b->vb_bool;
753
0
    break;
754
755
0
  case T_MUL:   /* MUL is just AND here! */
756
0
  case T_AND:
757
0
    dst->vb_bool = a->vb_bool & b->vb_bool;
758
0
    break;
759
760
0
  case T_OR:
761
0
    dst->vb_bool = a->vb_bool | b->vb_bool;
762
0
    break;
763
764
0
  case T_XOR:
765
0
    dst->vb_bool = a->vb_bool ^ b->vb_bool;
766
0
    break;
767
768
0
  default:
769
0
    return ERR_INVALID;
770
0
  }
771
772
0
  return 0;
773
0
}
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
0
{
777
0
  fr_value_box_t one, two;
778
0
  bool overflow;
779
0
  int64_t when;
780
781
0
  fr_assert(dst->type == FR_TYPE_DATE);
782
783
0
  if ((a->type == FR_TYPE_DATE) && (b->type == FR_TYPE_DATE)) {
784
0
    fr_strerror_const("Cannot perform operation on two values of type 'date'.  One value must be a number.");
785
0
    return -1;
786
0
  }
787
788
0
  fr_assert(!dst->enumv);  /* unix time is always seconds */
789
790
  /*
791
   *  Cast dates to time delta, do the conversions.
792
   */
793
0
  COERCE_A(FR_TYPE_TIME_DELTA, NULL);
794
0
  COERCE_B(FR_TYPE_TIME_DELTA, NULL);
795
796
0
  switch (op) {
797
0
  case T_ADD:
798
0
    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
0
    dst->vb_date = fr_unix_time_from_integer(&overflow, when, FR_TIME_RES_NSEC);
801
0
    if (overflow) return ERR_OVERFLOW;
802
0
    break;
803
804
0
  case T_SUB:
805
0
    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
0
    dst->vb_date = fr_unix_time_from_integer(&overflow, when, FR_TIME_RES_NSEC);
808
0
    if (overflow) return ERR_UNDERFLOW;
809
0
    break;
810
811
0
  default:
812
0
    return ERR_INVALID; /* invalid operator */
813
0
  }
814
815
0
  return 0;
816
0
}
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
0
{
820
0
  fr_value_box_t one, two;
821
0
  int64_t when;
822
823
0
  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
0
  if ((a->type == FR_TYPE_DATE) && (b->type == FR_TYPE_DATE)) {
830
0
    if (op != T_SUB) {
831
0
      fr_strerror_const("Cannot perform operation on two values of type 'date'.");
832
0
      return -1;
833
0
    }
834
0
  }
835
836
  /*
837
   *  date % (time_delta) 1d --> time_delta
838
   */
839
0
  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
0
    if ((b->type != FR_TYPE_TIME_DELTA) || !fr_time_delta_ispos(b->vb_time_delta)) {
845
0
      return ERR_INVALID;
846
0
    }
847
848
0
    dst->vb_time_delta = fr_time_delta_wrap(fr_unix_time_unwrap(a->vb_date) % fr_time_delta_unwrap(b->vb_time_delta));
849
0
    return 0;
850
0
  }
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
0
  COERCE_A(FR_TYPE_TIME_DELTA, dst->enumv);
859
860
0
  if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
861
    /*
862
     *  Don't touch the RHS.
863
     */
864
0
    fr_assert(b->type == FR_TYPE_UINT32);
865
866
0
  } else {
867
0
    COERCE_B(FR_TYPE_TIME_DELTA, dst->enumv);
868
0
  }
869
870
0
  switch (op) {
871
0
  case T_ADD:
872
0
    if (!fr_add(&when, fr_time_delta_unwrap(a->vb_time_delta), fr_time_delta_unwrap(b->vb_time_delta))) return ERR_OVERFLOW;
873
0
    dst->vb_time_delta = fr_time_delta_wrap(when);
874
0
    break;
875
876
0
  case T_SUB:
877
0
    if (!fr_sub(&when, fr_time_delta_unwrap(a->vb_time_delta), fr_time_delta_unwrap(b->vb_time_delta))) return ERR_UNDERFLOW;
878
0
    dst->vb_time_delta = fr_time_delta_wrap(when);
879
0
    break;
880
881
0
  case T_RSHIFT:
882
0
    if (b->vb_uint32 >= 64) return ERR_UNDERFLOW;
883
884
0
    when = fr_time_delta_unwrap(a->vb_time_delta) >> b->vb_uint32;
885
0
    dst->vb_time_delta = fr_time_delta_wrap(when);
886
0
    break;
887
888
0
  case T_LSHIFT:
889
0
    if (b->vb_uint32 >= 64) return ERR_OVERFLOW;
890
891
0
    when = fr_time_delta_unwrap(a->vb_time_delta) << b->vb_uint32;
892
0
    dst->vb_time_delta = fr_time_delta_wrap(when);
893
0
    break;
894
895
0
  default:
896
0
    return ERR_INVALID; /* invalid operator */
897
0
  }
898
899
0
  return 0;
900
901
0
}
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
0
{
905
0
  uint8_t *buf;
906
0
  size_t len;
907
0
  fr_value_box_t one = {};
908
0
  fr_value_box_t two = {};
909
910
0
  fr_assert(dst->type == FR_TYPE_OCTETS);
911
912
0
  COERCE_A(FR_TYPE_OCTETS, dst->enumv);
913
914
0
  if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
915
    /*
916
     *  Don't touch the RHS.
917
     */
918
0
    fr_assert(b->type == FR_TYPE_UINT32);
919
920
0
  } else {
921
0
    COERCE_B(FR_TYPE_OCTETS, dst->enumv);
922
0
  }
923
924
0
  len = a->vb_length + b->vb_length;
925
926
0
  switch (op) {
927
0
  case T_ADD: /* dst = a . b */
928
0
    buf = talloc_array(ctx, uint8_t, len);
929
0
    if (!buf) {
930
0
    oom:
931
0
      fr_strerror_const("Out of memory");
932
0
      return -1;
933
0
    }
934
935
0
    memcpy(buf, a->vb_octets, a->vb_length);
936
0
    memcpy(buf + a->vb_length, b->vb_octets, b->vb_length);
937
938
0
    fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, false);
939
0
    fr_value_box_safety_copy(dst, a);
940
0
    fr_value_box_safety_merge(dst, b);
941
0
    break;
942
943
0
  case T_SUB:
944
    /*
945
     *  The inverse of add!
946
     */
947
0
    if (a->vb_length < b->vb_length) {
948
0
      fr_strerror_const("Suffix to remove is longer than input string.");
949
0
      return -1;
950
0
    }
951
952
0
    if (memcmp(a->vb_octets + a->vb_length - b->vb_length, b->vb_strvalue, b->vb_length) != 0) {
953
0
      fr_strerror_const("Suffix to remove is not a suffix of the input string.");
954
0
      return -1;
955
0
    }
956
957
0
    len = a->vb_length - b->vb_length;
958
0
    buf = talloc_array(ctx, uint8_t, len);
959
0
    if (!buf) goto oom;
960
961
0
    memcpy(buf, a->vb_strvalue, len);
962
963
0
    fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, false);
964
0
    fr_value_box_safety_copy(dst, a);
965
0
    break;
966
967
0
  case T_AND:
968
0
    if (a->vb_length != b->vb_length) {
969
0
    length_error:
970
0
      fr_strerror_const("Cannot perform operation on strings of different length");
971
0
      return -1;
972
0
    }
973
974
0
    buf = talloc_array(ctx, uint8_t, a->vb_length);
975
0
    if (!buf) goto oom;
976
977
0
    for (len = 0; len < a->vb_length; len++) {
978
0
      buf[len] = a->vb_octets[len] & b->vb_octets[len];
979
0
    }
980
981
0
  set_result:
982
0
    fr_value_box_memdup_shallow(dst, dst->enumv, buf, a->vb_length, false);
983
0
    fr_value_box_safety_copy(dst, a);
984
0
    fr_value_box_safety_merge(dst, b);
985
0
    break;
986
987
0
  case T_OR:
988
0
    if (a->vb_length != b->vb_length) goto length_error;
989
990
0
    buf = talloc_array(ctx, uint8_t, a->vb_length);
991
0
    if (!buf) goto oom;
992
993
0
    for (len = 0; len < a->vb_length; len++) {
994
0
      buf[len] = a->vb_octets[len] | b->vb_octets[len];
995
0
    }
996
0
    goto set_result;
997
998
0
  case T_XOR:
999
0
    if (a->vb_length != b->vb_length) goto length_error;
1000
1001
0
    buf = talloc_array(ctx, uint8_t, a->vb_length);
1002
0
    if (!buf) goto oom;
1003
1004
0
    for (len = 0; len < a->vb_length; len++) {
1005
0
      buf[len] = a->vb_octets[len] ^ b->vb_octets[len];
1006
0
    }
1007
1008
0
    goto set_result;
1009
1010
0
  case T_RSHIFT:
1011
0
    if (b->vb_uint32 > a->vb_length) return ERR_UNDERFLOW;
1012
1013
0
    len = a->vb_length - b->vb_uint32;
1014
0
    buf = talloc_array(ctx, uint8_t, len);
1015
0
    if (!buf) goto oom;
1016
1017
0
    memcpy(buf, a->vb_octets, len);
1018
1019
0
    fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, false);
1020
0
    fr_value_box_safety_copy(dst, a);
1021
0
    break;
1022
1023
0
  case T_LSHIFT:
1024
0
    if (b->vb_uint32 > a->vb_length) return ERR_OVERFLOW;
1025
1026
0
    len = a->vb_length - b->vb_uint32;
1027
1028
0
    buf = talloc_array(ctx, uint8_t, len);
1029
0
    if (!buf) goto oom;
1030
1031
0
    memcpy(buf, a->vb_octets + b->vb_uint32, len);
1032
1033
0
    fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, false);
1034
0
    fr_value_box_safety_copy(dst, a);
1035
0
    break;
1036
1037
0
  default:
1038
0
    return ERR_INVALID; /* invalid operator */
1039
0
  }
1040
1041
0
  if (a == &one) fr_value_box_clear_value(&one);
1042
0
  if (b == &two) fr_value_box_clear_value(&two);
1043
1044
0
  return 0;
1045
0
}
1046
1047
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)
1048
0
{
1049
0
  char *buf;
1050
0
  size_t len;
1051
0
  fr_value_box_t one = {};
1052
0
  fr_value_box_t two = {};
1053
1054
0
  fr_assert(dst->type == FR_TYPE_STRING);
1055
1056
0
  COERCE_A(FR_TYPE_STRING, dst->enumv);
1057
1058
0
  if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
1059
    /*
1060
     *  Don't touch the RHS.
1061
     */
1062
0
    fr_assert(b->type == FR_TYPE_UINT32);
1063
1064
0
  } else {
1065
0
    COERCE_B(FR_TYPE_STRING, dst->enumv);
1066
0
  }
1067
1068
0
  len = a->vb_length + b->vb_length;
1069
1070
0
  switch (op) {
1071
0
  case T_ADD:
1072
0
    buf = talloc_array(ctx, char, len + 1);
1073
0
    if (!buf) {
1074
0
    oom:
1075
0
      fr_strerror_const("Out of memory");
1076
0
      return -1;
1077
0
    }
1078
1079
0
    len = a->vb_length + b->vb_length;
1080
0
    memcpy(buf, a->vb_strvalue, a->vb_length);
1081
0
    memcpy(buf + a->vb_length, b->vb_strvalue, b->vb_length);
1082
0
    buf[len] = '\0';
1083
1084
0
    fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1085
0
    fr_value_box_safety_copy(dst, a);
1086
0
    fr_value_box_safety_merge(dst, b);
1087
0
    break;
1088
1089
0
  case T_XOR:   /* is prepend for strings */
1090
0
    buf = talloc_array(ctx, char, len + 1);
1091
0
    if (!buf) goto oom;
1092
1093
0
    len = a->vb_length + b->vb_length;
1094
0
    memcpy(buf, b->vb_strvalue, b->vb_length);
1095
0
    memcpy(buf + b->vb_length, a->vb_strvalue, a->vb_length);
1096
0
    buf[len] = '\0';
1097
1098
0
    fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1099
0
    fr_value_box_safety_copy(dst, a);
1100
0
    fr_value_box_safety_merge(dst, b);
1101
0
    break;
1102
1103
0
  case T_SUB:
1104
    /*
1105
     *  The inverse of add!
1106
     */
1107
0
    if (a->vb_length < b->vb_length) {
1108
0
      fr_strerror_const("Suffix to remove is longer than input string");
1109
0
      return -1;
1110
0
    }
1111
1112
0
    if (memcmp(a->vb_strvalue + a->vb_length - b->vb_length, b->vb_strvalue, b->vb_length) != 0) {
1113
0
      fr_strerror_const("Right side of substract is not a suffix of the input string");
1114
0
      return -1;
1115
0
    }
1116
1117
0
    len = a->vb_length - b->vb_length;
1118
0
    buf = talloc_array(ctx, char, len + 1);
1119
0
    if (!buf) goto oom;
1120
1121
0
    memcpy(buf, a->vb_strvalue, len);
1122
0
    buf[len] = '\0';
1123
1124
0
    fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1125
0
    fr_value_box_safety_copy(dst, a);
1126
0
    break;
1127
1128
0
  case T_RSHIFT:
1129
0
    if (b->vb_uint32 > a->vb_length) return ERR_UNDERFLOW;
1130
1131
0
    len = a->vb_length - b->vb_uint32;
1132
0
    buf = talloc_array(ctx, char, len + 1);
1133
0
    if (!buf) goto oom;
1134
1135
0
    memcpy(buf, a->vb_strvalue, len);
1136
0
    buf[len] = '\0';
1137
1138
0
    fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1139
0
    fr_value_box_safety_copy(dst, a);
1140
0
    break;
1141
1142
0
  case T_LSHIFT:
1143
0
    if (b->vb_uint32 > a->vb_length) return ERR_OVERFLOW;
1144
1145
0
    len = a->vb_length - b->vb_uint32;
1146
1147
0
    buf = talloc_array(ctx, char, len + 1);
1148
0
    if (!buf) goto oom;
1149
1150
0
    memcpy(buf, a->vb_strvalue + b->vb_uint32, len);
1151
0
    buf[len] = '\0';
1152
1153
0
    fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, false);
1154
0
    fr_value_box_safety_copy(dst, a);
1155
0
    break;
1156
1157
0
  default:
1158
0
    return ERR_INVALID; /* invalid operator */
1159
0
  }
1160
1161
0
  if (a == &one) fr_value_box_clear_value(&one);
1162
0
  if (b == &two) fr_value_box_clear_value(&two);
1163
1164
0
  return 0;
1165
0
}
1166
1167
static int cast_ipv4_addr(fr_value_box_t *out, fr_value_box_t const *in)
1168
0
{
1169
0
  switch (in->type) {
1170
0
  default:
1171
0
    fr_strerror_printf("Cannot operate on ipaddr and %s",
1172
0
           fr_type_to_str(in->type));
1173
0
    return -1;
1174
1175
0
  case FR_TYPE_COMBO_IP_ADDR:
1176
0
    if (in->vb_ip.af == AF_INET6) goto cast_ipv6_addr;
1177
1178
0
    fr_value_box_init(out, FR_TYPE_IPV4_ADDR, NULL, in->tainted);
1179
0
    out->vb_ip = in->vb_ip;
1180
0
    break;
1181
1182
0
  case FR_TYPE_COMBO_IP_PREFIX:
1183
0
    if (in->vb_ip.af == AF_INET6) goto cast_ipv6_prefix;
1184
1185
0
    fr_value_box_init(out, FR_TYPE_IPV4_PREFIX, NULL, in->tainted);
1186
0
    out->vb_ip = in->vb_ip;
1187
0
    break;
1188
1189
0
  case FR_TYPE_IPV4_PREFIX:
1190
0
  case FR_TYPE_IPV4_ADDR:
1191
0
    if (unlikely(fr_value_box_copy(NULL, out, in) < 0)) return -1;
1192
0
    break;
1193
1194
0
  case FR_TYPE_IPV6_ADDR:
1195
0
  cast_ipv6_addr:
1196
0
    if (fr_value_box_cast(NULL, out, FR_TYPE_IPV4_ADDR, NULL, in) < 0) return -1;
1197
0
    break;
1198
1199
0
  case FR_TYPE_IPV6_PREFIX:
1200
0
  cast_ipv6_prefix:
1201
0
    if (fr_value_box_cast(NULL, out, FR_TYPE_IPV4_PREFIX, NULL, in) < 0) return -1;
1202
0
    break;
1203
1204
    /*
1205
     *  All of these get mashed to 32-bits.  The cast
1206
     *  operation will check bounds (both negative and
1207
     *  positive) on the run-time values.
1208
     */
1209
0
  case FR_TYPE_BOOL:
1210
1211
0
  case FR_TYPE_UINT8:
1212
0
  case FR_TYPE_UINT16:
1213
0
  case FR_TYPE_UINT32:
1214
0
  case FR_TYPE_UINT64:
1215
1216
0
  case FR_TYPE_SIZE:
1217
1218
0
  case FR_TYPE_INT8:
1219
0
  case FR_TYPE_INT16:
1220
0
  case FR_TYPE_INT32:
1221
0
  case FR_TYPE_INT64:
1222
1223
0
  case FR_TYPE_FLOAT32:
1224
0
  case FR_TYPE_FLOAT64:
1225
0
    if (fr_value_box_cast(NULL, out, FR_TYPE_UINT32, NULL, in) < 0) return -1;
1226
0
    break;
1227
0
  }
1228
1229
0
  return 0;
1230
0
}
1231
1232
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)
1233
0
{
1234
0
  fr_value_box_t one, two;
1235
0
  fr_value_box_t *a, *b;
1236
1237
0
  fr_assert((dst->type == FR_TYPE_IPV4_ADDR) || (dst->type == FR_TYPE_COMBO_IP_ADDR));
1238
1239
0
  if (cast_ipv4_addr(&one, in1) < 0) return -1;
1240
0
  a = &one;
1241
1242
0
  if (cast_ipv4_addr(&two, in2) < 0) return -1;
1243
0
  b = &two;
1244
1245
0
  switch (op) {
1246
0
  case T_ADD:
1247
0
  case T_OR:
1248
    /*
1249
     *  For simplicity, make sure that the prefix is first.
1250
     */
1251
0
    if (b->type == FR_TYPE_IPV4_PREFIX) swap(a,b);
1252
1253
    /*
1254
     *  We can only add something to a prefix, and
1255
     *  that something has to be a number. The cast
1256
     *  operation already ensured that the number is
1257
     *  uint32, and is at least vaguely within the
1258
     *  allowed range.
1259
     */
1260
0
    if (a->type != FR_TYPE_IPV4_PREFIX) return ERR_INVALID;
1261
1262
0
    if (b->type != FR_TYPE_UINT32) return ERR_INVALID;
1263
1264
    /*
1265
     *  Trying to add a number outside of the given prefix.  That's not allowed.
1266
     */
1267
0
    if (b->vb_uint32 >= (((uint32_t) 1) << (32 - a->vb_ip.prefix))) return ERR_OVERFLOW;
1268
1269
0
    dst->vb_ip.af = AF_INET;
1270
0
    dst->vb_ip.addr.v4.s_addr = htonl(ntohl(a->vb_ip.addr.v4.s_addr) | b->vb_uint32);
1271
0
    dst->vb_ip.prefix = 32;
1272
0
    fr_value_box_safety_copy(dst, a);
1273
0
    fr_value_box_safety_merge(dst, b);
1274
0
    break;
1275
1276
0
  default:
1277
0
    return ERR_INVALID;
1278
0
  }
1279
1280
0
  return 0;
1281
0
}
1282
1283
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)
1284
0
{
1285
0
  int prefix;
1286
0
  fr_value_box_t one, two, tmp;
1287
1288
0
  fr_assert((dst->type == FR_TYPE_IPV4_PREFIX) || (dst->type == FR_TYPE_COMBO_IP_PREFIX));
1289
1290
0
  switch (op) {
1291
0
  case T_AND:
1292
0
    if (fr_type_is_integer(a->type)) {
1293
0
      if (fr_value_box_cast(NULL, &one, FR_TYPE_UINT32, NULL, a) < 0) return -1;
1294
1295
0
      a = &one;
1296
0
      swap(a, b);
1297
1298
0
    } else if (fr_type_is_integer(b->type)) {
1299
0
      if (fr_value_box_cast(NULL, &two, FR_TYPE_UINT32, NULL, b) < 0) return -1;
1300
0
      b = &two;
1301
1302
0
    } else {
1303
0
      fr_strerror_const("Invalid input types for ipv4prefix");
1304
0
      return -1;
1305
0
    }
1306
1307
0
    switch (a->type) {
1308
0
    case FR_TYPE_IPV6_ADDR:
1309
0
      if (fr_value_box_cast(NULL, &tmp, FR_TYPE_IPV4_ADDR, NULL, a) < 0) return -1;
1310
0
      a = &tmp;
1311
0
      break;
1312
1313
0
    case FR_TYPE_IPV4_ADDR:
1314
0
      fr_value_box_safety_copy(dst, a);
1315
0
      break;
1316
1317
0
    default:
1318
0
      fr_strerror_printf("Invalid input data type '%s' for logical 'and'",
1319
0
             fr_type_to_str(a->type));
1320
1321
0
      return -1;
1322
0
    }
1323
1324
0
    if (b->vb_uint32 == 0) { /* set everything to zero */
1325
0
      dst->vb_ip.addr.v4.s_addr = 0;
1326
0
      prefix = 0;
1327
1328
0
    } else if ((~b->vb_uint32) == 0) { /* all 1's */
1329
0
      dst->vb_ip.addr.v4.s_addr = a->vb_ip.addr.v4.s_addr;
1330
0
      prefix = 32;
1331
1332
0
    } else {
1333
0
      uint32_t mask;
1334
1335
0
      mask = ~b->vb_uint32; /* 0xff00 -> 0x00ff */
1336
0
      mask++;     /* 0x00ff -> 0x0100 */
1337
0
      if ((mask & b->vb_uint32) != mask) {
1338
0
        fr_strerror_printf("Invalid network mask '0x%08x'", b->vb_uint32);
1339
0
        return -1;
1340
0
      }
1341
1342
0
      mask = 0xfffffffe;
1343
0
      prefix = 31;
1344
1345
0
      while (prefix > 0) {
1346
0
        if (mask == b->vb_uint32) break;
1347
1348
0
        prefix--;
1349
        /* coverity[overflow_const] */
1350
0
        mask <<= 1;
1351
0
      }
1352
0
      fr_assert(prefix > 0);
1353
1354
0
      dst->vb_ip.addr.v4.s_addr = htonl(ntohl(a->vb_ip.addr.v4.s_addr) & b->vb_uint32);
1355
0
    }
1356
1357
0
    dst->vb_ip.af = AF_INET;
1358
0
    dst->vb_ip.prefix = prefix;
1359
0
    break;
1360
1361
0
  default:
1362
0
    return ERR_INVALID;
1363
0
  }
1364
1365
0
  return 0;
1366
0
}
1367
1368
static int cast_ipv6_addr(fr_value_box_t *out, fr_value_box_t const *in)
1369
0
{
1370
0
  switch (in->type) {
1371
0
  default:
1372
0
    fr_strerror_printf("Cannot operate on ipv6addr and %s",
1373
0
           fr_type_to_str(in->type));
1374
0
    return -1;
1375
1376
0
  case FR_TYPE_COMBO_IP_ADDR:
1377
0
    if (in->vb_ip.af == AF_INET) goto cast_ipv4_addr;
1378
1379
0
    fr_value_box_init(out, FR_TYPE_IPV4_ADDR, NULL, in->tainted);
1380
0
    out->vb_ip = in->vb_ip;
1381
0
    break;
1382
1383
0
  case FR_TYPE_COMBO_IP_PREFIX:
1384
0
    if (in->vb_ip.af == AF_INET) goto cast_ipv4_prefix;
1385
1386
0
    fr_value_box_init(out, FR_TYPE_IPV4_PREFIX, NULL, in->tainted);
1387
0
    out->vb_ip = in->vb_ip;
1388
0
    break;
1389
1390
1391
0
  case FR_TYPE_IPV6_PREFIX:
1392
0
  case FR_TYPE_IPV6_ADDR:
1393
0
    if (unlikely(fr_value_box_copy(NULL, out, in) < 0)) return -1;
1394
0
    break;
1395
1396
0
  case FR_TYPE_IPV4_ADDR:
1397
0
  cast_ipv4_addr:
1398
0
    if (fr_value_box_cast(NULL, out, FR_TYPE_IPV6_ADDR, NULL, in) < 0) return -1;
1399
0
    break;
1400
1401
0
  case FR_TYPE_IPV4_PREFIX:
1402
0
  cast_ipv4_prefix:
1403
0
    if (fr_value_box_cast(NULL, out, FR_TYPE_IPV6_PREFIX, NULL, in) < 0) return -1;
1404
0
    break;
1405
1406
    /*
1407
     *  All of these get mashed to 64-bits.  The cast
1408
     *  operation will check bounds (both negative and
1409
     *  positive) on the run-time values.
1410
     */
1411
0
  case FR_TYPE_BOOL:
1412
1413
0
  case FR_TYPE_UINT8:
1414
0
  case FR_TYPE_UINT16:
1415
0
  case FR_TYPE_UINT32:
1416
0
  case FR_TYPE_UINT64:
1417
1418
0
  case FR_TYPE_SIZE:
1419
1420
0
  case FR_TYPE_INT8:
1421
0
  case FR_TYPE_INT16:
1422
0
  case FR_TYPE_INT32:
1423
0
  case FR_TYPE_INT64:
1424
1425
0
  case FR_TYPE_FLOAT32:
1426
0
  case FR_TYPE_FLOAT64:
1427
0
    if (fr_value_box_cast(NULL, out, FR_TYPE_UINT64, NULL, in) < 0) return -1;
1428
0
    break;
1429
0
  }
1430
1431
0
  return 0;
1432
0
}
1433
1434
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)
1435
0
{
1436
0
  fr_value_box_t one, two;
1437
0
  fr_value_box_t *a, *b;
1438
0
  int i;
1439
0
  uint64_t mask;
1440
1441
0
  fr_assert((dst->type == FR_TYPE_IPV6_ADDR) || (dst->type == FR_TYPE_COMBO_IP_ADDR));
1442
1443
0
  if (cast_ipv6_addr(&one, in1) < 0) return -1;
1444
0
  a = &one;
1445
1446
0
  if (cast_ipv6_addr(&two, in2) < 0) return -1;
1447
0
  b = &two;
1448
1449
0
  switch (op) {
1450
0
  case T_ADD:
1451
    /*
1452
     *  For simplicity, make sure that the prefix is first.
1453
     */
1454
0
    if (b->type == FR_TYPE_IPV6_PREFIX) swap(a, b);
1455
1456
    /*
1457
     *  We can only add something to a prefix, and
1458
     *  that something has to be a number. The cast
1459
     *  operation already ensured that the number is
1460
     *  uint32, and is at least vaguely within the
1461
     *  allowed range.
1462
     */
1463
0
    if (a->type != FR_TYPE_IPV6_PREFIX) return ERR_INVALID;
1464
1465
0
    if (b->type != FR_TYPE_UINT64) return ERR_INVALID;
1466
1467
    /*
1468
     *  If we're adding a UINT64, the prefix can't be shorter than 64.
1469
     */
1470
0
    if (a->vb_ip.prefix <= 64) return ERR_OVERFLOW;
1471
1472
    /*
1473
     *  Trying to add a number outside of the given prefix.  That's not allowed.
1474
     */
1475
0
    if (b->vb_uint64 >= (((uint64_t) 1) << (128 - a->vb_ip.prefix))) return ERR_OVERFLOW;
1476
1477
    /*
1478
     *  Add in the relevant low bits.
1479
     */
1480
0
    mask = b->vb_uint64;
1481
0
    for (i = 15; i >= ((a->vb_ip.prefix + 7) >> 3); i--) {
1482
0
      dst->vb_ip.addr.v6.s6_addr[i] |= mask & 0xff;
1483
0
      mask >>= 8;
1484
0
    }
1485
1486
0
    dst->vb_ip.af = AF_INET6;
1487
0
    dst->vb_ip.prefix = 0;
1488
0
    dst->vb_ip.scope_id = a->vb_ip.scope_id;
1489
0
    fr_value_box_safety_copy(dst, a);
1490
0
    break;
1491
1492
0
  default:
1493
0
    return ERR_INVALID;
1494
0
  }
1495
1496
0
  return 0;
1497
0
}
1498
1499
static int get_ipv6_prefix(uint8_t const *in)
1500
0
{
1501
0
  int i, j, prefix;
1502
1503
0
  prefix = 128;
1504
0
  for (i = 15; i >= 0; i--) {
1505
0
    if (!in[i]) {
1506
0
      prefix -= 8;
1507
0
      continue;
1508
0
    }
1509
1510
0
    for (j = 0; j < 8; j++) {
1511
0
      if ((in[i] & (1 << j)) == 0) {
1512
0
        prefix--;
1513
0
        continue;
1514
0
      }
1515
0
      return prefix;
1516
0
    }
1517
0
  }
1518
1519
0
  return prefix;
1520
0
}
1521
1522
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)
1523
0
{
1524
0
  int i, prefix = 128;
1525
0
  uint8_t const *pa, *pb;
1526
0
  uint8_t *pdst;
1527
1528
0
  fr_assert((dst->type == FR_TYPE_IPV6_PREFIX) || (dst->type == FR_TYPE_COMBO_IP_PREFIX));
1529
1530
0
  if (a->type == FR_TYPE_OCTETS) {
1531
0
    if (a->vb_length != (128 / 8)) {
1532
0
      fr_strerror_printf("Invalid length %zu for octets network mask", a->vb_length);
1533
0
      return -1;
1534
0
    }
1535
0
    pa = a->vb_octets;
1536
0
    prefix = get_ipv6_prefix(pa);
1537
1538
0
  } else if (a->type == FR_TYPE_IPV6_ADDR) {
1539
0
    pa = (const uint8_t *) &a->vb_ip.addr.v6.s6_addr;
1540
1541
0
  } else {
1542
0
    return ERR_INVALID;
1543
0
  }
1544
1545
0
  if (b->type == FR_TYPE_OCTETS) {
1546
0
    if (b->vb_length != (128 / 8)) {
1547
0
      fr_strerror_printf("Invalid length %zu for octets network mask", b->vb_length);
1548
0
      return -1;
1549
0
    }
1550
0
    pb = b->vb_octets;
1551
0
    prefix = get_ipv6_prefix(pb);
1552
1553
0
  } else if (a->type == FR_TYPE_IPV6_ADDR) {
1554
0
    pb = (const uint8_t *) &b->vb_ip.addr.v6;
1555
1556
0
  } else {
1557
0
    return ERR_INVALID;
1558
0
  }
1559
1560
0
  switch (op) {
1561
0
  case T_AND:
1562
0
    fr_value_box_init(dst, FR_TYPE_IPV6_PREFIX, NULL, false);
1563
0
    pdst = (uint8_t *) &dst->vb_ip.addr.v6;
1564
1565
0
    for (i = 0; i < 16; i++) {
1566
0
      pdst[i] = pa[i] & pb[i];
1567
0
    }
1568
1569
0
    dst->vb_ip.af = AF_INET6;
1570
0
    dst->vb_ip.prefix = prefix;
1571
0
    fr_value_box_safety_copy(dst, a);
1572
0
    fr_value_box_safety_merge(dst, b);
1573
0
    break;
1574
1575
0
  default:
1576
0
    return ERR_INVALID;
1577
0
  }
1578
1579
0
  return 0;
1580
0
}
1581
1582
0
#define is_ipv6(_x) (((_x)->type == FR_TYPE_IPV6_ADDR) || ((_x)->type == FR_TYPE_IPV6_PREFIX) || ((((_x)->type == FR_TYPE_COMBO_IP_ADDR) || ((_x)->type == FR_TYPE_COMBO_IP_PREFIX)) && ((_x)->vb_ip.af == AF_INET6)))
1583
1584
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)
1585
0
{
1586
  /*
1587
   *  IPv6 is better than IPv4!
1588
   */
1589
0
  if (is_ipv6(in1) || is_ipv6(in2)) {
1590
0
    return calc_ipv6_addr(ctx, dst, in1, op, in2);
1591
0
  }
1592
1593
0
  return calc_ipv4_addr(ctx, dst, in1, op, in2);
1594
0
}
1595
1596
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)
1597
0
{
1598
0
  if (is_ipv6(in1) || is_ipv6(in2)) {
1599
0
    return calc_ipv6_prefix(ctx, dst, in1, op, in2);
1600
0
  }
1601
1602
0
  return calc_ipv4_prefix(ctx, dst, in1, op, in2);
1603
0
}
1604
1605
1606
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)
1607
0
{
1608
0
  fr_value_box_t one, two;
1609
0
  fr_value_box_t const *a = in1;
1610
0
  fr_value_box_t const *b = in2;
1611
1612
0
  fr_assert(dst->type == FR_TYPE_FLOAT32);
1613
1614
  /*
1615
   *  Intermediate calculations are done using increased precision.
1616
   */
1617
0
  COERCE_A(FR_TYPE_FLOAT64, NULL);
1618
0
  COERCE_B(FR_TYPE_FLOAT64, NULL);
1619
1620
0
  switch (op) {
1621
0
  case T_ADD:
1622
0
    dst->vb_float32 = a->vb_float64 + b->vb_float64;
1623
0
    break;
1624
1625
0
  case T_SUB:
1626
0
    dst->vb_float32 = a->vb_float64 - b->vb_float64;
1627
0
    break;
1628
1629
0
  case T_MUL:
1630
0
    dst->vb_float32 = a->vb_float64 * b->vb_float64;
1631
0
    break;
1632
1633
0
  case T_DIV:
1634
0
    if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
1635
1636
0
    dst->vb_float32 = a->vb_float64 / b->vb_float64;
1637
0
    break;
1638
1639
0
  case T_MOD:
1640
0
    if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
1641
1642
0
    dst->vb_float32 = fmod(a->vb_float64, b->vb_float64);
1643
0
    break;
1644
1645
0
  default:
1646
0
    return ERR_INVALID;
1647
0
  }
1648
1649
0
  fr_value_box_safety_copy(dst, a);
1650
0
  fr_value_box_safety_merge(dst, b);
1651
1652
0
  return 0;
1653
1654
0
}
1655
1656
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)
1657
0
{
1658
0
  fr_value_box_t one, two;
1659
0
  fr_value_box_t const *a = in1;
1660
0
  fr_value_box_t const *b = in2;
1661
1662
0
  fr_assert(dst->type == FR_TYPE_FLOAT64);
1663
1664
0
  COERCE_A(FR_TYPE_FLOAT64, NULL);
1665
0
  COERCE_B(FR_TYPE_FLOAT64, NULL);
1666
1667
0
  switch (op) {
1668
0
  case T_ADD:
1669
0
    dst->vb_float64 = a->vb_float64 + b->vb_float64;
1670
0
    break;
1671
1672
0
  case T_SUB:
1673
0
    dst->vb_float64 = a->vb_float64 - b->vb_float64;
1674
0
    break;
1675
1676
0
  case T_MUL:
1677
0
    dst->vb_float64 = a->vb_float64 * b->vb_float64;
1678
0
    break;
1679
1680
0
  case T_DIV:
1681
0
    if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
1682
1683
0
    dst->vb_float64 = a->vb_float64 / b->vb_float64;
1684
0
    break;
1685
1686
0
  case T_MOD:
1687
0
    if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
1688
1689
0
    dst->vb_float64 = fmod(a->vb_float64, b->vb_float64);
1690
0
    break;
1691
1692
0
  default:
1693
0
    return ERR_INVALID;
1694
0
  }
1695
1696
0
  fr_value_box_safety_copy(dst, a);
1697
0
  fr_value_box_safety_merge(dst, b);
1698
1699
0
  return 0;
1700
0
}
1701
1702
/*
1703
 *  Do all intermediate operations on 64-bit numbers.
1704
 */
1705
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)
1706
0
{
1707
0
  fr_value_box_t one, two, result;
1708
0
  fr_value_box_t const *a = in1;
1709
0
  fr_value_box_t const *b = in2;
1710
1711
0
  fr_value_box_init(&result, FR_TYPE_UINT64, NULL, a->tainted | b->tainted);
1712
1713
0
  COERCE_A(FR_TYPE_UINT64, NULL);
1714
1715
0
  if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
1716
    /*
1717
     *  Don't touch the RHS.
1718
     */
1719
0
    fr_assert(b->type == FR_TYPE_UINT32);
1720
1721
0
  } else {
1722
0
    COERCE_B(FR_TYPE_UINT64, dst->enumv);
1723
0
  }
1724
1725
0
  switch (op) {
1726
0
  case T_ADD:
1727
0
    if (!fr_add(&result.vb_uint64, a->vb_uint64, b->vb_uint64)) return ERR_OVERFLOW;
1728
0
    break;
1729
1730
0
  case T_SUB:
1731
0
    if (!fr_sub(&result.vb_uint64, a->vb_uint64, b->vb_uint64)) return ERR_UNDERFLOW;
1732
0
    break;
1733
1734
0
  case T_MUL:
1735
0
    if (!fr_multiply(&result.vb_uint64, a->vb_uint64, b->vb_uint64)) return ERR_OVERFLOW;
1736
0
    break;
1737
1738
0
  case T_DIV:
1739
0
    if (b->vb_uint64 == 0) return ERR_ZERO;
1740
1741
0
    result.vb_uint64 = a->vb_uint64 / b->vb_uint64;
1742
0
    break;
1743
1744
0
  case T_MOD:
1745
0
    if (b->vb_uint64 == 0) return ERR_ZERO;
1746
1747
0
    result.vb_uint64 = a->vb_uint64 % in2->vb_uint64;
1748
0
    break;
1749
1750
0
  case T_AND:
1751
0
    result.vb_uint64 = a->vb_uint64 & b->vb_uint64;
1752
0
    break;
1753
1754
0
  case T_OR:
1755
0
    result.vb_uint64 = a->vb_uint64 | b->vb_uint64;
1756
0
    break;
1757
1758
0
  case T_XOR:
1759
0
    result.vb_uint64 = a->vb_uint64 ^ b->vb_uint64;
1760
0
    break;
1761
1762
0
  case T_RSHIFT:
1763
0
    if (b->vb_uint32 >= (8 * sizeof(a->vb_uint64))) return ERR_UNDERFLOW;
1764
1765
0
    result.vb_uint64 = a->vb_uint64 >> b->vb_uint32;
1766
0
    break;
1767
1768
0
  case T_LSHIFT:
1769
0
    if (b->vb_uint32 >= (8 * sizeof(a->vb_uint64))) return ERR_OVERFLOW;
1770
1771
0
    result.vb_uint64 = a->vb_uint64 <<  b->vb_uint32;
1772
0
    break;
1773
1774
0
  default:
1775
0
    return ERR_INVALID;
1776
0
  }
1777
1778
  /*
1779
   *  Once we're done, cast the result to the final data type.
1780
   */
1781
0
  if (fr_value_box_cast(ctx, dst, dst->type, dst->enumv, &result) < 0) return -1;
1782
1783
0
  fr_value_box_safety_copy(dst, a);
1784
0
  fr_value_box_safety_merge(dst, b);
1785
1786
0
  return 0;
1787
0
}
1788
1789
/*
1790
 *  Same as above, except uint64 -> int64.  These functions should be kept in sync!
1791
 */
1792
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)
1793
0
{
1794
0
  fr_value_box_t one, two, result;
1795
0
  fr_value_box_t const *a = in1;
1796
0
  fr_value_box_t const *b = in2;
1797
1798
0
  fr_value_box_init(&result, FR_TYPE_INT64, NULL, a->tainted | b->tainted);
1799
1800
0
  COERCE_A(FR_TYPE_INT64, NULL);
1801
1802
0
  if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
1803
    /*
1804
     *  Don't touch the RHS.
1805
     */
1806
0
    fr_assert(b->type == FR_TYPE_UINT32);
1807
1808
0
  } else {
1809
0
    COERCE_B(FR_TYPE_INT64, dst->enumv);
1810
0
  }
1811
1812
0
  switch (op) {
1813
0
  case T_ADD:
1814
0
    if (!fr_add(&result.vb_int64, a->vb_int64, b->vb_int64)) return ERR_OVERFLOW;
1815
0
    break;
1816
1817
0
  case T_SUB:
1818
0
    if (!fr_sub(&result.vb_int64, a->vb_int64, b->vb_int64)) return ERR_UNDERFLOW;
1819
0
    break;
1820
1821
0
  case T_MUL:
1822
0
    if (!fr_multiply(&result.vb_int64, a->vb_int64, b->vb_int64)) return ERR_OVERFLOW;
1823
0
    break;
1824
1825
0
  case T_DIV:
1826
0
    if (b->vb_int64 == 0) return ERR_ZERO;
1827
1828
0
    result.vb_int64 = a->vb_int64 / b->vb_int64;
1829
0
    break;
1830
1831
0
  case T_MOD:
1832
0
    if (b->vb_int64 == 0) return ERR_ZERO;
1833
1834
0
    result.vb_int64 = a->vb_int64 % in2->vb_int64;
1835
0
    break;
1836
1837
0
  case T_AND:
1838
0
    result.vb_int64 = a->vb_int64 & b->vb_int64;
1839
0
    break;
1840
1841
0
  case T_OR:
1842
0
    result.vb_int64 = a->vb_int64 | b->vb_int64;
1843
0
    break;
1844
1845
0
  case T_XOR:
1846
0
    result.vb_int64 = a->vb_int64 ^ b->vb_int64;
1847
0
    break;
1848
1849
0
  case T_RSHIFT:
1850
0
    if (b->vb_uint32 >= (8 * sizeof(a->vb_int64))) return ERR_UNDERFLOW;
1851
1852
0
    result.vb_int64 = a->vb_int64 >> b->vb_uint32;
1853
0
    break;
1854
1855
0
  case T_LSHIFT:
1856
0
    if (b->vb_uint32 >= (8 * sizeof(a->vb_int64))) return ERR_OVERFLOW;
1857
1858
0
    result.vb_int64 = a->vb_int64 <<  b->vb_uint32;
1859
0
    break;
1860
1861
0
  default:
1862
0
    return ERR_INVALID;
1863
0
  }
1864
1865
  /*
1866
   *  Once we're done, cast the result to the final data type.
1867
   */
1868
0
  if (fr_value_box_cast(ctx, dst, dst->type, dst->enumv, &result) < 0) return -1;
1869
1870
0
  fr_value_box_safety_copy(dst, a);
1871
0
  fr_value_box_safety_merge(dst, b);
1872
1873
0
  return 0;
1874
0
}
1875
1876
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);
1877
1878
/** Map output type to its associated function
1879
 *
1880
 */
1881
static const fr_binary_op_t calc_type[FR_TYPE_MAX + 1] = {
1882
  [FR_TYPE_BOOL]    = calc_bool,
1883
1884
  [FR_TYPE_OCTETS]  = calc_octets,
1885
  [FR_TYPE_STRING]  = calc_string,
1886
1887
  [FR_TYPE_IPV4_ADDR] = calc_ipv4_addr,
1888
  [FR_TYPE_IPV4_PREFIX] = calc_ipv4_prefix,
1889
1890
  [FR_TYPE_IPV6_ADDR] = calc_ipv6_addr,
1891
  [FR_TYPE_IPV6_PREFIX] = calc_ipv6_prefix,
1892
1893
  [FR_TYPE_COMBO_IP_ADDR] = calc_combo_ip_addr,
1894
  [FR_TYPE_COMBO_IP_PREFIX] = calc_combo_ip_prefix,
1895
1896
  [FR_TYPE_UINT8]   = calc_uint64,
1897
  [FR_TYPE_UINT16]        = calc_uint64,
1898
  [FR_TYPE_UINT32]        = calc_uint64,
1899
  [FR_TYPE_UINT64]        = calc_uint64,
1900
1901
  [FR_TYPE_SIZE]        = calc_uint64,
1902
1903
  [FR_TYPE_INT8]    = calc_int64,
1904
  [FR_TYPE_INT16]         = calc_int64,
1905
  [FR_TYPE_INT32]         = calc_int64,
1906
  [FR_TYPE_INT64]         = calc_int64,
1907
1908
  [FR_TYPE_DATE]    = calc_date,
1909
  [FR_TYPE_TIME_DELTA]  = calc_time_delta,
1910
1911
  [FR_TYPE_FLOAT32] = calc_float32,
1912
  [FR_TYPE_FLOAT64] = calc_float64,
1913
};
1914
1915
/** Calculate DST = A OP B
1916
 *
1917
 *  The result is written to DST only *after* it has been calculated.
1918
 *  So it's safe to pass DST as either A or B.  DST should already exist.
1919
 *
1920
 *  This function should arguably not take comparison operators, but
1921
 *  whatever.  The "promote types" code is the same for all of the
1922
 *  binary operations, so we might as well just have one function.
1923
 */
1924
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)
1925
0
{
1926
0
  int rcode = -1;
1927
0
  fr_value_box_t one, two;
1928
0
  fr_value_box_t out;
1929
0
  fr_binary_op_t func;
1930
1931
0
  if ((hint != FR_TYPE_NULL) && !fr_type_is_leaf(hint)) return invalid_type(hint);
1932
1933
  /*
1934
   *  Casting to structural types should be a parse error,
1935
   *  and not a run-time calculation error.
1936
   */
1937
0
  if (!fr_type_is_leaf(a->type)) return invalid_type(a->type);
1938
0
  if (!fr_type_is_leaf(b->type)) return invalid_type(b->type);
1939
1940
  /*
1941
   *  === and !== also check types.  If the types are
1942
   *  different, it's a failure.  Otherwise they revert to == and !=.
1943
   */
1944
0
  switch (op) {
1945
0
  case T_OP_CMP_EQ_TYPE:
1946
0
    if (a->type != b->type) {
1947
0
    mismatch_type:
1948
0
      fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false); /* @todo - enum */
1949
0
      dst->vb_bool = false;
1950
0
      return 0;
1951
0
    }
1952
0
    op = T_OP_CMP_EQ;
1953
0
    break;
1954
1955
0
  case T_OP_CMP_NE_TYPE:
1956
0
    if (a->type != b->type) goto mismatch_type;
1957
1958
0
    op = T_OP_NE;
1959
0
    break;
1960
1961
0
  case T_OP_REG_EQ:
1962
0
  case T_OP_REG_NE:
1963
0
    if (b->type != FR_TYPE_STRING) {
1964
0
      fr_strerror_const("Invalid type for regular expression");
1965
0
      return -1;
1966
0
    }
1967
1968
0
    rcode = fr_regex_cmp_op(op, a, b);
1969
0
    if (rcode < 0) return rcode;
1970
1971
0
    fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false); /* @todo - enum */
1972
0
    dst->vb_bool = (rcode != 0);
1973
0
    return 0;
1974
1975
0
  default:
1976
0
    break;
1977
0
  }
1978
1979
0
  fr_value_box_init_null(&one);
1980
0
  fr_value_box_init_null(&two);
1981
1982
  /*
1983
   *  We don't know what the output type should be.  Try to
1984
   *  guess based on a variety of factors.
1985
   */
1986
0
  if (hint == FR_TYPE_NULL) do {
1987
    /*
1988
     *  All kinds of special cases :(
1989
     *
1990
     *  date1 - date2 --> time_delta
1991
     *
1992
     *  time_delta * FOO --> float64, because time_delta is _printed_ as a floating point
1993
     *  number.  And this is the least surprising thing to do.
1994
     */
1995
0
    if ((op == T_SUB) && (a->type == b->type) && (a->type == FR_TYPE_DATE)) {
1996
0
      hint = FR_TYPE_TIME_DELTA;
1997
0
      break;
1998
0
    }
1999
2000
0
    if (op == T_MUL) {
2001
0
      if (a->type == FR_TYPE_TIME_DELTA) {
2002
0
        hint = upcast_op[FR_TYPE_FLOAT64][b->type];
2003
0
        if (hint == FR_TYPE_NULL) hint = upcast_op[b->type][FR_TYPE_FLOAT64];
2004
2005
0
      } else if (b->type == FR_TYPE_TIME_DELTA) {
2006
0
        hint = upcast_op[a->type][FR_TYPE_FLOAT64];
2007
0
        if (hint == FR_TYPE_NULL) hint = upcast_op[FR_TYPE_FLOAT64][a->type];
2008
0
      }
2009
2010
0
      if (hint != FR_TYPE_NULL) break;
2011
0
    }
2012
2013
    /*
2014
     *  date % time_delta --> time_delta
2015
     */
2016
0
    if ((op == T_MOD) && (a->type == FR_TYPE_DATE)) {
2017
0
      hint = FR_TYPE_TIME_DELTA;
2018
0
      break;
2019
0
    }
2020
2021
0
    switch (op) {
2022
0
    case T_OP_CMP_EQ:
2023
0
    case T_OP_NE:
2024
0
    case T_OP_GE:
2025
0
    case T_OP_GT:
2026
0
    case T_OP_LE:
2027
0
    case T_OP_LT:
2028
      /*
2029
       *  Comparison operators always return
2030
       *  "bool".
2031
       */
2032
0
      hint = FR_TYPE_BOOL;
2033
0
      break;
2034
2035
0
    case T_AND:
2036
      /*
2037
       *  Get mask from IP + number
2038
       */
2039
0
      if ((a->type == FR_TYPE_IPV4_ADDR) || (b->type == FR_TYPE_IPV4_ADDR)) {
2040
0
        hint = FR_TYPE_IPV4_PREFIX;
2041
0
        break;
2042
0
      }
2043
2044
0
      if ((a->type == FR_TYPE_IPV6_ADDR) || (b->type == FR_TYPE_IPV6_ADDR)) {
2045
0
        hint = FR_TYPE_IPV6_PREFIX;
2046
0
        break;
2047
0
      }
2048
0
      FALL_THROUGH;
2049
2050
0
    case T_OR:
2051
0
    case T_ADD:
2052
0
    case T_SUB:
2053
0
    case T_MUL:
2054
0
    case T_DIV:
2055
0
    case T_MOD:
2056
0
    case T_XOR:
2057
      /*
2058
       *  Try to "up-cast" the types.  This is
2059
       *  so that we can take (for example)
2060
       *  uint8 + uint16, and have the output as
2061
       *  uint16.
2062
       *
2063
       *  There must be only one entry per [a,b]
2064
       *  pairing.  That way we're sure that [a,b]==[b,a]
2065
       */
2066
0
      hint = upcast_op[a->type][b->type];
2067
0
      if (hint == FR_TYPE_NULL) {
2068
0
        hint = upcast_op[b->type][a->type];
2069
0
      } else if (a->type != b->type) {
2070
0
        fr_assert(upcast_op[b->type][a->type] == FR_TYPE_NULL);
2071
0
      }
2072
2073
      /*
2074
       *  No idea what to do. :(
2075
       */
2076
0
      if (hint == FR_TYPE_NULL) {
2077
0
        fr_strerror_printf("Invalid operation on data types - '%s' %s '%s'",
2078
0
               fr_type_to_str(a->type), fr_tokens[op], fr_type_to_str(b->type));
2079
0
        goto done;
2080
0
      }
2081
2082
0
      break;
2083
2084
      /*
2085
       *  The RHS MUST be a numerical type.  We don't need to do any upcasting here.
2086
       *
2087
       *  @todo - the output type could be larger than the input type, if the shift is
2088
       *  more than the input type can handle.  e.g. uint8 << 4 could result in uint16
2089
       */
2090
0
    case T_LSHIFT:
2091
0
      if (!fr_type_is_integer(a->type)) {
2092
0
        return handle_result(a->type, T_LSHIFT, ERR_INVALID);
2093
0
      }
2094
2095
0
      if (fr_type_is_signed(a->type)) {
2096
0
        hint = FR_TYPE_INT64;
2097
0
        break;
2098
0
      }
2099
0
      hint = FR_TYPE_UINT64;
2100
0
      break;
2101
2102
0
    case T_RSHIFT:
2103
0
      hint = a->type;
2104
0
      break;
2105
2106
0
    default:
2107
0
      return handle_result(a->type, op, ERR_INVALID);
2108
0
    }
2109
0
  } while (0);
2110
2111
  /*
2112
   *  Now that we've figured out the correct types, perform the operation.
2113
   */
2114
0
  switch (op) {
2115
0
  case T_OP_CMP_EQ:
2116
0
  case T_OP_NE:
2117
0
  case T_OP_GE:
2118
0
  case T_OP_GT:
2119
0
  case T_OP_LE:
2120
0
  case T_OP_LT:
2121
0
    if (hint != FR_TYPE_BOOL) {
2122
0
      fr_strerror_printf("Invalid destination type '%s' for comparison operator",
2123
0
             fr_type_to_str(hint));
2124
0
      goto done;
2125
0
    }
2126
2127
    /*
2128
     *  Convert the types to ones which are comparable.
2129
     */
2130
0
    if (a->type != b->type) {
2131
0
      fr_dict_attr_t const *enumv = NULL;
2132
2133
      /*
2134
       *  If we're doing comparisons and one of them has an enum, and the other is an
2135
       *  enum name, then use the enum name to convert the string to the other type.
2136
       *
2137
       *  We can then do type-specific comparisons.
2138
       */
2139
0
      if ((a->type == FR_TYPE_STRING) && b->enumv) {
2140
0
        enumv = b->enumv;
2141
0
        hint = b->type;
2142
2143
0
      } else if ((b->type == FR_TYPE_STRING) && a->enumv) {
2144
0
        enumv = a->enumv;
2145
0
        hint = a->type;
2146
2147
0
      } else {
2148
        /*
2149
         *  Try to "up-cast" the types.  This is so that we can take (for example)
2150
         *  uint8 < uint16, and have it make sense.
2151
         *
2152
         *  There must be only one entry per [a,b] pairing.  That way we're sure
2153
         *  that [a,b]==[b,a]
2154
         */
2155
0
        hint = upcast_cmp[a->type][b->type];
2156
0
        if (hint == FR_TYPE_NULL) {
2157
0
          hint = upcast_cmp[b->type][a->type];
2158
0
        } else {
2159
0
          fr_assert(upcast_cmp[b->type][a->type] == FR_TYPE_NULL);
2160
0
        }
2161
2162
        /*
2163
         *  time_deltas have a scale in the enumv, but default to "seconds" if
2164
         *  there's no scale.  As a result, if we compare time_delta(ms) to integer,
2165
         *  then the integer is interpreted as seconds, and the scale is wrong.
2166
         *
2167
         *  The solution is to use the appropriate scale.
2168
         */
2169
0
        if (hint == a->type) enumv = a->enumv;
2170
0
        if (hint == b->type) enumv = b->enumv;
2171
2172
0
        if (hint == FR_TYPE_NULL) {
2173
0
          fr_strerror_printf("Cannot compare incompatible types (%s)... %s (%s)...",
2174
0
                 fr_type_to_str(a->type),
2175
0
                 fr_tokens[op],
2176
0
                 fr_type_to_str(b->type));
2177
0
          goto done;
2178
0
        }
2179
0
      }
2180
2181
      /*
2182
       *  Cast them to the appropriate type, which may be different from either of the
2183
       *  inputs.
2184
       */
2185
0
      if (a->type != hint) {
2186
0
        if (fr_value_box_cast(NULL, &one, hint, enumv, a) < 0) goto done;
2187
0
        a = &one;
2188
0
      }
2189
2190
0
      if (b->type != hint) {
2191
0
        if (fr_value_box_cast(NULL, &two, hint, enumv, b) < 0) goto done;
2192
0
        b = &two;
2193
0
      }
2194
0
    }
2195
2196
0
    rcode = fr_value_box_cmp_op(op, a, b);
2197
0
    if (rcode < 0) goto done;
2198
2199
0
    fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false);
2200
0
    dst->vb_bool = (rcode > 0);
2201
0
    break;
2202
2203
    /*
2204
     *  For shifts, the RHS value MUST be an integer.  There's no reason to have it as
2205
     *  anything other than an 8-bit field.
2206
     */
2207
0
  case T_LSHIFT:
2208
0
  case T_RSHIFT:
2209
0
    if (b->type != FR_TYPE_UINT32) {
2210
0
      if (fr_value_box_cast(ctx, &two, FR_TYPE_UINT32, NULL, b) < 0) {
2211
0
        fr_strerror_printf("Cannot parse shift value as integer - %s",
2212
0
               fr_strerror());
2213
0
        goto done;
2214
0
      }
2215
0
      b = &two;
2216
0
    }
2217
0
    FALL_THROUGH;
2218
2219
0
  case T_ADD:
2220
0
  case T_SUB:
2221
0
  case T_MUL:
2222
0
  case T_DIV:
2223
0
  case T_MOD:
2224
0
  case T_AND:
2225
0
  case T_OR:
2226
0
  case T_XOR:
2227
0
    fr_assert(hint != FR_TYPE_NULL);
2228
2229
0
    func = calc_type[hint];
2230
0
    if (!func) {
2231
0
      fr_strerror_printf("Cannot perform any operations for destination type %s",
2232
0
             fr_type_to_str(hint));
2233
0
      rcode = -1;
2234
0
      break;
2235
0
    }
2236
2237
    /*
2238
     *  It's OK to use one of the inputs as the
2239
     *  output.  In order to ensure that nothing bad
2240
     *  happens, we use an intermediate value-box.
2241
     */
2242
0
    fr_value_box_init(&out, hint, NULL, false);
2243
2244
0
    rcode = func(ctx, &out, a, op, b); /* not calc_type[hint], to shut up clang */
2245
0
    if (rcode < 0) goto done;
2246
2247
0
    fr_value_box_copy_shallow(NULL, dst, &out);
2248
0
    dst->tainted = a->tainted | b->tainted;
2249
0
    break;
2250
2251
0
  default:
2252
0
    rcode = ERR_INVALID;
2253
0
    break;
2254
0
  }
2255
2256
0
done:
2257
0
  fr_value_box_clear_value(&one);
2258
0
  fr_value_box_clear_value(&two);
2259
2260
0
  return handle_result(hint, op, rcode);
2261
0
}
2262
2263
/** Calculate DST = OP { A, B, C, ... }
2264
 *
2265
 *  The result is written to DST only *after* it has been calculated.
2266
 *  So it's safe to pass DST as one of the inputs.  DST should already
2267
 *  exist.
2268
 */
2269
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)
2270
0
{
2271
0
  fr_value_box_t out, *vb;
2272
0
  fr_binary_op_t calc;
2273
2274
0
  if (group->type != FR_TYPE_GROUP) {
2275
0
    fr_strerror_const("Invalid type passed to multivalue calculation");
2276
0
    return -1;
2277
0
  }
2278
2279
0
  if (fr_type_is_structural(type)) {
2280
0
  invalid_type:
2281
0
    fr_strerror_printf("Invalid operation %s for data type %s", fr_tokens[op], fr_type_to_str(type));
2282
0
    return -1;
2283
0
  }
2284
2285
0
  if (type == FR_TYPE_STRING) {
2286
0
    fr_sbuff_t *sbuff;
2287
2288
0
    if (op != T_ADD) goto invalid_type;
2289
2290
0
    FR_SBUFF_TALLOC_THREAD_LOCAL(&sbuff, 1024, (1 << 16));
2291
2292
0
    if (fr_value_box_list_concat_as_string(dst, sbuff, UNCONST(fr_value_box_list_t *, &group->vb_group),
2293
0
                   NULL, 0, NULL, FR_VALUE_BOX_LIST_NONE, FR_VALUE_BOX_SAFE_FOR_ANY, false) < 0) return -1;
2294
2295
0
    if (fr_value_box_bstrndup(ctx, dst, NULL, fr_sbuff_start(sbuff), fr_sbuff_used(sbuff), false) < 0) return -1;
2296
0
    return 0;
2297
0
  }
2298
2299
0
  if (type == FR_TYPE_OCTETS) {
2300
0
    fr_dbuff_t *dbuff;
2301
2302
0
    if (op != T_ADD) goto invalid_type;
2303
2304
0
    FR_DBUFF_TALLOC_THREAD_LOCAL(&dbuff, 1024, (1 << 16));
2305
2306
0
    if (fr_value_box_list_concat_as_octets(dst, dbuff, UNCONST(fr_value_box_list_t *, &group->vb_group), NULL, 0, FR_VALUE_BOX_LIST_NONE, false) < 0) return -1;
2307
2308
0
    if (fr_value_box_memdup(ctx, dst, NULL, fr_dbuff_start(dbuff), fr_dbuff_used(dbuff), false) < 0) return -1;
2309
2310
0
    return 0;
2311
0
  }
2312
2313
  /*
2314
   *  Can't add or multiply booleans.
2315
   */
2316
0
  if ((type == FR_TYPE_BOOL) && !((op == T_AND) || (op == T_OR) || (op == T_XOR))) goto unsupported;
2317
2318
0
  switch (op) {
2319
0
  case T_ADD:
2320
0
  case T_MUL:
2321
0
  case T_AND:
2322
0
  case T_OR:
2323
0
  case T_XOR:
2324
0
    break;
2325
2326
0
  default:
2327
0
    goto invalid_type;
2328
0
  }
2329
2330
  /*
2331
   *  Strings and octets are different.
2332
   */
2333
0
  if (!fr_type_is_numeric(type)) {
2334
0
  unsupported:
2335
0
    fr_strerror_printf("Not yet supported operation %s for data type %s", fr_tokens[op], fr_type_to_str(type));
2336
0
    return -1;
2337
0
  }
2338
2339
0
  switch (type) {
2340
0
  case FR_TYPE_UINT8:
2341
0
  case FR_TYPE_UINT16:
2342
0
  case FR_TYPE_UINT32:
2343
0
  case FR_TYPE_UINT64:
2344
0
    calc = calc_uint64;
2345
0
    break;
2346
2347
0
  case FR_TYPE_INT8:
2348
0
  case FR_TYPE_INT16:
2349
0
  case FR_TYPE_INT32:
2350
0
  case FR_TYPE_INT64:
2351
0
    calc = calc_int64;
2352
0
    break;
2353
2354
0
  case FR_TYPE_TIME_DELTA:
2355
0
    if ((op != T_ADD) && (op != T_SUB)) goto invalid_type;
2356
0
    calc = calc_time_delta;
2357
0
    break;
2358
2359
0
  case FR_TYPE_FLOAT32:
2360
0
    calc = calc_float32;
2361
0
    break;
2362
2363
0
  case FR_TYPE_FLOAT64:
2364
0
    calc = calc_float64;
2365
0
    break;
2366
2367
0
  default:
2368
0
    goto unsupported;
2369
0
  }
2370
2371
0
  vb = fr_value_box_list_head(&group->vb_group);
2372
0
  if (!vb) {
2373
0
    fr_strerror_printf("Empty input is invalid");
2374
0
    return -1;
2375
0
  }
2376
2377
0
  if (fr_value_box_cast(ctx, &out, type, NULL, vb) < 0) return -1;
2378
2379
0
  while ((vb = fr_value_box_list_next(&group->vb_group, vb)) != NULL) {
2380
0
    int rcode;
2381
0
    fr_value_box_t box;
2382
2383
0
    if (vb->type == type) {
2384
0
      rcode = calc(ctx, &out, &out, op, vb);
2385
0
      if (rcode < 0) return rcode;
2386
2387
0
    } else {
2388
0
      if (fr_value_box_cast(ctx, &box, type, NULL, vb) < 0) return -1;
2389
2390
0
      rcode = calc(ctx, &out, &out, op, &box);
2391
0
      if (rcode < 0) return rcode;
2392
0
    }
2393
0
  }
2394
2395
0
  return fr_value_box_copy(ctx, dst, &out);
2396
0
}
2397
2398
2399
#define T(_x) [T_OP_ ## _x ## _EQ] = T_ ## _x
2400
2401
static const fr_token_t assignment2op[T_TOKEN_LAST] = {
2402
  T(ADD),
2403
  T(SUB),
2404
  T(MUL),
2405
  T(DIV),
2406
  T(AND),
2407
  T(OR),
2408
  T(XOR),
2409
  T(RSHIFT),
2410
  T(LSHIFT),
2411
};
2412
2413
/** Calculate DST OP SRC
2414
 *
2415
 *  e.g. "foo += bar".
2416
 *
2417
 *  This is done by doing some sanity checks, and then just calling
2418
 *  the "binary operation" function.
2419
 */
2420
int fr_value_calc_assignment_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_token_t op, fr_value_box_t const *src)
2421
0
{
2422
0
  int rcode;
2423
2424
0
  if (!fr_type_is_leaf(dst->type)) return invalid_type(dst->type);
2425
0
  if (!fr_type_is_leaf(src->type)) return invalid_type(src->type);
2426
2427
0
  if (dst->immutable) {
2428
0
    fr_strerror_printf("Cannot modify immutable value");
2429
0
    return -1;
2430
0
  }
2431
2432
  /*
2433
   *  These operators are included here for testing and completeness.  But see comments in
2434
   *  fr_edit_list_apply_pair_assignment() for what the caller should be doing.
2435
   */
2436
0
  if ((op == T_OP_EQ) || (op == T_OP_SET)) {
2437
    /*
2438
     *  Allow for unintentional mistakes.
2439
     */
2440
0
    if (src == dst) return 0;
2441
2442
0
    fr_value_box_clear_value(dst);
2443
0
    return fr_value_box_cast(ctx, dst, dst->type, dst->enumv, src); /* cast, as the RHS might not (yet) be the same! */
2444
0
  }
2445
2446
0
  if (assignment2op[op] == T_INVALID) {
2447
0
    return handle_result(dst->type, op, ERR_INVALID);
2448
0
  }
2449
0
  op = assignment2op[op];
2450
2451
  /*
2452
   *  Just call the binary op function.  It already ensures that (a) the inputs are "const", and (b)
2453
   *  the output is over-written only at the final step.
2454
   */
2455
0
  if (src->type != FR_TYPE_GROUP) {
2456
0
    rcode = fr_value_calc_binary_op(ctx, dst, dst->type, dst, op, src);
2457
2458
0
  } else {
2459
0
    fr_value_box_t *vb = NULL;
2460
2461
    /*
2462
     *  If the RHS is a group, then we loop over the group recursively, doing the operation.
2463
     */
2464
0
    rcode = 0;  /* in case group is empty */
2465
2466
0
    while ((vb = fr_value_box_list_next(&src->vb_group, vb)) != NULL) {
2467
0
      rcode = fr_value_calc_binary_op(ctx, dst, dst->type, dst, op, vb);
2468
0
      if (rcode < 0) break;
2469
0
    }
2470
0
  }
2471
2472
0
  if (rcode < 0) return handle_result(dst->type, op, rcode);
2473
2474
0
  return 0;
2475
0
}
2476
2477
/** Calculate unary operations
2478
 *
2479
 *  e.g. "foo++", or "-foo".
2480
 */
2481
int fr_value_calc_unary_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_token_t op, fr_value_box_t const *src)
2482
0
{
2483
0
  int rcode = -1;
2484
0
  fr_value_box_t one;
2485
2486
0
  if (!fr_type_is_numeric(src->type)) return invalid_type(src->type);
2487
2488
0
  if (dst->immutable) {
2489
0
    fr_strerror_printf("Cannot modify immutable value");
2490
0
    return -1;
2491
0
  }
2492
2493
0
  if (op == T_OP_INCRM) {
2494
    /*
2495
     *  Add 1 or subtract 1 means RHS is always 1.
2496
     */
2497
0
    fr_value_box_init(&one, src->type, NULL, false);
2498
0
    switch (src->type) {
2499
0
    case FR_TYPE_UINT8:
2500
0
      one.vb_uint8 = 1;
2501
0
      break;
2502
2503
0
    case FR_TYPE_UINT16:
2504
0
      one.vb_uint16 = 1;
2505
0
      break;
2506
2507
0
    case FR_TYPE_UINT32:
2508
0
      one.vb_uint32 = 1;
2509
0
      break;
2510
2511
0
    case FR_TYPE_UINT64:
2512
0
      one.vb_uint64 = 1;
2513
0
      break;
2514
2515
0
    case FR_TYPE_SIZE:
2516
0
      one.vb_size = 1;
2517
0
      break;
2518
2519
0
    case FR_TYPE_INT8:
2520
0
      one.vb_int8 = 1;
2521
0
      break;
2522
2523
0
    case FR_TYPE_INT16:
2524
0
      one.vb_int16 = 1;
2525
0
      break;
2526
2527
0
    case FR_TYPE_INT32:
2528
0
      one.vb_int32 = 1;
2529
0
      break;
2530
2531
0
    case FR_TYPE_INT64:
2532
0
      one.vb_int64 = 1;
2533
0
      break;
2534
2535
0
    case FR_TYPE_FLOAT32:
2536
0
      one.vb_float32 = 1;
2537
0
      break;
2538
2539
0
    case FR_TYPE_FLOAT64:
2540
0
      one.vb_float64 = 1;
2541
0
      break;
2542
2543
0
    default:
2544
0
      fr_assert(0);
2545
0
      return -1;
2546
0
    }
2547
2548
0
    rcode = fr_value_calc_binary_op(ctx, dst, src->type, src, T_ADD, &one);
2549
0
    return handle_result(dst->type, op, rcode);
2550
2551
0
  } else if (op == T_COMPLEMENT) {
2552
0
    if (dst != src) {
2553
0
      fr_value_box_init(dst, src->type, src->enumv, false);
2554
0
      fr_value_box_safety_copy(dst, src);
2555
0
    }
2556
2557
0
#undef COMP
2558
0
#define COMP(_type, _field) case FR_TYPE_ ## _type: dst->vb_ ##_field = (_field ## _t) ~src->vb_ ##_field; break
2559
0
    switch (src->type) {
2560
0
      COMP(UINT8, uint8);
2561
0
      COMP(UINT16, uint16);
2562
0
      COMP(UINT32, uint32);
2563
0
      COMP(UINT64, uint64);
2564
0
      COMP(SIZE, size);
2565
2566
0
      COMP(INT8, int8);
2567
0
      COMP(INT16, int16);
2568
0
      COMP(INT32, int32);
2569
0
      COMP(INT64, int64);
2570
2571
0
    default:
2572
0
      goto invalid;
2573
0
    }
2574
2575
0
    return 0;
2576
2577
0
  } else if (op == T_SUB) {
2578
0
    fr_type_t type = src->type;
2579
2580
0
    if ((dst != src) && !fr_type_is_signed(src->type)) {
2581
0
      type = upcast_unsigned[src->type];
2582
2583
0
      if (type == FR_TYPE_NULL) {
2584
0
        type = src->type; /* hope for the best */
2585
0
      }
2586
0
    }
2587
2588
0
    fr_value_box_init(&one, type, NULL, src->tainted); /* init to zero */
2589
0
    rcode = fr_value_calc_binary_op(ctx, dst, type, &one, T_SUB, src);
2590
2591
0
    return handle_result(dst->type, op, rcode);
2592
2593
0
  } else if (op == T_NOT) {
2594
0
    bool value = fr_value_box_is_truthy(src);
2595
2596
0
    fr_value_box_clear(dst);
2597
0
    fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false); // @todo - add enum!
2598
0
    dst->vb_bool = !value;
2599
2600
0
    return 0;
2601
2602
0
  } else {
2603
0
  invalid:
2604
0
    return handle_result(src->type, op, ERR_INVALID);
2605
0
  }
2606
2607
0
}
2608
2609
/*
2610
 *  Empty lists are empty:
2611
 *
2612
 *    {}
2613
 *    {{}}
2614
 *    {''}
2615
 *    {{},''}
2616
 *
2617
 *    etc.
2618
 */
2619
static bool fr_value_calc_list_empty(fr_value_box_list_t const *list)
2620
0
{
2621
0
  fr_value_box_list_foreach(list, item) {
2622
0
    switch (item->type) {
2623
0
    default:
2624
0
      return false;
2625
2626
0
    case FR_TYPE_GROUP:
2627
0
      if (!fr_value_calc_list_empty(&item->vb_group)) return false;
2628
0
      break;
2629
2630
0
    case FR_TYPE_STRING:
2631
0
    case FR_TYPE_OCTETS:
2632
0
      if (item->vb_length != 0) return false;
2633
0
      break;
2634
0
    }
2635
0
  }
2636
2637
0
  return true;
2638
0
}
2639
2640
2641
/*
2642
 *  Loop over input lists, calling fr_value_calc_binary_op()
2643
 *
2644
 *  This implementation is arguably wrong... it should be checking individual entries in list1 against individual entries in list2.
2645
 *  Instead, it checks if ANY entry in list1 matches ANY entry in list2.
2646
 */
2647
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)
2648
0
{
2649
0
  int rcode;
2650
0
  bool invert = false;
2651
0
  bool a_empty, b_empty;
2652
2653
0
  if (!fr_comparison_op[op]) {
2654
0
    fr_strerror_printf("Invalid operator '%s' passed to list comparison", fr_tokens[op]);
2655
0
    return -1;
2656
0
  }
2657
2658
  /*
2659
   *  v3 hack.  != really means !( ... == ... )
2660
   */
2661
0
  if (op == T_OP_NE) {
2662
0
    invert = true;
2663
0
    op = T_OP_CMP_EQ;
2664
0
  }
2665
2666
  /*
2667
   *  It's annoying when the debug prints out cmp({},{}) and says "not equal".
2668
   *
2669
   *  What's happening behind the scenes is that one side is an empty value-box group, such as when
2670
   *  an xlat expansion fails.  And the other side is an empty string.  If we believe that strings
2671
   *  are actually sets of characters, then {}=='', and we're all OK
2672
   */
2673
0
  a_empty = fr_value_box_list_empty(list1) || fr_value_calc_list_empty(list1);
2674
0
  b_empty = fr_value_box_list_empty(list2) || fr_value_calc_list_empty(list2);
2675
2676
  /*
2677
   *  Both lists are empty, they should be equal when checked for equality.
2678
   */
2679
0
  if (a_empty && b_empty) {
2680
0
    switch (op) {
2681
0
    case T_OP_CMP_EQ:
2682
0
    case T_OP_LE:
2683
0
    case T_OP_GE:
2684
0
      invert = !invert;
2685
0
      break;
2686
2687
0
    default:
2688
0
      break;
2689
0
    }
2690
2691
0
    goto done;
2692
0
  }
2693
2694
  /*
2695
   *  Emulate v3.  :(
2696
   */
2697
0
  fr_value_box_list_foreach(list1, a) {
2698
0
    fr_value_box_list_foreach(list2, b) {
2699
0
      rcode = fr_value_calc_binary_op(ctx, dst, FR_TYPE_BOOL, a, op, b);
2700
0
      if (rcode < 0) return rcode;
2701
2702
      /*
2703
       *  No match: keep looking for a match.
2704
       */
2705
0
      fr_assert(dst->type == FR_TYPE_BOOL);
2706
0
      if (!dst->vb_bool) continue;
2707
2708
      /*
2709
       *  Found a match, we're done.
2710
       */
2711
0
      dst->vb_bool = !invert;
2712
0
      return 0;
2713
0
    }
2714
0
  }
2715
2716
  /*
2717
   *  No match,
2718
   */
2719
0
done:
2720
0
  fr_value_box_clear(dst);
2721
0
  fr_value_box_init(dst, FR_TYPE_BOOL, NULL, false); // @todo - add enum!
2722
0
  dst->vb_bool = invert;
2723
0
  return 0;
2724
0
}