Coverage Report

Created: 2026-03-31 06:21

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