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/value.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
/** Boxed value structures and functions to manipulate them
18
 *
19
 * @file src/lib/util/value.c
20
 *
21
 * There are three notional data formats used in the server:
22
 *
23
 * - #fr_value_box_t are the INTERNAL format.  This is usually close to the in-memory representation
24
 *   of the data, though uint32s and IPs are always converted to/from octets with BIG ENDIAN
25
 *   uint8 ordering for consistency.
26
 *   - #fr_value_box_cast is used to convert (cast) #fr_value_box_t between INTERNAL formats.
27
 *   - #fr_value_box_strdup* is used to ingest nul terminated strings into the INTERNAL format.
28
 *   - #fr_value_box_memdup* is used to ingest binary data into the INTERNAL format.
29
 *
30
 * - NETWORK format is the format we send/receive on the wire.  It is not a perfect representation
31
 *   of data packing for all protocols, so you will likely need to overload conversion for some types.
32
 *   - fr_value_box_to_network is used to convert INTERNAL format data to generic NETWORK format data.
33
 *     For uint32s, IP addresses etc... This means BIG ENDIAN uint8 ordering.
34
 *   - fr_value_box_from_network is used to convert packet buffer fragments in NETWORK format to
35
 *     INTERNAL format.
36
 *
37
 * - PRESENTATION format is what we print to the screen, and what we get from the user, databases
38
 *   and configuration files.
39
 *   - #fr_value_box_aprint is used to convert from INTERNAL to PRESENTATION format.
40
 *   - #fr_value_box_from_substr is used to convert from PRESENTATION to INTERNAL format.
41
 *
42
 * @copyright 2014-2017 The FreeRADIUS server project
43
 * @copyright 2017 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
44
 */
45
RCSID("$Id: 027e545beeed696608524371d3d035a178c8b981 $")
46
47
#define _VALUE_PRIVATE
48
#include <freeradius-devel/util/value.h>
49
#undef _VALUE_PRIVATE
50
51
#include <freeradius-devel/util/atexit.h>
52
#include <freeradius-devel/util/base16.h>
53
#include <freeradius-devel/util/size.h>
54
55
#include <math.h>
56
#include <float.h>
57
58
/** Sanity checks
59
 *
60
 * There should never be an instance where these fail.
61
 */
62
static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_ip.addr.v4.s_addr) == 4,
63
        "in_addr.s_addr has unexpected length");
64
static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_ip.addr.v6.s6_addr) == 16,
65
        "in6_addr.s6_addr has unexpected length");
66
static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_ifid) == 8,
67
        "vb_ifid has unexpected length");
68
static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_ether) == 6,
69
        "vb_ether has unexpected length");
70
71
static_assert(SIZEOF_MEMBER(fr_value_box_t, datum.boolean) == 1,
72
        "datum.boolean has unexpected length");
73
static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_uint8) == 1,
74
        "vb_uint8 has unexpected length");
75
static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_uint16) == 2,
76
        "vb_uint16 has unexpected length");
77
static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_uint32) == 4,
78
        "vb_uint32 has unexpected length");
79
static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_uint64) == 8,
80
        "vb_uint64 has unexpected length");
81
82
static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_int8) == 1,
83
        "vb_int16 has unexpected length");
84
static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_int16) == 2,
85
        "vb_int16 has unexpected length");
86
static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_int32) == 4,
87
        "vb_int32 has unexpected length");
88
static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_int64) == 8,
89
        "vb_int64 has unexpected length");
90
91
static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_float32) == 4,
92
        "vb_float32 has unexpected length");
93
static_assert(SIZEOF_MEMBER(fr_value_box_t, vb_float64) == 8,
94
        "vb_float64 has unexpected length");
95
96
/** How many bytes on-the-wire would a #fr_value_box_t value consume
97
 *
98
 * This is for the generic NETWORK format.  For field sizes in the in-memory
99
 * structure use #fr_value_box_field_sizes.
100
 *
101
 * @note Don't use this array directly when determining the length
102
 *   that would be consumed by the on-the-wire representation.
103
 *   Use #fr_value_box_network_length instead, as that deals with variable
104
 *   length attributes too.
105
 */
106
4.23M
#define network_min_size(_x) (fr_value_box_network_sizes[_x][0])
107
4.04M
#define network_max_size(_x) (fr_value_box_network_sizes[_x][1])
108
static size_t const fr_value_box_network_sizes[FR_TYPE_MAX + 1][2] = {
109
  [FR_TYPE_NULL]        = {~0, 0},
110
111
  [FR_TYPE_STRING]      = {0, ~0},
112
  [FR_TYPE_OCTETS]      = {0, ~0},
113
114
  [FR_TYPE_IPV4_ADDR]     = {4, 4},
115
  [FR_TYPE_IPV4_PREFIX]     = {5, 5},
116
  [FR_TYPE_IPV6_ADDR]     = {16, 17},
117
  [FR_TYPE_IPV6_PREFIX]     = {17, 18},
118
  [FR_TYPE_COMBO_IP_ADDR]     = {4, 17},
119
  [FR_TYPE_COMBO_IP_PREFIX]   = {16, 18},
120
  [FR_TYPE_IFID]        = {8, 8},
121
  [FR_TYPE_ETHERNET]      = {6, 6},
122
123
  [FR_TYPE_BOOL]        = {1, 1},
124
  [FR_TYPE_UINT8]       = {1, 1},
125
  [FR_TYPE_UINT16]      = {2, 2},
126
  [FR_TYPE_UINT32]      = {4, 4},
127
  [FR_TYPE_UINT64]      = {8, 8},
128
129
  [FR_TYPE_INT8]        = {1, 1},
130
  [FR_TYPE_INT16]       = {2, 2},
131
  [FR_TYPE_INT32]       = {4, 4},
132
  [FR_TYPE_INT64]       = {8, 8},
133
134
  [FR_TYPE_SIZE]        = {8, 8},
135
136
  [FR_TYPE_FLOAT32]     = {4, 4},
137
  [FR_TYPE_FLOAT64]     = {8, 8},
138
139
  [FR_TYPE_DATE]        = {2, 8},  //!< 2, 4, or 8 only
140
  [FR_TYPE_TIME_DELTA]        = {2, 8},  //!< 2, 4, or 8 only
141
142
  [FR_TYPE_ATTR]        = {1, ~0},
143
144
  [FR_TYPE_MAX]       = {~0, 0}   //!< Ensure array covers all types.
145
};
146
147
/** How many bytes wide each of the value data fields are
148
 *
149
 * This is useful when copying a value from a fr_value_box_t to a memory
150
 * location passed as a void *.
151
 */
152
size_t const fr_value_box_field_sizes[] = {
153
  [FR_TYPE_STRING]      = SIZEOF_MEMBER(fr_value_box_t, vb_strvalue),
154
  [FR_TYPE_OCTETS]      = SIZEOF_MEMBER(fr_value_box_t, vb_octets),
155
156
  [FR_TYPE_IPV4_ADDR]     = SIZEOF_MEMBER(fr_value_box_t, vb_ip),
157
  [FR_TYPE_IPV4_PREFIX]     = SIZEOF_MEMBER(fr_value_box_t, vb_ip),
158
  [FR_TYPE_IPV6_ADDR]     = SIZEOF_MEMBER(fr_value_box_t, vb_ip),
159
  [FR_TYPE_IPV6_PREFIX]     = SIZEOF_MEMBER(fr_value_box_t, vb_ip),
160
  [FR_TYPE_COMBO_IP_ADDR]     = SIZEOF_MEMBER(fr_value_box_t, vb_ip),
161
  [FR_TYPE_COMBO_IP_PREFIX]         = SIZEOF_MEMBER(fr_value_box_t, vb_ip),
162
  [FR_TYPE_IFID]        = SIZEOF_MEMBER(fr_value_box_t, vb_ifid),
163
  [FR_TYPE_ETHERNET]      = SIZEOF_MEMBER(fr_value_box_t, vb_ether),
164
165
  [FR_TYPE_BOOL]        = SIZEOF_MEMBER(fr_value_box_t, datum.boolean),
166
  [FR_TYPE_UINT8]       = SIZEOF_MEMBER(fr_value_box_t, vb_uint8),
167
  [FR_TYPE_UINT16]      = SIZEOF_MEMBER(fr_value_box_t, vb_uint16),
168
  [FR_TYPE_UINT32]      = SIZEOF_MEMBER(fr_value_box_t, vb_uint32),
169
  [FR_TYPE_UINT64]      = SIZEOF_MEMBER(fr_value_box_t, vb_uint64),
170
171
  [FR_TYPE_INT8]        = SIZEOF_MEMBER(fr_value_box_t, vb_int8),
172
  [FR_TYPE_INT16]       = SIZEOF_MEMBER(fr_value_box_t, vb_int16),
173
  [FR_TYPE_INT32]       = SIZEOF_MEMBER(fr_value_box_t, vb_int32),
174
  [FR_TYPE_INT64]       = SIZEOF_MEMBER(fr_value_box_t, vb_int64),
175
176
  [FR_TYPE_FLOAT32]     = SIZEOF_MEMBER(fr_value_box_t, vb_float32),
177
  [FR_TYPE_FLOAT64]     = SIZEOF_MEMBER(fr_value_box_t, vb_float64),
178
179
  [FR_TYPE_DATE]        = SIZEOF_MEMBER(fr_value_box_t, vb_date),
180
181
  [FR_TYPE_TIME_DELTA]      = SIZEOF_MEMBER(fr_value_box_t, datum.time_delta),
182
  [FR_TYPE_SIZE]        = SIZEOF_MEMBER(fr_value_box_t, datum.size),
183
184
  [FR_TYPE_ATTR]        = SIZEOF_MEMBER(fr_value_box_t, vb_attr),
185
186
  [FR_TYPE_VALUE_BOX]     = sizeof(fr_value_box_t),
187
188
  [FR_TYPE_MAX]       = 0 //!< Ensure array covers all types.
189
};
190
191
/** Where the value starts in the #fr_value_box_t
192
 *
193
 */
194
size_t const fr_value_box_offsets[] = {
195
  [FR_TYPE_STRING]      = offsetof(fr_value_box_t, vb_strvalue),
196
  [FR_TYPE_OCTETS]      = offsetof(fr_value_box_t, vb_octets),
197
198
  [FR_TYPE_IPV4_ADDR]     = offsetof(fr_value_box_t, vb_ip),
199
  [FR_TYPE_IPV4_PREFIX]     = offsetof(fr_value_box_t, vb_ip),
200
  [FR_TYPE_IPV6_ADDR]     = offsetof(fr_value_box_t, vb_ip),
201
  [FR_TYPE_IPV6_PREFIX]     = offsetof(fr_value_box_t, vb_ip),
202
  [FR_TYPE_COMBO_IP_ADDR]     = offsetof(fr_value_box_t, vb_ip),
203
  [FR_TYPE_COMBO_IP_PREFIX]         = offsetof(fr_value_box_t, vb_ip),
204
  [FR_TYPE_IFID]        = offsetof(fr_value_box_t, vb_ifid),
205
  [FR_TYPE_ETHERNET]      = offsetof(fr_value_box_t, vb_ether),
206
207
  [FR_TYPE_BOOL]        = offsetof(fr_value_box_t, vb_bool),
208
  [FR_TYPE_UINT8]       = offsetof(fr_value_box_t, vb_uint8),
209
  [FR_TYPE_UINT16]      = offsetof(fr_value_box_t, vb_uint16),
210
  [FR_TYPE_UINT32]      = offsetof(fr_value_box_t, vb_uint32),
211
  [FR_TYPE_UINT64]      = offsetof(fr_value_box_t, vb_uint64),
212
213
  [FR_TYPE_INT8]        = offsetof(fr_value_box_t, vb_int8),
214
  [FR_TYPE_INT16]       = offsetof(fr_value_box_t, vb_int16),
215
  [FR_TYPE_INT32]       = offsetof(fr_value_box_t, vb_int32),
216
  [FR_TYPE_INT64]       = offsetof(fr_value_box_t, vb_int64),
217
218
  [FR_TYPE_FLOAT32]     = offsetof(fr_value_box_t, vb_float32),
219
  [FR_TYPE_FLOAT64]     = offsetof(fr_value_box_t, vb_float64),
220
221
  [FR_TYPE_DATE]        = offsetof(fr_value_box_t, vb_date),
222
223
  [FR_TYPE_TIME_DELTA]      = offsetof(fr_value_box_t, vb_time_delta),
224
  [FR_TYPE_SIZE]        = offsetof(fr_value_box_t, vb_size),
225
  [FR_TYPE_ATTR]        = offsetof(fr_value_box_t, vb_attr),
226
227
  [FR_TYPE_VALUE_BOX]     = 0,
228
229
  [FR_TYPE_MAX]       = 0 //!< Ensure array covers all types.
230
};
231
232
static uint64_t const fr_value_box_integer_max[] = {
233
  [FR_TYPE_BOOL]        = true,
234
  [FR_TYPE_UINT8]       = UINT8_MAX,
235
  [FR_TYPE_UINT16]      = UINT16_MAX,
236
  [FR_TYPE_UINT32]      = UINT32_MAX,
237
  [FR_TYPE_UINT64]      = UINT64_MAX,
238
239
  [FR_TYPE_INT8]        = INT8_MAX,
240
  [FR_TYPE_INT16]       = INT16_MAX,
241
  [FR_TYPE_INT32]       = INT32_MAX,
242
  [FR_TYPE_INT64]       = INT64_MAX,
243
244
  [FR_TYPE_DATE]        = UINT64_MAX,
245
  [FR_TYPE_TIME_DELTA]      = INT64_MAX,
246
247
  [FR_TYPE_SIZE]        = SIZE_MAX,
248
249
  [FR_TYPE_MAX]       = 0 //!< Ensure array covers all types.
250
};
251
252
static int64_t const fr_value_box_integer_min[] = {
253
  [FR_TYPE_BOOL]        = false,
254
  [FR_TYPE_UINT8]       = 0,
255
  [FR_TYPE_UINT16]      = 0,
256
  [FR_TYPE_UINT32]      = 0,
257
  [FR_TYPE_UINT64]      = 0,
258
259
  [FR_TYPE_INT8]        = INT8_MIN,
260
  [FR_TYPE_INT16]       = INT16_MIN,
261
  [FR_TYPE_INT32]       = INT32_MIN,
262
  [FR_TYPE_INT64]       = INT64_MIN,
263
264
  [FR_TYPE_DATE]        = 0,
265
  [FR_TYPE_TIME_DELTA]      = INT64_MIN,
266
267
  [FR_TYPE_SIZE]        = 0,
268
269
  [FR_TYPE_MAX]       = 0 //!< Ensure array covers all types.
270
};
271
272
fr_sbuff_unescape_rules_t fr_value_unescape_double = {
273
  .name = "double",
274
  .chr = '\\',
275
  .subs = {
276
    ['"'] = '"',  /* Quoting char */
277
    ['%'] = '%',  /* xlat expansions */
278
    ['\\'] = '\\',
279
    ['a'] = '\a',
280
    ['b'] = '\b',
281
    ['e'] = '\\',
282
    ['n'] = '\n',
283
    ['r'] = '\r',
284
    ['t'] = '\t',
285
    ['v'] = '\v'
286
  },
287
  .do_hex = true,
288
  .do_oct = true
289
};
290
291
fr_sbuff_unescape_rules_t fr_value_unescape_single = {
292
  .name = "single",
293
  .chr = '\\',
294
  .subs = {
295
    ['\''] = '\'',  /* Quoting char */
296
    ['\\'] = '\\'
297
  },
298
  .do_hex = false,
299
  .do_oct = false
300
};
301
302
fr_sbuff_unescape_rules_t fr_value_unescape_solidus = {
303
  .name = "solidus",
304
  .chr = '\\',
305
  .subs = {
306
    ['%'] = '%',  /* xlat expansions */
307
    ['/'] = '/',  /* Quoting char */
308
    ['a'] = '\a',
309
    ['b'] = '\b',
310
    ['e'] = '\\',
311
    ['n'] = '\n',
312
    ['r'] = '\r',
313
    ['t'] = '\t',
314
    ['v'] = '\v'
315
  },
316
  .skip = {
317
    ['\\'] = '\\' /* Leave this for the regex library */
318
  },
319
  .do_hex = true,
320
  .do_oct = true
321
};
322
323
fr_sbuff_unescape_rules_t fr_value_unescape_backtick = {
324
  .name = "backtick",
325
  .chr = '\\',
326
  .subs = {
327
    ['%'] = '%',  /* xlat expansions */
328
    ['\\'] = '\\',
329
    ['`'] = '`',  /* Quoting char */
330
    ['a'] = '\a',
331
    ['b'] = '\b',
332
    ['e'] = '\\',
333
    ['n'] = '\n',
334
    ['r'] = '\r',
335
    ['t'] = '\t',
336
    ['v'] = '\v'
337
  },
338
  .do_hex = true,
339
  .do_oct = true
340
};
341
342
fr_sbuff_unescape_rules_t *fr_value_unescape_by_quote[T_TOKEN_LAST] = {
343
  [T_DOUBLE_QUOTED_STRING]  = &fr_value_unescape_double,
344
  [T_SINGLE_QUOTED_STRING]  = &fr_value_unescape_single,
345
  [T_SOLIDUS_QUOTED_STRING] = &fr_value_unescape_solidus,
346
  [T_BACK_QUOTED_STRING]    = &fr_value_unescape_backtick,
347
};
348
349
fr_sbuff_unescape_rules_t *fr_value_unescape_by_char[UINT8_MAX + 1] = {
350
  ['"'] = &fr_value_unescape_double,
351
  ['\'']  = &fr_value_unescape_single,
352
  ['/'] = &fr_value_unescape_solidus,
353
  ['`'] = &fr_value_unescape_backtick,
354
};
355
356
fr_sbuff_escape_rules_t fr_value_escape_double = {
357
  .name = "double",
358
  .chr = '\\',
359
  .subs = {
360
    ['"'] = '"',  /* Quoting char */
361
    ['%'] = '%',  /* xlat expansions */
362
    ['\\'] = '\\',
363
    ['\a'] = 'a',
364
    ['\b'] = 'b',
365
    ['\n'] = 'n',
366
    ['\r'] = 'r',
367
    ['\t'] = 't',
368
    ['\v'] = 'v'
369
  },
370
  .esc = {
371
    SBUFF_CHAR_UNPRINTABLES_LOW,
372
    SBUFF_CHAR_UNPRINTABLES_EXTENDED
373
  },
374
  .do_utf8 = true,
375
  .do_oct = true
376
};
377
378
#ifdef __clang__
379
#pragma clang diagnostic ignored "-Wgnu-designator"
380
#endif
381
382
/** Escape secret fields by simply mashing all data to '.'
383
 *
384
 *  The length of the secret still leaks, but that is likely fine.  Fixing that is more work.
385
 *
386
 */
387
fr_sbuff_escape_rules_t fr_value_escape_secret = {
388
  .name = "secret",
389
  .subs = {
390
    [ 0 ... 255 ] = '.',
391
  },
392
};
393
394
fr_sbuff_escape_rules_t fr_value_escape_single = {
395
  .name = "single",
396
  .chr = '\\',
397
  .subs = {
398
    ['\''] = '\'',  /* Quoting char */
399
    ['\\'] = '\\'
400
  },
401
  .do_utf8 = true,
402
};
403
404
fr_sbuff_escape_rules_t fr_value_escape_solidus = {
405
  .name = "solidus",
406
  .chr = '\\',
407
  .subs = {
408
    ['%'] = '%',  /* xlat expansions */
409
    ['/'] = '/',  /* Quoting char */
410
    ['\a'] = 'a',
411
    ['\b'] = 'b',
412
    ['\n'] = 'n',
413
    ['\r'] = 'r',
414
    ['\t'] = 't',
415
    ['\v'] = 'v'
416
  },
417
  .esc = {
418
    SBUFF_CHAR_UNPRINTABLES_LOW,
419
    SBUFF_CHAR_UNPRINTABLES_EXTENDED
420
  },
421
  .do_utf8 = true,
422
  .do_oct = true
423
};
424
425
fr_sbuff_escape_rules_t fr_value_escape_backtick = {
426
  .name = "backtick",
427
  .chr = '\\',
428
  .subs = {
429
    ['%'] = '%',  /* xlat expansions */
430
    ['\\'] = '\\',
431
    ['`'] = '`',  /* Quoting char */
432
    ['\a'] = 'a',
433
    ['\b'] = 'b',
434
    ['\n'] = 'n',
435
    ['\r'] = 'r',
436
    ['\t'] = 't',
437
    ['\v'] = 'v'
438
  },
439
  .esc = {
440
    SBUFF_CHAR_UNPRINTABLES_LOW,
441
    SBUFF_CHAR_UNPRINTABLES_EXTENDED
442
  },
443
  .do_utf8 = true,
444
  .do_oct = true
445
};
446
447
fr_sbuff_escape_rules_t *fr_value_escape_by_quote[T_TOKEN_LAST] = {
448
  [T_DOUBLE_QUOTED_STRING]  = &fr_value_escape_double,
449
  [T_SINGLE_QUOTED_STRING]  = &fr_value_escape_single,
450
  [T_SOLIDUS_QUOTED_STRING] = &fr_value_escape_solidus,
451
  [T_BACK_QUOTED_STRING]    = &fr_value_escape_backtick,
452
};
453
454
fr_sbuff_escape_rules_t *fr_value_escape_by_char[UINT8_MAX + 1] = {
455
  ['"'] = &fr_value_escape_double,
456
  ['\'']  = &fr_value_escape_single,
457
  ['/'] = &fr_value_escape_solidus,
458
  ['`'] = &fr_value_escape_backtick,
459
};
460
461
fr_sbuff_escape_rules_t fr_value_escape_unprintables = {
462
  .name = "unprintables",
463
  .chr = '\\',
464
  .subs = {
465
    ['\\'] = '\\',
466
  },
467
  .esc = {
468
    SBUFF_CHAR_UNPRINTABLES_LOW,
469
    SBUFF_CHAR_UNPRINTABLES_EXTENDED
470
  },
471
  .do_utf8 = true,
472
  .do_oct = true
473
};
474
475
476
/** @name Produce a #tmpl_t from a string or substring
477
 *
478
 * @{
479
 */
480
481
/* clang-format off */
482
/** Default formatting rules
483
 *
484
 * Control token termination, escaping and how the tmpl is printed.
485
 */
486
fr_sbuff_parse_rules_t const value_parse_rules_bareword_unquoted = {
487
488
};
489
490
fr_sbuff_parse_rules_t const value_parse_rules_double_unquoted = {
491
  .escapes = &fr_value_unescape_double
492
};
493
494
fr_sbuff_parse_rules_t const value_parse_rules_single_unquoted = {
495
  .escapes = &fr_value_unescape_single
496
};
497
498
fr_sbuff_parse_rules_t const value_parse_rules_solidus_unquoted = {
499
  .escapes = &fr_value_unescape_solidus
500
};
501
502
fr_sbuff_parse_rules_t const value_parse_rules_backtick_unquoted = {
503
  .escapes = &fr_value_unescape_backtick
504
};
505
506
/** Parse rules for non-quoted strings
507
 *
508
 * These parse rules should be used for processing escape sequences in
509
 * data from external data sources like SQL databases and REST APIs.
510
 *
511
 * They do not include terminals to stop parsing as it assumes the values
512
 * are discrete, and not wrapped in quotes.
513
 */
514
fr_sbuff_parse_rules_t const *value_parse_rules_unquoted[T_TOKEN_LAST] = {
515
  [T_BARE_WORD]     = &value_parse_rules_bareword_unquoted,
516
  [T_DOUBLE_QUOTED_STRING]  = &value_parse_rules_double_unquoted,
517
  [T_SINGLE_QUOTED_STRING]  = &value_parse_rules_single_unquoted,
518
  [T_SOLIDUS_QUOTED_STRING] = &value_parse_rules_solidus_unquoted,
519
  [T_BACK_QUOTED_STRING]    = &value_parse_rules_backtick_unquoted
520
};
521
522
fr_sbuff_parse_rules_t const *value_parse_rules_unquoted_char[UINT8_MAX] = {
523
  ['\0']        = &value_parse_rules_bareword_unquoted,
524
  ['"']       = &value_parse_rules_double_unquoted,
525
  ['\'']        = &value_parse_rules_single_unquoted,
526
  ['/']       = &value_parse_rules_solidus_unquoted,
527
  ['`']       = &value_parse_rules_backtick_unquoted
528
};
529
530
fr_sbuff_parse_rules_t const value_parse_rules_bareword_quoted = {
531
  .escapes = &(fr_sbuff_unescape_rules_t){
532
    .chr = '\\',
533
    /*
534
     *  Allow barewords to contain whitespace
535
     *  if they're escaped.
536
     */
537
    .subs = {
538
      ['\t'] = '\t',
539
      ['\n'] = '\n',
540
      [' '] = ' '
541
    },
542
    .do_hex = false,
543
    .do_oct = false
544
  },
545
  .terminals = &FR_SBUFF_TERMS(
546
    L(""),
547
    L("\t"),
548
    L("\n"),
549
    L(" ")
550
  )
551
};
552
553
fr_sbuff_parse_rules_t const value_parse_rules_double_quoted = {
554
  .escapes = &fr_value_unescape_double,
555
  .terminals = &FR_SBUFF_TERMS(
556
    L(""), L("\n"), L("\r"), L("\""))
557
};
558
559
fr_sbuff_parse_rules_t const value_parse_rules_single_quoted = {
560
  .escapes = &fr_value_unescape_single,
561
  .terminals = &FR_SBUFF_TERMS(
562
    L(""), L("\n"), L("\r"), L("'"))
563
};
564
565
fr_sbuff_parse_rules_t const value_parse_rules_solidus_quoted = {
566
  .escapes = &fr_value_unescape_solidus,
567
  .terminals = &FR_SBUFF_TERMS(
568
    L(""), L("\n"), L("\r"), L("/"))
569
};
570
571
fr_sbuff_parse_rules_t const value_parse_rules_backtick_quoted = {
572
  .escapes = &fr_value_unescape_backtick,
573
  .terminals = &FR_SBUFF_TERMS(
574
    L(""), L("\n"), L("\r"), L("`"))
575
};
576
577
/*
578
 *  And triple-quoted versions of the above.
579
 */
580
fr_sbuff_parse_rules_t const value_parse_rules_double_3quoted = {
581
  .escapes = &fr_value_unescape_double,
582
  .terminals = &FR_SBUFF_TERMS(
583
    L(""), L("\n"), L("\r"), L("\"\"\""))
584
};
585
586
fr_sbuff_parse_rules_t const value_parse_rules_single_3quoted = {
587
  .escapes = &fr_value_unescape_single,
588
  .terminals = &FR_SBUFF_TERMS(
589
    L(""), L("\n"), L("\r"), L("'''"))
590
};
591
592
fr_sbuff_parse_rules_t const value_parse_rules_solidus_3quoted = {
593
  .escapes = &fr_value_unescape_solidus,
594
  .terminals = &FR_SBUFF_TERMS(
595
    L(""), L("\n"), L("\r"), L("///"))
596
};
597
598
fr_sbuff_parse_rules_t const value_parse_rules_backtick_3quoted = {
599
  .escapes = &fr_value_unescape_backtick,
600
  .terminals = &FR_SBUFF_TERMS(
601
    L(""), L("\n"), L("\r"), L("```"))
602
};
603
604
/** Parse rules for quoted strings
605
 *
606
 * These parse rules should be used for internal parsing functions that
607
 * are working with configuration files.
608
 *
609
 * They include appropriate quote terminals to force functions parsing
610
 * quoted strings to return when they reach a quote character.
611
 */
612
fr_sbuff_parse_rules_t const *value_parse_rules_quoted[T_TOKEN_LAST] = {
613
  [T_BARE_WORD]     = &value_parse_rules_bareword_quoted,
614
  [T_DOUBLE_QUOTED_STRING]  = &value_parse_rules_double_quoted,
615
  [T_SINGLE_QUOTED_STRING]  = &value_parse_rules_single_quoted,
616
  [T_SOLIDUS_QUOTED_STRING] = &value_parse_rules_solidus_quoted,
617
  [T_BACK_QUOTED_STRING]    = &value_parse_rules_backtick_quoted
618
};
619
620
fr_sbuff_parse_rules_t const *value_parse_rules_quoted_char[UINT8_MAX] = {
621
  ['\0']        = &value_parse_rules_bareword_quoted,
622
  ['"']       = &value_parse_rules_double_quoted,
623
  ['\'']        = &value_parse_rules_single_quoted,
624
  ['/']       = &value_parse_rules_solidus_quoted,
625
  ['`']       = &value_parse_rules_backtick_quoted
626
};
627
628
fr_sbuff_parse_rules_t const *value_parse_rules_3quoted[T_TOKEN_LAST] = {
629
  [T_BARE_WORD]     = &value_parse_rules_bareword_quoted,
630
  [T_DOUBLE_QUOTED_STRING]  = &value_parse_rules_double_3quoted,
631
  [T_SINGLE_QUOTED_STRING]  = &value_parse_rules_single_3quoted,
632
  [T_SOLIDUS_QUOTED_STRING] = &value_parse_rules_solidus_3quoted,
633
  [T_BACK_QUOTED_STRING]    = &value_parse_rules_backtick_3quoted
634
};
635
636
/* clang-format on */
637
/** @} */
638
639
/** Copy flags and type data from one value box to another
640
 *
641
 * @param[in] dst to copy flags to
642
 * @param[in] src of data.
643
 */
644
static inline void fr_value_box_copy_meta(fr_value_box_t *dst, fr_value_box_t const *src)
645
38.5k
{
646
38.5k
  switch (src->type) {
647
0
  case FR_TYPE_VARIABLE_SIZE:
648
0
    dst->vb_length = src->vb_length;
649
0
    break;
650
  /*
651
   *  Not 100% sure this should be done here
652
   *  but if the intent is to make a null
653
   *  box usable, then we need to do this
654
   *  somewhere.
655
   */
656
0
  case FR_TYPE_GROUP:
657
0
    fr_value_box_list_init(&dst->vb_group);
658
0
    break;
659
660
356k
  case FR_TYPE_NUMERIC:
661
356k
  case FR_TYPE_IP:
662
192k
  case FR_TYPE_IFID:
663
38.5k
  case FR_TYPE_ETHERNET:
664
38.5k
  case FR_TYPE_ATTR:
665
38.5k
  case FR_TYPE_NULL:
666
38.5k
    break;
667
668
0
  case FR_TYPE_TLV:
669
0
  case FR_TYPE_STRUCT:
670
0
  case FR_TYPE_VSA:
671
0
  case FR_TYPE_VENDOR:
672
0
  case FR_TYPE_UNION:
673
0
  case FR_TYPE_INTERNAL:
674
0
    fr_assert(0);
675
0
    break;
676
38.5k
  }
677
678
38.5k
  dst->enumv = src->enumv;
679
38.5k
  dst->type = src->type;
680
38.5k
  dst->tainted = src->tainted;
681
38.5k
  dst->safe_for = src->safe_for;
682
38.5k
  dst->secret = src->secret;
683
38.5k
  fr_value_box_list_entry_init(dst);
684
38.5k
}
685
686
/** Compare two floating point numbers for equality.
687
 *
688
 *  We're not _quite_ supposed to use DBL_EPSILON here, and are instead supposed to choose our own epsilon.
689
 *  But this is good enough for most purposed.
690
 */
691
static int8_t float_cmp(double a, double b)
692
0
{
693
0
  double sum, diff;
694
695
  /*
696
   *  Handles the best cast scenario.
697
   */
698
0
  if (a == b) return 0;
699
700
0
  diff = fabs(a - b);
701
702
  /*
703
   *  One of the numbers is zero.  The other might be close to zero, in which case it might as well
704
   *  be zero.
705
   *
706
   *  Otherwise, the non-zero number is far from zero, and we can just compare them.
707
   */
708
0
  if ((fpclassify(a) == FP_ZERO) || (fpclassify(b) == FP_ZERO)) {
709
0
  check:
710
0
    if (diff < DBL_EPSILON) return 0;
711
712
0
    return CMP(a, b);
713
0
  }
714
715
  /*
716
   *  Get the rough scale of the two numbers.
717
   */
718
0
  sum = fabs(a) + fabs(b);
719
720
  /*
721
   *  The two numbers are not zero, but both are close to it.
722
   */
723
0
  if (sum < DBL_MIN) goto check;
724
725
  /*
726
   *  Get the relative differences.  This check also handles overflow of sum.
727
   */
728
0
  if ((diff / fmin(sum, DBL_MAX)) < DBL_EPSILON) return 0;
729
730
0
  return CMP(a, b);
731
0
}
732
733
/** Compare two values
734
 *
735
 * @param[in] a Value to compare.
736
 * @param[in] b Value to compare.
737
 * @return
738
 *  - -1 if a is less than b.
739
 *  - 0 if both are equal.
740
 *  - 1 if a is more than b.
741
 *  - < -1 on failure.
742
 */
743
int8_t fr_value_box_cmp(fr_value_box_t const *a, fr_value_box_t const *b)
744
12.5k
{
745
12.5k
  if (a->type != b->type) {
746
0
    fr_strerror_printf("%s: Can't compare values of different types", __FUNCTION__);
747
0
    return -2;
748
0
  }
749
750
  /*
751
   *  After doing the previous check for special comparisons,
752
   *  do the per-type comparison here.
753
   */
754
12.5k
  switch (a->type) {
755
0
  case FR_TYPE_VARIABLE_SIZE:
756
0
  {
757
0
    size_t length;
758
759
0
    if (a->vb_length < b->vb_length) {
760
0
      length = a->vb_length;
761
0
    } else {
762
0
      length = b->vb_length;
763
0
    }
764
765
0
    if (length) {
766
0
      int cmp;
767
768
      /*
769
       *  Use constant-time comparisons for secret values.
770
       */
771
0
      if (a->secret || b->secret) {
772
0
        cmp = fr_digest_cmp(a->datum.ptr, b->datum.ptr, length);
773
0
      } else {
774
0
        cmp = memcmp(a->datum.ptr, b->datum.ptr, length);
775
0
      }
776
0
      if (cmp != 0) return CMP(cmp, 0);
777
0
    }
778
779
    /*
780
     *  Contents are the same.  The return code
781
     *  is therefore the difference in lengths.
782
     *
783
     *  i.e. "0x00" is smaller than "0x0000"
784
     */
785
0
    return CMP(a->vb_length, b->vb_length);
786
0
  }
787
788
  /*
789
   *  Short-hand for simplicity.
790
   */
791
12.5k
#define RETURN(_type) return CMP(a->datum._type, b->datum._type)
792
0
#define COMPARE(_type) return CMP(memcmp(&a->datum._type, &b->datum._type, sizeof(a->datum._type)), 0)
793
794
0
  case FR_TYPE_BOOL:
795
0
    RETURN(boolean);
796
797
0
  case FR_TYPE_DATE:
798
0
    return fr_unix_time_cmp(a->datum.date, b->datum.date);
799
800
1.85k
  case FR_TYPE_UINT8:
801
1.85k
    RETURN(uint8);
802
803
10.4k
  case FR_TYPE_UINT16:
804
10.4k
    RETURN(uint16);
805
806
294
  case FR_TYPE_UINT32:
807
294
    RETURN(uint32);
808
809
0
  case FR_TYPE_UINT64:
810
0
    RETURN(uint64);
811
812
0
  case FR_TYPE_INT8:
813
0
    RETURN(int8);
814
815
0
  case FR_TYPE_INT16:
816
0
    RETURN(int16);
817
818
0
  case FR_TYPE_INT32:
819
0
    RETURN(int32);
820
821
0
  case FR_TYPE_INT64:
822
0
    RETURN(int64);
823
824
0
  case FR_TYPE_SIZE:
825
0
    RETURN(size);
826
827
0
  case FR_TYPE_TIME_DELTA:
828
0
    return fr_time_delta_cmp(a->datum.time_delta, b->datum.time_delta);
829
830
0
  case FR_TYPE_FLOAT32:
831
0
    return float_cmp(a->vb_float32, b->vb_float32);
832
833
0
  case FR_TYPE_FLOAT64:
834
0
    return float_cmp(a->vb_float64, b->vb_float64);
835
836
0
  case FR_TYPE_ETHERNET:
837
0
    COMPARE(ether);
838
839
0
  case FR_TYPE_COMBO_IP_ADDR:
840
0
  case FR_TYPE_COMBO_IP_PREFIX:
841
0
  case FR_TYPE_IPV4_ADDR:
842
0
  case FR_TYPE_IPV4_PREFIX:
843
0
  case FR_TYPE_IPV6_ADDR:
844
0
  case FR_TYPE_IPV6_PREFIX:
845
0
    return fr_ipaddr_cmp(&a->vb_ip, &b->vb_ip);
846
847
0
  case FR_TYPE_IFID:
848
0
    COMPARE(ifid);
849
850
0
  case FR_TYPE_NULL:  /* NULLs are not comparable */
851
0
    return -2;
852
853
0
  case FR_TYPE_ATTR:
854
    /*
855
     *  @todo - this makes things _distinct_, but doesn't provide a _full_ order.  We
856
     *  generally don't need a full ordering for attributes.
857
     *
858
     *  The need to call fr_dict_attr_cmp() here is for comparing raw / unknown attributes
859
     *  which come from xlats.  Unknown / raw attributes which are in policies are added to
860
     *  the dictionaries when the server starts, and are thus known.
861
     */
862
0
    return fr_dict_attr_cmp(a->vb_attr, b->vb_attr);
863
864
  /*
865
   *  These should be handled at some point
866
   */
867
0
  default:
868
0
    (void)fr_cond_assert(0);  /* unknown type */
869
0
    return -2;
870
871
  /*
872
   *  Do NOT add a default here, as new types are added
873
   *  static analysis will warn us they're not handled
874
   */
875
12.5k
  }
876
0
  return 0;
877
12.5k
}
878
879
/*
880
 *  We leverage the fact that IPv4 and IPv6 prefixes both
881
 *  have the same format:
882
 *
883
 *  reserved, prefix-len, data...
884
 */
885
static int fr_value_box_cidr_cmp_op(fr_token_t op, int bytes,
886
         uint8_t a_net, uint8_t const *a,
887
         uint8_t b_net, uint8_t const *b)
888
0
{
889
0
  int i, common;
890
0
  uint32_t mask;
891
892
  /*
893
   *  Handle the case of netmasks being identical.
894
   */
895
0
  if (a_net == b_net) {
896
0
    int compare;
897
898
0
    compare = memcmp(a, b, bytes);
899
900
    /*
901
     *  If they're identical return true for
902
     *  identical.
903
     */
904
0
    if ((compare == 0) &&
905
0
        ((op == T_OP_CMP_EQ) ||
906
0
         (op == T_OP_LE) ||
907
0
         (op == T_OP_GE))) {
908
0
      return true;
909
0
    }
910
911
    /*
912
     *  Everything else returns false.
913
     *
914
     *  10/8 == 24/8  --> false
915
     *  10/8 <= 24/8  --> false
916
     *  10/8 >= 24/8  --> false
917
     */
918
0
    return false;
919
0
  }
920
921
  /*
922
   *  Netmasks are different.  That limits the
923
   *  possible results, based on the operator.
924
   */
925
0
  switch (op) {
926
0
  case T_OP_CMP_EQ:
927
0
    return false;
928
929
0
  case T_OP_NE:
930
0
    return true;
931
932
0
  case T_OP_LE:
933
0
  case T_OP_LT: /* 192/8 < 192.168/16 --> false */
934
0
    if (a_net < b_net) {
935
0
      return false;
936
0
    }
937
0
    break;
938
939
0
  case T_OP_GE:
940
0
  case T_OP_GT: /* 192/16 > 192.168/8 --> false */
941
0
    if (a_net > b_net) {
942
0
      return false;
943
0
    }
944
0
    break;
945
946
0
  default:
947
0
    return false;
948
0
  }
949
950
0
  if (a_net < b_net) {
951
0
    common = a_net;
952
0
  } else {
953
0
    common = b_net;
954
0
  }
955
956
  /*
957
   *  Do the check uint8 by uint8.  If the bytes are
958
   *  identical, it MAY be a match.  If they're different,
959
   *  it is NOT a match.
960
   */
961
0
  i = 0;
962
0
  while (i < bytes) {
963
    /*
964
     *  All leading bytes are identical.
965
     */
966
0
    if (common == 0) return true;
967
968
    /*
969
     *  Doing bitmasks takes more work.
970
     */
971
0
    if (common < 8) break;
972
973
0
    if (a[i] != b[i]) return false;
974
975
0
    common -= 8;
976
0
    i++;
977
0
    continue;
978
0
  }
979
980
0
  mask = 1;
981
0
  mask <<= (8 - common);
982
0
  mask--;
983
0
  mask = ~mask;
984
985
0
  if ((a[i] & mask) == ((b[i] & mask))) {
986
0
    return true;
987
0
  }
988
989
0
  return false;
990
0
}
991
992
/*
993
 *  So we don't have to include <util/regex.h> in a recursive fashion.
994
 */
995
extern int fr_regex_cmp_op(fr_token_t op, fr_value_box_t const *a, fr_value_box_t const *b);
996
997
/** Compare two attributes using an operator
998
 *
999
 * @param[in] op to use in comparison.
1000
 * @param[in] a Value to compare.
1001
 * @param[in] b Value to compare.
1002
 * @return
1003
 *  - 1 if true
1004
 *  - 0 if false
1005
 *  - -1 on failure.
1006
 *  - < -1 on failure.
1007
 */
1008
int fr_value_box_cmp_op(fr_token_t op, fr_value_box_t const *a, fr_value_box_t const *b)
1009
0
{
1010
0
  int compare = 0;
1011
1012
0
  if (unlikely((op == T_OP_REG_EQ) || (op == T_OP_REG_NE))) return fr_regex_cmp_op(op, a, b);
1013
1014
0
  switch (a->type) {
1015
0
  case FR_TYPE_IPV4_ADDR:
1016
0
    switch (b->type) {
1017
0
    case FR_TYPE_COMBO_IP_ADDR:
1018
0
      if (b->vb_ip.af != AF_INET) goto fail_cmp_v4;
1019
0
      FALL_THROUGH;
1020
1021
0
    case FR_TYPE_IPV4_ADDR:   /* IPv4 and IPv4 */
1022
0
      goto cmp;
1023
1024
0
    case FR_TYPE_COMBO_IP_PREFIX:
1025
0
      if (b->vb_ip.af != AF_INET) goto fail_cmp_v4;
1026
0
      FALL_THROUGH;
1027
1028
0
    case FR_TYPE_IPV4_PREFIX: /* IPv4 and IPv4 Prefix */
1029
0
      return fr_value_box_cidr_cmp_op(op, 4, 32, (uint8_t const *) &a->vb_ip.addr.v4.s_addr,
1030
0
                 b->vb_ip.prefix, (uint8_t const *) &b->vb_ip.addr.v4.s_addr);
1031
1032
0
    default:
1033
0
    fail_cmp_v4:
1034
0
      fr_strerror_const("Cannot compare IPv4 with IPv6 address");
1035
0
      return -1;
1036
0
    }
1037
1038
0
  case FR_TYPE_IPV4_PREFIX:   /* IPv4 and IPv4 Prefix */
1039
0
  cmp_prefix_v4:
1040
0
    switch (b->type) {
1041
0
    case FR_TYPE_COMBO_IP_ADDR:
1042
0
      if (b->vb_ip.af != AF_INET) goto fail_cmp_v4;
1043
0
      FALL_THROUGH;
1044
1045
0
    case FR_TYPE_IPV4_ADDR:
1046
0
      return fr_value_box_cidr_cmp_op(op, 4, a->vb_ip.prefix,
1047
0
                 (uint8_t const *) &a->vb_ip.addr.v4.s_addr,
1048
0
                 32, (uint8_t const *) &b->vb_ip.addr.v4);
1049
1050
0
    case FR_TYPE_COMBO_IP_PREFIX:
1051
0
      if (b->vb_ip.af != AF_INET) goto fail_cmp_v4;
1052
0
      FALL_THROUGH;
1053
1054
0
    case FR_TYPE_IPV4_PREFIX: /* IPv4 Prefix and IPv4 Prefix */
1055
0
      return fr_value_box_cidr_cmp_op(op, 4, a->vb_ip.prefix,
1056
0
                 (uint8_t const *) &a->vb_ip.addr.v4.s_addr,
1057
0
                 b->vb_ip.prefix, (uint8_t const *) &b->vb_ip.addr.v4.s_addr);
1058
1059
0
    default:
1060
0
      fr_strerror_const("Cannot compare IPv4 with IPv6 address");
1061
0
      return -1;
1062
0
    }
1063
1064
0
  case FR_TYPE_IPV6_ADDR:
1065
0
    switch (b->type) {
1066
0
    case FR_TYPE_COMBO_IP_ADDR:
1067
0
      if (b->vb_ip.af != AF_INET6) goto fail_cmp_v6;
1068
0
      FALL_THROUGH;
1069
1070
0
    case FR_TYPE_IPV6_ADDR:   /* IPv6 and IPv6 */
1071
0
      goto cmp;
1072
1073
0
    case FR_TYPE_COMBO_IP_PREFIX:
1074
0
      if (b->vb_ip.af != AF_INET6) goto fail_cmp_v6;
1075
0
      FALL_THROUGH;
1076
1077
0
    case FR_TYPE_IPV6_PREFIX: /* IPv6 and IPv6 Preifx */
1078
0
      return fr_value_box_cidr_cmp_op(op, 16, 128, (uint8_t const *) &a->vb_ip.addr.v6,
1079
0
                 b->vb_ip.prefix, (uint8_t const *) &b->vb_ip.addr.v6);
1080
1081
0
    default:
1082
0
    fail_cmp_v6:
1083
0
      fr_strerror_const("Cannot compare IPv6 with IPv4 address");
1084
0
      return -1;
1085
0
    }
1086
1087
0
  case FR_TYPE_IPV6_PREFIX:
1088
0
  cmp_prefix_v6:
1089
0
    switch (b->type) {
1090
0
    case FR_TYPE_COMBO_IP_ADDR:
1091
0
      if (b->vb_ip.af != AF_INET6) goto fail_cmp_v6;
1092
0
      FALL_THROUGH;
1093
1094
0
    case FR_TYPE_IPV6_ADDR:   /* IPv6 Prefix and IPv6 */
1095
0
      return fr_value_box_cidr_cmp_op(op, 16, a->vb_ip.prefix,
1096
0
                 (uint8_t const *) &a->vb_ip.addr.v6,
1097
0
                 128, (uint8_t const *) &b->vb_ip.addr.v6);
1098
1099
0
    case FR_TYPE_COMBO_IP_PREFIX:
1100
0
      if (b->vb_ip.af != AF_INET6) goto fail_cmp_v6;
1101
0
      FALL_THROUGH;
1102
1103
0
    case FR_TYPE_IPV6_PREFIX: /* IPv6 Prefix and IPv6 */
1104
0
      return fr_value_box_cidr_cmp_op(op, 16, a->vb_ip.prefix,
1105
0
                 (uint8_t const *) &a->vb_ip.addr.v6,
1106
0
                 b->vb_ip.prefix, (uint8_t const *) &b->vb_ip.addr.v6);
1107
1108
0
    default:
1109
0
      fr_strerror_const("Cannot compare IPv6 with IPv4 address");
1110
0
      return -1;
1111
0
    }
1112
1113
0
  case FR_TYPE_COMBO_IP_ADDR:
1114
0
    if (a->vb_ip.af != b->vb_ip.af) goto fail_cmp_v4; /* as good as any */
1115
1116
0
    goto cmp;
1117
1118
0
  case FR_TYPE_COMBO_IP_PREFIX:
1119
0
    if (a->vb_ip.af != b->vb_ip.af) goto fail_cmp_v4; /* as good as any */
1120
1121
0
    if (a->vb_ip.af == AF_INET) goto cmp_prefix_v4;
1122
1123
0
    goto cmp_prefix_v6;
1124
1125
0
  case FR_TYPE_NUMERIC:
1126
0
  case FR_TYPE_IFID:
1127
0
  case FR_TYPE_ETHERNET:
1128
0
  case FR_TYPE_VARIABLE_SIZE:
1129
0
  case FR_TYPE_ATTR:
1130
0
  case FR_TYPE_NULL:
1131
0
  cmp:
1132
0
    compare = fr_value_box_cmp(a, b);
1133
0
    if (compare < -1) { /* comparison error */
1134
0
      return -2;
1135
0
    }
1136
0
    break;
1137
1138
0
  case FR_TYPE_GROUP:
1139
0
  case FR_TYPE_TLV:
1140
0
  case FR_TYPE_STRUCT:
1141
0
  case FR_TYPE_VSA:
1142
0
  case FR_TYPE_VENDOR:
1143
0
  case FR_TYPE_UNION:
1144
0
  case FR_TYPE_INTERNAL:
1145
0
    fr_assert(0);
1146
0
    return -2;
1147
0
  }
1148
1149
  /*
1150
   *  Now do the operator comparison.
1151
   */
1152
0
  switch (op) {
1153
0
  case T_OP_CMP_EQ:
1154
0
    return (compare == 0);
1155
1156
0
  case T_OP_NE:
1157
0
    return (compare != 0);
1158
1159
0
  case T_OP_LT:
1160
0
    return (compare < 0);
1161
1162
0
  case T_OP_GT:
1163
0
    return (compare > 0);
1164
1165
0
  case T_OP_LE:
1166
0
    return (compare <= 0);
1167
1168
0
  case T_OP_GE:
1169
0
    return (compare >= 0);
1170
1171
0
  default:
1172
0
    return 0;
1173
0
  }
1174
0
}
1175
1176
/** Convert a string value with escape sequences into its binary form
1177
 *
1178
 * The quote character determines the escape sequences recognised.
1179
 *
1180
 * - Literal mode ("'" quote char) will unescape:
1181
 @verbatim
1182
   - \\        - Literal backslash.
1183
   - \<quote>  - The quotation char.
1184
 @endverbatim
1185
 * - Expanded mode ('"' quote char) will also unescape:
1186
 @verbatim
1187
   - \a        - Alert.
1188
   - \b        - Backspace.
1189
   - \e        - Escape character i.e. (\)
1190
   - \r        - Carriage return.
1191
   - \n        - Newline.
1192
   - \t        - Tab.
1193
   - \v        - Vertical tab
1194
   - \<oct>    - An octal escape sequence.
1195
   - \x<hex>   - A hex escape sequence.
1196
 @endverbatim
1197
 * - Backtick mode ('`' quote char) identical to expanded mode.
1198
 * - Regex mode ('/') identical to expanded mode but two successive
1199
 * backslashes will be interpreted as an escape sequence, but not
1200
 * unescaped, so that they will be passed to the underlying regex
1201
 * library.
1202
 * - Verbatim mode ('\0' quote char) copies in to out verbatim.
1203
 *
1204
 * @note The resulting output may contain embedded \0s.
1205
 * @note Unrecognised escape sequences will be copied verbatim.
1206
 * @note In and out may point to the same underlying buffer.
1207
 * @note Copying will stop early if an unescaped instance of the
1208
 *   quoting char is found in the input buffer.
1209
 *
1210
 * @param[out] out  Where to write the unescaped string.
1211
 * @param[in] in  The string to unescape.
1212
 * @param[in] inlen Length of input string.  Pass SIZE_MAX to copy all data
1213
 *      in the input buffer.
1214
 * @param[in] quote Character around the string, determines unescaping mode.
1215
 *
1216
 * @return
1217
 *  - 0 if input string was empty.
1218
 *  - >0 the number of bytes written to out.
1219
 */
1220
size_t fr_value_str_unescape(fr_sbuff_t *out, fr_sbuff_t *in, size_t inlen, char quote)
1221
0
{
1222
0
  switch (quote) {
1223
0
  default:
1224
0
    break;
1225
1226
0
  case '"':
1227
0
  {
1228
0
    return fr_sbuff_out_unescape_until(out, in, inlen, NULL, &fr_value_unescape_double);
1229
0
  }
1230
0
  case '\'':
1231
0
  {
1232
0
    return fr_sbuff_out_unescape_until(out, in, inlen, NULL, &fr_value_unescape_single);
1233
0
  }
1234
1235
0
  case '`':
1236
0
  {
1237
0
    return fr_sbuff_out_unescape_until(out, in, inlen, NULL, &fr_value_unescape_backtick);
1238
0
  }
1239
1240
0
  case '/':
1241
0
  {
1242
0
    return fr_sbuff_out_unescape_until(out, in, inlen, NULL, &fr_value_unescape_solidus);
1243
0
  }
1244
0
  }
1245
1246
0
  return fr_sbuff_out_bstrncpy(out, in, inlen);
1247
0
}
1248
1249
/** Convert a string value with escape sequences into its binary form
1250
 *
1251
 * The quote character determines the escape sequences recognised.
1252
 *
1253
 * - Literal mode ("'" quote char) will unescape:
1254
 @verbatim
1255
   - \\        - Literal backslash.
1256
   - \<quote>  - The quotation char.
1257
 @endverbatim
1258
 * - Expanded mode ('"' quote char) will also unescape:
1259
 @verbatim
1260
   - \a        - Alert.
1261
   - \b        - Backspace.
1262
   - \e        - Escape character i.e. (\)
1263
   - \r        - Carriage return.
1264
   - \n        - Newline.
1265
   - \t        - Tab.
1266
   - \v        - Vertical tab
1267
   - \<oct>    - An octal escape sequence.
1268
   - \x<hex>   - A hex escape sequence.
1269
 @endverbatim
1270
 * - Backtick mode ('`' quote char) identical to expanded mode.
1271
 * - Regex mode ('/') identical to expanded mode but two successive
1272
 * backslashes will be interpreted as an escape sequence, but not
1273
 * unescaped, so that they will be passed to the underlying regex
1274
 * library.
1275
 * - Verbatim mode ('\0' quote char) copies in to out verbatim.
1276
 *
1277
 * @note The resulting output may contain embedded \0s.
1278
 * @note Unrecognised escape sequences will be copied verbatim.
1279
 * @note In and out may point to the same underlying buffer.
1280
 * @note Copying will stop early if an unescaped instance of the
1281
 *   quoting char is found in the input buffer.
1282
 *
1283
 * @param[out] out  Where to write the unescaped string.
1284
 * @param[in] in  The string to unescape.
1285
 * @param[in] inlen Length of input string.  Pass SIZE_MAX to copy all data
1286
 *      in the input buffer.
1287
 * @param[in] quote Character around the string, determines unescaping mode.
1288
 *
1289
 * @return
1290
 *  - 0 if input string was empty.
1291
 *  - >0 the number of bytes written to out.
1292
 */
1293
size_t fr_value_substr_unescape(fr_sbuff_t *out, fr_sbuff_t *in, size_t inlen, char quote)
1294
0
{
1295
0
  switch (quote) {
1296
0
  default:
1297
0
    break;
1298
1299
0
  case '"':
1300
0
    return fr_sbuff_out_unescape_until(out, in, inlen, &FR_SBUFF_TERM("\""), &fr_value_unescape_double);
1301
1302
0
  case '\'':
1303
0
    return fr_sbuff_out_unescape_until(out, in, inlen, &FR_SBUFF_TERM("'"), &fr_value_unescape_single);
1304
1305
0
  case '`':
1306
0
    return fr_sbuff_out_unescape_until(out, in, inlen, &FR_SBUFF_TERM("`"), &fr_value_unescape_backtick);
1307
1308
0
  case '/':
1309
0
    return fr_sbuff_out_unescape_until(out, in, inlen, &FR_SBUFF_TERM("/"), &fr_value_unescape_solidus);
1310
0
  }
1311
1312
0
  return fr_sbuff_out_bstrncpy(out, in, inlen);
1313
0
}
1314
1315
/** Performs byte order reversal for types that need it
1316
 *
1317
 * @param[in] dst Where to write the result.  May be the same as src.
1318
 * @param[in] src #fr_value_box_t containing an uint32 value.
1319
 * @return
1320
 *  - 0 on success.
1321
 *  - -1 on failure.
1322
 */
1323
int fr_value_box_hton(fr_value_box_t *dst, fr_value_box_t const *src)
1324
89.2k
{
1325
89.2k
  switch (src->type) {
1326
194
  case FR_TYPE_INT16:
1327
428
  case FR_TYPE_INT32:
1328
623
  case FR_TYPE_INT64:
1329
73.8k
  case FR_TYPE_UINT16:
1330
87.6k
  case FR_TYPE_UINT32:
1331
88.8k
  case FR_TYPE_UINT64:
1332
89.0k
  case FR_TYPE_FLOAT32:
1333
89.2k
  case FR_TYPE_FLOAT64:
1334
89.2k
  case FR_TYPE_DATE:
1335
89.2k
  case FR_TYPE_TIME_DELTA:
1336
89.2k
    break;
1337
1338
0
  case FR_TYPE_BOOL:
1339
0
  case FR_TYPE_UINT8:
1340
0
  case FR_TYPE_INT8:
1341
0
  case FR_TYPE_IPV4_ADDR:
1342
0
  case FR_TYPE_IPV4_PREFIX:
1343
0
  case FR_TYPE_IPV6_ADDR:
1344
0
  case FR_TYPE_IPV6_PREFIX:
1345
0
  case FR_TYPE_COMBO_IP_ADDR:
1346
0
  case FR_TYPE_COMBO_IP_PREFIX:
1347
0
  case FR_TYPE_IFID:
1348
0
  case FR_TYPE_ETHERNET:
1349
0
  case FR_TYPE_SIZE:
1350
0
    if (unlikely(fr_value_box_copy(NULL, dst, src) < 0)) return -1;
1351
0
    return 0;
1352
1353
0
  case FR_TYPE_NULL:
1354
0
    fr_value_box_init_null(dst);
1355
0
    return 0;
1356
1357
0
  case FR_TYPE_ATTR:
1358
0
  case FR_TYPE_OCTETS:
1359
0
  case FR_TYPE_STRING:
1360
0
  case FR_TYPE_INTERNAL:
1361
0
  case FR_TYPE_STRUCTURAL:
1362
0
    fr_assert_fail(NULL);
1363
0
    return -1; /* shouldn't happen */
1364
89.2k
  }
1365
1366
  /*
1367
   *  If we're not just flipping in place
1368
   *  initialise the destination box
1369
   *  with similar meta data as the src.
1370
   *
1371
   *  Don't use the copy meta data function
1372
   *  here as that doesn't initialise the
1373
   *  destination box.
1374
   */
1375
89.2k
  if (dst != src) fr_value_box_init(dst, src->type, src->enumv, src->tainted);
1376
1377
89.2k
  switch (src->type) {
1378
73.1k
  case FR_TYPE_UINT16:
1379
73.1k
    dst->vb_uint16 = htons(src->vb_uint16);
1380
73.1k
    break;
1381
1382
13.7k
  case FR_TYPE_UINT32:
1383
13.7k
    dst->vb_uint32 = htonl(src->vb_uint32);
1384
13.7k
    break;
1385
1386
1.20k
  case FR_TYPE_UINT64:
1387
1.20k
    dst->vb_uint64 = htonll(src->vb_uint64);
1388
1.20k
    break;
1389
1390
194
  case FR_TYPE_INT16:
1391
194
    dst->vb_int16 = htons(src->vb_int16);
1392
194
    break;
1393
1394
234
  case FR_TYPE_INT32:
1395
234
    dst->vb_int32 = htonl(src->vb_int32);
1396
234
    break;
1397
1398
195
  case FR_TYPE_INT64:
1399
195
    dst->vb_int64 = htonll(src->vb_int64);
1400
195
    break;
1401
1402
0
  case FR_TYPE_DATE:
1403
0
    dst->vb_date = fr_unix_time_wrap(htonll(fr_unix_time_unwrap(src->vb_date)));
1404
0
    break;
1405
1406
0
  case FR_TYPE_TIME_DELTA:
1407
0
    dst->vb_time_delta = fr_time_delta_wrap(htonll(fr_time_delta_unwrap(src->vb_time_delta)));
1408
0
    break;
1409
1410
195
  case FR_TYPE_FLOAT32:
1411
195
    dst->vb_float32 = htonl((uint32_t)src->vb_float32);
1412
195
    break;
1413
1414
205
  case FR_TYPE_FLOAT64:
1415
205
    dst->vb_float64 = htonll((uint64_t)src->vb_float64);
1416
205
    break;
1417
1418
0
  default:
1419
0
    fr_assert_fail(NULL);
1420
0
    return -1; /* shouldn't happen */
1421
89.2k
  }
1422
1423
89.2k
  return 0;
1424
89.2k
}
1425
1426
/** Get the size of the value held by the fr_value_box_t
1427
 *
1428
 * This is the length of the NETWORK presentation
1429
 */
1430
size_t fr_value_box_network_length(fr_value_box_t const *value)
1431
37.2k
{
1432
37.2k
  switch (value->type) {
1433
0
  case FR_TYPE_VARIABLE_SIZE:
1434
0
    if (value->enumv) {
1435
      /*
1436
       *  Fixed-width fields.
1437
       */
1438
0
      if (value->enumv->flags.length) {
1439
0
        return value->enumv->flags.length;
1440
0
      }
1441
1442
      /*
1443
       *  Clamp length at maximum we're allowed to encode.
1444
       */
1445
0
      if (da_is_length_field8(value->enumv)) {
1446
0
        if (value->vb_length > UINT8_MAX) return UINT8_MAX;
1447
1448
0
      } else if (da_is_length_field16(value->enumv)) {
1449
0
        if (value->vb_length > UINT16_MAX) return UINT16_MAX;
1450
0
      }
1451
0
    }
1452
0
    return value->vb_length;
1453
1454
    /*
1455
     *  These can have different encodings, depending on the underlying protocol.
1456
     */
1457
305
  case FR_TYPE_DATE:
1458
3.48k
  case FR_TYPE_TIME_DELTA:
1459
3.48k
    if (value->enumv) return value->enumv->flags.length;
1460
3.48k
    FALL_THROUGH;
1461
1462
37.2k
  default:
1463
37.2k
    fr_assert(network_min_size(value->type) != 0);
1464
37.2k
    return network_min_size(value->type);
1465
1466
0
  case FR_TYPE_TLV:
1467
0
  case FR_TYPE_STRUCT:
1468
0
  case FR_TYPE_VSA:
1469
0
  case FR_TYPE_VENDOR:
1470
0
  case FR_TYPE_INTERNAL:
1471
0
    fr_assert(0);
1472
0
    return -1;
1473
37.2k
  }
1474
37.2k
}
1475
1476
/** Encode a single value box, serializing its contents in generic network format
1477
 *
1478
 * The serialized form of #fr_value_box_t may not match the requirements of your protocol
1479
 * completely.  In cases where they do not, you should overload specific types in the
1480
 * function calling #fr_value_box_to_network.
1481
 *
1482
 * The general serialization rules are:
1483
 *
1484
 * - Octets are encoded in binary form (not hex).
1485
 * - Strings are encoded without the trailing \0 byte.
1486
 * - Integers are encoded big-endian.
1487
 * - Bools are encoded using one byte, with value 0x00 (false) or 0x01 (true).
1488
 * - Signed integers are encoded two's complement, with the MSB as the sign bit.
1489
 *   Byte order is big-endian.
1490
 * - Network addresses are encoded big-endian.
1491
 * - IPv4 prefixes are encoded with 1 byte for the prefix, then 4 bytes of address.
1492
 * - IPv6 prefixes are encoded with 1 byte for the scope_id, 1 byte for the prefix,
1493
 *   and 16 bytes of address.
1494
 * - Floats are encoded in IEEE-754 format with a big-endian byte order.  We rely
1495
 *   on the fact that the C standards require floats to be represented in IEEE-754
1496
 *   format in memory.
1497
 * - Dates are encoded as 16/32/64-bit unsigned UNIX timestamps.
1498
 * - time_deltas are encoded as 16/32/64-bit signed integers.
1499
 *
1500
 * #FR_TYPE_SIZE is not encodable, as it is system specific.
1501
 *
1502
 * This function will not encode structural types (TLVs, VSAs etc...).  These are usually
1503
 * specific to the protocol anyway.
1504
 *
1505
 *  All of the dictionary rules are respected.  string/octets can have
1506
 *  a fixed length (which is zero-padded if necessary), or can have an
1507
 *  8/16-bit "length" prefix.
1508
 *
1509
 * @param[out] dbuff  Where to write serialized data.
1510
 * @param[in] value to encode.
1511
 * @return
1512
 *  - 0 no bytes were written.
1513
 *  - >0 the number of bytes written to out.
1514
 *  - <0 the number of bytes we'd need in dbuff to complete the operation.
1515
 */
1516
ssize_t fr_value_box_to_network(fr_dbuff_t *dbuff, fr_value_box_t const *value)
1517
1.20M
{
1518
1.20M
  size_t    min, max;
1519
1.20M
  fr_dbuff_t  work_dbuff = FR_DBUFF(dbuff);
1520
1521
  /*
1522
   *  We cannot encode structural types here.
1523
   */
1524
1.20M
  if (!fr_type_is_leaf(value->type)) {
1525
0
  unsupported:
1526
0
    fr_strerror_printf("%s: Cannot encode type \"%s\"",
1527
0
           __FUNCTION__,
1528
0
           fr_type_to_str(value->type));
1529
0
    return FR_VALUE_BOX_NET_ERROR;
1530
0
  }
1531
1532
  /*
1533
   *  Variable length types
1534
   */
1535
1.20M
  switch (value->type) {
1536
935k
  case FR_TYPE_OCTETS:
1537
1.04M
  case FR_TYPE_STRING:
1538
1.04M
    max = value->vb_length;
1539
1540
    /*
1541
     *  Sometimes variable length *inside* the server
1542
     *  has maximum length on the wire.
1543
     */
1544
1.04M
    if (value->enumv) {
1545
1.04M
      if (value->enumv->flags.length) {
1546
        /*
1547
         *  The field is fixed size, and the data is smaller than that,  We zero-pad the field.
1548
         */
1549
4.38k
        if (max < value->enumv->flags.length) {
1550
1.18k
          FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, (uint8_t const *)value->datum.ptr, max);
1551
1.18k
          FR_DBUFF_MEMSET_RETURN(&work_dbuff, 0, value->enumv->flags.length - max);
1552
1.18k
          return fr_dbuff_set(dbuff, &work_dbuff);
1553
1554
3.19k
        } else if (max > value->enumv->flags.length) {
1555
          /*
1556
           *  Truncate the input to the maximum allowed length.
1557
           */
1558
0
          max = value->enumv->flags.length;
1559
0
        }
1560
1561
1.04M
      } else if (da_is_length_field8(value->enumv)) {
1562
        /*
1563
         *  Truncate the output to the max allowed for this field and encode the length.
1564
         */
1565
2.37k
        if (max > UINT8_MAX) max = UINT8_MAX;
1566
2.37k
        FR_DBUFF_IN_RETURN(&work_dbuff, (uint8_t) max);
1567
1568
1.04M
      } else if (da_is_length_field16(value->enumv)) {
1569
1570
334
        if (max > UINT16_MAX) max = UINT16_MAX;
1571
334
        FR_DBUFF_IN_RETURN(&work_dbuff, (uint16_t) max);
1572
334
      }
1573
1.04M
    }
1574
1575
1.04M
    FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, (uint8_t const *)value->datum.ptr, max);
1576
1.04M
    return fr_dbuff_set(dbuff, &work_dbuff);
1577
1578
    /*
1579
     *  The data can be encoded in a variety of widths.
1580
     */
1581
2.24k
  case FR_TYPE_DATE:
1582
14.7k
  case FR_TYPE_TIME_DELTA:
1583
14.7k
    if (value->enumv) {
1584
14.7k
      min = value->enumv->flags.length;
1585
14.7k
    } else {
1586
0
      min = 4;
1587
0
    }
1588
14.7k
    break;
1589
1590
146k
  default:
1591
146k
    fr_assert(network_min_size(value->type) != 0);
1592
146k
    min = network_min_size(value->type);
1593
146k
    break;
1594
1595
0
  case FR_TYPE_TLV:
1596
0
  case FR_TYPE_STRUCT:
1597
0
  case FR_TYPE_VSA:
1598
0
  case FR_TYPE_VENDOR:
1599
0
  case FR_TYPE_INTERNAL:
1600
0
    fr_assert(0);
1601
0
    return -1;
1602
1.20M
  }
1603
1604
  /*
1605
   *  We have to encode actual data here.
1606
   */
1607
161k
  fr_assert(min > 0);
1608
1609
161k
  switch (value->type) {
1610
10.6k
  case FR_TYPE_IPV4_ADDR:
1611
11.0k
  ipv4addr:
1612
11.0k
    FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff,
1613
11.0k
            (uint8_t const *)&value->vb_ip.addr.v4.s_addr,
1614
11.0k
            sizeof(value->vb_ip.addr.v4.s_addr));
1615
11.0k
    break;
1616
  /*
1617
   *  Needs special mangling
1618
   */
1619
11.0k
  case FR_TYPE_IPV4_PREFIX:
1620
194
  ipv4prefix:
1621
194
    FR_DBUFF_IN_RETURN(&work_dbuff, value->vb_ip.prefix);
1622
194
    FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff,
1623
194
            (uint8_t const *)&value->vb_ip.addr.v4.s_addr,
1624
194
            sizeof(value->vb_ip.addr.v4.s_addr));
1625
194
    break;
1626
1627
886
  case FR_TYPE_IPV6_ADDR:
1628
1.38k
  ipv6addr:
1629
1.38k
    if (value->vb_ip.scope_id > 0) FR_DBUFF_IN_RETURN(&work_dbuff, value->vb_ip.scope_id);
1630
1.37k
    FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, value->vb_ip.addr.v6.s6_addr, sizeof(value->vb_ip.addr.v6.s6_addr));
1631
1.37k
    break;
1632
1633
1.37k
  case FR_TYPE_IPV6_PREFIX:
1634
327
  ipv6prefix:
1635
327
    if (value->vb_ip.scope_id > 0) FR_DBUFF_IN_RETURN(&work_dbuff, value->vb_ip.scope_id);
1636
327
    FR_DBUFF_IN_RETURN(&work_dbuff, value->vb_ip.prefix);
1637
327
    FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, value->vb_ip.addr.v6.s6_addr, sizeof(value->vb_ip.addr.v6.s6_addr));
1638
327
    break;
1639
1640
2.13k
  case FR_TYPE_BOOL:
1641
2.13k
    FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, value->datum.boolean);
1642
2.13k
    break;
1643
1644
2.13k
  case FR_TYPE_COMBO_IP_ADDR:
1645
861
    switch (value->vb_ip.af) {
1646
367
    case AF_INET:
1647
367
      goto ipv4addr;
1648
1649
494
    case AF_INET6:
1650
494
      goto ipv6addr;
1651
1652
0
    default:
1653
0
      break;
1654
861
    }
1655
1656
0
    fr_strerror_const("Combo IP value missing af");
1657
0
    return 0;
1658
1659
118
  case FR_TYPE_COMBO_IP_PREFIX:
1660
118
    switch (value->vb_ip.af) {
1661
0
    case AF_INET:
1662
0
      goto ipv4prefix;
1663
1664
118
    case AF_INET6:
1665
118
      goto ipv6prefix;
1666
1667
0
    default:
1668
0
      break;
1669
118
    }
1670
1671
0
    fr_strerror_const("Combo IP value missing af");
1672
0
    return 0;
1673
1674
  /*
1675
   *  Already in network byte-order
1676
   */
1677
228
  case FR_TYPE_IFID:
1678
665
  case FR_TYPE_ETHERNET:
1679
40.8k
  case FR_TYPE_UINT8:
1680
42.0k
  case FR_TYPE_INT8:
1681
42.0k
    FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, fr_value_box_raw(value, value->type), min);
1682
42.0k
    break;
1683
1684
  /*
1685
   *  Needs a bytesex operation
1686
   */
1687
73.1k
  case FR_TYPE_UINT16:
1688
86.9k
  case FR_TYPE_UINT32:
1689
88.1k
  case FR_TYPE_UINT64:
1690
88.3k
  case FR_TYPE_INT16:
1691
88.6k
  case FR_TYPE_INT32:
1692
88.8k
  case FR_TYPE_INT64:
1693
89.0k
  case FR_TYPE_FLOAT32:
1694
89.2k
  case FR_TYPE_FLOAT64:
1695
89.2k
  {
1696
89.2k
    fr_value_box_t tmp;
1697
1698
89.2k
    fr_value_box_hton(&tmp, value);
1699
1700
89.2k
    FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, fr_value_box_raw(&tmp, value->type), min);
1701
89.2k
  }
1702
89.2k
    break;
1703
1704
89.2k
  case FR_TYPE_ATTR:
1705
0
  {
1706
0
    fr_value_box_t tmp, base;
1707
1708
    /*
1709
     *  For now, we only encode at depth 1.  The protocol-specific encoders need to do
1710
     *  something special for attributes at other depths.
1711
     */
1712
0
    if (value->vb_attr->depth != 1) {
1713
0
      fr_strerror_printf("Unsupported depth '%u' for encoding attribute %s",
1714
0
             value->vb_attr->depth, value->vb_attr->name);
1715
0
      return 0;
1716
0
    }
1717
1718
0
    switch (value->vb_attr->flags.length) {
1719
0
    case 1:
1720
0
      fr_value_box_init(&base, FR_TYPE_UINT8, NULL, false);
1721
0
      base.vb_uint8 = value->vb_attr->attr;
1722
0
      break;
1723
1724
0
    case 2:
1725
0
      fr_value_box_init(&base, FR_TYPE_UINT16, NULL, false);
1726
0
      base.vb_uint16 = value->vb_attr->attr;
1727
0
      break;
1728
1729
0
    case 4:
1730
0
      fr_value_box_init(&base, FR_TYPE_UINT32, NULL, false);
1731
0
      base.vb_uint32 = value->vb_attr->attr;
1732
0
      break;
1733
1734
0
    default:
1735
0
      fr_strerror_printf("Unsupported length '%d' for decoding attribute %s",
1736
0
             value->vb_attr->flags.length, value->vb_attr->name);
1737
0
      return 0;
1738
0
    }
1739
1740
0
    fr_value_box_hton(&tmp, &base);
1741
1742
0
    FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, fr_value_box_raw(&tmp, tmp.type), min);
1743
0
  }
1744
0
    break;
1745
1746
  /*
1747
   *  Dates and deltas are stored internally as
1748
   *  64-bit nanoseconds.  We have to convert to the
1749
   *  network format.  First by resolution (ns, us,
1750
   *  ms, s), and then by size (16/32/64-bit).
1751
   */
1752
2.24k
  case FR_TYPE_DATE:
1753
2.24k
  {
1754
2.24k
    uint64_t date = 0;
1755
2.24k
    fr_time_res_t res;
1756
1757
2.24k
    if (!value->enumv) {
1758
0
      res = FR_TIME_RES_SEC;
1759
2.24k
    } else {
1760
2.24k
      res = value->enumv->flags.flag_time_res;
1761
2.24k
    }
1762
2.24k
    date = fr_unix_time_to_integer(value->vb_date, res);
1763
1764
2.24k
    if (!value->enumv) {
1765
0
      goto date_size4;
1766
1767
2.24k
    } else switch (value->enumv->flags.length) {
1768
258
    case 2:
1769
258
      if (date > UINT16_MAX) date = UINT16_MAX;
1770
258
      FR_DBUFF_IN_RETURN(&work_dbuff, (int16_t) date);
1771
258
      break;
1772
1773
258
    date_size4:
1774
1.99k
    case 4:
1775
1.99k
      if (date > UINT32_MAX) date = UINT32_MAX;
1776
1.99k
      FR_DBUFF_IN_RETURN(&work_dbuff, (int32_t) date);
1777
1.99k
      break;
1778
1779
1.99k
    case 8:
1780
0
      FR_DBUFF_IN_RETURN(&work_dbuff, date);
1781
0
      break;
1782
1783
0
    default:
1784
0
      goto unsupported;
1785
2.24k
    }
1786
1787
2.24k
  }
1788
2.24k
    break;
1789
1790
12.5k
  case FR_TYPE_TIME_DELTA:
1791
12.5k
  {
1792
12.5k
    int64_t date = 0; /* may be negative */
1793
12.5k
    fr_time_res_t res = FR_TIME_RES_SEC;
1794
12.5k
    if (value->enumv) res = value->enumv->flags.flag_time_res;
1795
1796
12.5k
    date = fr_time_delta_to_integer(value->vb_time_delta, res);
1797
1798
12.5k
    if (!value->enumv) {
1799
0
      goto delta_size4;
1800
1801
12.5k
    } else if (!value->enumv->flags.is_unsigned) {
1802
7.71k
      switch (value->enumv->flags.length) {
1803
606
      case 2:
1804
606
        if (date < INT16_MIN) {
1805
0
          date = INT16_MIN;
1806
606
        } else if (date > INT16_MAX) {
1807
0
          date = INT16_MAX;
1808
0
        }
1809
606
        FR_DBUFF_IN_RETURN(&work_dbuff, (int16_t)date);
1810
606
        break;
1811
1812
606
      delta_size4:
1813
7.10k
      case 4:
1814
7.10k
        if (date < INT32_MIN) {
1815
0
          date = INT32_MIN;
1816
7.10k
        } else if (date > INT32_MAX) {
1817
0
          date = INT32_MAX;
1818
0
        }
1819
7.10k
        FR_DBUFF_IN_RETURN(&work_dbuff, (int32_t)date);
1820
7.10k
        break;
1821
1822
7.10k
      case 8:
1823
0
        FR_DBUFF_IN_RETURN(&work_dbuff, (int64_t)date);
1824
0
        break;
1825
1826
0
      default:
1827
0
        goto unsupported;
1828
7.71k
      }
1829
7.71k
    } else { /* time delta is unsigned! */
1830
4.79k
      switch (value->enumv->flags.length) {
1831
0
      case 2:
1832
0
        if (date < 0) {
1833
0
          date = 0;
1834
0
        } else if (date > UINT16_MAX) {
1835
0
          date = UINT16_MAX;
1836
0
        }
1837
0
        FR_DBUFF_IN_RETURN(&work_dbuff, (uint16_t)date);
1838
0
        break;
1839
1840
4.79k
      case 4:
1841
4.79k
        if (date < 0) {
1842
0
          date = 0;
1843
4.79k
        } else if (date > UINT32_MAX) {
1844
0
          date = UINT32_MAX;
1845
0
        }
1846
4.79k
        FR_DBUFF_IN_RETURN(&work_dbuff, (uint32_t)date);
1847
4.79k
        break;
1848
1849
4.79k
      case 8:
1850
0
        FR_DBUFF_IN_RETURN(&work_dbuff, (uint64_t)date);
1851
0
        break;
1852
1853
0
      default:
1854
0
        goto unsupported;
1855
4.79k
      }
1856
4.79k
    }
1857
12.5k
  }
1858
12.4k
    break;
1859
1860
12.4k
  case FR_TYPE_OCTETS:
1861
0
  case FR_TYPE_STRING:
1862
0
  case FR_TYPE_SIZE:
1863
0
  case FR_TYPE_NON_LEAF:
1864
0
    goto unsupported;
1865
161k
  }
1866
1867
161k
  return fr_dbuff_set(dbuff, &work_dbuff);
1868
161k
}
1869
1870
/** Decode a #fr_value_box_t from serialized binary data
1871
 *
1872
 * The general deserialization rules are:
1873
 *
1874
 * - Octets are decoded in binary form (not hex).
1875
 * - Strings are decoded without the trailing \0 byte. Strings must consist only of valid UTF8 chars.
1876
 * - Integers are decoded big-endian.
1877
 * - Bools are decoded using one byte, with value 0x00 (false) or 0x01 (true).
1878
 * - Signed integers are decoded two's complement, with the MSB as the sign bit.
1879
 *   Byte order is big-endian.
1880
 * - Network addresses are decoded big-endian.
1881
 * - IPv4 prefixes are decoded with 1 byte for the prefix, then 4 bytes of address.
1882
 * - IPv6 prefixes are decoded with 1 byte for the scope_id, 1 byte for the prefix,
1883
 *   and 16 bytes of address.
1884
 * - Floats are decoded in IEEE-754 format with a big-endian byte order.  We rely
1885
 *   on the fact that the C standards require floats to be represented in IEEE-754
1886
 *   format in memory.
1887
 * - Dates are decoded as 32bit unsigned UNIX timestamps.
1888
 *
1889
 *  All of the dictionary rules are respected.  string/octets can have
1890
 *  a fixed length, or can have an 8/16-bit "length" prefix.  If the
1891
 *  enumv is not an array, then the input # len MUST be the correct size
1892
 *  (not too large or small), otherwise an error is returned.
1893
 *
1894
 *  If the enumv is an array, then the input must have the minimum
1895
 *  length, and the number of bytes decoded is capped at the maximum
1896
 *  length allowed to be decoded.  This behavior allows the caller to
1897
 *  decode an array of values simply by calling this function in a
1898
 *  loop.
1899
 *
1900
 * @param[in] ctx Where to allocate any talloc buffers required.
1901
 * @param[out] dst  value_box to write the result to.
1902
 * @param[in] type  to decode data to.
1903
 * @param[in] enumv Aliases for values.
1904
 * @param[in] dbuff Binary data to decode.
1905
 * @param[in] len Length of data to decode.  For fixed length types we only
1906
 *      decode complete values.
1907
 * @param[in] tainted Whether the value came from a trusted source.
1908
 * @return
1909
 *  - >= 0 The number of bytes consumed.
1910
 *  - <0 - The negative offset where the error occurred.
1911
 *  - FR_VALUE_BOX_NET_OOM (negative value) - Out of memory.
1912
 */
1913
ssize_t fr_value_box_from_network(TALLOC_CTX *ctx,
1914
          fr_value_box_t *dst, fr_type_t type, fr_dict_attr_t const *enumv,
1915
          fr_dbuff_t *dbuff, size_t len,
1916
          bool tainted)
1917
4.04M
{
1918
4.04M
  size_t    min, max;
1919
4.04M
  fr_dbuff_t  work_dbuff = FR_DBUFF(dbuff);
1920
1921
4.04M
  min = network_min_size(type);
1922
4.04M
  max = network_max_size(type);
1923
1924
4.04M
  fr_assert(max > 0);
1925
1926
4.04M
  if (len < min) {
1927
23.3k
    fr_strerror_printf("Got truncated value parsing type \"%s\". "
1928
23.3k
           "Expected length >= %zu bytes, got %zu bytes",
1929
23.3k
           fr_type_to_str(type),
1930
23.3k
           min, len);
1931
23.3k
    return -(min);
1932
23.3k
  }
1933
1934
  /*
1935
   *  For array entries, we only decode one value at a time.
1936
   */
1937
4.02M
  if (len > max) {
1938
25.2k
    if (enumv && !enumv->flags.array) {
1939
6.47k
      fr_strerror_printf("Found trailing garbage parsing type \"%s\". "
1940
6.47k
             "Expected length <= %zu bytes, got %zu bytes",
1941
6.47k
             fr_type_to_str(type),
1942
6.47k
           max, len);
1943
6.47k
      return -(max);
1944
6.47k
    }
1945
1946
18.8k
    len = max;
1947
18.8k
  }
1948
1949
  /*
1950
   *  String / octets are special.
1951
   */
1952
4.01M
  if (fr_type_is_variable_size(type)) {
1953
3.75M
    size_t newlen = len;
1954
3.75M
    size_t offset = 0;
1955
1956
    /*
1957
     *  Decode fixed-width fields.
1958
     */
1959
3.75M
    if (enumv) {
1960
3.75M
      if (enumv->flags.length) {
1961
9.76k
        newlen = enumv->flags.length;
1962
1963
3.74M
      } else if (da_is_length_field8(enumv)) {
1964
6.89k
        uint8_t num = 0;
1965
1966
6.89k
        FR_DBUFF_OUT_RETURN(&num, &work_dbuff);
1967
6.89k
        newlen = num;
1968
6.89k
        offset = 1;
1969
1970
3.73M
      } else if (da_is_length_field16(enumv)) {
1971
776
        uint16_t num = 0;
1972
1973
776
        FR_DBUFF_OUT_RETURN(&num, &work_dbuff);
1974
684
        newlen = num;
1975
684
        offset = 2;
1976
684
      }
1977
3.75M
    }
1978
1979
    /*
1980
     *  If we need more data than exists, that's an error.
1981
     *
1982
     *  Otherwise, bound the decoding to the count we found.
1983
     */
1984
3.75M
    if (newlen > len) return -(newlen + offset);
1985
3.75M
    len = newlen;
1986
1987
3.75M
    switch (type) {
1988
134k
    case FR_TYPE_STRING:
1989
134k
      if (fr_value_box_bstrndup_dbuff(ctx, dst, enumv, &work_dbuff, len, tainted) < 0) {
1990
663
        return FR_VALUE_BOX_NET_OOM;
1991
663
      }
1992
134k
      return fr_dbuff_set(dbuff, &work_dbuff);
1993
1994
3.61M
    case FR_TYPE_OCTETS:
1995
3.61M
      if (fr_value_box_memdup_dbuff(ctx, dst, enumv, &work_dbuff, len, tainted) < 0) {
1996
46
        return FR_VALUE_BOX_NET_OOM;
1997
46
      }
1998
3.61M
      return fr_dbuff_set(dbuff, &work_dbuff);
1999
2000
0
    default:
2001
0
      return -1;
2002
3.75M
    }
2003
3.75M
  }
2004
2005
  /*
2006
   *  Pre-Initialise box for non-variable types
2007
   */
2008
257k
  fr_value_box_init(dst, type, enumv, tainted);
2009
257k
  switch (type) {
2010
  /*
2011
   *  Already in network byte order
2012
   */
2013
25.3k
  case FR_TYPE_IPV4_ADDR:
2014
26.0k
  ipv4addr:
2015
26.0k
    dst->vb_ip = (fr_ipaddr_t){
2016
26.0k
      .af = AF_INET,
2017
26.0k
      .prefix = 32,
2018
26.0k
    };
2019
26.0k
    FR_DBUFF_OUT_MEMCPY_RETURN((uint8_t *)&dst->vb_ip.addr.v4, &work_dbuff, len);
2020
26.0k
    break;
2021
2022
26.0k
  case FR_TYPE_IPV4_PREFIX:
2023
297
  ipv4prefix:
2024
297
    dst->vb_ip = (fr_ipaddr_t){
2025
297
      .af = AF_INET,
2026
297
    };
2027
297
    FR_DBUFF_OUT_RETURN(&dst->vb_ip.prefix, &work_dbuff);
2028
297
    FR_DBUFF_OUT_MEMCPY_RETURN((uint8_t *)&dst->vb_ip.addr.v4, &work_dbuff, len - 1);
2029
297
    break;
2030
2031
2.99k
  case FR_TYPE_IPV6_ADDR:
2032
3.69k
  ipv6addr:
2033
3.69k
    dst->vb_ip = (fr_ipaddr_t){
2034
3.69k
      .af = AF_INET6,
2035
3.69k
      .scope_id = 0,
2036
3.69k
      .prefix = 128
2037
3.69k
    };
2038
3.69k
    if (len == max) {
2039
1.02k
      uint8_t scope_id = 0;
2040
2041
1.02k
      FR_DBUFF_OUT_RETURN(&scope_id, &work_dbuff);
2042
1.02k
      dst->vb_ip.scope_id = scope_id;
2043
1.02k
      len--;
2044
1.02k
    }
2045
3.69k
    FR_DBUFF_OUT_MEMCPY_RETURN((uint8_t *)&dst->vb_ip.addr.v6, &work_dbuff, len);
2046
3.69k
    break;
2047
2048
3.69k
  case FR_TYPE_IPV6_PREFIX:
2049
328
  ipv6prefix:
2050
328
    dst->vb_ip = (fr_ipaddr_t){
2051
328
      .af = AF_INET6,
2052
328
      .scope_id = 0,
2053
328
    };
2054
328
    if (len == max) {
2055
67
      uint8_t scope_id = 0;
2056
2057
67
      FR_DBUFF_OUT_RETURN(&scope_id, &work_dbuff);
2058
67
      dst->vb_ip.scope_id = scope_id;
2059
67
      len--;
2060
67
    }
2061
328
    FR_DBUFF_OUT_RETURN(&dst->vb_ip.prefix, &work_dbuff);
2062
328
    FR_DBUFF_OUT_MEMCPY_RETURN((uint8_t *)&dst->vb_ip.addr.v6, &work_dbuff, len - 1);
2063
328
    break;
2064
2065
1.61k
  case FR_TYPE_COMBO_IP_ADDR:
2066
1.61k
    if ((len >= network_min_size(FR_TYPE_IPV6_ADDR)) &&
2067
696
        (len <= network_max_size(FR_TYPE_IPV6_ADDR))) goto ipv6addr;  /* scope is optional */
2068
922
    else if ((len >= network_min_size(FR_TYPE_IPV4_ADDR)) &&
2069
922
           (len <= network_max_size(FR_TYPE_IPV4_ADDR))) goto ipv4addr;
2070
2071
186
    fr_strerror_const("Invalid combo ip address value");
2072
186
    return -1;
2073
2074
120
  case FR_TYPE_COMBO_IP_PREFIX:
2075
120
    if ((len >= network_min_size(FR_TYPE_IPV6_PREFIX)) &&
2076
119
        (len <= network_max_size(FR_TYPE_IPV6_PREFIX))) goto ipv6prefix;  /* scope is optional */
2077
1
    else if ((len >= network_min_size(FR_TYPE_IPV4_PREFIX)) &&
2078
1
           (len <= network_max_size(FR_TYPE_IPV4_PREFIX))) goto ipv4prefix;
2079
2080
1
    fr_strerror_const("Invalid combo ip prefix value");
2081
1
    return -1;
2082
2083
3.04k
  case FR_TYPE_BOOL:
2084
3.04k
    {
2085
3.04k
      uint8_t val = 0;
2086
2087
3.04k
      FR_DBUFF_OUT_RETURN(&val, &work_dbuff);
2088
3.04k
      dst->datum.boolean = (val != 0);
2089
3.04k
    }
2090
0
    break;
2091
2092
304
  case FR_TYPE_IFID:
2093
1.21k
  case FR_TYPE_ETHERNET:
2094
1.21k
    FR_DBUFF_OUT_MEMCPY_RETURN(fr_value_box_raw(dst, type), &work_dbuff, len);
2095
1.21k
    break;
2096
2097
57.1k
  case FR_TYPE_UINT8:
2098
57.1k
    FR_DBUFF_OUT_RETURN(&dst->vb_uint8, &work_dbuff);
2099
57.1k
    break;
2100
2101
89.8k
  case FR_TYPE_UINT16:
2102
89.8k
    FR_DBUFF_OUT_RETURN(&dst->vb_uint16, &work_dbuff);
2103
89.8k
    break;
2104
2105
89.8k
  case FR_TYPE_UINT32:
2106
18.4k
    FR_DBUFF_OUT_RETURN(&dst->vb_uint32, &work_dbuff);
2107
18.4k
    break;
2108
2109
18.4k
  case FR_TYPE_UINT64:
2110
1.55k
    FR_DBUFF_OUT_RETURN(&dst->vb_uint64, &work_dbuff);
2111
1.55k
    break;
2112
2113
1.55k
  case FR_TYPE_INT8:
2114
1.17k
    FR_DBUFF_OUT_RETURN(&dst->vb_int8, &work_dbuff);
2115
1.17k
    break;
2116
2117
1.17k
  case FR_TYPE_INT16:
2118
194
    FR_DBUFF_OUT_RETURN(&dst->vb_int16, &work_dbuff);
2119
194
    break;
2120
2121
286
  case FR_TYPE_INT32:
2122
286
    FR_DBUFF_OUT_RETURN(&dst->vb_int32, &work_dbuff);
2123
286
    break;
2124
2125
286
  case FR_TYPE_INT64:
2126
195
    FR_DBUFF_OUT_RETURN(&dst->vb_int64, &work_dbuff);
2127
195
    break;
2128
2129
197
  case FR_TYPE_FLOAT32:
2130
197
    FR_DBUFF_OUT_RETURN(&dst->vb_float32, &work_dbuff);
2131
197
    break;
2132
2133
205
  case FR_TYPE_FLOAT64:
2134
205
    FR_DBUFF_OUT_RETURN(&dst->vb_float64, &work_dbuff);
2135
205
    break;
2136
2137
28.6k
  case FR_TYPE_ATTR:
2138
28.6k
    if (!enumv) {
2139
0
      fr_strerror_const("No enumv (i.e. root) passed to fr_value_box_from_network for type 'attribute'");
2140
0
      return -1;
2141
0
    }
2142
2143
    /*
2144
     *  Decode the number, and see if we can create a
2145
     *  matching attribute.
2146
     */
2147
28.6k
    {
2148
28.6k
      unsigned int num;
2149
28.6k
      uint8_t num8;
2150
28.6k
      uint16_t num16;
2151
28.6k
      uint32_t num32;
2152
2153
28.6k
      switch (enumv->flags.length) {
2154
27.9k
      case 1:
2155
27.9k
        FR_DBUFF_OUT_RETURN(&num8, &work_dbuff);
2156
27.9k
        num = num8;
2157
27.9k
        break;
2158
2159
718
      case 2:
2160
718
        FR_DBUFF_OUT_RETURN(&num16, &work_dbuff);
2161
718
        num = num16;
2162
718
        break;
2163
2164
0
      case 4:
2165
0
        FR_DBUFF_OUT_RETURN(&num32, &work_dbuff);
2166
0
        num = num32;
2167
0
        break;
2168
2169
0
      default:
2170
0
        fr_strerror_const("Unsupported parent length");
2171
0
        return -1;
2172
28.6k
      }
2173
2174
28.6k
      dst->vb_attr = fr_dict_attr_child_by_num(enumv, num);
2175
28.6k
      if (!dst->vb_attr) {
2176
9.03k
        dst->vb_attr = fr_dict_attr_unknown_raw_afrom_num(ctx, enumv, num);
2177
9.03k
        if (!dst->vb_attr) return -1;
2178
9.03k
      }
2179
2180
28.6k
      break;
2181
28.6k
    }
2182
2183
  /*
2184
   *  Dates and deltas are stored internally as
2185
   *  64-bit nanoseconds.  We have to convert from
2186
   *  the network format.  First by size
2187
   *  (16/32/64-bit), and then by resolution (ns,
2188
   *  us, ms, s).
2189
   */
2190
28.6k
  case FR_TYPE_DATE:
2191
4.02k
  {
2192
4.02k
    size_t length = 4;
2193
4.02k
    fr_time_res_t precision = FR_TIME_RES_SEC;
2194
4.02k
    uint64_t date;
2195
2196
4.02k
    if (enumv) {
2197
4.02k
      length = enumv->flags.length;
2198
4.02k
      precision = (fr_time_res_t)enumv->flags.flag_time_res;
2199
4.02k
    }
2200
2201
    /*
2202
     *  Input data doesn't match what we were told we
2203
     *  need.
2204
     */
2205
4.02k
    if (len > length) return -(length);
2206
2207
3.57k
    dst->enumv = enumv;
2208
2209
3.57k
    FR_DBUFF_OUT_UINT64V_RETURN(&date, &work_dbuff, length);
2210
2211
2.94k
    if (!fr_multiply(&date, date, fr_time_multiplier_by_res[precision])) {
2212
0
      fr_strerror_const("date would overflow");
2213
0
      return -1;
2214
0
    }
2215
2216
2.94k
    dst->vb_date = fr_unix_time_wrap(date);
2217
2.94k
  }
2218
0
    break;
2219
2220
21.2k
  case FR_TYPE_TIME_DELTA:
2221
21.2k
  {
2222
21.2k
    size_t length = 4;
2223
21.2k
    fr_time_res_t precision = FR_TIME_RES_SEC;
2224
21.2k
    int64_t date;
2225
2226
21.2k
    if (enumv) {
2227
21.2k
      length = enumv->flags.length;
2228
21.2k
      precision = (fr_time_res_t)enumv->flags.flag_time_res;
2229
21.2k
    }
2230
2231
    /*
2232
     *  Input data doesn't match what we were told we
2233
     *  need.
2234
     */
2235
21.2k
    if (len > length) return -(length);
2236
2237
21.1k
    dst->enumv = enumv;
2238
2239
21.1k
    if (!enumv || !enumv->flags.is_unsigned) {
2240
14.1k
      FR_DBUFF_OUT_INT64V_RETURN(&date, &work_dbuff, length);
2241
14.1k
    } else {
2242
7.02k
      uint64_t tmp;
2243
2244
      /*
2245
       *  Else it's an unsigned time delta, but
2246
       *  we do have to clamp it at the max
2247
       *  value for a signed 64-bit integer.
2248
       */
2249
7.02k
      FR_DBUFF_OUT_UINT64V_RETURN(&tmp, &work_dbuff, length);
2250
2251
7.02k
      if (tmp > INT64_MAX) tmp = INT64_MAX;
2252
2253
7.02k
      date = tmp;
2254
7.02k
    }
2255
2256
20.9k
    dst->vb_time_delta = fr_time_delta_wrap(fr_time_scale(date, precision));
2257
20.9k
  }
2258
0
    break;
2259
2260
0
  case FR_TYPE_STRING:
2261
0
  case FR_TYPE_OCTETS:
2262
0
    break;   /* Already dealt with */
2263
2264
1
  case FR_TYPE_SIZE:
2265
11
  case FR_TYPE_NON_LEAF:
2266
11
    fr_strerror_printf("Cannot decode type \"%s\" - Is not a value",
2267
11
           fr_type_to_str(type));
2268
11
    return -1;
2269
257k
  }
2270
2271
256k
  return fr_dbuff_set(dbuff, &work_dbuff);
2272
257k
}
2273
2274
/** Get a key from a value box
2275
 *
2276
 * @param[in,out] out - set to a small buffer on input.  If the callback has more data
2277
 *      than is available here, the callback can update "out" to point elsewhere
2278
 * @param[in,out] outlen The number of bits available in the initial buffer.  On output,
2279
 *      the number of bits available in the key
2280
 * @param[in] value the value box which contains the key
2281
 * @return
2282
 *  - <0 on error
2283
 *  - 0 on success
2284
 */
2285
int fr_value_box_to_key(uint8_t **out, size_t *outlen, fr_value_box_t const *value)
2286
0
{
2287
0
  ssize_t slen;
2288
0
  fr_dbuff_t dbuff;
2289
2290
0
  switch (value->type) {
2291
0
  case FR_TYPE_BOOL:
2292
0
    if (*outlen < 8) return -1;
2293
2294
0
    *out[0] = (value->vb_bool) << 7;
2295
0
    *outlen = 1;
2296
0
    break;
2297
2298
0
  case FR_TYPE_INTEGER_EXCEPT_BOOL:
2299
0
    if (*outlen < (fr_value_box_network_sizes[value->type][1] * 8)) return -1;
2300
2301
    /*
2302
     *  Integers are put into network byte order.
2303
     */
2304
0
    fr_dbuff_init(&dbuff, *out, *outlen >> 3);
2305
2306
0
    slen = fr_value_box_to_network(&dbuff, value);
2307
0
    if (slen < 0) return -1;
2308
0
    *outlen = slen * 8; /* bits not bytes */
2309
0
    break;
2310
2311
0
  case FR_TYPE_IP:
2312
    /*
2313
     *  IPs are already in network byte order.
2314
     */
2315
0
    *out = UNCONST(uint8_t *, &value->vb_ip.addr);
2316
0
    *outlen = value->vb_ip.prefix;
2317
0
    break;
2318
2319
0
  case FR_TYPE_STRING:
2320
0
  case FR_TYPE_OCTETS:
2321
0
    *out = value->datum.ptr;
2322
0
    *outlen = value->vb_length * 8;
2323
0
    break;
2324
2325
0
  case FR_TYPE_ETHERNET:
2326
0
    *out = UNCONST(uint8_t *, &value->vb_ether[0]);
2327
0
    *outlen = sizeof(value->vb_ether) * 8;
2328
0
    break;
2329
2330
0
  default:
2331
0
    fr_strerror_printf("Invalid data type '%s' for getting key",
2332
0
           fr_type_to_str(value->type));
2333
0
    return -1;
2334
0
  }
2335
2336
0
  return 0;
2337
0
}
2338
2339
/** Convert octets to a fixed size value box value
2340
 *
2341
 * All fixed size types are allowed.
2342
 *
2343
 * @param dst   Where to write result of casting.
2344
 * @param dst_type  to cast to.
2345
 * @param dst_enumv enumeration values.
2346
 * @param src   Input data.
2347
 */
2348
static int fr_value_box_fixed_size_from_octets(fr_value_box_t *dst,
2349
                fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2350
                fr_value_box_t const *src)
2351
0
{
2352
0
  uint8_t *ptr;
2353
2354
0
  if (!fr_type_is_fixed_size(dst_type)) if (!fr_cond_assert(false)) return -1;
2355
2356
0
  if (src->vb_length > network_max_size(dst_type)) {
2357
0
    fr_strerror_printf("Invalid cast from %s to %s.  Source length %zu is greater than "
2358
0
           "destination type size %zu",
2359
0
           fr_type_to_str(src->type),
2360
0
           fr_type_to_str(dst_type),
2361
0
           src->vb_length,
2362
0
           network_max_size(dst_type));
2363
0
    return -1;
2364
0
  }
2365
2366
0
  fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
2367
2368
  /*
2369
   *  No data to copy means just reset it to zero.
2370
   */
2371
0
  if (!src->vb_length) return 0;
2372
2373
0
  ptr = (uint8_t *) &dst->datum;
2374
2375
  /*
2376
   *  If the source is too small, just left-fill with zeroes.
2377
   */
2378
0
  if (src->vb_length < network_min_size(dst_type)) {
2379
0
    ptr += network_min_size(dst_type) - src->vb_length;
2380
0
  }
2381
2382
  /*
2383
   *  Copy the raw octets into the datum of a value_box
2384
   *  inverting bytesex for uint32s (if LE).
2385
   */
2386
0
  memcpy(ptr, src->vb_octets, src->vb_length);
2387
0
  fr_value_box_hton(dst, dst);
2388
2389
0
  return 0;
2390
0
}
2391
2392
/** v4 to v6 mapping prefix
2393
 *
2394
 * Part of the IPv6 range is allocated to represent IPv4 addresses.
2395
 */
2396
static uint8_t const v4_v6_map[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2397
             0x00, 0x00, 0x00, 0x00, 0xff, 0xff };
2398
2399
2400
/** Convert any supported type to a string
2401
 *
2402
 * All non-structural types are allowed.
2403
 *
2404
 * @param ctx   unused.
2405
 * @param dst   Where to write result of casting.
2406
 * @param dst_type  to cast to.
2407
 * @param dst_enumv enumeration values.
2408
 * @param src   Input data.
2409
 */
2410
static inline int fr_value_box_cast_to_strvalue(TALLOC_CTX *ctx, fr_value_box_t *dst,
2411
            fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2412
            fr_value_box_t const *src)
2413
0
{
2414
0
  if (!fr_cond_assert(dst_type == FR_TYPE_STRING)) return -1;
2415
2416
0
  fr_value_box_init(dst, FR_TYPE_STRING, dst_enumv, false);
2417
2418
0
  switch (src->type) {
2419
  /*
2420
   *  The presentation format of octets is hex
2421
   *  What we actually want here is the raw string
2422
   */
2423
0
  case FR_TYPE_OCTETS:
2424
0
    fr_value_box_safety_copy(dst, src);
2425
0
    return fr_value_box_bstrndup(ctx, dst, dst_enumv,
2426
0
               (char const *)src->vb_octets, src->vb_length, src->tainted);
2427
2428
0
  case FR_TYPE_GROUP:
2429
0
    return fr_value_box_list_concat_in_place(ctx,
2430
0
               dst, UNCONST(fr_value_box_list_t *, &src->vb_group),
2431
0
               FR_TYPE_STRING,
2432
0
               FR_VALUE_BOX_LIST_NONE, false,
2433
0
               SIZE_MAX);
2434
2435
  /*
2436
   *  Get the presentation format
2437
   */
2438
0
  default:
2439
0
  {
2440
0
    char *str;
2441
2442
0
    fr_value_box_aprint(ctx, &str, src, NULL);
2443
0
    if (unlikely(!str)) return -1;
2444
2445
0
    fr_value_box_safety_copy_changed(dst, src);
2446
0
    return fr_value_box_bstrdup_buffer_shallow(NULL, dst, dst_enumv, str, src->tainted);
2447
0
  }
2448
0
  }
2449
0
}
2450
2451
/** Convert any supported type to octets
2452
 *
2453
 * All non-structural types are allowed.
2454
 *
2455
 * @param ctx   unused.
2456
 * @param dst   Where to write result of casting.
2457
 * @param dst_type  to cast to.
2458
 * @param dst_enumv enumeration values.
2459
 * @param src   Input data.
2460
 */
2461
static inline int fr_value_box_cast_to_octets(TALLOC_CTX *ctx, fr_value_box_t *dst,
2462
                fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2463
                fr_value_box_t const *src)
2464
0
{
2465
0
  if (!fr_cond_assert(dst_type == FR_TYPE_OCTETS)) return -1;
2466
2467
0
  fr_value_box_init(dst, FR_TYPE_OCTETS, dst_enumv, false);
2468
0
  fr_value_box_safety_copy_changed(dst, src);
2469
2470
0
  switch (src->type) {
2471
  /*
2472
   *  <string> (excluding terminating \0)
2473
   */
2474
0
  case FR_TYPE_STRING:
2475
0
    fr_value_box_safety_copy(dst, src);
2476
0
    return fr_value_box_memdup(ctx, dst, dst_enumv,
2477
0
             (uint8_t const *)src->vb_strvalue, src->vb_length, src->tainted);
2478
2479
0
  case FR_TYPE_GROUP:
2480
0
    return fr_value_box_list_concat_in_place(ctx,
2481
0
               dst, UNCONST(fr_value_box_list_t *, &src->vb_group),
2482
0
               FR_TYPE_OCTETS,
2483
0
               FR_VALUE_BOX_LIST_NONE, false,
2484
0
               SIZE_MAX);
2485
  /*
2486
   *  <4 bytes address>
2487
   */
2488
0
  case FR_TYPE_IPV4_ADDR:
2489
0
    return fr_value_box_memdup(ctx, dst, dst_enumv,
2490
0
             (uint8_t const *)&src->vb_ip.addr.v4.s_addr,
2491
0
             sizeof(src->vb_ip.addr.v4.s_addr), src->tainted);
2492
2493
  /*
2494
   *  <1 uint8 prefix> + <4 bytes address>
2495
   */
2496
0
  case FR_TYPE_IPV4_PREFIX:
2497
0
  {
2498
0
    uint8_t *bin;
2499
2500
0
    if (fr_value_box_mem_alloc(ctx, &bin, dst, dst_enumv,
2501
0
             sizeof(src->vb_ip.addr.v4.s_addr) + 1, src->tainted) < 0) return -1;
2502
2503
0
    bin[0] = src->vb_ip.prefix;
2504
0
    memcpy(&bin[1], (uint8_t const *)&src->vb_ip.addr.v4.s_addr, sizeof(src->vb_ip.addr.v4.s_addr));
2505
0
  }
2506
0
    return 0;
2507
2508
  /*
2509
   *  <16 bytes address>
2510
   */
2511
0
  case FR_TYPE_IPV6_ADDR:
2512
0
    return fr_value_box_memdup(ctx, dst, dst_enumv,
2513
0
             (uint8_t const *)src->vb_ip.addr.v6.s6_addr,
2514
0
             sizeof(src->vb_ip.addr.v6.s6_addr), src->tainted);
2515
2516
  /*
2517
   *  <1 uint8 prefix> + <1 uint8 scope> + <16 bytes address>
2518
   */
2519
0
  case FR_TYPE_IPV6_PREFIX:
2520
0
  {
2521
0
    uint8_t *bin;
2522
2523
0
    if (fr_value_box_mem_alloc(ctx, &bin, dst, dst_enumv,
2524
0
             sizeof(src->vb_ip.addr.v6.s6_addr) + 2, src->tainted) < 0) return -1;
2525
0
    bin[0] = src->vb_ip.scope_id;
2526
0
    bin[1] = src->vb_ip.prefix;
2527
0
    memcpy(&bin[2], src->vb_ip.addr.v6.s6_addr, sizeof(src->vb_ip.addr.v6.s6_addr));
2528
0
  }
2529
0
    return 0;
2530
2531
  /*
2532
   *  Get the raw binary in memory representation
2533
   */
2534
0
  case FR_TYPE_NUMERIC:
2535
0
  {
2536
0
    fr_value_box_t tmp;
2537
2538
0
    fr_value_box_hton(&tmp, src); /* Flip any numeric representations */
2539
0
    return fr_value_box_memdup(ctx, dst, dst_enumv,
2540
0
             fr_value_box_raw(&tmp, src->type),
2541
0
             fr_value_box_field_sizes[src->type], src->tainted);
2542
0
  }
2543
2544
0
  case FR_TYPE_TLV:
2545
0
  case FR_TYPE_STRUCT:
2546
0
  case FR_TYPE_VSA:
2547
0
  case FR_TYPE_VENDOR:
2548
0
  case FR_TYPE_UNION:
2549
0
  case FR_TYPE_INTERNAL:
2550
0
  case FR_TYPE_NULL:
2551
0
  case FR_TYPE_ATTR:
2552
0
  case FR_TYPE_COMBO_IP_ADDR: /* the types should have been realized to ipv4 / ipv6 */
2553
0
  case FR_TYPE_COMBO_IP_PREFIX:
2554
0
  case FR_TYPE_OCTETS:  /* handled above*/
2555
0
    break;
2556
2557
2558
    /* Not the same talloc_memdup call as above.  The above memdup reads data from the dst */
2559
0
  case FR_TYPE_IFID:
2560
0
  case FR_TYPE_ETHERNET:
2561
0
    return fr_value_box_memdup(ctx, dst, dst_enumv,
2562
0
             fr_value_box_raw(src, src->type),
2563
0
             fr_value_box_field_sizes[src->type], src->tainted);
2564
0
  }
2565
2566
0
  fr_assert(0);
2567
0
  return -1;
2568
0
}
2569
2570
#define CAST_IP_FIX_COMBO   \
2571
0
  case FR_TYPE_COMBO_IP_ADDR: \
2572
0
    if (src->vb_ip.af == AF_INET) { \
2573
0
      src_type = FR_TYPE_IPV4_ADDR; \
2574
0
    } else if (src->vb_ip.af == AF_INET6) { \
2575
0
      src_type = FR_TYPE_IPV6_ADDR; \
2576
0
    } \
2577
0
    break; \
2578
0
  case FR_TYPE_COMBO_IP_PREFIX: \
2579
0
    if (src->vb_ip.af == AF_INET) { \
2580
0
      src_type = FR_TYPE_IPV4_PREFIX; \
2581
0
    } else if (src->vb_ip.af == AF_INET6) { \
2582
0
      src_type = FR_TYPE_IPV6_PREFIX; \
2583
0
    } \
2584
0
    break
2585
2586
2587
static inline int fr_value_box_cast_unsupported(fr_type_t dst, fr_type_t src)
2588
0
{
2589
0
  fr_strerror_printf("Invalid cast from %s to %s.  Unsupported",
2590
0
         fr_type_to_str(src),
2591
0
         fr_type_to_str(dst));
2592
0
  return -1;
2593
0
}
2594
2595
2596
/** Convert any supported type to an IPv4 address
2597
 *
2598
 * Allowed input types are:
2599
 * - FR_TYPE_IPV6_ADDR (with v4 prefix).
2600
 * - FR_TYPE_IPV4_PREFIX (with 32bit mask).
2601
 * - FR_TYPE_IPV6_PREFIX (with v4 prefix and 128bit mask).
2602
 * - FR_TYPE_OCTETS (of length 4).
2603
 * - FR_TYPE_UINT32
2604
 *
2605
 * @param ctx   unused.
2606
 * @param dst   Where to write result of casting.
2607
 * @param dst_type  to cast to.
2608
 * @param dst_enumv enumeration values.
2609
 * @param src   Input data.
2610
 */
2611
static inline int fr_value_box_cast_to_ipv4addr(TALLOC_CTX *ctx, fr_value_box_t *dst,
2612
            fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2613
            fr_value_box_t const *src)
2614
0
{
2615
0
  fr_type_t src_type = src->type;
2616
2617
0
  fr_assert(dst_type == FR_TYPE_IPV4_ADDR);
2618
0
  fr_value_box_safety_copy_changed(dst, src);
2619
2620
0
  switch (src_type) {
2621
0
  case FR_TYPE_STRING:
2622
0
    return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
2623
0
               src->vb_strvalue, src->vb_length,
2624
0
               NULL);
2625
2626
0
  CAST_IP_FIX_COMBO;
2627
2628
0
  default:
2629
0
    break;
2630
0
  }
2631
2632
  /*
2633
   *  Pre-initialise box for non-variable types
2634
   */
2635
0
  fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
2636
0
  dst->vb_ip.af = AF_INET;
2637
0
  dst->vb_ip.prefix = 32;
2638
0
  dst->vb_ip.scope_id = 0;
2639
2640
0
  switch (src_type) {
2641
0
  case FR_TYPE_IPV6_ADDR:
2642
0
    if (memcmp(src->vb_ip.addr.v6.s6_addr, v4_v6_map, sizeof(v4_v6_map)) != 0) {
2643
0
    bad_v6_prefix_map:
2644
0
      fr_strerror_printf("Invalid cast from %s to %s.  No IPv4-IPv6 mapping prefix",
2645
0
             fr_type_to_str(src->type),
2646
0
             fr_type_to_str(dst_type));
2647
0
      return -1;
2648
0
    }
2649
2650
0
    memcpy(&dst->vb_ip.addr.v4, &src->vb_ip.addr.v6.s6_addr[sizeof(v4_v6_map)],
2651
0
           sizeof(dst->vb_ip.addr.v4));
2652
2653
0
    break;
2654
2655
0
  case FR_TYPE_IPV4_PREFIX:
2656
0
    if (src->vb_ip.prefix != 32) {
2657
0
      fr_strerror_printf("Invalid cast from %s to %s.  Only /32 (not %i/) prefixes may be "
2658
0
             "cast to IP address types",
2659
0
             fr_type_to_str(src->type),
2660
0
             fr_type_to_str(dst_type),
2661
0
             src->vb_ip.prefix);
2662
0
      return -1;
2663
0
    }
2664
0
    FALL_THROUGH;
2665
2666
0
  case FR_TYPE_IPV4_ADDR:   /* Needed for handling combo addresses */
2667
0
    memcpy(&dst->vb_ip.addr.v4, &src->vb_ip.addr.v4, sizeof(dst->vb_ip.addr.v4));
2668
0
    break;
2669
2670
0
  case FR_TYPE_IPV6_PREFIX:
2671
0
    if (src->vb_ip.prefix != 128) {
2672
0
      fr_strerror_printf("Invalid cast from %s to %s.  Only /128 (not /%i) prefixes may be "
2673
0
             "cast to IP address types",
2674
0
             fr_type_to_str(src->type),
2675
0
             fr_type_to_str(dst_type),
2676
0
             src->vb_ip.prefix);
2677
0
      return -1;
2678
0
    }
2679
0
    if (memcmp(&src->vb_ip.addr.v6.s6_addr, v4_v6_map, sizeof(v4_v6_map)) != 0) goto bad_v6_prefix_map;
2680
0
    memcpy(&dst->vb_ip.addr.v4, &src->vb_ip.addr.v6.s6_addr[sizeof(v4_v6_map)],
2681
0
           sizeof(dst->vb_ip.addr.v4));
2682
0
    break;
2683
2684
0
  case FR_TYPE_OCTETS:
2685
0
    if (src->vb_length != sizeof(dst->vb_ip.addr.v4.s_addr)) {
2686
0
      fr_strerror_printf("Invalid cast from %s to %s.  Needed octet string of length %zu, got %zu",
2687
0
             fr_type_to_str(src->type),
2688
0
             fr_type_to_str(dst_type),
2689
0
             sizeof(dst->vb_ip.addr.v4.s_addr), src->vb_length);
2690
0
      return -1;
2691
0
    }
2692
0
    memcpy(&dst->vb_ip.addr.v4, src->vb_octets, sizeof(dst->vb_ip.addr.v4.s_addr));
2693
0
    break;
2694
2695
0
  case FR_TYPE_UINT32:
2696
0
  {
2697
0
    uint32_t net;
2698
2699
0
    net = ntohl(src->vb_uint32);
2700
0
    memcpy(&dst->vb_ip.addr.v4, (uint8_t *)&net, sizeof(dst->vb_ip.addr.v4.s_addr));
2701
0
  }
2702
0
    break;
2703
2704
0
  default:
2705
0
    return fr_value_box_cast_unsupported(dst_type, src->type);
2706
0
  }
2707
2708
0
  return 0;
2709
0
}
2710
2711
/** Convert any supported type to an IPv6 address
2712
 *
2713
 * Allowed input types are:
2714
 * - FR_TYPE_IPV4_ADDR
2715
 * - FR_TYPE_IPV4_PREFIX (with 32bit mask).
2716
 * - FR_TYPE_IPV6_PREFIX (with 128bit mask).
2717
 * - FR_TYPE_OCTETS (of length 16).
2718
 *
2719
 * @param ctx   unused.
2720
 * @param dst   Where to write result of casting.
2721
 * @param dst_type  to cast to.
2722
 * @param dst_enumv enumeration values.
2723
 * @param src   Input data.
2724
 */
2725
static inline int fr_value_box_cast_to_ipv4prefix(TALLOC_CTX *ctx, fr_value_box_t *dst,
2726
              fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2727
              fr_value_box_t const *src)
2728
1.00k
{
2729
1.00k
  fr_type_t src_type = src->type;
2730
2731
1.00k
  fr_assert(dst_type == FR_TYPE_IPV4_PREFIX);
2732
1.00k
  fr_value_box_safety_copy_changed(dst, src);
2733
2734
1.00k
  switch (src_type) {
2735
0
  case FR_TYPE_STRING:
2736
0
    return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
2737
0
               src->vb_strvalue, src->vb_length,
2738
0
               NULL);
2739
2740
0
  CAST_IP_FIX_COMBO;
2741
2742
1.00k
  default:
2743
1.00k
    break;
2744
1.00k
  }
2745
2746
  /*
2747
   *  Pre-initialise box for non-variable types
2748
   */
2749
1.00k
  fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
2750
1.00k
  dst->vb_ip.af = AF_INET;
2751
1.00k
  dst->vb_ip.scope_id = 0;
2752
2753
1.00k
  switch (src_type) {
2754
0
  case FR_TYPE_IPV4_PREFIX:   /* Needed for handling combo prefixes */
2755
0
    dst->vb_ip.prefix = src->vb_ip.prefix;
2756
0
    FALL_THROUGH;
2757
2758
1.00k
  case FR_TYPE_IPV4_ADDR:
2759
1.00k
    memcpy(&dst->vb_ip, &src->vb_ip, sizeof(dst->vb_ip));
2760
1.00k
    break;
2761
2762
  /*
2763
   *  Copy the last four bytes, to make an IPv4prefix
2764
   */
2765
0
  case FR_TYPE_IPV6_ADDR:
2766
0
    if (memcmp(src->vb_ip.addr.v6.s6_addr, v4_v6_map, sizeof(v4_v6_map)) != 0) {
2767
0
    bad_v6_prefix_map:
2768
0
      fr_strerror_printf("Invalid cast from %s to %s.  No IPv4-IPv6 mapping prefix",
2769
0
             fr_type_to_str(src->type),
2770
0
             fr_type_to_str(dst_type));
2771
0
      return -1;
2772
0
    }
2773
0
    memcpy(&dst->vb_ip.addr.v4.s_addr, &src->vb_ip.addr.v6.s6_addr[sizeof(v4_v6_map)],
2774
0
           sizeof(dst->vb_ip.addr.v4.s_addr));
2775
0
    dst->vb_ip.prefix = 32;
2776
0
    break;
2777
2778
0
  case FR_TYPE_IPV6_PREFIX:
2779
0
    if (memcmp(src->vb_ip.addr.v6.s6_addr, v4_v6_map, sizeof(v4_v6_map)) != 0) goto bad_v6_prefix_map;
2780
2781
0
    if (src->vb_ip.prefix < (sizeof(v4_v6_map) << 3)) {
2782
0
      fr_strerror_printf("Invalid cast from %s to %s. Expected prefix >= %u bits got %u bits",
2783
0
             fr_type_to_str(src->type),
2784
0
             fr_type_to_str(dst_type),
2785
0
             (unsigned int)(sizeof(v4_v6_map) << 3), src->vb_ip.prefix);
2786
0
      return -1;
2787
0
    }
2788
0
    memcpy(&dst->vb_ip.addr.v4.s_addr, &src->vb_ip.addr.v6.s6_addr[sizeof(v4_v6_map)],
2789
0
           sizeof(dst->vb_ip.addr.v4.s_addr));
2790
2791
    /*
2792
     *  Subtract the bits used by the v4_v6_map to get the v4 prefix bits
2793
     */
2794
0
    dst->vb_ip.prefix = src->vb_ip.prefix - (sizeof(v4_v6_map) << 3);
2795
0
    break;
2796
2797
0
  case FR_TYPE_OCTETS:
2798
0
    if (src->vb_length != sizeof(dst->vb_ip.addr.v4.s_addr) + 1) {
2799
0
      fr_strerror_printf("Invalid cast from %s to %s.  Needed octet string of length %zu, got %zu",
2800
0
             fr_type_to_str(src->type),
2801
0
             fr_type_to_str(dst_type),
2802
0
             sizeof(dst->vb_ip.addr.v4.s_addr) + 1, src->vb_length);
2803
0
      return -1;
2804
0
    }
2805
0
    dst->vb_ip.prefix = src->vb_octets[0];
2806
0
    memcpy(&dst->vb_ip.addr.v4, &src->vb_octets[1], sizeof(dst->vb_ip.addr.v4.s_addr));
2807
0
    break;
2808
2809
0
  case FR_TYPE_UINT32:
2810
0
  {
2811
0
    uint32_t net;
2812
2813
0
    net = ntohl(src->vb_uint32);
2814
0
    memcpy(&dst->vb_ip.addr.v4, (uint8_t *)&net, sizeof(dst->vb_ip.addr.v4.s_addr));
2815
0
    dst->vb_ip.prefix = 32;
2816
0
    break;
2817
0
  }
2818
2819
0
  default:
2820
0
    return fr_value_box_cast_unsupported(dst_type, src->type);
2821
1.00k
  }
2822
2823
1.00k
  return 0;
2824
1.00k
}
2825
2826
/** Convert any supported type to an IPv6 address
2827
 *
2828
 * Allowed input types are:
2829
 * - FR_TYPE_IPV4_ADDR
2830
 * - FR_TYPE_IPV4_PREFIX (with 32bit mask).
2831
 * - FR_TYPE_IPV6_PREFIX (with 128bit mask).
2832
 * - FR_TYPE_OCTETS (of length 16).
2833
 *
2834
 * @param ctx   unused.
2835
 * @param dst   Where to write result of casting.
2836
 * @param dst_type  to cast to.
2837
 * @param dst_enumv enumeration values.
2838
 * @param src   Input data.
2839
 */
2840
static inline int fr_value_box_cast_to_ipv6addr(TALLOC_CTX *ctx, fr_value_box_t *dst,
2841
            fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2842
            fr_value_box_t const *src)
2843
0
{
2844
0
  fr_type_t src_type = src->type;
2845
2846
0
  static_assert((sizeof(v4_v6_map) + sizeof(src->vb_ip.addr.v4)) <=
2847
0
          sizeof(src->vb_ip.addr.v6), "IPv6 storage too small");
2848
2849
0
  fr_assert(dst_type == FR_TYPE_IPV6_ADDR);
2850
0
  fr_value_box_safety_copy_changed(dst, src);
2851
2852
0
  switch (src_type) {
2853
0
  case FR_TYPE_STRING:
2854
0
    return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
2855
0
               src->vb_strvalue, src->vb_length,
2856
0
               NULL);
2857
2858
0
  CAST_IP_FIX_COMBO;
2859
2860
0
  default:
2861
0
    break;
2862
0
  }
2863
2864
  /*
2865
   *  Pre-initialise box for non-variable types
2866
   */
2867
0
  fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
2868
0
  dst->vb_ip.af = AF_INET6;
2869
0
  dst->vb_ip.prefix = 128;
2870
2871
0
  switch (src_type) {
2872
0
  case FR_TYPE_IPV4_ADDR:
2873
0
  {
2874
0
    uint8_t *p = dst->vb_ip.addr.v6.s6_addr;
2875
2876
    /* Add the v4/v6 mapping prefix */
2877
0
    memcpy(p, v4_v6_map, sizeof(v4_v6_map));
2878
0
    p += sizeof(v4_v6_map);
2879
0
    memcpy(p, (uint8_t const *)&src->vb_ip.addr.v4.s_addr, sizeof(src->vb_ip.addr.v4.s_addr));
2880
0
    dst->vb_ip.scope_id = 0;
2881
0
  }
2882
0
    break;
2883
2884
0
  case FR_TYPE_IPV4_PREFIX:
2885
0
  {
2886
0
    uint8_t *p = dst->vb_ip.addr.v6.s6_addr;
2887
2888
0
    if (src->vb_ip.prefix != 32) {
2889
0
      fr_strerror_printf("Invalid cast from %s to %s.  Only /32 (not /%i) prefixes may be "
2890
0
               "cast to IP address types",
2891
0
               fr_type_to_str(src->type),
2892
0
             fr_type_to_str(dst_type),
2893
0
             src->vb_ip.prefix);
2894
0
      return -1;
2895
0
    }
2896
2897
    /* Add the v4/v6 mapping prefix */
2898
0
    memcpy(p, v4_v6_map, sizeof(v4_v6_map));
2899
0
    p += sizeof(v4_v6_map);
2900
0
    memcpy(p, (uint8_t const *)&src->vb_ip.addr.v4.s_addr, sizeof(src->vb_ip.addr.v4.s_addr));
2901
0
    dst->vb_ip.scope_id = 0;
2902
0
  }
2903
0
    break;
2904
2905
0
  case FR_TYPE_IPV6_PREFIX:
2906
0
    if (src->vb_ip.prefix != 128) {
2907
0
      fr_strerror_printf("Invalid cast from %s to %s.  Only /128 (not /%i) prefixes may be "
2908
0
               "cast to IP address types",
2909
0
               fr_type_to_str(src->type),
2910
0
             fr_type_to_str(dst_type),
2911
0
             src->vb_ip.prefix);
2912
0
      return -1;
2913
0
    }
2914
0
    FALL_THROUGH;
2915
2916
0
  case FR_TYPE_IPV6_ADDR:   /* Needed for handling combo addresses */
2917
0
    memcpy(dst->vb_ip.addr.v6.s6_addr, src->vb_ip.addr.v6.s6_addr,
2918
0
           sizeof(dst->vb_ip.addr.v6.s6_addr));
2919
0
    dst->vb_ip.scope_id = src->vb_ip.scope_id;
2920
0
    break;
2921
2922
0
  case FR_TYPE_OCTETS:
2923
0
    if (src->vb_length != sizeof(dst->vb_ip.addr.v6.s6_addr)) {
2924
0
      fr_strerror_printf("Invalid cast from %s to %s.  Needed octet string of length %zu, got %zu",
2925
0
             fr_type_to_str(src->type),
2926
0
             fr_type_to_str(dst_type),
2927
0
             sizeof(dst->vb_ip.addr.v6.s6_addr), src->vb_length);
2928
0
      return -1;
2929
0
    }
2930
0
    memcpy(&dst->vb_ip.addr.v6.s6_addr, src->vb_octets, sizeof(dst->vb_ip.addr.v6.s6_addr));
2931
0
    break;
2932
2933
0
  default:
2934
0
    return fr_value_box_cast_unsupported(dst_type, src->type);
2935
0
  }
2936
2937
0
  return 0;
2938
0
}
2939
2940
/** Convert any supported type to an IPv6 address
2941
 *
2942
 * Allowed input types are:
2943
 * - FR_TYPE_IPV4_ADDR
2944
 * - FR_TYPE_IPV4_PREFIX (with 32bit mask).
2945
 * - FR_TYPE_IPV6_PREFIX (with 128bit mask).
2946
 * - FR_TYPE_OCTETS (of length 16).
2947
 *
2948
 * @param ctx   unused.
2949
 * @param dst   Where to write result of casting.
2950
 * @param dst_type  to cast to.
2951
 * @param dst_enumv enumeration values.
2952
 * @param src   Input data.
2953
 */
2954
static inline int fr_value_box_cast_to_ipv6prefix(TALLOC_CTX *ctx, fr_value_box_t *dst,
2955
              fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
2956
              fr_value_box_t const *src)
2957
0
{
2958
0
  fr_type_t src_type = src->type;
2959
2960
0
  fr_assert(dst_type == FR_TYPE_IPV6_PREFIX);
2961
0
  fr_value_box_safety_copy_changed(dst, src);
2962
2963
0
  switch (src_type) {
2964
0
  case FR_TYPE_STRING:
2965
0
    return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
2966
0
               src->vb_strvalue, src->vb_length,
2967
0
               NULL);
2968
2969
0
  CAST_IP_FIX_COMBO;
2970
2971
0
  default:
2972
0
    break;
2973
0
  }
2974
2975
  /*
2976
   *  Pre-initialise box for non-variable types
2977
   */
2978
0
  fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
2979
0
  dst->vb_ip.af = AF_INET6;
2980
2981
0
  switch (src_type) {
2982
0
  case FR_TYPE_IPV4_ADDR:
2983
0
  {
2984
0
    uint8_t *p = dst->vb_ip.addr.v6.s6_addr;
2985
2986
    /* Add the v4/v6 mapping prefix */
2987
0
    memcpy(p, v4_v6_map, sizeof(v4_v6_map));
2988
0
    p += sizeof(v4_v6_map);
2989
0
    memcpy(p, (uint8_t const *)&src->vb_ip.addr.v4.s_addr, sizeof(src->vb_ip.addr.v4.s_addr));
2990
0
    dst->vb_ip.prefix = 128;
2991
0
    dst->vb_ip.scope_id = 0;
2992
0
  }
2993
0
    break;
2994
2995
0
  case FR_TYPE_IPV4_PREFIX:
2996
0
  {
2997
0
    uint8_t *p = dst->vb_ip.addr.v6.s6_addr;
2998
2999
    /* Add the v4/v6 mapping prefix */
3000
0
    memcpy(p, v4_v6_map, sizeof(v4_v6_map));
3001
0
    p += sizeof(v4_v6_map);
3002
0
    memcpy(p, (uint8_t const *)&src->vb_ip.addr.v4.s_addr, sizeof(src->vb_ip.addr.v4.s_addr));
3003
0
    dst->vb_ip.prefix = (sizeof(v4_v6_map) << 3) + src->vb_ip.prefix;
3004
0
    dst->vb_ip.scope_id = 0;
3005
0
  }
3006
0
    break;
3007
3008
0
  case FR_TYPE_IPV6_PREFIX:   /* Needed for handling combo prefixes */
3009
0
    dst->vb_ip.prefix = src->vb_ip.prefix;
3010
0
    goto v6_common;
3011
3012
0
  case FR_TYPE_IPV6_ADDR:
3013
0
    dst->vb_ip.prefix = 128;
3014
0
  v6_common:
3015
0
    memcpy(dst->vb_ip.addr.v6.s6_addr, src->vb_ip.addr.v6.s6_addr,
3016
0
           sizeof(dst->vb_ip.addr.v6.s6_addr));
3017
0
    dst->vb_ip.scope_id = src->vb_ip.scope_id;
3018
0
    break;
3019
3020
0
  case FR_TYPE_OCTETS:
3021
0
    if (src->vb_length != (sizeof(dst->vb_ip.addr.v6.s6_addr) + 2)) {
3022
0
      fr_strerror_printf("Invalid cast from %s to %s.  Needed octet string of length %zu, got %zu",
3023
0
             fr_type_to_str(src->type),
3024
0
             fr_type_to_str(dst_type),
3025
0
             sizeof(dst->vb_ip.addr.v6.s6_addr) + 2, src->vb_length);
3026
0
      return -1;
3027
0
    }
3028
0
    dst->vb_ip.scope_id = src->vb_octets[0];
3029
0
    dst->vb_ip.prefix = src->vb_octets[1];
3030
0
    memcpy(&dst->vb_ip.addr.v6.s6_addr, src->vb_octets, sizeof(dst->vb_ip.addr.v6.s6_addr));
3031
0
    break;
3032
3033
0
  default:
3034
0
    return fr_value_box_cast_unsupported(dst_type, src->type);
3035
0
  }
3036
0
  return 0;
3037
0
}
3038
3039
/** Convert any supported type to an ethernet address
3040
 *
3041
 * Allowed input types are:
3042
 * - FR_TYPE_STRING ("00:11:22:33:44:55")
3043
 * - FR_TYPE_OCTETS (0x001122334455)
3044
 *
3045
 *
3046
 * @param ctx   unused.
3047
 * @param dst   Where to write result of casting.
3048
 * @param dst_type  to cast to.
3049
 * @param dst_enumv enumeration values.
3050
 * @param src   Input data.
3051
 */
3052
static inline int fr_value_box_cast_to_ethernet(TALLOC_CTX *ctx, fr_value_box_t *dst,
3053
            fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
3054
            fr_value_box_t const *src)
3055
0
{
3056
0
  fr_assert(dst_type == FR_TYPE_ETHERNET);
3057
0
  fr_value_box_safety_copy_changed(dst, src);
3058
3059
0
  switch (src->type) {
3060
0
  case FR_TYPE_STRING:
3061
0
    return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
3062
0
               src->vb_strvalue, src->vb_length,
3063
0
               NULL);
3064
3065
0
  case FR_TYPE_OCTETS:
3066
0
    return fr_value_box_fixed_size_from_octets(dst, dst_type, dst_enumv, src);
3067
3068
0
  default:
3069
0
    break;
3070
0
  }
3071
3072
  /*
3073
   *  Pre-initialise box for non-variable types
3074
   */
3075
0
  fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
3076
3077
0
  switch (src->type) {
3078
0
  case FR_TYPE_UINT64: {
3079
0
    uint8_t array[8];
3080
3081
0
    fr_nbo_from_uint64(array, src->vb_uint64);
3082
3083
    /*
3084
     *  For OUIs in the DB.
3085
     */
3086
0
    if ((array[0] != 0) || (array[1] != 0)) return -1;
3087
3088
0
    memcpy(dst->vb_ether, &array[2], 6);
3089
0
    break;
3090
0
  }
3091
3092
0
  default:
3093
0
    return fr_value_box_cast_unsupported(dst_type, src->type);
3094
0
  }
3095
3096
0
  return 0;
3097
0
}
3098
3099
/** Convert any supported type to a bool
3100
 *
3101
 * Allowed input types are:
3102
 * - FR_TYPE_STRING ("yes", "true", "no", "false")
3103
 *
3104
 * @param ctx   unused.
3105
 * @param dst   Where to write result of casting.
3106
 * @param dst_type  to cast to.
3107
 * @param dst_enumv enumeration values.
3108
 * @param src   Input data.
3109
 */
3110
static inline int fr_value_box_cast_to_bool(TALLOC_CTX *ctx, fr_value_box_t *dst,
3111
              fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
3112
              fr_value_box_t const *src)
3113
0
{
3114
0
  fr_assert(dst_type == FR_TYPE_BOOL);
3115
0
  fr_value_box_safety_copy_changed(dst, src);
3116
3117
0
  switch (src->type) {
3118
0
  case FR_TYPE_STRING:
3119
0
    return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
3120
0
               src->vb_strvalue, src->vb_length,
3121
0
               NULL);
3122
3123
0
  case FR_TYPE_OCTETS:
3124
    /*
3125
     *  This is really "bool from network"
3126
     */
3127
0
    return fr_value_box_fixed_size_from_octets(dst, dst_type, dst_enumv, src);
3128
3129
0
  default:
3130
0
    break;
3131
0
  }
3132
3133
  /*
3134
   *  Pre-initialise box for non-variable types
3135
   */
3136
0
  fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
3137
3138
0
  switch (src->type) {
3139
0
  case FR_TYPE_INT8:
3140
0
    dst->vb_bool = (src->vb_int8 != 0);
3141
0
    break;
3142
3143
0
  case FR_TYPE_UINT8:
3144
0
    dst->vb_bool = (src->vb_uint8 != 0);
3145
0
    break;
3146
3147
0
  case FR_TYPE_INT16:
3148
0
    dst->vb_bool = (src->vb_int16 != 0);
3149
0
    break;
3150
3151
0
  case FR_TYPE_UINT16:
3152
0
    dst->vb_bool = (src->vb_uint16 != 0);
3153
0
    break;
3154
3155
0
  case FR_TYPE_INT32:
3156
0
    dst->vb_bool = (src->vb_int32 != 0);
3157
0
    break;
3158
3159
0
  case FR_TYPE_UINT32:
3160
0
    dst->vb_bool = (src->vb_uint32 != 0);
3161
0
    break;
3162
3163
0
  case FR_TYPE_INT64:
3164
0
    dst->vb_bool = (src->vb_int64 != 0);
3165
0
    break;
3166
3167
0
  case FR_TYPE_UINT64:
3168
0
    dst->vb_bool = (src->vb_uint64 != 0);
3169
0
    break;
3170
3171
0
  case FR_TYPE_SIZE:
3172
0
    dst->vb_bool = (src->vb_size != 0);
3173
0
    break;
3174
3175
0
  case FR_TYPE_TIME_DELTA:
3176
0
    dst->vb_bool = (fr_time_delta_unwrap(src->vb_time_delta) != 0);
3177
0
    break;
3178
3179
0
  case FR_TYPE_FLOAT32:
3180
0
    dst->vb_bool = (fpclassify(src->vb_float32) == FP_ZERO);
3181
0
    break;
3182
3183
0
  case FR_TYPE_FLOAT64:
3184
0
    dst->vb_bool = (fpclassify(src->vb_float64) == FP_ZERO);
3185
0
    break;
3186
3187
0
  default:
3188
0
    return fr_value_box_cast_unsupported(dst_type, src->type);
3189
0
  }
3190
3191
0
  return 0;
3192
0
}
3193
3194
/** Convert any signed or unsigned integer type to any other signed or unsigned integer type
3195
 *
3196
 */
3197
static inline int fr_value_box_cast_integer_to_integer(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst,
3198
                   fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
3199
                   fr_value_box_t const *src)
3200
1.56k
{
3201
1.56k
  uint64_t    tmp = 0;
3202
1.56k
  size_t      len = fr_value_box_field_sizes[src->type];
3203
1.56k
  int64_t     min;
3204
3205
1.56k
  fr_value_box_safety_copy_changed(dst, src);
3206
3207
1.56k
#define SIGN_BIT_HIGH(_int, _len) ((((uint64_t)1) << (((_len) << 3) - 1)) & (_int))
3208
1.56k
#define SIGN_PROMOTE(_int, _len)  ((_len) < sizeof(_int) ? \
3209
109
          (_int) | (~((__typeof__(_int))0)) << ((_len) << 3) : (_int))
3210
3211
1.56k
#if !defined(NDEBUG) || defined(STATIC_ANALYZER)
3212
  /*
3213
   *  Helps catch invalid fr_value_box_field_sizes
3214
   *  entries, and shuts up clang analyzer.
3215
   */
3216
1.56k
  if (!fr_cond_assert_msg(len > 0, "Invalid cast from %s to %s. "
3217
1.56k
              "invalid source type len, expected > 0, got %zu",
3218
1.56k
              fr_type_to_str(src->type),
3219
1.56k
              fr_type_to_str(dst_type),
3220
1.56k
              len)) return -1;
3221
3222
1.56k
  if (!fr_cond_assert_msg(len <= sizeof(uint64_t),
3223
1.56k
        "Invalid cast from %s to %s. "
3224
1.56k
        "invalid source type len, expected <= %zu, got %zu",
3225
1.56k
        fr_type_to_str(src->type),
3226
1.56k
        fr_type_to_str(dst_type),
3227
1.56k
        sizeof(uint64_t), len)) return -1;
3228
1.56k
#endif
3229
3230
1.56k
  switch (src->type) {
3231
  /*
3232
   *  Dates are always represented in nanoseconds
3233
   *  internally, but when we convert to another
3234
   *  integer type, we scale appropriately.
3235
   *
3236
   *  i.e. if the attribute value resolution is
3237
   *  seconds, then the integer value is
3238
   *  nanoseconds -> seconds.
3239
   */
3240
1.01k
  case FR_TYPE_DATE:
3241
1.01k
  {
3242
1.01k
    fr_time_res_t res = FR_TIME_RES_SEC;
3243
1.01k
    if (src->enumv) res = src->enumv->flags.flag_time_res;
3244
3245
1.01k
    tmp = fr_unix_time_to_integer(src->vb_date, res);
3246
1.01k
  }
3247
1.01k
    break;
3248
3249
  /*
3250
   *  Same deal with time deltas.  Note that
3251
   *  even though we store the value as an
3252
   *  unsigned integer, it'll be cast to a
3253
   *  signed integer for comparisons.
3254
   */
3255
280
  case FR_TYPE_TIME_DELTA:
3256
280
  {
3257
280
    fr_time_res_t res = FR_TIME_RES_SEC;
3258
3259
280
    if (src->enumv) res = src->enumv->flags.flag_time_res;
3260
3261
280
    tmp = (uint64_t)fr_time_delta_to_integer(src->vb_time_delta, res);
3262
280
  }
3263
280
    break;
3264
3265
268
  default:
3266
#ifdef WORDS_BIGENDIAN
3267
    memcpy(((uint8_t *)&tmp) + (sizeof(tmp) - len),
3268
           fr_value_box_raw(src, src->type), len);
3269
#else
3270
268
    memcpy(&tmp, fr_value_box_raw(src, src->type), len);
3271
268
#endif
3272
268
    break;
3273
1.56k
  }
3274
3275
1.56k
  min = fr_value_box_integer_min[dst_type];
3276
3277
  /*
3278
   *  Sign promote the input if the source type is
3279
   *  signed, and the high bit is set.
3280
   */
3281
1.56k
  if (fr_value_box_integer_min[src->type] < 0) {
3282
280
    if (SIGN_BIT_HIGH(tmp, len)) tmp = SIGN_PROMOTE(tmp, len);
3283
3284
280
    if ((int64_t)tmp < min) {
3285
109
      fr_strerror_printf("Invalid cast from %s to %s.  %"PRId64" "
3286
109
             "outside value range %"PRId64"-%"PRIu64,
3287
109
             fr_type_to_str(src->type),
3288
109
             fr_type_to_str(dst_type),
3289
109
             (int64_t)tmp,
3290
109
             min, fr_value_box_integer_max[dst_type]);
3291
109
      return -1;
3292
109
    }
3293
1.28k
  } else if (tmp > fr_value_box_integer_max[dst_type]) {
3294
0
    fr_strerror_printf("Invalid cast from %s to %s.  %"PRIu64" "
3295
0
           "outside value range 0-%"PRIu64,
3296
0
           fr_type_to_str(src->type),
3297
0
           fr_type_to_str(dst_type),
3298
0
           tmp, fr_value_box_integer_max[dst_type]);
3299
0
    return -1;
3300
0
  }
3301
3302
1.45k
  fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
3303
1.45k
  switch (dst_type) {
3304
0
  case FR_TYPE_DATE:
3305
0
  {
3306
0
    bool overflow;
3307
0
    fr_time_res_t res = FR_TIME_RES_SEC;
3308
0
    if (dst->enumv) res = dst->enumv->flags.flag_time_res;
3309
3310
0
    dst->vb_date = fr_unix_time_from_integer(&overflow, tmp, res);
3311
0
    if (overflow) {
3312
0
      fr_strerror_const("Input to date type would overflow");
3313
0
      return -1;
3314
0
    }
3315
0
  }
3316
0
    break;
3317
3318
0
  case FR_TYPE_TIME_DELTA:
3319
0
  {
3320
0
    bool overflow;
3321
0
    fr_time_res_t res = FR_TIME_RES_SEC;
3322
0
    if (dst->enumv) res = dst->enumv->flags.flag_time_res;
3323
3324
0
    dst->vb_time_delta = fr_time_delta_from_integer(&overflow, tmp, res);
3325
0
    if (overflow) {
3326
0
      fr_strerror_const("Input to time_delta type would overflow");
3327
0
      return -1;
3328
0
    }
3329
0
  }
3330
0
    break;
3331
3332
1.45k
  default:
3333
#ifdef WORDS_BIGENDIAN
3334
    memcpy(fr_value_box_raw(dst, dst->type),
3335
           ((uint8_t *)&tmp) + (sizeof(tmp) - len), fr_value_box_field_sizes[dst_type]);
3336
#else
3337
1.45k
    memcpy(fr_value_box_raw(dst, dst->type),
3338
1.45k
           &tmp, fr_value_box_field_sizes[dst_type]);
3339
1.45k
#endif
3340
1.45k
    break;
3341
1.45k
  }
3342
3343
1.45k
  return 0;
3344
1.45k
}
3345
3346
/** Convert any value to a signed or unsigned integer
3347
 *
3348
 * @param ctx   unused.
3349
 * @param dst   Where to write result of casting.
3350
 * @param dst_type  to cast to.
3351
 * @param dst_enumv enumeration values.
3352
 * @param src   Input data.
3353
 */
3354
static inline int fr_value_box_cast_to_integer(TALLOC_CTX *ctx, fr_value_box_t *dst,
3355
                 fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
3356
                 fr_value_box_t const *src)
3357
1.56k
{
3358
1.56k
  switch (src->type) {
3359
0
  case FR_TYPE_STRING:
3360
0
    return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
3361
0
               src->vb_strvalue, src->vb_length,
3362
0
               NULL);
3363
3364
0
  case FR_TYPE_OCTETS:
3365
0
    return fr_value_box_fixed_size_from_octets(dst, dst_type, dst_enumv, src);
3366
3367
1.56k
  case FR_TYPE_INTEGER:
3368
1.56k
    fr_value_box_init(dst, dst_type, dst_enumv, false);
3369
1.56k
    return fr_value_box_cast_integer_to_integer(ctx, dst, dst_type, dst_enumv, src);
3370
3371
0
  case FR_TYPE_IPV4_ADDR:
3372
0
  case FR_TYPE_IPV4_PREFIX:
3373
0
  {
3374
0
    fr_value_box_t  tmp;
3375
3376
0
    switch (dst_type) {
3377
0
    case FR_TYPE_UINT32:
3378
0
    case FR_TYPE_INT64:
3379
0
    case FR_TYPE_UINT64:
3380
0
    case FR_TYPE_DATE:
3381
0
    case FR_TYPE_TIME_DELTA:
3382
0
      break;
3383
3384
0
    default:
3385
0
      goto bad_cast;
3386
0
    }
3387
3388
0
    fr_value_box_init(&tmp, FR_TYPE_UINT32, src->enumv, src->tainted);
3389
0
    memcpy(&tmp.vb_uint32, &src->vb_ip.addr.v4, sizeof(tmp.vb_uint32));
3390
0
    fr_value_box_hton(&tmp, &tmp);
3391
0
    return fr_value_box_cast_integer_to_integer(ctx, dst, dst_type, dst_enumv, &tmp);
3392
0
  }
3393
3394
0
  case FR_TYPE_ETHERNET:
3395
0
  {
3396
0
    fr_value_box_t  tmp;
3397
3398
0
    switch (dst_type) {
3399
0
    case FR_TYPE_INT64:
3400
0
    case FR_TYPE_UINT64:
3401
0
    case FR_TYPE_DATE:
3402
0
    case FR_TYPE_TIME_DELTA:
3403
0
      break;
3404
3405
0
    default:
3406
0
      goto bad_cast;
3407
0
    }
3408
3409
0
    fr_value_box_init(&tmp, FR_TYPE_UINT64, src->enumv, src->tainted);
3410
0
    memcpy(((uint8_t *)&tmp.vb_uint64) + (sizeof(tmp.vb_uint64) - sizeof(src->vb_ether)),
3411
0
           &src->vb_ether, sizeof(src->vb_ether));
3412
0
#ifndef WORDS_BIGENDIAN
3413
    /*
3414
     *  Ethernet addresses are always stored bigendian,
3415
     *  convert to native on little endian systems
3416
     */
3417
0
    fr_value_box_hton(&tmp, &tmp);
3418
0
#endif
3419
0
    return fr_value_box_cast_integer_to_integer(ctx, dst, dst_type, dst_enumv, &tmp);
3420
0
  }
3421
3422
0
  case FR_TYPE_IFID:
3423
0
  {
3424
0
    switch (dst_type) {
3425
0
    case FR_TYPE_UINT64:
3426
0
      break;
3427
3428
0
    default:
3429
0
      goto bad_cast;
3430
0
    }
3431
3432
0
    fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
3433
0
    dst->vb_uint64 = fr_nbo_to_uint64(&src->vb_ifid[0]);
3434
0
    return 0;
3435
0
  }
3436
3437
0
  case FR_TYPE_FLOAT32:
3438
0
    if (src->vb_float32 < (double) fr_value_box_integer_min[dst_type]) {
3439
0
    underflow:
3440
0
      fr_strerror_const("Source value for cast would underflow destination type");
3441
0
      return -1;
3442
0
    }
3443
3444
0
    if (src->vb_float32 > (double) fr_value_box_integer_max[dst_type]) {
3445
0
    overflow:
3446
0
      fr_strerror_const("Source value for cast would overflow destination type");
3447
0
      return -1;
3448
0
    }
3449
3450
0
    switch (dst_type) {
3451
0
    case FR_TYPE_UINT8:
3452
0
      dst->vb_uint8 = src->vb_float32;
3453
0
      break;
3454
3455
0
    case FR_TYPE_UINT16:
3456
0
      dst->vb_uint16 = src->vb_float32;
3457
0
      break;
3458
3459
0
    case FR_TYPE_UINT32:
3460
0
      dst->vb_uint32 = src->vb_float32;
3461
0
      break;
3462
3463
0
    case FR_TYPE_UINT64:
3464
0
      dst->vb_uint64 = src->vb_float32;
3465
0
      break;
3466
3467
0
    case FR_TYPE_INT8:
3468
0
      dst->vb_int8 = src->vb_float32;
3469
0
      break;
3470
3471
0
    case FR_TYPE_INT16:
3472
0
      dst->vb_int16 = src->vb_float32;
3473
0
      break;
3474
3475
0
    case FR_TYPE_INT32:
3476
0
      dst->vb_int32 = src->vb_float32;
3477
0
      break;
3478
3479
0
    case FR_TYPE_INT64:
3480
0
      dst->vb_int64 = src->vb_float32;
3481
0
      break;
3482
3483
0
    case FR_TYPE_SIZE:
3484
0
      dst->vb_size = src->vb_float32;
3485
0
      break;
3486
3487
0
    case FR_TYPE_DATE: {
3488
0
      int64_t sec, nsec;
3489
3490
0
      sec = src->vb_float32;
3491
0
      sec *= NSEC;
3492
0
      nsec = ((src->vb_float32 * NSEC) - ((float) sec));
3493
3494
0
      dst->vb_date = fr_unix_time_from_nsec(sec + nsec);
3495
0
    }
3496
0
      break;
3497
3498
0
    case FR_TYPE_TIME_DELTA: {
3499
0
      int64_t sec, nsec;
3500
0
      int64_t res = NSEC;
3501
0
      bool fail = false;
3502
3503
0
      if (dst->enumv) res = fr_time_multiplier_by_res[dst->enumv->flags.flag_time_res];
3504
3505
0
      sec = src->vb_float32;
3506
0
      sec *= res;
3507
0
      nsec = ((src->vb_float32 * res) - ((double) sec));
3508
3509
0
      dst->vb_time_delta = fr_time_delta_from_integer(&fail, sec + nsec,
3510
0
                  dst->enumv ? dst->enumv->flags.flag_time_res : FR_TIME_RES_NSEC);
3511
0
      if (fail) goto overflow;
3512
0
    }
3513
0
      break;
3514
3515
0
    default:
3516
0
      goto bad_cast;
3517
0
    }
3518
0
    return 0;
3519
3520
0
  case FR_TYPE_FLOAT64:
3521
0
    if (src->vb_float64 < (double) fr_value_box_integer_min[dst_type]) goto underflow;
3522
3523
0
    if (src->vb_float64 > (double) fr_value_box_integer_max[dst_type]) goto overflow;
3524
3525
0
    switch (dst_type) {
3526
0
    case FR_TYPE_UINT8:
3527
0
      dst->vb_uint8 = src->vb_float64;
3528
0
      break;
3529
3530
0
    case FR_TYPE_UINT16:
3531
0
      dst->vb_uint16 = src->vb_float64;
3532
0
      break;
3533
3534
0
    case FR_TYPE_UINT32:
3535
0
      dst->vb_uint32 = src->vb_float64;
3536
0
      break;
3537
3538
0
    case FR_TYPE_UINT64:
3539
0
      dst->vb_uint64 = src->vb_float64;
3540
0
      break;
3541
3542
0
    case FR_TYPE_INT8:
3543
0
      dst->vb_int8 = src->vb_float64;
3544
0
      break;
3545
3546
0
    case FR_TYPE_INT16:
3547
0
      dst->vb_int16 = src->vb_float64;
3548
0
      break;
3549
3550
0
    case FR_TYPE_INT32:
3551
0
      dst->vb_int32 = src->vb_float64;
3552
0
      break;
3553
3554
0
    case FR_TYPE_INT64:
3555
0
      dst->vb_int64 = src->vb_float64;
3556
0
      break;
3557
3558
0
    case FR_TYPE_SIZE:
3559
0
      dst->vb_size = src->vb_float64;
3560
0
      break;
3561
3562
0
    case FR_TYPE_DATE: {
3563
0
      int64_t sec, nsec;
3564
3565
0
      sec = src->vb_float64;
3566
0
      sec *= NSEC;
3567
0
      nsec = ((src->vb_float64 * NSEC) - ((double) sec));
3568
3569
0
      dst->vb_date = fr_unix_time_from_nsec(sec + nsec);
3570
0
    }
3571
0
      break;
3572
3573
0
    case FR_TYPE_TIME_DELTA: {
3574
0
      int64_t sec, nsec;
3575
0
      int64_t res = NSEC;
3576
0
      bool fail = false;
3577
3578
0
      if (dst->enumv) res = fr_time_multiplier_by_res[dst->enumv->flags.flag_time_res];
3579
3580
0
      sec = src->vb_float64;
3581
0
      sec *= res;
3582
0
      nsec = ((src->vb_float64 * res) - ((double) sec));
3583
3584
0
      dst->vb_time_delta = fr_time_delta_from_integer(&fail, sec + nsec,
3585
0
                  dst->enumv ? dst->enumv->flags.flag_time_res : FR_TIME_RES_NSEC);
3586
0
      if (fail) goto overflow;
3587
0
    }
3588
0
      break;
3589
3590
0
    default:
3591
0
      goto bad_cast;
3592
0
    }
3593
0
    return 0;
3594
3595
0
  default:
3596
0
    break;
3597
1.56k
  }
3598
3599
0
bad_cast:
3600
0
  return fr_value_box_cast_unsupported(dst_type, src->type);
3601
1.56k
}
3602
3603
/** Convert any value to a floating point value
3604
 *
3605
 * @param ctx   unused.
3606
 * @param dst   Where to write result of casting.
3607
 * @param dst_type  to cast to.
3608
 * @param dst_enumv enumeration values.
3609
 * @param src   Input data.
3610
 */
3611
static inline int fr_value_box_cast_to_float(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst,
3612
               fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
3613
               fr_value_box_t const *src)
3614
0
{
3615
0
  double num;
3616
3617
0
  switch (src->type) {
3618
0
  case FR_TYPE_FLOAT32:
3619
0
    if (dst_type == FR_TYPE_FLOAT64) {
3620
0
      num = (double) src->vb_float32;
3621
0
      goto good_cast;
3622
0
    }
3623
3624
0
    goto bad_cast;
3625
3626
0
  case FR_TYPE_FLOAT64:
3627
0
    if (dst_type == FR_TYPE_FLOAT32) {
3628
0
      num = src->vb_float64;
3629
0
      goto good_cast;
3630
0
    }
3631
3632
0
    goto bad_cast;
3633
3634
0
  case FR_TYPE_BOOL:
3635
0
    num = src->vb_bool;
3636
0
    goto good_cast;
3637
3638
0
  case FR_TYPE_INT8:
3639
0
    num = src->vb_int8;
3640
0
    goto good_cast;
3641
3642
0
  case FR_TYPE_INT16:
3643
0
    num = src->vb_int16;
3644
0
    goto good_cast;
3645
3646
0
  case FR_TYPE_INT32:
3647
0
    num = src->vb_int32;
3648
0
    goto good_cast;
3649
3650
0
  case FR_TYPE_INT64:
3651
0
    num = src->vb_int64;
3652
0
    goto good_cast;
3653
3654
0
  case FR_TYPE_UINT8:
3655
0
    num = src->vb_uint8;
3656
0
    goto good_cast;
3657
3658
0
  case FR_TYPE_UINT16:
3659
0
    num = src->vb_uint16;
3660
0
    goto good_cast;
3661
3662
0
  case FR_TYPE_UINT32:
3663
0
    num = src->vb_uint32;
3664
0
    goto good_cast;
3665
3666
0
  case FR_TYPE_UINT64:
3667
0
    num = src->vb_uint64;
3668
0
    goto good_cast;
3669
3670
0
  case FR_TYPE_DATE:
3671
    /*
3672
     *  Unix times are in nanoseconds
3673
     */
3674
0
    num = fr_unix_time_unwrap(src->vb_date);
3675
0
    num /= NSEC;
3676
0
    goto good_cast;
3677
3678
0
  case FR_TYPE_TIME_DELTA:
3679
    /*
3680
     *  Time deltas are in nanoseconds, but scaled.
3681
     */
3682
0
    num = fr_time_delta_unwrap(src->vb_time_delta);
3683
0
    if (src->enumv) {
3684
0
      num /= fr_time_multiplier_by_res[src->enumv->flags.flag_time_res];
3685
0
    } else {
3686
0
      num /= NSEC;
3687
0
    }
3688
0
    goto good_cast;
3689
3690
0
  case FR_TYPE_SIZE:
3691
0
    num = src->vb_size;
3692
3693
0
  good_cast:
3694
0
    fr_value_box_init(dst, dst_type, dst_enumv, src->tainted);
3695
0
    fr_value_box_safety_copy_changed(dst, src);
3696
3697
0
    if (dst_type == FR_TYPE_FLOAT32) {
3698
0
      dst->vb_float32 = num;
3699
0
    } else {
3700
0
      dst->vb_float64 = num;
3701
0
    }
3702
0
    return 0;
3703
3704
0
  default:
3705
0
    break;
3706
0
  }
3707
3708
0
bad_cast:
3709
0
  return fr_value_box_cast_unsupported(dst_type, src->type);
3710
0
}
3711
3712
3713
/** Convert one type of fr_value_box_t to another
3714
 *
3715
 * This should be the canonical function used to convert between INTERNAL data formats.
3716
 *
3717
 * If you want to convert from PRESENTATION format, use #fr_value_box_from_substr.
3718
 *
3719
 * @note src and dst must not be the same box.  We do not support casting in place.
3720
 *
3721
 * @param ctx   to allocate buffers in (usually the same as dst)
3722
 * @param dst   Where to write result of casting.
3723
 * @param dst_type  to cast to.
3724
 * @param dst_enumv Aliases for values contained within this fr_value_box_t.
3725
 *      If #fr_value_box_t is passed to #fr_value_box_aprint
3726
 *      names will be printed instead of actual value.
3727
 * @param src   Input data.
3728
 * @return
3729
 *  - 0 on success.
3730
 *  - -1 on failure.
3731
 */
3732
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst,
3733
          fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
3734
          fr_value_box_t const *src)
3735
2.57k
{
3736
2.57k
  if (!fr_cond_assert(src != dst)) return -1;
3737
3738
2.57k
  if (fr_type_is_non_leaf(dst_type)) {
3739
0
    fr_strerror_printf("Invalid cast from %s to %s.  Can only cast simple data types",
3740
0
           fr_type_to_str(src->type),
3741
0
           fr_type_to_str(dst_type));
3742
0
    return -1;
3743
0
  }
3744
3745
  /*
3746
   *  If it's the same type, copy, but set the enumv
3747
   *  in the destination box to be the one provided.
3748
   *
3749
   *  The theory here is that the attribute value isn't
3750
   *  being converted into its presentation format and
3751
   *  re-parsed, and the enumv names only get applied
3752
   *  when converting internal values to/from strings,
3753
   *  so it's OK just to swap out the enumv.
3754
   *
3755
   *  If there's a compelling case in the future we
3756
   *  might revisit this, but it'd likely mean fixing
3757
   *  all the casting functions to treat any value
3758
   *  with an enumv as a string, which seems weird.
3759
   */
3760
2.57k
  if (dst_type == src->type) {
3761
10
    int ret;
3762
3763
10
    ret = fr_value_box_copy(ctx, dst, src);
3764
10
    if (ret < 0) return ret;
3765
3766
10
    dst->enumv = dst_enumv;
3767
3768
10
    return ret;
3769
10
  }
3770
3771
  /*
3772
   *  Initialise dst
3773
   */
3774
2.56k
  fr_value_box_init(dst, dst_type, NULL, src->tainted);
3775
3776
  /*
3777
   *  Dispatch to specialised cast functions
3778
   */
3779
2.56k
  switch (dst_type) {
3780
0
  case FR_TYPE_STRING:
3781
0
    return fr_value_box_cast_to_strvalue(ctx, dst, dst_type, dst_enumv, src);
3782
3783
0
  case FR_TYPE_OCTETS:
3784
0
    return fr_value_box_cast_to_octets(ctx, dst, dst_type, dst_enumv, src);
3785
3786
0
  case FR_TYPE_IPV4_ADDR:
3787
0
    return fr_value_box_cast_to_ipv4addr(ctx, dst, dst_type, dst_enumv, src);
3788
3789
1.00k
  case FR_TYPE_IPV4_PREFIX:
3790
1.00k
    return fr_value_box_cast_to_ipv4prefix(ctx, dst, dst_type, dst_enumv, src);
3791
3792
0
  case FR_TYPE_IPV6_ADDR:
3793
0
    return fr_value_box_cast_to_ipv6addr(ctx, dst, dst_type, dst_enumv, src);
3794
3795
0
  case FR_TYPE_IPV6_PREFIX:
3796
0
    return fr_value_box_cast_to_ipv6prefix(ctx, dst, dst_type, dst_enumv, src);
3797
3798
0
  case FR_TYPE_COMBO_IP_ADDR:
3799
0
  case FR_TYPE_COMBO_IP_PREFIX:
3800
0
    break;
3801
  /*
3802
   *  Need func
3803
   */
3804
0
  case FR_TYPE_IFID:
3805
0
    break;
3806
3807
0
  case FR_TYPE_ETHERNET:
3808
0
    return fr_value_box_cast_to_ethernet(ctx, dst, dst_type, dst_enumv, src);
3809
3810
0
  case FR_TYPE_BOOL:
3811
0
    return fr_value_box_cast_to_bool(ctx, dst, dst_type, dst_enumv, src);
3812
3813
0
  case FR_TYPE_DATE:
3814
0
    if (src->type != FR_TYPE_TIME_DELTA) return fr_value_box_cast_to_integer(ctx, dst, dst_type, dst_enumv, src);
3815
3816
0
    if (fr_time_delta_isneg(src->vb_time_delta)) {
3817
0
      fr_strerror_const("Input to data type would underflow");
3818
0
      return -1;
3819
0
    }
3820
3821
0
    fr_value_box_safety_copy_changed(dst, src);
3822
0
    dst->enumv = dst_enumv;
3823
0
    dst->vb_date = fr_unix_time_wrap(fr_time_delta_unwrap(src->vb_time_delta));
3824
0
    return 0;
3825
3826
0
  case FR_TYPE_TIME_DELTA:
3827
    /*
3828
     *  Unix time cast to time_delta is just nanoseconds since the epoch.
3829
     *
3830
     *  Note that we do NOT change time resolution, but we DO change enumv.  Both unix time
3831
     *  and time_delta are tracked internally as nanoseconds, and the only use of precision is
3832
     *  for printing / parsing.
3833
     */
3834
0
    if (src->type == FR_TYPE_DATE) {
3835
0
      uint64_t when;
3836
3837
0
      when = fr_unix_time_unwrap(src->vb_date);
3838
0
      if (when > INT64_MAX) {
3839
0
        fr_strerror_const("Input to data type would overflow");
3840
0
        return -1;
3841
0
      }
3842
3843
0
      fr_value_box_safety_copy_changed(dst, src);
3844
0
      dst->enumv = dst_enumv;
3845
0
      dst->vb_time_delta = fr_time_delta_wrap((int64_t) when);
3846
0
      return 0;
3847
0
    }
3848
0
    FALL_THROUGH;
3849
3850
52
  case FR_TYPE_UINT8:
3851
256
  case FR_TYPE_UINT16:
3852
268
  case FR_TYPE_UINT32:
3853
1.56k
  case FR_TYPE_UINT64:
3854
1.56k
  case FR_TYPE_INT8:
3855
1.56k
  case FR_TYPE_INT16:
3856
1.56k
  case FR_TYPE_INT32:
3857
1.56k
  case FR_TYPE_INT64:
3858
1.56k
  case FR_TYPE_SIZE:
3859
1.56k
    return fr_value_box_cast_to_integer(ctx, dst, dst_type, dst_enumv, src);
3860
3861
0
  case FR_TYPE_FLOAT32:
3862
0
  case FR_TYPE_FLOAT64:
3863
0
    if (fr_type_is_fixed_size(src->type)) {
3864
0
      return fr_value_box_cast_to_float(ctx, dst, dst_type, dst_enumv, src);
3865
0
    }
3866
0
    break;   /* use generic string/octets stuff below */
3867
3868
#if 0
3869
  case FR_TYPE_ATTR:
3870
    /*
3871
     *  Convert it to an integer of the correct length. Then, cast it in place.
3872
     */
3873
    switch (src->vb_attr->flags.length) {
3874
    case 1:
3875
      fr_value_box_init(dst, FR_TYPE_UINT8, NULL, false);
3876
      dst->vb_uint8 = src->vb_attr->attr;
3877
      break;
3878
3879
    case 2:
3880
      fr_value_box_init(dst, FR_TYPE_UINT16, NULL, false);
3881
      dst->vb_uint16 = src->vb_attr->attr;
3882
      break;
3883
3884
    case 4:
3885
      fr_value_box_init(dst, FR_TYPE_UINT32, NULL, false);
3886
      dst->vb_uint32 = src->vb_attr->attr;
3887
      break;
3888
3889
    default:
3890
      fr_strerror_printf("Unsupported length '%d' for attribute %s",
3891
             src->vb_attr->flags.length, src->vb_attr->name);
3892
      return 0;
3893
    }
3894
3895
    return fr_value_box_cast_in_place(ctx, dst, dst_type, dst_enumv);
3896
#else
3897
0
  case FR_TYPE_ATTR:
3898
0
#endif
3899
  /*
3900
   *  Invalid types for casting (were caught earlier)
3901
   */
3902
0
  case FR_TYPE_NON_LEAF:
3903
0
    fr_strerror_printf("Invalid cast from %s to %s.  Invalid destination type",
3904
0
           fr_type_to_str(src->type),
3905
0
           fr_type_to_str(dst_type));
3906
0
    return -1;
3907
2.56k
  }
3908
3909
  /*
3910
   *  Deserialise a fr_value_box_t
3911
   */
3912
0
  if (src->type == FR_TYPE_STRING) return fr_value_box_from_str(ctx, dst, dst_type, dst_enumv,
3913
0
                      src->vb_strvalue, src->vb_length,
3914
0
                      NULL);
3915
3916
0
  if (src->type == FR_TYPE_OCTETS) {
3917
0
    fr_value_box_t tmp;
3918
3919
0
    if (src->vb_length < network_min_size(dst_type)) {
3920
0
      fr_strerror_printf("Invalid cast from %s to %s.  Source is length %zu is smaller than "
3921
0
             "destination type size %zu",
3922
0
             fr_type_to_str(src->type),
3923
0
             fr_type_to_str(dst_type),
3924
0
             src->vb_length,
3925
0
             network_min_size(dst_type));
3926
0
      return -1;
3927
0
    }
3928
3929
0
    if (src->vb_length > network_max_size(dst_type)) {
3930
0
      fr_strerror_printf("Invalid cast from %s to %s.  Source length %zu is greater than "
3931
0
             "destination type size %zu",
3932
0
             fr_type_to_str(src->type),
3933
0
             fr_type_to_str(dst_type),
3934
0
             src->vb_length,
3935
0
             network_max_size(dst_type));
3936
0
      return -1;
3937
0
    }
3938
3939
0
    fr_value_box_init(&tmp, dst_type, NULL, false);
3940
3941
    /*
3942
     *  Copy the raw octets into the datum of a value_box
3943
     *  inverting bytesex for uint32s (if LE).
3944
     */
3945
0
    memcpy(&tmp.datum, src->vb_octets, fr_value_box_field_sizes[dst_type]);
3946
0
    tmp.type = dst_type;
3947
0
    dst->enumv = dst_enumv;
3948
3949
0
    fr_value_box_hton(dst, &tmp);
3950
0
    fr_value_box_safety_copy(dst, src);
3951
0
    return 0;
3952
0
  }
3953
3954
0
  memcpy(&dst->datum, &src->datum, fr_value_box_field_sizes[src->type]);
3955
3956
0
  fr_value_box_safety_copy_changed(dst, src);
3957
0
  dst->enumv = dst_enumv;
3958
3959
0
  return 0;
3960
0
}
3961
3962
/** Convert one type of fr_value_box_t to another in place
3963
 *
3964
 * This should be the canonical function used to convert between INTERNAL data formats.
3965
 *
3966
 * If you want to convert from PRESENTATION format, use #fr_value_box_from_substr.
3967
 *
3968
 * @param ctx   to allocate buffers in (usually the same as dst)
3969
 * @param vb    to cast.
3970
 * @param dst_type  to cast to.
3971
 * @param dst_enumv Aliases for values contained within this fr_value_box_t.
3972
 *      If #fr_value_box_t is passed to #fr_value_box_aprint
3973
 *      names will be printed instead of actual value.
3974
 * @return
3975
 *  - 0 on success.
3976
 *  - -1 on failure.
3977
 */
3978
int fr_value_box_cast_in_place(TALLOC_CTX *ctx, fr_value_box_t *vb,
3979
             fr_type_t dst_type, fr_dict_attr_t const *dst_enumv)
3980
256
{
3981
256
  fr_value_box_t tmp;
3982
  /*
3983
   *  Store list pointers to restore later - fr_value_box_cast clears them
3984
   */
3985
256
  fr_value_box_entry_t entry = vb->entry;
3986
3987
  /*
3988
   *  Simple case, destination type and current
3989
   *  type are the same.
3990
   */
3991
256
  if (vb->type == dst_type) {
3992
0
    vb->enumv = dst_enumv;  /* Update the enumv as this may be different */
3993
0
    return 0;
3994
0
  }
3995
3996
  /*
3997
   *  Copy meta data and any existing buffers to
3998
   *  a temporary box.  We then clear that value
3999
   *  box after the cast has been completed,
4000
   *  freeing any old buffers.
4001
   */
4002
256
  fr_value_box_copy_shallow(NULL, &tmp, vb);
4003
4004
256
  if (fr_value_box_cast(ctx, vb, dst_type, dst_enumv, &tmp) < 0) {
4005
    /*
4006
     *  On error, make sure the original
4007
     *  box is left in a consistent state.
4008
     */
4009
0
    fr_value_box_copy_shallow(NULL, vb, &tmp);
4010
0
    vb->entry = entry;
4011
0
    return -1;
4012
0
  }
4013
256
  fr_value_box_clear_value(&tmp); /* Clear out any old buffers */
4014
4015
  /*
4016
   *  Restore list pointers
4017
   */
4018
256
  vb->entry = entry;
4019
4020
256
  return 0;
4021
256
}
4022
4023
/** Return a uint64_t from a #fr_value_box_t
4024
 *
4025
 * @param[in] vb  the value-box.  Must be an unsigned integer data type.
4026
 * @return    the value as uint64_t.
4027
 */
4028
uint64_t fr_value_box_as_uint64(fr_value_box_t const *vb)
4029
4.33k
{
4030
4.33k
#undef O
4031
4.33k
#define O(_x, _y) case FR_TYPE_##_x: return vb->vb_##_y
4032
4033
4034
4.33k
  switch (vb->type) {
4035
0
    O(BOOL, bool);
4036
3.16k
    O(UINT8, uint8);
4037
1.16k
    O(UINT16, uint16);
4038
0
    O(UINT32, uint32);
4039
0
    O(UINT64, uint64);
4040
0
    O(SIZE, size);
4041
4042
0
  default:
4043
0
    fr_assert(0);
4044
0
    return 0;
4045
4.33k
  }
4046
4.33k
}
4047
4048
4049
/** Assign a #fr_value_box_t value from an #fr_ipaddr_t
4050
 *
4051
 * Automatically determines the type of the value box from the ipaddr address family
4052
 * and the length of the prefix field.
4053
 *
4054
 * @param[in] dst to assign ipaddr to.
4055
 * @param[in] enumv Aliases for values.
4056
 * @param[in] ipaddr  to copy address from.
4057
 * @param[in] tainted Whether the value came from a trusted source.
4058
 * @return
4059
 *  - 0 on success.
4060
 *  - -1 on failure.
4061
 */
4062
int fr_value_box_ipaddr(fr_value_box_t *dst, fr_dict_attr_t const *enumv, fr_ipaddr_t const *ipaddr, bool tainted)
4063
0
{
4064
0
  fr_type_t type;
4065
4066
0
  switch (ipaddr->af) {
4067
0
  case AF_INET:
4068
0
    type = (fr_ipaddr_is_prefix(ipaddr) == 1) ? FR_TYPE_IPV4_PREFIX : FR_TYPE_IPV4_ADDR;
4069
0
    break;
4070
4071
0
  case AF_INET6:
4072
0
    type = (fr_ipaddr_is_prefix(ipaddr) == 1) ? FR_TYPE_IPV6_PREFIX : FR_TYPE_IPV6_ADDR;
4073
0
    break;
4074
4075
0
  default:
4076
0
    fr_strerror_printf("Invalid address family %i", ipaddr->af);
4077
0
    return -1;
4078
0
  }
4079
4080
0
  fr_value_box_init(dst, type, enumv, tainted);
4081
0
  memcpy(&dst->vb_ip, ipaddr, sizeof(dst->vb_ip));
4082
4083
0
  return 0;
4084
0
}
4085
4086
/** Unbox an IP address performing a type check
4087
 *
4088
 * @param[out] dst  Where to copy the IP address to.
4089
 * @param[in] src Where to copy the IP address from.
4090
 * @return
4091
 *  - 0 on success.
4092
 *  - -1 on type mismatch.
4093
 */
4094
int fr_value_unbox_ipaddr(fr_ipaddr_t *dst, fr_value_box_t *src)
4095
0
{
4096
0
  if (!fr_type_is_ip(src->type)) {
4097
0
    fr_strerror_printf("Unboxing failed.  Needed IPv4/6 addr/prefix, had type %s",
4098
0
           fr_type_to_str(src->type));
4099
0
    return -1;
4100
0
  }
4101
4102
0
  memcpy(dst, &src->vb_ip, sizeof(*dst));
4103
4104
0
  return 0;
4105
0
}
4106
4107
/** Clear/free any existing value
4108
 *
4109
 * @note Do not use on uninitialised memory.
4110
 *
4111
 * @param[in] data to clear.
4112
 */
4113
void fr_value_box_clear_value(fr_value_box_t *data)
4114
95.4k
{
4115
95.4k
  switch (data->type) {
4116
26.7k
  case FR_TYPE_OCTETS:
4117
58.2k
  case FR_TYPE_STRING:
4118
58.2k
    if (data->secret) memset_explicit(data->datum.ptr, 0, data->vb_length);
4119
58.2k
    talloc_free(data->datum.ptr);
4120
58.2k
    break;
4121
4122
0
  case FR_TYPE_GROUP:
4123
    /*
4124
     *  Depth first freeing of children
4125
     *
4126
     *  This ensures orderly freeing, regardless
4127
     *  of talloc hierarchy.
4128
     */
4129
0
    {
4130
0
      fr_value_box_t  *vb = NULL;
4131
4132
0
      while ((vb = fr_value_box_list_next(&data->vb_group, vb))) {
4133
0
        fr_value_box_clear_value(vb);
4134
0
        talloc_free(vb);
4135
0
      }
4136
0
    }
4137
0
    return;
4138
4139
0
  case FR_TYPE_NULL:
4140
0
    return;
4141
4142
0
  case FR_TYPE_PAIR_CURSOR:
4143
0
    talloc_free(data->vb_cursor);
4144
0
    break;
4145
4146
37.1k
  default:
4147
37.1k
    break;
4148
95.4k
  }
4149
4150
95.4k
  memset(&data->datum, 0, sizeof(data->datum));
4151
95.4k
}
4152
4153
/** Clear/free any existing value and metadata
4154
 *
4155
 * @note Do not use on uninitialised memory.
4156
 *
4157
 * @param[in] data to clear.
4158
 */
4159
void fr_value_box_clear(fr_value_box_t *data)
4160
69.5k
{
4161
69.5k
  fr_value_box_clear_value(data);
4162
69.5k
  fr_value_box_init(data, FR_TYPE_NULL, NULL, false);
4163
69.5k
}
4164
4165
/** Copy value data verbatim duplicating any buffers
4166
 *
4167
 * @note Will free any exiting buffers associated with the dst #fr_value_box_t.
4168
 *
4169
 * @param ctx To allocate buffers in.
4170
 * @param dst Where to copy value_box to.
4171
 * @param src Where to copy value_box from.
4172
 * @return
4173
 *  - 0 on success.
4174
 *  - -1 on failure.
4175
 */
4176
int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
4177
38.5k
{
4178
38.5k
  switch (src->type) {
4179
356k
  case FR_TYPE_NUMERIC:
4180
356k
  case FR_TYPE_IP:
4181
192k
  case FR_TYPE_IFID:
4182
38.5k
  case FR_TYPE_ETHERNET:
4183
38.5k
    fr_value_box_memcpy_out(fr_value_box_raw(dst, src->type), src);
4184
38.5k
    fr_value_box_copy_meta(dst, src);
4185
38.5k
    break;
4186
4187
0
  case FR_TYPE_NULL:
4188
0
    fr_value_box_copy_meta(dst, src);
4189
0
    break;
4190
4191
0
  case FR_TYPE_STRING:
4192
0
  {
4193
0
    char *str = NULL;
4194
4195
    /*
4196
     *  Zero length strings still have a one uint8 buffer
4197
     */
4198
0
    str = talloc_bstrndup(ctx, src->vb_strvalue, src->vb_length);
4199
0
    if (!str) {
4200
0
      fr_strerror_const("Failed allocating string buffer");
4201
0
      return -1;
4202
0
    }
4203
0
    dst->vb_strvalue = str;
4204
0
    fr_value_box_copy_meta(dst, src);
4205
0
  }
4206
0
    break;
4207
4208
0
  case FR_TYPE_OCTETS:
4209
0
  {
4210
0
    uint8_t *bin;
4211
4212
0
    if (src->vb_length) {
4213
0
      bin = talloc_memdup(ctx, src->vb_octets, src->vb_length);
4214
0
      if (!bin) {
4215
0
        fr_strerror_const("Failed allocating octets buffer");
4216
0
        return -1;
4217
0
      }
4218
0
      talloc_set_type(bin, uint8_t);
4219
0
    } else {
4220
0
      bin = talloc_array(ctx, uint8_t, 0);
4221
0
    }
4222
0
    dst->vb_octets = bin;
4223
0
    fr_value_box_copy_meta(dst, src);
4224
0
  }
4225
0
    break;
4226
4227
0
  case FR_TYPE_GROUP:
4228
0
  {
4229
0
    fr_value_box_t *child = NULL;
4230
4231
0
    fr_value_box_copy_meta(dst, src); /* Initialises group child dlist */
4232
4233
0
    while ((child = fr_value_box_list_next(&src->vb_group, child))) {
4234
0
      fr_value_box_t *new;
4235
4236
      /*
4237
       *  Build out the child
4238
       */
4239
0
      new = fr_value_box_alloc_null(ctx);
4240
0
      if (unlikely(!new)) {
4241
0
      group_error:
4242
0
        fr_strerror_const("Failed duplicating group child");
4243
0
        fr_value_box_list_talloc_free(&dst->vb_group);
4244
0
        return -1;
4245
0
      }
4246
4247
      /*
4248
       *  Populate it with the data from the original child.
4249
       *
4250
       *  We do NOT update the dst safety.  The individual boxes have safety.  A group
4251
       *  doesn't.
4252
       */
4253
0
      if (unlikely(fr_value_box_copy(new, new, child) < 0)) goto group_error;
4254
0
      fr_value_box_list_insert_tail(&dst->vb_group, new);
4255
0
    }
4256
0
  }
4257
0
    break;
4258
4259
0
  case FR_TYPE_ATTR:
4260
0
    fr_value_box_copy_meta(dst, src);
4261
4262
    /* raw also sets is_unknown */
4263
0
    if (src->vb_attr->flags.is_unknown) {
4264
0
      dst->vb_attr = fr_dict_attr_unknown_copy(ctx, src->vb_attr);
4265
0
      if (!dst->vb_attr) return -1;
4266
0
      break;
4267
0
    }
4268
0
    dst->vb_attr = src->vb_attr;
4269
0
    break;
4270
4271
0
  case FR_TYPE_TLV:
4272
0
  case FR_TYPE_STRUCT:
4273
0
  case FR_TYPE_VSA:
4274
0
  case FR_TYPE_VENDOR:
4275
0
  case FR_TYPE_UNION:
4276
0
  case FR_TYPE_VOID:
4277
0
  case FR_TYPE_VALUE_BOX:
4278
0
  case FR_TYPE_VALUE_BOX_CURSOR:
4279
0
  case FR_TYPE_PAIR_CURSOR:
4280
0
  case FR_TYPE_MAX:
4281
0
    fr_assert(0);
4282
0
    fr_strerror_printf("Cannot copy data type '%s'", fr_type_to_str(src->type));
4283
0
    return -1;
4284
38.5k
  }
4285
4286
38.5k
  return 0;
4287
38.5k
}
4288
4289
/** Perform a shallow copy of a value_box
4290
 *
4291
 * Like #fr_value_box_copy, but does not duplicate the buffers of the src value_box.
4292
 *
4293
 * For #FR_TYPE_STRING and #FR_TYPE_OCTETS adds a reference from ctx so that the
4294
 * buffer cannot be freed until the ctx is freed.
4295
 *
4296
 * @param[in] ctx to add reference from.  If NULL no reference will be added.
4297
 * @param[in] dst to copy value to.
4298
 * @param[in] src to copy value from.
4299
 */
4300
void fr_value_box_copy_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *src)
4301
256
{
4302
256
  switch (src->type) {
4303
256
  default:
4304
256
    if (unlikely(fr_value_box_copy(NULL, dst, src) < 0)) return;
4305
256
    break;
4306
4307
256
  case FR_TYPE_STRING:
4308
0
  case FR_TYPE_OCTETS:
4309
0
    dst->datum.ptr = ctx ? talloc_reference(ctx, src->datum.ptr) : src->datum.ptr;
4310
0
    fr_value_box_copy_meta(dst, src);
4311
0
    break;
4312
4313
0
  case FR_TYPE_ATTR:
4314
0
    dst->vb_attr = src->vb_attr;
4315
0
    fr_value_box_copy_meta(dst, src);
4316
0
    break;
4317
256
  }
4318
256
}
4319
4320
/** Copy value data verbatim moving any buffers to the specified context
4321
 *
4322
 * @param[in] ctx   to allocate any new buffers in.
4323
 * @param[in] dst to copy value to.
4324
 * @param[in] src to copy value from.
4325
 * @return
4326
 *  - 0 on success.
4327
 *  - -1 on failure.
4328
 */
4329
int fr_value_box_steal(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t *src)
4330
0
{
4331
0
  switch (src->type) {
4332
0
  default:
4333
0
    return fr_value_box_copy(ctx, dst, src);
4334
4335
0
  case FR_TYPE_STRING:
4336
0
  {
4337
0
    char const *str;
4338
4339
0
    str = talloc_steal(ctx, src->vb_strvalue);
4340
0
    if (!str) {
4341
0
      fr_strerror_const("Failed stealing string buffer");
4342
0
      return -1;
4343
0
    }
4344
0
    talloc_set_type(str, char);
4345
0
    dst->vb_strvalue = str;
4346
0
    fr_value_box_copy_meta(dst, src);
4347
0
    memset(&src->datum, 0, sizeof(src->datum));
4348
0
  }
4349
0
    return 0;
4350
4351
0
  case FR_TYPE_OCTETS:
4352
0
  {
4353
0
    uint8_t const *bin;
4354
4355
0
    bin = talloc_steal(ctx, src->vb_octets);
4356
0
    if (!bin) {
4357
0
      fr_strerror_const("Failed stealing octets buffer");
4358
0
      return -1;
4359
0
    }
4360
0
    talloc_set_type(bin, uint8_t);
4361
4362
0
    dst->vb_octets = bin;
4363
0
    fr_value_box_copy_meta(dst, src);
4364
0
    memset(&src->datum, 0, sizeof(src->datum));
4365
0
  }
4366
0
    return 0;
4367
4368
0
  case FR_TYPE_GROUP:
4369
0
  {
4370
0
    fr_value_box_t *child;
4371
4372
0
    while ((child = fr_value_box_list_pop_head(&src->vb_group))) {
4373
0
      child = talloc_steal(ctx, child);
4374
0
      if (unlikely(!child)) {
4375
0
        fr_strerror_const("Failed stealing child");
4376
0
        return -1;
4377
0
      }
4378
0
      fr_value_box_list_insert_tail(&dst->vb_group, child);
4379
0
    }
4380
0
  }
4381
0
    return 0;
4382
0
  }
4383
0
}
4384
4385
/** Copy a nul terminated string to a #fr_value_box_t
4386
 *
4387
 * @param[in] ctx   to allocate any new buffers in.
4388
 * @param[in] dst   to assign new buffer to.
4389
 * @param[in] enumv Aliases for values.
4390
 * @param[in] src   a nul terminated buffer.
4391
 * @param[in] tainted Whether the value came from a trusted source.
4392
 * @return
4393
 *  - 0 on success.
4394
 *  - -1 on failure.
4395
 */
4396
int fr_value_box_strdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4397
      char const *src, bool tainted)
4398
6.26k
{
4399
6.26k
  char const  *str;
4400
4401
6.26k
  str = talloc_typed_strdup(ctx, src);
4402
6.26k
  if (!str) {
4403
0
    fr_strerror_const("Failed allocating string buffer");
4404
0
    return -1;
4405
0
  }
4406
4407
6.26k
  fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4408
6.26k
  dst->vb_strvalue = str;
4409
6.26k
  dst->vb_length = talloc_array_length(str) - 1;
4410
4411
6.26k
  return 0;
4412
6.26k
}
4413
4414
/** Trim the length of the string buffer to match the length of the C string
4415
 *
4416
 * @param[in] ctx to re-alloc the buffer in.
4417
 * @param[in,out] vb  to trim.
4418
 * @return
4419
 *  - 0 on success.
4420
 *  - -1 on failure.
4421
 */
4422
int fr_value_box_strtrim(TALLOC_CTX *ctx, fr_value_box_t *vb)
4423
0
{
4424
0
  size_t  len;
4425
0
  char  *str;
4426
4427
0
  if (!fr_cond_assert(vb->type == FR_TYPE_STRING)) return -1;
4428
4429
0
  len = strlen(vb->vb_strvalue);
4430
0
  str = talloc_realloc(ctx, UNCONST(char *, vb->vb_strvalue), char, len + 1);
4431
0
  if (!str) {
4432
0
    fr_strerror_const("Failed re-allocing string buffer");
4433
0
    return -1;
4434
0
  }
4435
0
  vb->vb_length = len;
4436
4437
0
  return 0;
4438
0
}
4439
4440
/** Print a formatted string using our internal printf wrapper and assign it to a value box
4441
 *
4442
 * @param[in] ctx   to allocate any new buffers in.
4443
 * @param[in] dst   to assign new buffer to.
4444
 * @param[in] enumv Aliases for values.
4445
 * @param[in] fmt The printf format string to process.
4446
 * @param[in] tainted Whether the value came from a trusted source.
4447
 * @param[in] ap  Substitution arguments.
4448
 * @return
4449
 *  - 0 on success.
4450
 *  - -1 on failure.
4451
 */
4452
int fr_value_box_vasprintf(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, bool tainted,
4453
         char const *fmt, va_list ap)
4454
0
{
4455
0
  va_list aq;
4456
0
  char *str;
4457
4458
0
  va_copy(aq, ap);  /* See vlog_module_failure_msg for why */
4459
0
  str = fr_vasprintf(ctx, fmt, aq);
4460
0
  va_end(aq);
4461
4462
0
  if (!str) return -1;
4463
4464
0
  fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4465
0
  dst->vb_strvalue = str;
4466
0
  dst->vb_length = talloc_array_length(str) - 1;
4467
4468
0
  return 0;
4469
0
}
4470
4471
/** Print a formatted string using our internal printf wrapper and assign it to a value box
4472
 *
4473
 * @param[in] ctx   to allocate any new buffers in.
4474
 * @param[in] dst   to assign new buffer to.
4475
 * @param[in] enumv Aliases for values.
4476
 * @param[in] tainted Whether the value came from a trusted source.
4477
 * @param[in] fmt The printf format string to process.
4478
 * @param[in] ... Substitution arguments.
4479
 * @return
4480
 *  - 0 on success.
4481
 *  - -1 on failure.
4482
 */
4483
int fr_value_box_asprintf(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, bool tainted,
4484
        char const *fmt, ...)
4485
0
{
4486
0
  va_list ap;
4487
0
  int ret;
4488
4489
0
  va_start(ap, fmt);
4490
0
  ret = fr_value_box_vasprintf(ctx, dst, enumv, tainted, fmt, ap);
4491
0
  va_end(ap);
4492
4493
0
  return ret;
4494
0
}
4495
4496
/** Assign a buffer containing a nul terminated string to a box, but don't copy it
4497
 *
4498
 * @note Input string will not be duplicated.
4499
 *
4500
 * @param[in] dst to assign string to.
4501
 * @param[in] enumv Aliases for values.
4502
 * @param[in] src to copy string from.
4503
 * @param[in] tainted Whether the value came from a trusted source.
4504
 */
4505
void fr_value_box_strdup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4506
         char const *src, bool tainted)
4507
2.05k
{
4508
2.05k
  fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4509
2.05k
  dst->vb_strvalue = src;
4510
2.05k
  dst->vb_length = strlen(src);
4511
2.05k
}
4512
4513
/** Free the existing buffer (if talloced) associated with the valuebox, and replace it with a new one
4514
 *
4515
 * @note Input string will not be duplicated.
4516
 *
4517
 * @param[in] vb  to replace string in.
4518
 * @param[in] src to assign string from.
4519
 * @param[in] len of src.
4520
 */
4521
void fr_value_box_strdup_shallow_replace(fr_value_box_t *vb, char const *src, ssize_t len)
4522
0
{
4523
0
  fr_value_box_clear_value(vb);
4524
0
  vb->vb_strvalue = src;
4525
0
  vb->vb_length = len < 0 ? strlen(src) : (size_t)len;
4526
0
}
4527
4528
/** Alloc and assign an empty \0 terminated string to a #fr_value_box_t
4529
 *
4530
 * @param[in] ctx   to allocate any new buffers in.
4531
 * @param[out] out  if non-null where to write a pointer to the new buffer.
4532
 * @param[in] dst   to assign new buffer to.
4533
 * @param[in] enumv Aliases for values.
4534
 * @param[in] len of buffer to allocate.
4535
 * @param[in] tainted Whether the value came from a trusted source.
4536
 * @return
4537
 *  - 0 on success.
4538
 *  - -1 on failure.
4539
 */
4540
int fr_value_box_bstr_alloc(TALLOC_CTX *ctx, char **out, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4541
          size_t len, bool tainted)
4542
37.7k
{
4543
37.7k
  char  *str;
4544
4545
37.7k
  str = talloc_zero_array(ctx, char, len + 1);
4546
37.7k
  if (!str) {
4547
0
    fr_strerror_const("Failed allocating string buffer");
4548
0
    return -1;
4549
0
  }
4550
37.7k
  str[len] = '\0';
4551
4552
37.7k
  fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4553
37.7k
  dst->vb_strvalue = str;
4554
37.7k
  dst->vb_length = len;
4555
4556
37.7k
  if (out) *out = str;
4557
4558
37.7k
  return 0;
4559
37.7k
}
4560
4561
/** Change the length of a buffer already allocated to a value box
4562
 *
4563
 * @note Do not use on an uninitialised box.
4564
 *
4565
 * @param[in] ctx to realloc buffer in.
4566
 * @param[out] out  if non-null where to write a pointer to the new buffer.
4567
 * @param[in] dst   to realloc buffer for.
4568
 * @param[in] len to realloc to (don't include nul byte).
4569
 * @return
4570
 *  - 0 on success.
4571
 *   - -1 on failure.
4572
 */
4573
int fr_value_box_bstr_realloc(TALLOC_CTX *ctx, char **out, fr_value_box_t *dst, size_t len)
4574
0
{
4575
0
  size_t  clen;
4576
0
  char  *cstr;
4577
0
  char  *str;
4578
4579
0
  fr_assert(dst->type == FR_TYPE_STRING);
4580
4581
0
  memcpy(&cstr, &dst->vb_strvalue, sizeof(cstr));
4582
4583
0
  clen = talloc_array_length(dst->vb_strvalue) - 1;
4584
0
  if (clen == len) return 0; /* No change */
4585
4586
0
  str = talloc_realloc(ctx, cstr, char, len + 1);
4587
0
  if (!str) {
4588
0
    fr_strerror_printf("Failed reallocing value box buffer to %zu bytes", len + 1);
4589
0
    return -1;
4590
0
  }
4591
4592
  /*
4593
   *  Zero out the additional bytes
4594
   */
4595
0
  if (clen < len) {
4596
0
    memset(str + clen, '\0', (len - clen) + 1);
4597
0
  } else {
4598
0
    cstr[len] = '\0';
4599
0
  }
4600
0
  dst->vb_strvalue = str;
4601
0
  dst->vb_length = len;
4602
4603
0
  if (out) *out = str;
4604
4605
0
  return 0;
4606
0
}
4607
4608
/** Copy a string to to a #fr_value_box_t
4609
 *
4610
 * @param[in] ctx   to allocate any new buffers in.
4611
 * @param[in] dst   to assign buffer to.
4612
 * @param[in] enumv Aliases for values.
4613
 * @param[in] src   a string.  May be NULL only if len == 0.
4614
 * @param[in] len of src.
4615
 * @param[in] tainted Whether the value came from a trusted source.
4616
 */
4617
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4618
        char const *src, size_t len, bool tainted)
4619
25.2k
{
4620
25.2k
  char const  *str;
4621
4622
25.2k
  if (unlikely((len > 0) && !src)) {
4623
0
    fr_strerror_printf("Invalid arguments to %s.  Len > 0 (%zu) but src string was NULL",
4624
0
           __FUNCTION__, len);
4625
0
    return -1;
4626
0
  }
4627
4628
25.2k
  str = talloc_bstrndup(ctx, src, len);
4629
25.2k
  if (!str) {
4630
0
    fr_strerror_const("Failed allocating string buffer");
4631
0
    return -1;
4632
0
  }
4633
4634
25.2k
  fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4635
25.2k
  dst->vb_strvalue = str;
4636
25.2k
  dst->vb_length = len;
4637
4638
25.2k
  return 0;
4639
25.2k
}
4640
4641
int fr_value_box_bstrndup_dbuff(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4642
        fr_dbuff_t *dbuff, size_t len, bool tainted)
4643
134k
{
4644
134k
  char  *str;
4645
4646
134k
  str = talloc_array(ctx, char, len + 1);
4647
134k
  if (!str) {
4648
0
    fr_strerror_printf("Failed allocating string buffer");
4649
0
    return -1;
4650
0
  }
4651
4652
134k
  if (fr_dbuff_out_memcpy((uint8_t *)str, dbuff, len) < 0) return -1;
4653
134k
  str[len] = '\0';
4654
4655
134k
  fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4656
134k
  dst->vb_strvalue = str;
4657
134k
  dst->vb_length = len;
4658
4659
134k
  return 0;
4660
134k
}
4661
4662
/** Copy a nul terminated talloced buffer to a #fr_value_box_t
4663
 *
4664
 * Copy a talloced nul terminated buffer, setting fields in the dst value box appropriately.
4665
 *
4666
 * The buffer must be \0 terminated, or an error will be returned.
4667
 *
4668
 * @param[in] ctx   to allocate any new buffers in.
4669
 * @param[in] dst   to assign new buffer to.
4670
 * @param[in] enumv Aliases for values.
4671
 * @param[in] src   a talloced nul terminated buffer.
4672
 * @param[in] tainted Whether the value came from a trusted source.
4673
 * @return
4674
 *  - 0 on success.
4675
 *  - -1 on failure.
4676
 */
4677
int fr_value_box_bstrdup_buffer(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4678
              char const *src, bool tainted)
4679
0
{
4680
0
  size_t  len;
4681
4682
0
  (void)talloc_get_type_abort_const(src, char);
4683
4684
0
  len = talloc_array_length(src);
4685
0
  if ((len == 0) || (src[len - 1] != '\0')) {
4686
0
    fr_strerror_const("Input buffer not \\0 terminated");
4687
0
    return -1;
4688
0
  }
4689
4690
0
  return fr_value_box_bstrndup(ctx, dst, enumv, src, len - 1, tainted);
4691
0
}
4692
4693
/** Assign a string to to a #fr_value_box_t
4694
 *
4695
 * @param[in] dst   to assign new buffer to.
4696
 * @param[in] enumv Aliases for values.
4697
 * @param[in] src   a string.
4698
 * @param[in] len of src.
4699
 * @param[in] tainted Whether the value came from a trusted source.
4700
 */
4701
void fr_value_box_bstrndup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4702
           char const *src, size_t len, bool tainted)
4703
0
{
4704
0
  fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4705
0
  dst->vb_strvalue = src;
4706
0
  dst->vb_length = len;
4707
0
}
4708
4709
/** Assign a talloced buffer containing a nul terminated string to a box, but don't copy it
4710
 *
4711
 * Adds a reference to the src buffer so that it cannot be freed until the ctx is freed.
4712
 *
4713
 * @param[in] ctx to add reference from.  If NULL no reference will be added.
4714
 * @param[in] dst to assign string to.
4715
 * @param[in] enumv Aliases for values.
4716
 * @param[in] src to copy string from.
4717
 * @param[in] tainted Whether the value came from a trusted source.
4718
 * @return
4719
 *  - 0 on success.
4720
 *  - -1 on failure.
4721
 */
4722
int fr_value_box_bstrdup_buffer_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4723
                char const *src, bool tainted)
4724
68
{
4725
68
  size_t  len;
4726
4727
68
  (void) talloc_get_type_abort_const(src, char);
4728
4729
68
  len = talloc_array_length(src);
4730
68
  if ((len == 0) || (src[len - 1] != '\0')) {
4731
0
    fr_strerror_const("Input buffer not \\0 terminated");
4732
0
    return -1;
4733
0
  }
4734
4735
68
  fr_value_box_init(dst, FR_TYPE_STRING, enumv, tainted);
4736
68
  dst->vb_strvalue = ctx ? talloc_reference(ctx, src) : src;
4737
68
  dst->vb_length = len - 1;
4738
4739
68
  return 0;
4740
68
}
4741
4742
/** Pre-allocate an octets buffer for filling by the caller
4743
 *
4744
 * @note Buffer will not be zeroed, as it's assumed the caller will be filling it.
4745
 *
4746
 * @param[in] ctx to allocate any new buffers in.
4747
 * @param[out] out  If non-null will be filled with a pointer to the
4748
 *      new buffer.
4749
 * @param[in] dst to assign new buffer to.
4750
 * @param[in] enumv Aliases for values.
4751
 * @param[in] len of data in the buffer. If 0, a zero length
4752
 *      talloc buffer will be alloced. dst->vb_octets
4753
 *      will *NOT* be NULL.  You should use the length
4754
 *      field of the box to determine if any value
4755
 *          is assigned.
4756
 * @param[in] tainted Whether the value came from a trusted source.
4757
 * @return
4758
 *  - 0 on success.
4759
 *  - -1 on failure.
4760
 */
4761
int fr_value_box_mem_alloc(TALLOC_CTX *ctx, uint8_t **out, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4762
         size_t len, bool tainted)
4763
1.22k
{
4764
1.22k
  uint8_t *bin;
4765
4766
1.22k
  bin = talloc_array(ctx, uint8_t, len);
4767
1.22k
  if (!bin) {
4768
0
    fr_strerror_const("Failed allocating octets buffer");
4769
0
    return -1;
4770
0
  }
4771
1.22k
  talloc_set_type(bin, uint8_t);
4772
4773
1.22k
  fr_value_box_init(dst, FR_TYPE_OCTETS, enumv, tainted);
4774
1.22k
  dst->vb_octets = bin;
4775
1.22k
  dst->vb_length = len;
4776
4777
1.22k
  if (out) *out = bin;
4778
4779
1.22k
  return 0;
4780
1.22k
}
4781
4782
/** Change the length of a buffer already allocated to a value box
4783
 *
4784
 * @note Do not use on an uninitialised box.
4785
 *
4786
 * @param[in] ctx to realloc buffer in.
4787
 * @param[out] out  if non-null where to write a pointer to the new buffer.
4788
 * @param[in] dst   to realloc buffer for.
4789
 * @param[in] len to realloc to.
4790
 * @return
4791
 *  - 0 on success.
4792
 *   - -1 on failure.
4793
 */
4794
int fr_value_box_mem_realloc(TALLOC_CTX *ctx, uint8_t **out, fr_value_box_t *dst, size_t len)
4795
0
{
4796
0
  size_t  clen;
4797
0
  uint8_t *cbin;
4798
0
  uint8_t *bin;
4799
4800
0
  fr_assert(dst->type == FR_TYPE_OCTETS);
4801
4802
0
  memcpy(&cbin, &dst->vb_octets, sizeof(cbin));
4803
4804
0
  clen = talloc_array_length(dst->vb_octets);
4805
0
  if (clen == len) return 0; /* No change */
4806
4807
  /*
4808
   *  Realloc the buffer.  If the new length is 0, we
4809
   *  need to call talloc_array() instead of talloc_realloc()
4810
   *  as talloc_realloc() will fail.
4811
   */
4812
0
  if (len > 0) {
4813
0
    bin = talloc_realloc(ctx, cbin, uint8_t, len);
4814
0
  } else {
4815
0
    bin = talloc_array(ctx, uint8_t, 0);
4816
0
  }
4817
0
  if (!bin) {
4818
0
    fr_strerror_printf("Failed reallocing value box buffer to %zu bytes", len);
4819
0
    return -1;
4820
0
  }
4821
4822
  /*
4823
   *  Only free the original buffer once we've allocated
4824
   *  a new empty array.
4825
   */
4826
0
  if (len == 0) talloc_free(cbin);
4827
4828
  /*
4829
   *  Zero out the additional bytes
4830
   */
4831
0
  if (clen < len) memset(bin + clen, 0x00, len - clen);
4832
0
  dst->vb_octets = bin;
4833
0
  dst->vb_length = len;
4834
4835
0
  if (out) *out = bin;
4836
4837
0
  return 0;
4838
0
}
4839
4840
/** Copy a buffer to a fr_value_box_t
4841
 *
4842
 * Copy a buffer containing binary data, setting fields in the dst value box appropriately.
4843
 *
4844
 * @param[in] ctx to allocate any new buffers in.
4845
 * @param[in] dst to assign new buffer to.
4846
 * @param[in] enumv Aliases for values.
4847
 * @param[in] src a buffer.
4848
 * @param[in] len of data in the buffer. If 0, a zero length
4849
 *      talloc buffer will be alloced. dst->vb_octets
4850
 *      will *NOT* be NULL.  You should use the length
4851
 *      field of the box to determine if any value
4852
 *          is assigned.
4853
 * @param[in] tainted Whether the value came from a trusted source.
4854
 * @return
4855
 *  - 0 on success.
4856
 *  - -1 on failure.
4857
 */
4858
int fr_value_box_memdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4859
      uint8_t const *src, size_t len, bool tainted)
4860
25.5k
{
4861
25.5k
  uint8_t *bin;
4862
4863
25.5k
  if (unlikely((len > 0) && !src)) {
4864
0
    fr_strerror_printf("Invalid arguments to %s.  Len > 0 (%zu) but src was NULL",
4865
0
           __FUNCTION__, len);
4866
0
    return -1;
4867
0
  }
4868
4869
25.5k
  bin = talloc_memdup(ctx, src, len);
4870
25.5k
  if (!bin) {
4871
0
    fr_strerror_const("Failed allocating octets buffer");
4872
0
    return -1;
4873
0
  }
4874
25.5k
  talloc_set_type(bin, uint8_t);
4875
4876
25.5k
  fr_value_box_init(dst, FR_TYPE_OCTETS, enumv, tainted);
4877
25.5k
  dst->vb_octets = bin;
4878
25.5k
  dst->vb_length = len;
4879
4880
25.5k
  return 0;
4881
25.5k
}
4882
4883
int fr_value_box_memdup_dbuff(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4884
            fr_dbuff_t *dbuff, size_t len, bool tainted)
4885
3.61M
{
4886
3.61M
  uint8_t *bin;
4887
4888
3.61M
  bin = talloc_size(ctx, len);
4889
3.61M
  if (!bin) {
4890
0
    fr_strerror_printf("Failed allocating octets buffer");
4891
0
    return -1;
4892
0
  }
4893
3.61M
  if (fr_dbuff_out_memcpy(bin, dbuff, len) < (ssize_t) len) return -1;
4894
3.61M
  talloc_set_type(bin, uint8_t);
4895
4896
3.61M
  fr_value_box_init(dst, FR_TYPE_OCTETS, enumv, tainted);
4897
3.61M
  dst->vb_octets = bin;
4898
3.61M
  dst->vb_length = len;
4899
4900
3.61M
  return 0;
4901
3.61M
}
4902
4903
/** Copy a talloced buffer to a fr_value_box_t
4904
 *
4905
 * Copy a buffer containing binary data, setting fields in the dst value box appropriately.
4906
 *
4907
 * @param[in] ctx to allocate any new buffers in.
4908
 * @param[in] dst to assign new buffer to.
4909
 * @param[in] enumv Aliases for values.
4910
 * @param[in] src a buffer.
4911
 * @param[in] tainted Whether the value came from a trusted source.
4912
 * @return
4913
 *  - 0 on success.
4914
 *  - -1 on failure.
4915
 */
4916
int fr_value_box_memdup_buffer(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4917
             uint8_t const *src, bool tainted)
4918
0
{
4919
0
  (void) talloc_get_type_abort_const(src, uint8_t);
4920
4921
0
  return fr_value_box_memdup(ctx, dst, enumv, src, talloc_array_length(src), tainted);
4922
0
}
4923
4924
/** Assign a buffer to a box, but don't copy it
4925
 *
4926
 * Adds a reference to the src buffer so that it cannot be freed until the ctx is freed.
4927
 *
4928
 * Caller should set dst->taint = true, where the value was acquired from an untrusted source.
4929
 *
4930
 * @note Will free any exiting buffers associated with the value box.
4931
 *
4932
 * @param[in] dst   to assign buffer to.
4933
 * @param[in] enumv Aliases for values.
4934
 * @param[in] src a talloced buffer.
4935
 * @param[in] len of buffer.
4936
 * @param[in] tainted Whether the value came from a trusted source.
4937
 */
4938
void fr_value_box_memdup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4939
         uint8_t const *src, size_t len, bool tainted)
4940
3.18k
{
4941
3.18k
  fr_value_box_init(dst, FR_TYPE_OCTETS, enumv, tainted);
4942
3.18k
  dst->vb_octets = src;
4943
3.18k
  dst->vb_length = len;
4944
3.18k
}
4945
4946
/** Assign a talloced buffer to a box, but don't copy it
4947
 *
4948
 * Adds a reference to the src buffer so that it cannot be freed until the ctx is freed.
4949
 *
4950
 * @param[in] ctx   to allocate any new buffers in.
4951
 * @param[in] dst   to assign buffer to.
4952
 * @param[in] enumv Aliases for values.
4953
 * @param[in] src a talloced buffer.
4954
 * @param[in] tainted Whether the value came from a trusted source.
4955
 */
4956
void fr_value_box_memdup_buffer_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv,
4957
                uint8_t const *src, bool tainted)
4958
65
{
4959
65
  (void) talloc_get_type_abort_const(src, uint8_t);
4960
4961
65
  fr_value_box_init(dst, FR_TYPE_OCTETS, enumv, tainted);
4962
65
  dst->vb_octets = ctx ? talloc_reference(ctx, src) : src;
4963
65
  dst->vb_length = talloc_array_length(src);
4964
65
}
4965
4966
/*
4967
 *  Assign a cursor to the data type.
4968
 */
4969
void fr_value_box_set_cursor(fr_value_box_t *dst, fr_type_t type, void *cursor, char const *name)
4970
0
{
4971
0
  fr_assert((type == FR_TYPE_VALUE_BOX_CURSOR) || (type == FR_TYPE_PAIR_CURSOR));
4972
4973
0
  fr_value_box_init(dst, type, NULL, false);
4974
0
  dst->vb_cursor = cursor;
4975
0
  dst->vb_cursor_name = name;
4976
0
}
4977
4978
void fr_value_box_set_attr(fr_value_box_t *dst, fr_dict_attr_t const *da)
4979
0
{
4980
0
  fr_value_box_init(dst, FR_TYPE_ATTR, NULL, false);
4981
0
  dst->vb_attr = da;
4982
0
  dst->enumv = da;
4983
0
}
4984
4985
/** Increment a boxed value
4986
 *
4987
 * Implements safe integer overflow.
4988
 *
4989
 * @param[in] vb  to increment.
4990
 */
4991
void fr_value_box_increment(fr_value_box_t *vb)
4992
0
{
4993
0
  switch (vb->type) {
4994
0
  case FR_TYPE_UINT8:
4995
0
    vb->vb_uint8 = vb->vb_uint8 == UINT8_MAX ? 0 : vb->vb_uint8 + 1;
4996
0
    return;
4997
4998
0
  case FR_TYPE_UINT16:
4999
0
    vb->vb_uint16 = vb->vb_uint16 == UINT16_MAX ? 0 : vb->vb_uint16 + 1;
5000
0
    return;
5001
5002
0
  case FR_TYPE_UINT32:
5003
0
    vb->vb_uint32 = vb->vb_uint32 == UINT32_MAX ? 0 : vb->vb_uint32 + 1;
5004
0
    return;
5005
5006
0
  case FR_TYPE_UINT64:
5007
0
    vb->vb_uint64 = vb->vb_uint64 == UINT64_MAX ? 0 : vb->vb_uint64 + 1;
5008
0
    return;
5009
5010
0
  case FR_TYPE_INT8:
5011
0
    vb->vb_int8 = vb->vb_int8 == INT8_MAX ? INT8_MIN : vb->vb_int8 + 1;
5012
0
    return;
5013
5014
0
  case FR_TYPE_INT16:
5015
0
    vb->vb_int16 = vb->vb_int16 == INT16_MAX ? INT16_MIN : vb->vb_int16 + 1;
5016
0
    return;
5017
5018
0
  case FR_TYPE_INT32:
5019
0
    vb->vb_int32 = vb->vb_int32 == INT32_MAX ? INT32_MIN : vb->vb_int32 + 1;
5020
0
    return;
5021
5022
0
  case FR_TYPE_INT64:
5023
0
    vb->vb_int64 = vb->vb_int64 == INT64_MAX ? INT64_MIN : vb->vb_int64 + 1;
5024
0
    return;
5025
5026
0
  default:
5027
0
    fr_assert_fail(NULL);
5028
0
    return;
5029
0
  }
5030
0
}
5031
5032
/** Convert integer encoded as string to a fr_value_box_t type
5033
 *
5034
 * @param[out] dst    where to write parsed value.
5035
 * @param[in] dst_type    type of integer to convert string to.
5036
 * @param[in] dst_enumv   Enumeration values.
5037
 * @param[in] in    String to convert to integer.
5038
 * @param[in] rules   for parsing string.
5039
 * @param[in] tainted   Whether the value came from a trusted source.
5040
 * @return
5041
 *  - >= 0 on success (number of bytes parsed).
5042
 *  - < 0 on error (where the parse error occurred).
5043
 */
5044
static inline CC_HINT(always_inline)
5045
fr_slen_t fr_value_box_from_numeric_substr(fr_value_box_t *dst, fr_type_t dst_type,
5046
             fr_dict_attr_t const *dst_enumv,
5047
             fr_sbuff_t *in, fr_sbuff_parse_rules_t const *rules, bool tainted)
5048
40.9k
{
5049
40.9k
  fr_slen_t   slen;
5050
40.9k
  fr_sbuff_parse_error_t  err;
5051
5052
40.9k
  fr_value_box_init(dst, dst_type, dst_enumv, tainted);
5053
5054
40.9k
  switch (dst_type) {
5055
3.20k
  case FR_TYPE_UINT8:
5056
3.20k
    slen = fr_sbuff_out(&err, &dst->vb_uint8, in);
5057
3.20k
    break;
5058
5059
2.36k
  case FR_TYPE_UINT16:
5060
2.36k
    slen = fr_sbuff_out(&err, &dst->vb_uint16, in);
5061
2.36k
    break;
5062
5063
34.7k
  case FR_TYPE_UINT32:
5064
34.7k
    slen = fr_sbuff_out(&err, &dst->vb_uint32, in);
5065
34.7k
    break;
5066
5067
279
  case FR_TYPE_UINT64:
5068
279
    slen = fr_sbuff_out(&err, &dst->vb_uint64, in);
5069
279
    break;
5070
5071
57
  case FR_TYPE_INT8:
5072
57
    slen = fr_sbuff_out(&err, &dst->vb_int8, in);
5073
57
    break;
5074
5075
70
  case FR_TYPE_INT16:
5076
70
    slen = fr_sbuff_out(&err, &dst->vb_int16, in);
5077
70
    break;
5078
5079
57
  case FR_TYPE_INT32:
5080
57
    slen = fr_sbuff_out(&err, &dst->vb_int32, in);
5081
57
    break;
5082
5083
31
  case FR_TYPE_INT64:
5084
31
    slen = fr_sbuff_out(&err, &dst->vb_int64, in);
5085
31
    break;
5086
5087
0
  case FR_TYPE_SIZE:
5088
0
    slen = fr_sbuff_out(&err, &dst->vb_size, in);
5089
0
    break;
5090
5091
54
  case FR_TYPE_FLOAT32:
5092
54
    slen = fr_sbuff_out(&err, &dst->vb_float32, in);
5093
54
    break;
5094
5095
49
  case FR_TYPE_FLOAT64:
5096
49
    slen = fr_sbuff_out(&err, &dst->vb_float64, in);
5097
49
    break;
5098
5099
0
  default:
5100
0
    fr_assert_fail(NULL);
5101
0
    return -1;
5102
40.9k
  }
5103
5104
40.9k
  if (slen < 0) {
5105
    /*
5106
     *  If an enumeration attribute is provided and we
5107
     *      don't find an integer, assume this is an enumv
5108
     *      lookup fail, and produce a better error.
5109
     */
5110
1.77k
    if (dst_enumv && dst_enumv->flags.has_value && (err == FR_SBUFF_PARSE_ERROR_NOT_FOUND)) {
5111
189
      fr_sbuff_t our_in = FR_SBUFF(in);
5112
189
      fr_sbuff_adv_until(&our_in, SIZE_MAX, rules->terminals,
5113
189
             rules->escapes ? rules->escapes->chr : '\0');
5114
5115
189
      fr_strerror_printf("Invalid enumeration value \"%pV\" for attribute %s",
5116
189
             fr_box_strvalue_len(fr_sbuff_start(&our_in), fr_sbuff_used(&our_in)),
5117
189
             dst_enumv->name);
5118
189
      return -1;
5119
189
    }
5120
5121
1.58k
    if (err == FR_SBUFF_PARSE_ERROR_NOT_FOUND) {
5122
495
      fr_strerror_printf("Failed parsing string as type '%s'",
5123
495
             fr_type_to_str(dst_type));
5124
1.09k
    } else {
5125
1.09k
      fr_sbuff_parse_error_to_strerror(err);
5126
1.09k
    }
5127
1.58k
  }
5128
5129
5130
40.7k
  return slen;
5131
40.9k
}
5132
5133
/** Convert string value to a fr_value_box_t type
5134
 *
5135
 * @param[in] ctx   to alloc strings in.
5136
 * @param[out] dst    where to write parsed value.
5137
 * @param[in,out] dst_type  of value data to create/dst_type of value created.
5138
 * @param[in] dst_enumv   fr_dict_attr_t with string names for uint32 values.
5139
 * @param[in] in    sbuff to read data from.
5140
 * @param[in] rules   unescape and termination rules.
5141
 * @return
5142
 *  - >0 on success.
5143
 *  - <= 0 on parse error.
5144
 */
5145
ssize_t fr_value_box_from_substr(TALLOC_CTX *ctx, fr_value_box_t *dst,
5146
         fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
5147
         fr_sbuff_t *in, fr_sbuff_parse_rules_t const *rules)
5148
50.9k
{
5149
50.9k
  static fr_sbuff_parse_rules_t default_rules;
5150
50.9k
  fr_sbuff_t      *unescaped = NULL;
5151
50.9k
  fr_sbuff_t      our_in = FR_SBUFF(in);
5152
50.9k
  fr_ipaddr_t     addr;
5153
50.9k
  fr_slen_t     slen;
5154
50.9k
  char        buffer[256];
5155
5156
50.9k
  if (!rules) rules = &default_rules;
5157
5158
50.9k
  fr_strerror_clear();
5159
5160
  /*
5161
   *  Lookup any names before continuing
5162
   */
5163
50.9k
  if (dst_enumv && dst_enumv->flags.has_value && (dst_type != FR_TYPE_ATTR)) {
5164
604
    size_t        name_len;
5165
604
    fr_dict_enum_value_t const  *enumv;
5166
5167
    /*
5168
     *  @todo - allow enum names for IPv6 addresses and prefixes.  See also
5169
     *  tmpl_afrom_enum().
5170
     */
5171
604
    (void) fr_sbuff_adv_past_str_literal(&our_in, "::");
5172
5173
    /*
5174
     *  If there is no escaping, then we ignore the terminals.  The list of allowed characters
5175
     *  in enum names will ensure that the parsing doesn't go too far.  i.e. to '\r', '\n'. '}', etc.
5176
     *
5177
     *  The reason is that the list of terminals may include things like '-', which is also a
5178
     *  valid character in enum names.  We don't want to parse "Framed-User" as "Framed - User".
5179
     */
5180
604
    if (!rules->escapes) {
5181
604
      size_t len;
5182
604
      fr_sbuff_marker_t m;
5183
5184
604
      fr_sbuff_marker(&m, &our_in);
5185
5186
604
      len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in),
5187
604
              fr_dict_enum_allowed_chars, NULL);
5188
604
      fr_sbuff_set(&our_in, &m);
5189
604
      fr_sbuff_marker_release(&m);
5190
5191
604
      if (!len) goto parse; /* Zero length name can't match enum */
5192
5193
435
      enumv = fr_dict_enum_by_name(dst_enumv, fr_sbuff_current(&our_in), len);
5194
435
      if (!enumv) {
5195
425
        goto parse; /* No enumeration matches escaped string */
5196
425
      }
5197
5198
10
      (void) fr_sbuff_advance(&our_in, len);
5199
10
      goto cast_enum;
5200
435
    }
5201
5202
    /*
5203
     *  Create a thread-local extensible buffer to
5204
     *  store unescaped data.
5205
     *
5206
     *  This is created once per-thread (the first time
5207
     *  this function is called), and freed when the
5208
     *  thread exits.
5209
     */
5210
0
    FR_SBUFF_TALLOC_THREAD_LOCAL(&unescaped, 256, 4096);
5211
5212
    /*
5213
     *  This function only does escaping until a terminal character, such as '-'.  So
5214
     *  Framed-User will get parsed as "Framed - User".
5215
     *
5216
     *  Pretty much no other enum has this problem. For Service-Type, it defines "Framed" ss
5217
     *  an equivalent name to "Framed-User".  The parser sees "Framed-User", stops at the '-',
5218
     *  and then finds the enum named "Framed".  It then returns the trailing "-User" as
5219
     *  something more to parse.
5220
     *
5221
     *  As a result, when the user passes in "Framed-User", the output is "Framed-User -
5222
     *  User", which is more than a bit surprising.
5223
     */
5224
0
    name_len = fr_sbuff_out_unescape_until(unescaped, &our_in, SIZE_MAX,
5225
0
                   rules->terminals, rules->escapes);
5226
0
    if (!name_len) {
5227
0
      fr_sbuff_set_to_start(&our_in);
5228
0
      goto parse; /* Zero length name can't match enum */
5229
0
    }
5230
5231
0
    enumv = fr_dict_enum_by_name(dst_enumv, fr_sbuff_start(unescaped), fr_sbuff_used(unescaped));
5232
0
    if (!enumv) {
5233
0
      fr_sbuff_set_to_start(&our_in);
5234
0
      goto parse; /* No enumeration matches escaped string */
5235
0
    }
5236
5237
10
  cast_enum:
5238
    /*
5239
     *  dst_type may not match enumv type
5240
     */
5241
10
    if (fr_value_box_cast(ctx, dst, dst_type, dst_enumv, enumv->value) < 0) return -1;
5242
5243
10
    FR_SBUFF_SET_RETURN(in, &our_in);
5244
10
  }
5245
5246
50.9k
parse:
5247
  /*
5248
   *  It's a variable ret src->dst_type so we just alloc a new buffer
5249
   *  of size len and copy.
5250
   */
5251
50.9k
  switch (dst_type) {
5252
68
  case FR_TYPE_STRING:
5253
    /*
5254
     *  We've not unescaped the string yet, produce an unescaped version
5255
     */
5256
68
    if (!dst_enumv || !unescaped) {
5257
68
      char *buff;
5258
5259
68
      if (unlikely(fr_sbuff_out_aunescape_until(ctx, &buff, &our_in, SIZE_MAX,
5260
68
                  rules->terminals, rules->escapes) < 0)) {
5261
0
        return -1;
5262
0
      }
5263
68
      fr_value_box_bstrdup_buffer_shallow(NULL, dst, dst_enumv, buff, false);
5264
    /*
5265
     *  We already have an unescaped version, just use that
5266
     */
5267
68
    } else {
5268
0
      fr_value_box_bstrndup(ctx, dst, dst_enumv,
5269
0
                fr_sbuff_start(unescaped), fr_sbuff_used(unescaped), false);
5270
0
    }
5271
68
    FR_SBUFF_SET_RETURN(in, &our_in);
5272
5273
  /* raw octets: 0x01020304... */
5274
131
  case FR_TYPE_OCTETS:
5275
131
  {
5276
131
    fr_sbuff_marker_t hex_start;
5277
131
    size_t      hex_len;
5278
131
    uint8_t     *bin_buff;
5279
5280
    /*
5281
     *  If there's escape sequences that need to be processed
5282
     *  or the string doesn't start with 0x, then assume this
5283
     *  is literal data, not hex encoded data.
5284
     */
5285
131
    if (rules->escapes || !fr_sbuff_adv_past_strcase_literal(&our_in, "0x")) {
5286
65
      if (!dst_enumv || !unescaped) {
5287
65
        char  *buff = NULL;
5288
65
        uint8_t *bin;
5289
5290
65
        if (fr_sbuff_extend(&our_in)) {
5291
64
          fr_sbuff_out_aunescape_until(ctx, &buff, &our_in, SIZE_MAX,
5292
64
                     rules->terminals, rules->escapes);
5293
5294
64
          if (talloc_array_length(buff) == 1) {
5295
0
            talloc_free(buff);
5296
0
            goto zero;
5297
0
          }
5298
5299
64
          bin = talloc_realloc(ctx, buff, uint8_t, talloc_array_length(buff) - 1);
5300
64
          if (unlikely(!bin)) {
5301
0
            fr_strerror_const("Failed trimming string buffer");
5302
0
            talloc_free(buff);
5303
0
            return -1;
5304
0
          }
5305
64
          talloc_set_type(bin, uint8_t); /* talloc_realloc doesn't do this */
5306
        /*
5307
         *  Input data is zero
5308
         *
5309
         *  talloc realloc will refuse to realloc to
5310
         *  a zero length buffer.  This is probably
5311
         *  a bug, because we can create zero length
5312
         *  arrays normally
5313
         */
5314
64
        } else {
5315
1
        zero:
5316
1
          bin = talloc_zero_array(ctx, uint8_t, 0);
5317
1
        }
5318
5319
65
        fr_value_box_memdup_buffer_shallow(NULL, dst, dst_enumv, bin, false);
5320
      /*
5321
       *  We already have an unescaped version, just use that
5322
       */
5323
65
      } else {
5324
0
        fr_value_box_memdup(ctx, dst, dst_enumv,
5325
0
                (uint8_t *)fr_sbuff_start(unescaped),
5326
0
                fr_sbuff_used(unescaped), false);
5327
0
      }
5328
65
      FR_SBUFF_SET_RETURN(in, &our_in);
5329
65
    }
5330
5331
66
    fr_sbuff_marker(&hex_start, &our_in); /* Record where the hexits start */
5332
5333
    /*
5334
     *  Find the end of the hex sequence.
5335
     *
5336
     *  We don't technically need to do this, fr_base16_decode
5337
     *  will find the end on its own.
5338
     *
5339
     *  We do this so we can alloc the correct sized
5340
     *  output buffer.
5341
     */
5342
66
    hex_len = fr_sbuff_adv_past_allowed(&our_in, SIZE_MAX, sbuff_char_class_hex, rules->terminals);
5343
66
    if (hex_len == 0) {
5344
3
      if (fr_value_box_memdup(ctx, dst, dst_enumv, (uint8_t[]){ 0x00 }, 0, false) < 0) return -1;
5345
3
      FR_SBUFF_SET_RETURN(in, &our_in);
5346
3
    }
5347
5348
63
    if ((hex_len & 0x01) != 0) {
5349
29
      fr_strerror_printf("Length of hex string is not even, got %zu bytes", hex_len);
5350
29
      FR_SBUFF_ERROR_RETURN(&our_in);
5351
29
    }
5352
5353
    /*
5354
     *  Pre-allocate the bin buff and initialise the box
5355
     */
5356
34
    if (fr_value_box_mem_alloc(ctx, &bin_buff, dst, dst_enumv, (hex_len >> 1), false) < 0) return -1;
5357
5358
    /*
5359
     *  Reset to the start of the hex string
5360
     */
5361
34
    fr_sbuff_set(&our_in, &hex_start);
5362
5363
34
    if (unlikely(fr_base16_decode(NULL, &FR_DBUFF_TMP(bin_buff, hex_len), &our_in, false) < 0)) {
5364
0
      talloc_free(bin_buff);
5365
0
      FR_SBUFF_ERROR_RETURN(&our_in);
5366
0
    }
5367
5368
34
    FR_SBUFF_SET_RETURN(in, &our_in);
5369
34
  }
5370
5371
1.78k
  case FR_TYPE_IPV4_ADDR:
5372
1.78k
  {
5373
1.78k
    size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
5374
1.78k
    if (!name_len) return 0;
5375
5376
1.67k
    if (fr_inet_pton4(&addr, fr_sbuff_current(in), name_len,
5377
1.67k
          fr_hostname_lookups, false, true) < 0) return -1;
5378
5379
    /*
5380
     *  We allow v4 addresses to have a /32 suffix as some databases (PostgreSQL)
5381
     *  print them this way.
5382
     */
5383
847
    if (addr.prefix != 32) {
5384
159
    fail_ipv4_prefix:
5385
159
      fr_strerror_printf("Invalid IPv4 mask length \"/%i\".  Only \"/32\" permitted "
5386
159
             "for non-prefix types", addr.prefix);
5387
159
      return -1;
5388
155
    }
5389
5390
692
    memcpy(&dst->vb_ip, &addr, sizeof(dst->vb_ip));
5391
692
  }
5392
0
    goto finish;
5393
5394
161
  case FR_TYPE_IPV4_PREFIX:
5395
161
  {
5396
161
    size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
5397
161
    if (!name_len) return 0;
5398
5399
160
    if (fr_inet_pton4(&dst->vb_ip, fr_sbuff_current(in), name_len,
5400
160
          fr_hostname_lookups, false, true) < 0) return -1;
5401
160
  }
5402
57
    goto finish;
5403
5404
71
  case FR_TYPE_IPV6_ADDR:
5405
71
  {
5406
71
    size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
5407
71
    if (!name_len) return 0;
5408
5409
    /*
5410
     *  Parse scope, too.
5411
     */
5412
69
    if (fr_sbuff_next_if_char(&our_in, '%')) {
5413
4
      name_len += fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_uint, rules->terminals);
5414
4
    }
5415
5416
69
    if (fr_inet_pton6(&addr, fr_sbuff_current(in), name_len,
5417
69
          fr_hostname_lookups, false, true) < 0) return -1;
5418
5419
    /*
5420
     *  We allow v6 addresses to have a /128 suffix as some databases (PostgreSQL)
5421
     *  print them this way.
5422
     */
5423
17
    if (addr.prefix != 128) {
5424
21
    fail_ipv6_prefix:
5425
21
      fr_strerror_printf("Invalid IPv6 mask length \"/%i\".  Only \"/128\" permitted "
5426
21
             "for non-prefix types", addr.prefix);
5427
21
      return -1;
5428
13
    }
5429
5430
4
    memcpy(&dst->vb_ip, &addr, sizeof(dst->vb_ip));
5431
4
  }
5432
0
    goto finish;
5433
5434
32
  case FR_TYPE_IPV6_PREFIX:
5435
32
  {
5436
32
    size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
5437
32
    if (!name_len) return 0;
5438
5439
31
    if (fr_inet_pton6(&dst->vb_ip, fr_sbuff_current(in), name_len,
5440
31
          fr_hostname_lookups, false, true) < 0) return -1;
5441
31
  }
5442
2
    goto finish;
5443
5444
240
  case FR_TYPE_COMBO_IP_ADDR:
5445
240
  {
5446
240
    size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
5447
240
    if (!name_len) return 0;
5448
5449
    /*
5450
     *  Parse scope, too.
5451
     */
5452
239
    if (fr_sbuff_next_if_char(&our_in, '%')) {
5453
3
      name_len += fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_uint, rules->terminals);
5454
3
    }
5455
5456
239
    if (fr_inet_pton(&addr, fr_sbuff_current(in), name_len, AF_UNSPEC,
5457
239
         fr_hostname_lookups, true) < 0) return -1;
5458
5459
174
    if ((addr.af == AF_INET) && (addr.prefix != 32)) {
5460
4
      goto fail_ipv4_prefix;
5461
4
    }
5462
5463
170
    if ((addr.af == AF_INET6) && (addr.prefix != 128)) {
5464
8
      goto fail_ipv6_prefix;
5465
8
    }
5466
5467
162
    memcpy(&dst->vb_ip, &addr, sizeof(dst->vb_ip));
5468
162
  }
5469
0
    goto finish;
5470
5471
92
  case FR_TYPE_COMBO_IP_PREFIX:
5472
92
  {
5473
92
    size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
5474
92
    if (!name_len) return 0;
5475
5476
91
    if (fr_inet_pton(&dst->vb_ip, fr_sbuff_current(in), name_len, AF_UNSPEC,
5477
91
          fr_hostname_lookups, true) < 0) return -1;
5478
91
  }
5479
41
    goto finish;
5480
5481
3.20k
  case FR_TYPE_UINT8:
5482
5.56k
  case FR_TYPE_UINT16:
5483
40.3k
  case FR_TYPE_UINT32:
5484
40.5k
  case FR_TYPE_UINT64:
5485
40.6k
  case FR_TYPE_INT8:
5486
40.7k
  case FR_TYPE_INT16:
5487
40.7k
  case FR_TYPE_INT32:
5488
40.8k
  case FR_TYPE_INT64:
5489
40.8k
  case FR_TYPE_FLOAT32:
5490
40.9k
  case FR_TYPE_FLOAT64:
5491
40.9k
    return fr_value_box_from_numeric_substr(dst, dst_type, dst_enumv, in, rules, false);
5492
5493
34
  case FR_TYPE_SIZE:
5494
34
    if (fr_size_from_str(&dst->datum.size, &our_in) < 0) return -1;
5495
15
    goto finish;
5496
5497
286
  case FR_TYPE_BOOL:
5498
286
    fr_value_box_init(dst, dst_type, dst_enumv, false);
5499
5500
    /*
5501
     *  Quoted boolean values are "yes", "no", "true", "false"
5502
     */
5503
286
    slen = fr_sbuff_out(NULL, &dst->vb_bool, in);
5504
286
    if (slen >= 0) return slen;
5505
5506
    /*
5507
     *  For barewords we also allow 0 for false and any other
5508
     *      integer value for true.
5509
     */
5510
279
    if (!rules->escapes) {
5511
279
      int64_t stmp;
5512
279
      uint64_t utmp;
5513
5514
279
      slen = fr_sbuff_out(NULL, &stmp, in);
5515
279
      if (slen >= 0) {
5516
236
        dst->vb_bool = (stmp != 0);
5517
236
        return slen;
5518
236
      }
5519
5520
43
      slen = fr_sbuff_out(NULL, &utmp, in);
5521
43
      if (slen >= 0) {
5522
6
        dst->vb_bool = (utmp != 0);
5523
6
        return slen;
5524
6
      }
5525
43
    }
5526
5527
37
    fr_strerror_const("Invalid boolean value.  Accepted values are "
5528
37
         "\"yes\", \"no\", \"true\", \"false\" or any unquoted integer");
5529
5530
37
    return slen;  /* Just whatever the last error offset was */
5531
5532
65
  case FR_TYPE_ETHERNET:
5533
65
  {
5534
65
    uint64_t    num;
5535
65
    fr_ethernet_t   ether;
5536
65
    fr_dbuff_t    dbuff;
5537
65
    fr_sbuff_parse_error_t  err;
5538
5539
65
    fr_dbuff_init(&dbuff, ether.addr, sizeof(ether.addr));
5540
5541
    /*
5542
     *  Convert things which are obviously integers to Ethernet addresses
5543
     *
5544
     *  We assume the number is the decimal
5545
     *  representation of the ethernet address.
5546
     *  i.e. the ethernet address converted to a
5547
     *  number, and printed.
5548
     *
5549
     *  The string gets converted to a network-order
5550
     *  8-byte number, and then the lower bytes of
5551
     *  that get copied to the ethernet address.
5552
     *
5553
     *  Note: We need to check for a terminal sequence
5554
     *  after the number, else we may just end up
5555
     *  parsing the first hexit and returning.
5556
     *
5557
     *  i.e. 1c:00:00:00:00 -> 1
5558
     */
5559
65
    if ((fr_sbuff_out(NULL, &num, &our_in) > 0) && fr_sbuff_is_terminal(&our_in, rules->terminals)) {
5560
1
      num = htonll(num);
5561
5562
1
      FR_DBUFF_IN_MEMCPY_RETURN(&dbuff, ((uint8_t *) &num) + 2, sizeof(dst->vb_ether));
5563
1
      fr_value_box_ethernet_addr(dst, dst_enumv, &ether, false);
5564
5565
1
      FR_SBUFF_SET_RETURN(in, &our_in);
5566
1
    }
5567
5568
64
    fr_sbuff_set_to_start(&our_in);
5569
5570
64
    fr_base16_decode(&err, &dbuff, &our_in, true);
5571
64
    if (err != FR_SBUFF_PARSE_OK) {
5572
25
    ether_error:
5573
25
      fr_sbuff_parse_error_to_strerror(err);
5574
25
      FR_SBUFF_ERROR_RETURN(&our_in);
5575
19
    }
5576
5577
45
    if (!fr_sbuff_next_if_char(&our_in, ':')) {
5578
38
    ether_sep_error:
5579
38
      fr_strerror_const("Missing separator, expected ':'");
5580
38
      FR_SBUFF_ERROR_RETURN(&our_in);
5581
32
    }
5582
5583
13
    fr_base16_decode(&err, &dbuff, &our_in, true);
5584
13
    if (err != FR_SBUFF_PARSE_OK) goto ether_error;
5585
5586
12
    if (!fr_sbuff_next_if_char(&our_in, ':')) goto ether_sep_error;
5587
5588
10
    fr_base16_decode(&err, &dbuff, &our_in, true);
5589
10
    if (err != FR_SBUFF_PARSE_OK) goto ether_error;
5590
5591
9
    if (!fr_sbuff_next_if_char(&our_in, ':')) goto ether_sep_error;
5592
5593
8
    fr_base16_decode(&err, &dbuff, &our_in, true);
5594
8
    if (err != FR_SBUFF_PARSE_OK) goto ether_error;
5595
5596
7
    if (!fr_sbuff_next_if_char(&our_in, ':')) goto ether_sep_error;
5597
5598
5
    fr_base16_decode(&err, &dbuff, &our_in, true);
5599
5
    if (err != FR_SBUFF_PARSE_OK) goto ether_error;
5600
5601
4
    if (!fr_sbuff_next_if_char(&our_in, ':')) goto ether_sep_error;
5602
5603
3
    fr_base16_decode(&err, &dbuff, &our_in, true);
5604
3
    if (err != FR_SBUFF_PARSE_OK) goto ether_error;
5605
5606
1
    fr_value_box_ethernet_addr(dst, dst_enumv, (fr_ethernet_t * const)fr_dbuff_start(&dbuff), false);
5607
5608
1
    FR_SBUFF_SET_RETURN(in, &our_in);
5609
3
  }
5610
5611
3.00k
  case FR_TYPE_TIME_DELTA:
5612
3.00k
    fr_value_box_init(dst, FR_TYPE_TIME_DELTA, dst_enumv, false);
5613
5614
3.00k
    slen = fr_time_delta_from_substr(&dst->datum.time_delta, &our_in,
5615
3.00k
             dst_enumv ? dst_enumv->flags.flag_time_res : FR_TIME_RES_SEC,
5616
3.00k
             false, rules->terminals);
5617
3.00k
    if (slen < 0) return slen;
5618
3.00k
    FR_SBUFF_SET_RETURN(in, &our_in);
5619
5620
0
  case FR_TYPE_NULL:
5621
0
    if (!rules->escapes && fr_sbuff_adv_past_str_literal(&our_in, "NULL")) {
5622
0
      fr_value_box_init(dst, dst_type, dst_enumv, false);
5623
0
      FR_SBUFF_SET_RETURN(in, &our_in);
5624
0
    }
5625
5626
0
    fr_strerror_const("Unexpected value for data type NULL");
5627
0
    return -1;
5628
5629
1
  case FR_TYPE_ATTR:
5630
1
    if (!dst_enumv) {
5631
1
      fr_strerror_const("No dictionary passed for data type 'attr'");
5632
1
      return -1;
5633
1
    }
5634
5635
    /*
5636
     *  @todo - have attributes of FR_TYPE_ATTR also
5637
     *  carry a ref to where their values are taken from.
5638
     */
5639
0
    if (dst_enumv->type == FR_TYPE_ATTR) {
5640
0
      if (!dst_enumv->flags.has_value) dst_enumv = fr_dict_root(dst_enumv->dict);
5641
5642
0
    } else if (!dst_enumv->flags.is_root) {
5643
0
      fr_strerror_printf("Can only start from dictionary root for data type 'attribute', and not from %s", dst_enumv->name);
5644
0
      return -1;
5645
0
    }
5646
5647
0
    fr_value_box_init(dst, dst_type, dst_enumv, false);
5648
5649
    /*
5650
     *  Allow '@' references in values.
5651
     */
5652
0
    if (fr_sbuff_is_char(&our_in, '@')) {
5653
0
      size_t len;
5654
0
      fr_sbuff_marker_t m;
5655
5656
0
      fr_sbuff_marker(&m, &our_in);
5657
0
      fr_sbuff_advance(&our_in, 1); /* '@' is not an allowed character for dictionary names */
5658
5659
0
      len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in),
5660
0
              fr_dict_attr_nested_allowed_chars, NULL);
5661
0
      fr_sbuff_set(&our_in, &m);
5662
0
      fr_sbuff_marker_release(&m);
5663
5664
0
      len++;  /* account for '@' */
5665
5666
      /*
5667
       *  This function needs the '@'.
5668
       */
5669
0
      if (fr_dict_protocol_reference(&dst->vb_attr, fr_dict_root(dst_enumv->dict), &FR_SBUFF_IN(fr_sbuff_current(&our_in), len)) < 0) {
5670
0
        return -1;
5671
0
      }
5672
5673
0
      if (!dst->vb_attr) {
5674
0
        fr_strerror_printf("Failed to find attribute reference %.*s", (int) len, fr_sbuff_current(&our_in));
5675
0
        return -1;
5676
0
      }
5677
5678
0
      fr_assert(dst->vb_attr != NULL);
5679
5680
0
      if (dst->vb_attr->dict != dst_enumv->dict) {
5681
0
        fr_strerror_const("Type 'attribute' cannot reference a different protocol");
5682
0
        return -1;
5683
0
      }
5684
5685
0
      fr_sbuff_advance(&our_in, len);
5686
0
      FR_SBUFF_SET_RETURN(in, &our_in);
5687
5688
0
    } else if (fr_sbuff_adv_past_str_literal(&our_in, "::")) {
5689
5690
0
      slen = fr_dict_attr_by_oid_substr(NULL, &dst->vb_attr, dst_enumv, &our_in, rules->terminals);
5691
0
      if (slen > 0) {
5692
0
        fr_assert(dst->vb_attr != NULL);
5693
0
        FR_SBUFF_SET_RETURN(in, &our_in);
5694
0
      }
5695
0
    }
5696
5697
0
    slen = fr_dict_attr_unknown_afrom_oid_substr(ctx, &dst->vb_attr, dst_enumv, &our_in, FR_TYPE_OCTETS);
5698
0
    if (slen <= 0) {
5699
0
      fr_strerror_printf("Failed to find the named attribute in %s", dst_enumv->name);
5700
0
      return -2;
5701
0
    }
5702
5703
0
    fr_assert(dst->vb_attr != NULL);
5704
0
    FR_SBUFF_SET_RETURN(in, &our_in);
5705
5706
  /*
5707
   *  Dealt with below
5708
   */
5709
4.06k
  default:
5710
4.06k
    break;
5711
50.9k
  }
5712
5713
  /*
5714
   *  We may have terminals.  If so, respect them.
5715
   */
5716
4.06k
  if (rules && rules->terminals) {
5717
0
    size_t len;
5718
5719
0
    len = fr_sbuff_out_unescape_until(&FR_SBUFF_OUT(buffer, sizeof(buffer)), &our_in, SIZE_MAX,
5720
0
              rules->terminals, rules->escapes);
5721
0
    if (len >= sizeof(buffer)) goto too_small;
5722
5723
0
    buffer[len] = '\0';
5724
5725
4.06k
  } else {
5726
    /*
5727
     *  It's a fixed size src->dst_type, copy to a temporary buffer and
5728
     *  \0 terminate.
5729
     *
5730
     *  @todo - note that this brute-force copy means that the input sbuff
5731
     *  is NOT advanced, and this function will return 0, even though it parsed data!
5732
     */
5733
4.06k
    if (fr_sbuff_remaining(in) >= sizeof(buffer)) {
5734
12
    too_small:
5735
12
      fr_strerror_const("Temporary buffer too small");
5736
12
      return -1;
5737
12
    }
5738
5739
4.05k
    memcpy(buffer, fr_sbuff_current(in), fr_sbuff_remaining(in));
5740
4.05k
    buffer[fr_sbuff_remaining(in)] = '\0';
5741
4.05k
  }
5742
5743
4.05k
  switch (dst_type) {
5744
4.02k
  case FR_TYPE_DATE:
5745
4.02k
  {
5746
4.02k
    if (dst_enumv) {
5747
2.99k
      if (fr_unix_time_from_str(&dst->vb_date, buffer, dst_enumv->flags.flag_time_res) < 0) return -1;
5748
2.99k
    } else {
5749
1.03k
      if (fr_unix_time_from_str(&dst->vb_date, buffer, FR_TIME_RES_SEC) < 0) return -1;
5750
1.03k
    }
5751
5752
1.49k
    dst->enumv = dst_enumv;
5753
1.49k
  }
5754
0
    break;
5755
5756
25
  case FR_TYPE_IFID:
5757
25
    if (fr_inet_ifid_pton((void *) dst->vb_ifid, buffer) == NULL) {
5758
24
      fr_strerror_printf("Failed to parse interface-id string \"%s\"", buffer);
5759
24
      return -1;
5760
24
    }
5761
1
    break;
5762
5763
1
  default:
5764
0
    fr_strerror_printf("Cannot parse input as data type %s", fr_type_to_str(dst_type));
5765
0
    return -1;
5766
4.05k
  }
5767
5768
2.47k
finish:
5769
2.47k
  dst->type = dst_type;
5770
2.47k
  dst->tainted = false;
5771
2.47k
  fr_value_box_mark_unsafe(dst);
5772
5773
  /*
5774
   *  Fixup enumvs
5775
   */
5776
2.47k
  dst->enumv = dst_enumv;
5777
2.47k
  fr_value_box_list_entry_init(dst);
5778
5779
2.47k
  FR_SBUFF_SET_RETURN(in, &our_in);
5780
4.05k
}
5781
5782
ssize_t fr_value_box_from_str(TALLOC_CTX *ctx, fr_value_box_t *dst,
5783
            fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
5784
            char const *in, size_t inlen,
5785
            fr_sbuff_unescape_rules_t const *erules)
5786
50.9k
{
5787
50.9k
  ssize_t slen;
5788
50.9k
  fr_sbuff_parse_rules_t prules = { .escapes = erules };
5789
5790
50.9k
  slen = fr_value_box_from_substr(ctx, dst, dst_type, dst_enumv, &FR_SBUFF_IN(in, inlen), &prules);
5791
50.9k
  if (slen <= 0) return slen;
5792
5793
41.8k
  if (slen != (ssize_t)inlen) {
5794
3.76k
    fr_strerror_printf("Failed parsing '%s'.  %zu bytes of trailing data after string value \"%pV\"",
5795
3.76k
           fr_type_to_str(dst_type),
5796
3.76k
           inlen - slen,
5797
3.76k
           fr_box_strvalue_len(in + slen, inlen - slen));
5798
3.76k
    return (slen - inlen) - 1;
5799
3.76k
  }
5800
5801
38.1k
  return slen;
5802
41.8k
}
5803
5804
/** Print one boxed value to a string
5805
 *
5806
 * This function should primarily be used when a #fr_value_box_t is being
5807
 * serialized in some non-standard way, i.e. as a value for a field
5808
 * in a database, in all other instances it's better to use
5809
 * #fr_value_box_print_quoted.
5810
 *
5811
 * @note - this function does NOT respect tainting!  The escaping rules
5812
 * are ONLY for escaping quotation characters, CR, LF, etc.
5813
 *
5814
 * @param[in] out Where to write the printed string.
5815
 * @param[in] data  Value box to print.
5816
 * @param[in] e_rules To apply to FR_TYPE_STRING types, for escaping quotation characters _only_.
5817
 *      Is not currently applied to any other box type.
5818
 */
5819
ssize_t fr_value_box_print(fr_sbuff_t *out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules)
5820
4.63k
{
5821
4.63k
  fr_sbuff_t  our_out = FR_SBUFF(out);
5822
5823
4.63k
  char    buf[1024];  /* Interim buffer to use with poorly behaved printing functions */
5824
5825
4.63k
  if (data->enumv && data->enumv->flags.has_value) {
5826
0
    char const *name;
5827
5828
0
    name = fr_dict_enum_name_by_value(data->enumv, data);
5829
0
    if (name) {
5830
0
      FR_SBUFF_IN_ESCAPE_BUFFER_RETURN(&our_out, name, NULL);
5831
0
      goto done;
5832
0
    }
5833
0
  }
5834
5835
4.63k
  switch (data->type) {
5836
4.06k
  case FR_TYPE_STRING:
5837
4.06k
    if (data->vb_length) FR_SBUFF_IN_ESCAPE_RETURN(&our_out,
5838
8.11k
                     data->vb_strvalue, data->vb_length, e_rules);
5839
4.06k
    break;
5840
5841
4.06k
  case FR_TYPE_OCTETS:
5842
0
    FR_SBUFF_IN_CHAR_RETURN(&our_out, '0', 'x');
5843
0
    if (data->vb_length) FR_SBUFF_RETURN(fr_base16_encode, &our_out,
5844
0
                 &FR_DBUFF_TMP(data->vb_octets, data->vb_length));
5845
0
    break;
5846
5847
  /*
5848
   *  We need to use the proper inet_ntop functions for IP
5849
   *  addresses, else the output might not match output of
5850
   *  other functions, which makes testing difficult.
5851
   *
5852
   *  An example is tunneled ipv4 in ipv6 addresses.
5853
   */
5854
395
  case FR_TYPE_IPV4_ADDR:
5855
395
  case FR_TYPE_IPV6_ADDR:
5856
395
  case FR_TYPE_COMBO_IP_ADDR:
5857
395
    if (!fr_inet_ntop(buf, sizeof(buf), &data->vb_ip)) return 0;
5858
395
    FR_SBUFF_IN_STRCPY_RETURN(&our_out, buf);
5859
395
    break;
5860
5861
395
  case FR_TYPE_IPV4_PREFIX:
5862
0
  case FR_TYPE_IPV6_PREFIX:
5863
0
  case FR_TYPE_COMBO_IP_PREFIX:
5864
0
    if (!fr_inet_ntop_prefix(buf, sizeof(buf), &data->vb_ip)) return 0;
5865
0
    FR_SBUFF_IN_STRCPY_RETURN(&our_out, buf);
5866
0
    break;
5867
5868
0
  case FR_TYPE_IFID:
5869
0
    if (!fr_inet_ifid_ntop(buf, sizeof(buf), data->vb_ifid)) return 0;
5870
0
    FR_SBUFF_IN_STRCPY_RETURN(&our_out, buf);
5871
0
    break;
5872
5873
0
  case FR_TYPE_ETHERNET:
5874
0
    FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%02x:%02x:%02x:%02x:%02x:%02x",
5875
0
             data->vb_ether[0], data->vb_ether[1],
5876
0
             data->vb_ether[2], data->vb_ether[3],
5877
0
             data->vb_ether[4], data->vb_ether[5]);
5878
0
    break;
5879
5880
0
  case FR_TYPE_BOOL:
5881
0
    FR_SBUFF_IN_STRCPY_RETURN(&our_out, data->vb_uint8 ? "yes" : "no");
5882
0
    break;
5883
5884
0
  case FR_TYPE_UINT8:
5885
0
    FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", data->vb_uint8);
5886
0
    break;
5887
5888
0
  case FR_TYPE_UINT16:
5889
0
    FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", data->vb_uint16);
5890
0
    break;
5891
5892
93
  case FR_TYPE_UINT32:
5893
93
    FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%u", data->vb_uint32);
5894
93
    break;
5895
5896
93
  case FR_TYPE_UINT64:
5897
166
    FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%" PRIu64, data->vb_uint64);
5898
83
    break;
5899
5900
83
  case FR_TYPE_INT8:
5901
0
    FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%d", data->vb_int8);
5902
0
    break;
5903
5904
0
  case FR_TYPE_INT16:
5905
0
    FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%d", data->vb_int16);
5906
0
    break;
5907
5908
0
  case FR_TYPE_INT32:
5909
0
    FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%d", data->vb_int32);
5910
0
    break;
5911
5912
0
  case FR_TYPE_INT64:
5913
0
    FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%" PRId64, data->vb_int64);
5914
0
    break;
5915
5916
0
  case FR_TYPE_FLOAT32:
5917
0
    FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%f", (double) data->vb_float32);
5918
0
    break;
5919
5920
0
  case FR_TYPE_FLOAT64:
5921
0
    FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%g", data->vb_float64);
5922
0
    break;
5923
5924
0
  case FR_TYPE_DATE:
5925
0
  {
5926
0
    fr_time_res_t res = FR_TIME_RES_SEC;
5927
5928
0
    if (data->enumv) res = data->enumv->flags.flag_time_res;
5929
5930
0
    FR_SBUFF_RETURN(fr_unix_time_to_str, &our_out, data->vb_date, res, true);
5931
0
    break;
5932
0
  }
5933
5934
0
  case FR_TYPE_SIZE:
5935
0
    FR_SBUFF_RETURN(fr_size_to_str, &our_out, data->datum.size);
5936
0
    break;
5937
5938
0
  case FR_TYPE_TIME_DELTA:
5939
0
  {
5940
0
    fr_time_res_t res = FR_TIME_RES_SEC;
5941
0
    bool    is_unsigned = false;
5942
5943
0
    if (data->enumv) {
5944
0
      res = data->enumv->flags.flag_time_res;
5945
0
      is_unsigned = data->enumv->flags.is_unsigned;
5946
0
    }
5947
5948
5949
0
    FR_SBUFF_RETURN(fr_time_delta_to_str, &our_out, data->vb_time_delta, res, is_unsigned);
5950
0
  }
5951
0
    break;
5952
5953
0
  case FR_TYPE_GROUP:
5954
    /*
5955
     *  If the caller didn't ask to escape binary data
5956
     *  in 'octets' types, then we force that now.
5957
     *  Otherwise any 'octets' type which is buried
5958
     *  inside of a 'group' will get copied verbatim
5959
     *  from input to output, with no escaping!
5960
     */
5961
0
    if (!e_rules || (!e_rules->do_oct && !e_rules->do_hex)) {
5962
0
      e_rules = &fr_value_escape_double;
5963
0
    }
5964
5965
    /*
5966
     *  Represent groups as:
5967
     *
5968
     *  { <value0>, <value1>, { <sub-value0>, <sub-value1>, <sub-valueN> }}
5969
     */
5970
0
    FR_SBUFF_IN_CHAR_RETURN(&our_out, '{');
5971
0
    FR_SBUFF_RETURN(fr_value_box_list_concat_as_string,
5972
0
        NULL, &our_out, UNCONST(fr_value_box_list_t *, &data->vb_group),
5973
0
        ", ", (sizeof(", ") - 1), e_rules,
5974
0
        FR_VALUE_BOX_LIST_NONE, FR_VALUE_BOX_SAFE_FOR_ANY, false);
5975
0
    FR_SBUFF_IN_CHAR_RETURN(&our_out, '}');
5976
0
    break;
5977
5978
0
  case FR_TYPE_ATTR:
5979
0
    FR_SBUFF_IN_CHAR_RETURN(&our_out, ':', ':');
5980
5981
0
    fr_assert(data->enumv != NULL);
5982
5983
    /*
5984
     *  No escaping, just dump the name as-is.
5985
     */
5986
0
    if (!e_rules) {
5987
0
      FR_DICT_ATTR_OID_PRINT_RETURN(&our_out, NULL, data->vb_attr, false);
5988
0
      break;
5989
0
    }
5990
5991
    /*
5992
     *  Escaping, use an intermediate buffer.  Because
5993
     *  we can't pipe sbuffs together.
5994
     */
5995
0
    {
5996
0
      fr_sbuff_t *unescaped = NULL;
5997
5998
0
      FR_SBUFF_TALLOC_THREAD_LOCAL(&unescaped, 256, 4096);
5999
6000
0
      FR_DICT_ATTR_OID_PRINT_RETURN(unescaped, NULL, data->vb_attr, false);
6001
6002
0
      FR_SBUFF_IN_ESCAPE_RETURN(&our_out, fr_sbuff_start(unescaped),
6003
0
              fr_sbuff_used(unescaped), e_rules);
6004
0
    }
6005
0
    break;
6006
6007
0
  case FR_TYPE_NULL:
6008
0
    FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "NULL");
6009
0
    break;
6010
6011
  /*
6012
   *  Don't add default here
6013
   */
6014
0
  case FR_TYPE_TLV:   /* Not a box type */
6015
0
  case FR_TYPE_STRUCT:    /* Not a box type */
6016
0
  case FR_TYPE_VSA:   /* Not a box type */
6017
0
  case FR_TYPE_VENDOR:    /* Not a box type */
6018
0
  case FR_TYPE_UNION:   /* Not a box type */
6019
0
  case FR_TYPE_VALUE_BOX:
6020
0
  case FR_TYPE_VOID:
6021
0
  case FR_TYPE_MAX:
6022
0
    (void)fr_cond_assert(0);
6023
0
    return 0;
6024
6025
0
  case FR_TYPE_VALUE_BOX_CURSOR:
6026
0
  case FR_TYPE_PAIR_CURSOR:
6027
0
    FR_SBUFF_IN_STRCPY_RETURN(&our_out, data->vb_cursor_name);
6028
0
    break;
6029
4.63k
  }
6030
6031
4.63k
done:
6032
4.63k
  FR_SBUFF_SET_RETURN(out, &our_out);
6033
4.63k
}
6034
6035
/** Print one boxed value to a string with quotes (where needed)
6036
 *
6037
 * @param[in] out Where to write the printed string.
6038
 * @param[in] data  Value box to print.
6039
 * @param[in] quote To apply to FR_TYPE_STRING types.
6040
 *      Is not currently applied to any
6041
 *      other box type.
6042
 */
6043
ssize_t fr_value_box_print_quoted(fr_sbuff_t *out, fr_value_box_t const *data, fr_token_t quote)
6044
619
{
6045
619
  fr_sbuff_t  our_out = FR_SBUFF(out);
6046
6047
619
  if (quote == T_BARE_WORD) return fr_value_box_print(out, data, NULL);
6048
6049
0
  switch (data->type) {
6050
0
  case FR_TYPE_QUOTED:
6051
0
    FR_SBUFF_IN_CHAR_RETURN(&our_out, fr_token_quote[quote]);
6052
0
    FR_SBUFF_RETURN(fr_value_box_print, &our_out, data, fr_value_escape_by_quote[quote]);
6053
0
    FR_SBUFF_IN_CHAR_RETURN(&our_out, fr_token_quote[quote]);
6054
0
    break;
6055
6056
0
  default:
6057
0
    return fr_value_box_print(out, data, NULL);
6058
0
  }
6059
6060
0
  FR_SBUFF_SET_RETURN(out, &our_out);
6061
0
}
6062
6063
/** Concatenate a list of value boxes together
6064
 *
6065
 * All boxes will be removed from the list.
6066
 *
6067
 * @param[out] safety   if !NULL, the results of tainted / secret / safe_for will be stored here.
6068
 * @param[out] sbuff    to write the result of the concatenation to.
6069
 * @param[in] list    to concatenate.
6070
 * @param[in] sep   Insert a separator between the values.
6071
 * @param[in] sep_len   Length of the separator.
6072
 * @param[in] e_rules   To apply to FR_TYPE_STRING types.
6073
 *        Is not currently applied to any other box type.
6074
 * @param[in] proc_action What to do with the boxes in the list once
6075
 *        they've been processed.
6076
 * @param[in] safe_for    if value has this safe_for value, don't apply the escape rules.
6077
 *        for values which are escaped, mash the safe_for value to this.
6078
 * @param[in] flatten   If true and we encounter a #FR_TYPE_GROUP,
6079
 *        we concat the contents of its children together.
6080
 *            If false, the contents will be cast to #FR_TYPE_STRING.
6081
 * @return
6082
 *      - >=0 the number of bytes written to the sbuff.
6083
 *  - <0 how many additional bytes we would have needed to
6084
 *    concat the next box.
6085
 */
6086
ssize_t fr_value_box_list_concat_as_string(fr_value_box_t *safety, fr_sbuff_t *sbuff, fr_value_box_list_t *list,
6087
             char const *sep, size_t sep_len, fr_sbuff_escape_rules_t const *e_rules,
6088
             fr_value_box_list_action_t proc_action, fr_value_box_safe_for_t safe_for, bool flatten)
6089
0
{
6090
0
  fr_sbuff_t our_sbuff = FR_SBUFF(sbuff);
6091
0
  ssize_t slen;
6092
6093
0
  if (fr_value_box_list_empty(list)) return 0;
6094
6095
0
  fr_value_box_list_foreach(list, vb) {
6096
0
    fr_value_box_safe_for_t box_safe_for = vb->safe_for;
6097
6098
0
    switch (vb->type) {
6099
0
    case FR_TYPE_GROUP:
6100
0
      if (!flatten) goto print;
6101
0
      slen = fr_value_box_list_concat_as_string(safety, &our_sbuff, &vb->vb_group,
6102
0
                  sep, sep_len, e_rules,
6103
0
                  proc_action, safe_for, flatten);
6104
0
      break;
6105
6106
0
    case FR_TYPE_OCTETS:
6107
6108
      /*
6109
       *  Copy the raw string over, if necessary with escaping.
6110
       */
6111
0
      if (e_rules && (!fr_value_box_is_safe_for(vb, safe_for) || e_rules->do_oct || e_rules->do_hex)) {
6112
0
        box_safe_for = safe_for;
6113
6114
0
        slen = fr_sbuff_in_escape(&our_sbuff, (char const *)vb->vb_strvalue, vb->vb_length, e_rules);
6115
0
      } else {
6116
0
        slen = fr_sbuff_in_bstrncpy(&our_sbuff, (char const *)vb->vb_strvalue, vb->vb_length);
6117
0
      }
6118
0
      break;
6119
6120
0
    case FR_TYPE_STRING:
6121
0
      if (!fr_value_box_is_safe_for(vb, safe_for) && e_rules) goto print;
6122
6123
0
      slen = fr_sbuff_in_bstrncpy(&our_sbuff, vb->vb_strvalue, vb->vb_length);
6124
0
      break;
6125
6126
0
    case FR_TYPE_NULL:  /* Skip null */
6127
0
      continue;
6128
6129
0
    default:
6130
0
    print:
6131
      /*
6132
       *  If we escaped it, set the output safe_for value.
6133
       */
6134
0
      if (e_rules) box_safe_for = safe_for;
6135
0
      slen = fr_value_box_print(&our_sbuff, vb, e_rules);
6136
0
      break;
6137
0
    }
6138
0
    if (slen < 0) return slen;
6139
6140
    /*
6141
     *  Add in the separator
6142
     */
6143
0
    if (sep && fr_value_box_list_next(list, vb)) {
6144
0
      slen = fr_sbuff_in_bstrncpy(&our_sbuff, sep, sep_len);
6145
0
      if (slen < 0) return slen;
6146
0
    }
6147
6148
    /*
6149
     *  Merge in the safety rules.
6150
     */
6151
0
    if (!safety || (vb->type == FR_TYPE_GROUP)) continue;
6152
6153
    /*
6154
     *  We can't call fr_box_safety_merge(), as we may have escaped the input box.
6155
     */
6156
0
    if ((safety->safe_for != FR_VALUE_BOX_SAFE_FOR_NONE) &&
6157
0
        (safety->safe_for != box_safe_for)) {
6158
0
      if (safety->safe_for == FR_VALUE_BOX_SAFE_FOR_ANY) {
6159
0
        safety->safe_for = box_safe_for;
6160
0
      } else {
6161
0
        safety->safe_for = FR_VALUE_BOX_SAFE_FOR_NONE;
6162
0
      }
6163
0
    }
6164
6165
0
    safety->tainted |= vb->tainted;
6166
0
    safety->secret |= vb->secret;
6167
0
  }
6168
6169
  /*
6170
   *  Free the boxes last so if there's
6171
   *  an issue concatenating them, everything
6172
   *  is still in a known state.
6173
   */
6174
0
  fr_value_box_list_foreach_safe(list, vb) {
6175
0
    if (vb_should_remove(proc_action)) fr_value_box_list_remove(list, vb);
6176
0
    if (vb_should_free_value(proc_action)) fr_value_box_clear_value(vb);
6177
0
    if (vb_should_free(proc_action)) talloc_free(vb);
6178
0
  }}
6179
6180
0
  FR_SBUFF_SET_RETURN(sbuff, &our_sbuff);
6181
0
}
6182
6183
/** Concatenate a list of value boxes together
6184
 *
6185
 * All boxes will be removed from the list.
6186
 *
6187
 * @param[out] safety   if !NULL, the results of tainted / secret / safe_for will be stored here.
6188
 * @param[out] dbuff    to write the result of the concatenation to.
6189
 * @param[in] list    to concatenate.
6190
 * @param[in] sep   Insert a separator between the values.
6191
 * @param[in] sep_len   Length of the separator.
6192
 * @param[in] proc_action What to do with the boxes in the list once
6193
 *        they've been processed.
6194
 * @param[in] flatten   If true and we encounter a #FR_TYPE_GROUP,
6195
 *        we concat the contents of its children together.
6196
 *            If false, the contents will be cast to #FR_TYPE_OCTETS.
6197
 * @return
6198
 *      - >=0 the number of bytes written to the sbuff.
6199
 *  - <0 how many additional bytes we would have needed to
6200
 *    concat the next box.
6201
 */
6202
ssize_t fr_value_box_list_concat_as_octets(fr_value_box_t *safety, fr_dbuff_t *dbuff, fr_value_box_list_t *list,
6203
             uint8_t const *sep, size_t sep_len,
6204
             fr_value_box_list_action_t proc_action, bool flatten)
6205
0
{
6206
0
  fr_dbuff_t  our_dbuff = FR_DBUFF(dbuff);
6207
0
  TALLOC_CTX  *tmp_ctx = NULL;
6208
0
  ssize_t   slen;
6209
6210
0
  if (fr_value_box_list_empty(list)) return 0;
6211
6212
0
  fr_value_box_list_foreach(list, vb) {
6213
0
    switch (vb->type) {
6214
0
    case FR_TYPE_GROUP:
6215
0
      if (!flatten) goto cast;
6216
0
      slen = fr_value_box_list_concat_as_octets(safety, &our_dbuff, &vb->vb_group,
6217
0
                  sep, sep_len,
6218
0
                  proc_action, flatten);
6219
0
      break;
6220
6221
0
    case FR_TYPE_OCTETS:
6222
0
      slen = fr_dbuff_in_memcpy(&our_dbuff, vb->vb_octets, vb->vb_length);
6223
0
      break;
6224
6225
0
    case FR_TYPE_STRING:
6226
0
      slen = fr_dbuff_in_memcpy(&our_dbuff, (uint8_t const *)vb->vb_strvalue, vb->vb_length);
6227
0
      break;
6228
6229
0
    case FR_TYPE_NULL:  /* Skip null */
6230
0
      continue;
6231
6232
0
    default:
6233
0
    cast:
6234
0
      {
6235
0
        fr_value_box_t tmp_vb;
6236
6237
0
        if (!tmp_ctx) tmp_ctx = talloc_pool(NULL, 1024);
6238
6239
        /*
6240
         *  Not equivalent to fr_value_box_to_network
6241
         */
6242
0
        if (fr_value_box_cast_to_octets(tmp_ctx, &tmp_vb, FR_TYPE_OCTETS, NULL, vb) < 0) {
6243
0
          slen = -1;
6244
0
          goto error;
6245
0
        }
6246
6247
0
        slen = fr_dbuff_in_memcpy(&our_dbuff, tmp_vb.vb_octets, tmp_vb.vb_length);
6248
0
        fr_value_box_clear_value(&tmp_vb);
6249
0
        break;
6250
0
      }
6251
0
    }
6252
6253
0
    if (slen < 0) {
6254
0
    error:
6255
0
      talloc_free(tmp_ctx);
6256
0
      return slen;
6257
0
    }
6258
6259
0
    if (sep && fr_value_box_list_next(list, vb)) {
6260
0
      slen = fr_dbuff_in_memcpy(&our_dbuff, sep, sep_len);
6261
0
      if (slen < 0) goto error;
6262
0
    }
6263
6264
0
    fr_value_box_safety_merge(safety, vb);
6265
0
  }
6266
6267
0
  talloc_free(tmp_ctx);
6268
6269
  /*
6270
   *  Free the boxes last so if there's
6271
   *  an issue concatenating them, everything
6272
   *  is still in a known state.
6273
   */
6274
0
  fr_value_box_list_foreach_safe(list, vb) {
6275
0
    if (vb_should_remove(proc_action)) fr_value_box_list_remove(list, vb);
6276
0
    if (vb_should_free_value(proc_action)) fr_value_box_clear_value(vb);
6277
0
    if (vb_should_free(proc_action)) talloc_free(vb);
6278
0
  }}
6279
6280
0
  return fr_dbuff_set(dbuff, &our_dbuff);
6281
0
}
6282
6283
/** Concatenate a list of value boxes
6284
 *
6285
 * @note Will automatically cast all #fr_value_box_t to type specified.
6286
 *
6287
 * @param[in] ctx   to allocate new value buffer in.
6288
 * @param[out] out    Where to write the resulting box.
6289
 * @param[in] list    to concatenate together.
6290
 * @param[in] type    May be #FR_TYPE_STRING or #FR_TYPE_OCTETS, no other types are
6291
 *        supported.
6292
 * @param[in] proc_action What to do with the boxes in the list once
6293
 *        they've been processed.
6294
 * @param[in] flatten   If true and we encounter a #FR_TYPE_GROUP,
6295
 *        we concat the contents of its children together.
6296
 *            If false, the contents will be cast to the given type.
6297
 * @param[in] max_size    of the value.
6298
 * @return
6299
 *  - 0 on success.
6300
 *  - -1 on failure.
6301
 */
6302
int fr_value_box_list_concat_in_place(TALLOC_CTX *ctx,
6303
              fr_value_box_t *out, fr_value_box_list_t *list, fr_type_t type,
6304
              fr_value_box_list_action_t proc_action, bool flatten,
6305
              size_t max_size)
6306
0
{
6307
0
  fr_dbuff_t      dbuff;    /* FR_TYPE_OCTETS */
6308
0
  fr_dbuff_uctx_talloc_t    dbuff_tctx;
6309
6310
0
  fr_sbuff_t      sbuff;    /* FR_TYPE_STRING */
6311
0
  fr_sbuff_uctx_talloc_t    sbuff_tctx;
6312
6313
0
  fr_value_box_t      *head_vb = fr_value_box_list_head(list);
6314
6315
0
  fr_value_box_entry_t    entry;
6316
6317
0
  if (fr_value_box_list_empty(list)) {
6318
0
    fr_strerror_const("Invalid arguments.  List contains no elements");
6319
0
    return -1;
6320
0
  }
6321
6322
  /*
6323
   *  Exit quickly if the list is only one box of the correct type and
6324
   *  out points at that box.
6325
   */
6326
0
  if ((fr_value_box_list_num_elements(list) == 1) && (head_vb == out) && (head_vb->type == type)) return 0;
6327
6328
0
  switch (type) {
6329
0
  case FR_TYPE_STRING:
6330
0
    if (unlikely(!fr_sbuff_init_talloc(ctx, &sbuff, &sbuff_tctx, 256, max_size))) return -1;
6331
0
    break;
6332
6333
0
  case FR_TYPE_OCTETS:
6334
0
    if (unlikely(!fr_dbuff_init_talloc(ctx, &dbuff, &dbuff_tctx, 256, max_size))) return -1;
6335
0
    break;
6336
6337
0
  default:
6338
0
    fr_strerror_printf("Invalid argument.  Can't concatenate boxes to type %s",
6339
0
           fr_type_to_str(type));
6340
0
    return -1;
6341
0
  }
6342
6343
  /*
6344
   *  Merge all siblings into list head.
6345
   *
6346
   *  This is where the first element in the
6347
   *  list is the output box.
6348
   *
6349
   *  i.e. we want to merge all its siblings
6350
   *  into it.
6351
   */
6352
0
  if (out == head_vb) {
6353
0
    switch (type) {
6354
0
    case FR_TYPE_STRING:
6355
      /*
6356
       *  Head gets dealt with specially as we don't
6357
       *  want to free it, and we don't want to free
6358
       *  the buffer associated with it (just yet).
6359
       *
6360
       *  Note that we don't convert 'octets' to a printable string
6361
       *  here.  Doing so breaks the keyword tests.
6362
       */
6363
0
      if (fr_value_box_list_concat_as_string(out, &sbuff, list,
6364
0
                     NULL, 0, NULL,
6365
0
                     FR_VALUE_BOX_LIST_REMOVE, FR_VALUE_BOX_SAFE_FOR_ANY, flatten) < 0) {
6366
0
        fr_strerror_printf("Concatenation exceeded max_size (%zu)", max_size);
6367
0
      error:
6368
0
        switch (type) {
6369
0
        case FR_TYPE_STRING:
6370
0
          talloc_free(fr_sbuff_buff(&sbuff));
6371
0
          break;
6372
6373
0
        case FR_TYPE_OCTETS:
6374
0
          talloc_free(fr_dbuff_buff(&dbuff));
6375
0
          break;
6376
6377
0
        default:
6378
0
          break;
6379
0
        }
6380
0
        return -1;
6381
0
      }
6382
6383
      /*
6384
       *  Concat the rest of the children...
6385
       */
6386
0
      if (fr_value_box_list_concat_as_string(out, &sbuff, list,
6387
0
                     NULL, 0, NULL,
6388
0
                     proc_action, FR_VALUE_BOX_SAFE_FOR_ANY, flatten) < 0) {
6389
0
        fr_value_box_list_insert_head(list, head_vb);
6390
0
        goto error;
6391
0
      }
6392
0
      (void)fr_sbuff_trim_talloc(&sbuff, SIZE_MAX);
6393
0
      if (vb_should_free_value(proc_action)) fr_value_box_clear_value(out);
6394
0
      if (fr_value_box_bstrndup(ctx, out, NULL, fr_sbuff_buff(&sbuff), fr_sbuff_used(&sbuff), out->tainted) < 0) goto error;
6395
0
      break;
6396
6397
0
    case FR_TYPE_OCTETS:
6398
0
      if (fr_value_box_list_concat_as_octets(out, &dbuff, list,
6399
0
                     NULL, 0,
6400
0
                     FR_VALUE_BOX_LIST_REMOVE, flatten) < 0) goto error;
6401
6402
0
      if (fr_value_box_list_concat_as_octets(out, &dbuff, list,
6403
0
                     NULL, 0,
6404
0
                     proc_action, flatten) < 0) {
6405
0
        fr_value_box_list_insert_head(list, head_vb);
6406
0
        goto error;
6407
0
      }
6408
0
      (void)fr_dbuff_trim_talloc(&dbuff, SIZE_MAX);
6409
0
      if (vb_should_free_value(proc_action)) fr_value_box_clear_value(out);
6410
0
      if (fr_value_box_memdup(ctx, out, NULL, fr_dbuff_buff(&dbuff), fr_dbuff_used(&dbuff), out->tainted) < 0) goto error;
6411
0
      break;
6412
6413
0
    default:
6414
0
      break;
6415
0
    }
6416
6417
0
    fr_value_box_list_insert_head(list, out);
6418
6419
  /*
6420
   *  Merge all the boxes in the list into
6421
   *  a single contiguous buffer.
6422
   *
6423
   *  This deals with an unrelated out and list
6424
   *  and also where list is the children of
6425
   *      out.
6426
   */
6427
0
  } else {
6428
0
    switch (type) {
6429
0
    case FR_TYPE_STRING:
6430
0
      if (fr_value_box_list_concat_as_string(out, &sbuff, list,
6431
0
                     NULL, 0, NULL,
6432
0
                     proc_action, FR_VALUE_BOX_SAFE_FOR_ANY, flatten) < 0) goto error;
6433
0
      (void)fr_sbuff_trim_talloc(&sbuff, SIZE_MAX);
6434
6435
0
      entry = out->entry;
6436
0
      if (fr_value_box_bstrndup(ctx, out, NULL, fr_sbuff_buff(&sbuff), fr_sbuff_used(&sbuff), out->tainted) < 0) goto error;
6437
0
      out->entry = entry;
6438
0
      break;
6439
6440
0
    case FR_TYPE_OCTETS:
6441
0
      if (fr_value_box_list_concat_as_octets(out, &dbuff, list,
6442
0
                     NULL, 0,
6443
0
                     proc_action, flatten) < 0) goto error;
6444
0
      (void)fr_dbuff_trim_talloc(&dbuff, SIZE_MAX);
6445
6446
0
      entry = out->entry;
6447
0
      if (fr_value_box_memdup(ctx, out, NULL, fr_dbuff_buff(&dbuff), fr_dbuff_used(&dbuff), out->tainted) < 0) goto error;
6448
0
      out->entry = entry;
6449
0
      break;
6450
6451
0
    default:
6452
0
      break;
6453
0
    }
6454
0
  }
6455
6456
0
  return 0;
6457
0
}
6458
6459
/** Escape a single value box in place
6460
 *
6461
 * @note Applies recursively to the children of group boxes.
6462
 *
6463
 * @param[in] vb    to escape.
6464
 * @param[in] escape    escape definition to apply to the value box.
6465
 * @param[in] uctx    user context to pass to the escape function.
6466
 * @return
6467
 *  - 0 on success.
6468
 *  - -1 on failure.
6469
 */
6470
int fr_value_box_escape_in_place(fr_value_box_t *vb, fr_value_box_escape_t const *escape, void *uctx)
6471
0
{
6472
0
  int ret;
6473
6474
0
  switch (vb->type) {
6475
0
  case FR_TYPE_GROUP:
6476
0
    return fr_value_box_list_escape_in_place(&vb->vb_group, escape, uctx);
6477
6478
0
  case FR_TYPE_NULL:
6479
0
  case FR_TYPE_TLV:
6480
0
  case FR_TYPE_STRUCT:
6481
0
  case FR_TYPE_VSA:
6482
0
  case FR_TYPE_VENDOR:
6483
0
  case FR_TYPE_INTERNAL:
6484
0
    fr_strerror_printf("Cannot escape data type '%s'", fr_type_to_str(vb->type));
6485
0
    return -1;
6486
6487
0
  case FR_TYPE_ATTR:
6488
0
    fr_assert(0);  /* @todo - print to string, and then escape? */
6489
0
    fr_strerror_printf("Cannot escape data type '%s'", fr_type_to_str(vb->type));
6490
0
    return -1;
6491
6492
0
  default:
6493
0
    break;
6494
0
  }
6495
6496
  /*
6497
   *  Don't do double escaping.
6498
   */
6499
0
  if (!escape->always_escape && fr_value_box_is_safe_for(vb, escape->safe_for)) return 0;
6500
6501
0
  ret = escape->func(vb, uctx);
6502
0
  if (unlikely(ret < 0)) return ret;
6503
6504
  /*
6505
   *  '1' means that the function mashed the safe_for value, so we don't need to.
6506
   */
6507
0
  if (!ret) vb->safe_for = escape->safe_for;
6508
0
  vb->tainted = false;
6509
6510
0
  return 0;
6511
0
}
6512
6513
/** Escape a list of value boxes in place
6514
 *
6515
 * @note Applies recursively to the children of group boxes.
6516
 *
6517
 * @note on error, the list may be left in an inconsistent/partially escaped state.
6518
 *
6519
 * @param[in] list    to escape.
6520
 * @param[in] escape    escape definition to apply to the value box.
6521
 * @param[in] uctx    user context to pass to the escape function.
6522
 * @return
6523
 *  - 0 on success.
6524
 *  - -1 on failure.
6525
 */
6526
int fr_value_box_list_escape_in_place(fr_value_box_list_t *list, fr_value_box_escape_t const *escape, void *uctx)
6527
0
{
6528
0
  int ret = 0;
6529
6530
0
  fr_value_box_list_foreach(list, vb) {
6531
0
    ret = fr_value_box_escape_in_place(vb, escape, uctx);
6532
0
    if (unlikely(ret < 0)) return ret;
6533
0
  }
6534
6535
0
  return ret;
6536
0
}
6537
6538
/** Removes a single layer of nesting, moving all children into the parent list
6539
 *
6540
 * @param[in] ctx to reparent children in if steal is true.
6541
 * @param[in] list  to flatten.
6542
 * @param[in] steal whether to change the talloc ctx of children.
6543
 * @param[in] free  whether to free any group boxes which have had
6544
 *      their children removed.
6545
 */
6546
void fr_value_box_flatten(TALLOC_CTX *ctx, fr_value_box_list_t *list, bool steal, bool free)
6547
0
{
6548
0
  fr_value_box_list_foreach_safe(list, child) {
6549
0
    if (!fr_type_is_structural(child->type)) continue;
6550
6551
0
    fr_value_box_list_foreach_safe(&child->vb_group, grandchild) {
6552
0
      fr_value_box_list_remove(&child->vb_group, grandchild);
6553
0
      if (steal) talloc_steal(ctx, grandchild);
6554
0
      fr_value_box_list_insert_before(list, child, grandchild);
6555
0
    }}
6556
6557
0
    if (free) talloc_free(child);
6558
0
  }}
6559
0
}
6560
6561
/** Concatenate the string representations of a list of value boxes together
6562
 *
6563
 * @param[in] ctx to allocate the buffer in.
6564
 * @param[in] list  of value boxes.
6565
 * @param[in] delim to insert between value box values.
6566
 * @param[in] e_rules to control escaping of the concatenated elements.
6567
 * @return
6568
 *  - NULL on error.
6569
 *  - The concatenation of the string values of the value box list on success.
6570
 */
6571
char *fr_value_box_list_aprint(TALLOC_CTX *ctx, fr_value_box_list_t const *list, char const *delim,
6572
             fr_sbuff_escape_rules_t const *e_rules)
6573
0
{
6574
0
  fr_value_box_t const  *vb = fr_value_box_list_head(list);
6575
0
  char      *aggr, *td = NULL;
6576
0
  TALLOC_CTX    *pool = NULL;
6577
6578
0
  if (!vb) return NULL;
6579
6580
0
  fr_value_box_aprint(ctx, &aggr, vb, e_rules);
6581
0
  if (!aggr) return NULL;
6582
0
  if (!fr_value_box_list_next(list, vb)) return aggr;
6583
6584
  /*
6585
   *  If we're aggregating more values,
6586
   *  allocate a temporary pool.
6587
   */
6588
0
  pool = talloc_pool(NULL, 255);
6589
0
  if (delim) td = talloc_typed_strdup(pool, delim);
6590
6591
0
  while ((vb = fr_value_box_list_next(list, vb))) {
6592
0
    char *str, *new_aggr;
6593
6594
0
    fr_value_box_aprint(pool, &str, vb, e_rules);
6595
0
    if (!str) continue;
6596
6597
0
    new_aggr = talloc_buffer_append_variadic_buffer(ctx, aggr, 2, td, str);
6598
0
    if (unlikely(!new_aggr)) {
6599
0
      talloc_free(aggr);
6600
0
      talloc_free(pool);
6601
0
      return NULL;
6602
0
    }
6603
0
    aggr = new_aggr;
6604
0
    talloc_free(str);
6605
0
  }
6606
0
  talloc_free(pool);
6607
6608
0
  return aggr;
6609
0
}
6610
6611
/** Concatenate the string representations of a list of value boxes together hiding "secret" values
6612
 *
6613
 * @param[in] ctx to allocate the buffer in.
6614
 * @param[in] list  of value boxes.
6615
 * @param[in] delim to insert between value box values.
6616
 * @param[in] e_rules to control escaping of the concatenated elements.
6617
 * @return
6618
 *  - NULL on error.
6619
 *  - The concatenation of the string values of the value box list on success.
6620
 */
6621
char *fr_value_box_list_aprint_secure(TALLOC_CTX *ctx, fr_value_box_list_t const *list, char const *delim,
6622
              fr_sbuff_escape_rules_t const *e_rules)
6623
0
{
6624
0
  fr_value_box_t const  *vb = fr_value_box_list_head(list);
6625
0
  char      *aggr, *td = NULL;
6626
0
  TALLOC_CTX    *pool = NULL;
6627
6628
0
  if (!vb) return NULL;
6629
6630
0
  if (unlikely (fr_value_box_contains_secret(vb))) {
6631
0
    aggr = talloc_typed_strdup(ctx, "<<< secret >>>");
6632
0
  } else {
6633
0
    fr_value_box_aprint(ctx, &aggr, vb, e_rules);
6634
0
  }
6635
0
  if (!aggr) return NULL;
6636
0
  if (!fr_value_box_list_next(list, vb)) return aggr;
6637
6638
  /*
6639
   *  If we're aggregating more values,
6640
   *  allocate a temporary pool.
6641
   */
6642
0
  pool = talloc_pool(NULL, 255);
6643
0
  if (delim) td = talloc_typed_strdup(pool, delim);
6644
6645
0
  while ((vb = fr_value_box_list_next(list, vb))) {
6646
0
    char *str, *new_aggr;
6647
6648
0
    if (unlikely (fr_value_box_contains_secret(vb))) {
6649
0
      str = talloc_typed_strdup(pool, "<<< secret >>>");
6650
0
    } else {
6651
0
      fr_value_box_aprint(pool, &str, vb, e_rules);
6652
0
    }
6653
0
    if (!str) continue;
6654
6655
0
    new_aggr = talloc_buffer_append_variadic_buffer(ctx, aggr, 2, td, str);
6656
0
    if (unlikely(!new_aggr)) {
6657
0
      talloc_free(aggr);
6658
0
      talloc_free(pool);
6659
0
      return NULL;
6660
0
    }
6661
0
    aggr = new_aggr;
6662
0
    talloc_free(str);
6663
0
  }
6664
0
  talloc_free(pool);
6665
6666
0
  return aggr;
6667
0
}
6668
6669
/** Hash the contents of a value box
6670
 *
6671
 */
6672
uint32_t fr_value_box_hash(fr_value_box_t const *vb)
6673
93.2k
{
6674
93.2k
  switch (vb->type) {
6675
93.2k
  case FR_TYPE_FIXED_SIZE:
6676
93.2k
    return fr_hash(fr_value_box_raw(vb, vb->type),
6677
93.2k
             fr_value_box_field_sizes[vb->type]);
6678
6679
0
  case FR_TYPE_STRING:
6680
0
    return fr_hash(vb->vb_strvalue, vb->vb_length);
6681
6682
0
  case FR_TYPE_OCTETS:
6683
0
    return fr_hash(vb->vb_octets, vb->vb_length);
6684
6685
0
  case FR_TYPE_ATTR:
6686
0
    return fr_hash(&vb->vb_attr, sizeof(vb->vb_attr));
6687
6688
0
  case FR_TYPE_STRUCTURAL:
6689
0
  case FR_TYPE_INTERNAL:
6690
0
  case FR_TYPE_COMBO_IP_ADDR:
6691
0
  case FR_TYPE_COMBO_IP_PREFIX:
6692
0
  case FR_TYPE_NULL:
6693
0
    fr_assert(0);
6694
0
    break;
6695
93.2k
  }
6696
6697
0
  return 0;
6698
93.2k
}
6699
6700
/** Do a full copy of a list of value boxes
6701
 *
6702
 * @param[in] ctx to allocate boxes in.
6703
 * @param[out] out  Where to write the head of the new list.
6704
 * @param[in] in  boxes to copy.
6705
 * @return
6706
 *  - A duplicate list of value boxes, allocated in the context of 'ctx'
6707
 *  - NULL on error, or empty input list.
6708
 */
6709
int fr_value_box_list_acopy(TALLOC_CTX *ctx, fr_value_box_list_t *out, fr_value_box_list_t const *in)
6710
0
{
6711
0
  fr_value_box_t const *in_p = NULL;
6712
6713
0
  while ((in_p = fr_value_box_list_next(in, in_p))) {
6714
0
        fr_value_box_t *n = NULL;
6715
6716
0
    n = fr_value_box_alloc_null(ctx);
6717
0
    if (!n) {
6718
0
    error:
6719
0
      fr_value_box_list_talloc_free(out);
6720
0
      return -1;
6721
0
    }
6722
6723
0
    if (fr_value_box_copy(n, n, in_p) < 0) goto error;
6724
0
    fr_dlist_insert_tail(fr_value_box_list_dlist_head(out), n);
6725
0
  }
6726
6727
0
  return 0;
6728
0
}
6729
6730
/** Check to see if any list members (or their children) are tainted
6731
 *
6732
 * @param[in] head  of list to check.
6733
 * @return
6734
 *  - true if a list member is tainted.
6735
 *  - false if no list members are tainted.
6736
 */
6737
bool fr_value_box_list_tainted(fr_value_box_list_t const *head)
6738
0
{
6739
0
  fr_value_box_t *vb = NULL;
6740
6741
0
  while ((vb = fr_value_box_list_next(head, vb))) {
6742
0
    if (fr_type_is_group(vb->type) && fr_value_box_list_tainted(&vb->vb_group)) return true;
6743
0
    if (vb->tainted) return true;
6744
0
  }
6745
6746
0
  return false;
6747
0
}
6748
6749
/** Taint every list member (and their children)
6750
 *
6751
 * @param[in] head  of list.
6752
 */
6753
void fr_value_box_list_taint(fr_value_box_list_t *head)
6754
0
{
6755
0
  fr_value_box_t *vb = NULL;
6756
6757
0
  while ((vb = fr_value_box_list_next(head, vb))) {
6758
0
    if (fr_type_is_group(vb->type)) fr_value_box_list_taint(&vb->vb_group);
6759
0
    fr_value_box_mark_unsafe(vb);
6760
0
    vb->tainted = true;
6761
0
  }
6762
0
}
6763
6764
/** Untaint every list member (and their children)
6765
 *
6766
 * @param[in] head  of list.
6767
 */
6768
void fr_value_box_list_untaint(fr_value_box_list_t *head)
6769
0
{
6770
0
  fr_value_box_t *vb = NULL;
6771
6772
0
  while ((vb = fr_value_box_list_next(head, vb))) {
6773
0
    if (fr_type_is_group(vb->type)) fr_value_box_list_untaint(&vb->vb_group);
6774
0
    vb->tainted = false;
6775
0
  }
6776
0
}
6777
6778
/** Validation function to check that a fr_value_box_t is correctly initialised
6779
 *
6780
 */
6781
void fr_value_box_verify(char const *file, int line, fr_value_box_t const *vb)
6782
2.68M
{
6783
2.68M
DIAG_OFF(nonnull-compare)
6784
  /*
6785
   *  nonnull only does something if we're building
6786
   *  with ubsan...  We still want to assert event
6787
   *  if we're building without sanitizers.
6788
   */
6789
2.68M
  fr_fatal_assert_msg(vb, "CONSISTENCY CHECK FAILED %s[%i]: fr_value_box_t pointer was NULL", file, line);
6790
2.68M
DIAG_ON(nonnull-compare)
6791
6792
2.68M
  if (vb->talloced) vb = talloc_get_type_abort_const(vb, fr_value_box_t);
6793
6794
2.68M
#ifndef NDEBUG
6795
2.68M
  fr_fatal_assert_msg(vb->magic == FR_VALUE_BOX_MAGIC, "CONSISTENCY CHECK FAILED %s[%i]: fr_value_box_t magic "
6796
2.68M
          "incorrect, expected %" PRIx64 ", got %" PRIx64, file, line, FR_VALUE_BOX_MAGIC, vb->magic);
6797
2.68M
#endif
6798
2.68M
  switch (vb->type) {
6799
394k
  case FR_TYPE_STRING:
6800
394k
    if (!vb->vb_length) {
6801
#if 0
6802
      fr_fatal_assert_msg(!vb->vb_strvalue || (talloc_array_length(vb->vb_strvalue) == 1), "CONSISTENCY CHECK FAILED %s[%d]: fr_value_box_t strvalue field "
6803
              "wasn non-NULL, but length was %u", file, line, vb->vb_length);
6804
#endif
6805
61.9k
      break;
6806
61.9k
    }
6807
6808
332k
    fr_fatal_assert_msg(vb->vb_strvalue, "CONSISTENCY CHECK FAILED %s[%d]: fr_value_box_t strvalue field "
6809
332k
            "was NULL", file, line);
6810
332k
    fr_fatal_assert_msg(vb->vb_strvalue[vb->vb_length] == '\0',
6811
332k
            "CONSISTENCY CHECK FAILED %s[%i]: fr_value_box_t strvalue field "
6812
332k
            "not null terminated", file, line);
6813
332k
    if (vb->talloced) {
6814
0
      size_t len = talloc_array_length(vb->vb_strvalue);
6815
6816
      /* We always \0 terminate to be safe, even though most things should use the len field */
6817
0
      if (len <= vb->vb_length) {
6818
0
        fr_fatal_assert_fail("CONSISTENCY CHECK FAILED %s[%d]: Expected fr_value_box_t->vb_strvalue talloc buffer "
6819
0
                "len >= %zu, got %zu",
6820
0
                file, line, vb->vb_length + 1, len);
6821
0
      }
6822
0
    }
6823
332k
    break;
6824
6825
1.15M
  case FR_TYPE_OCTETS:
6826
1.15M
    if (!vb->vb_length) {
6827
#if 0
6828
      fr_fatal_assert_msg(!vb->vb_octets || (talloc_array_length(vb->vb_octets) == 0), "CONSISTENCY CHECK FAILED %s[%d]: fr_value_box_t octets field "
6829
              "wasn non-NULL, but length was %u", file, line, vb->vb_length);
6830
#endif
6831
453k
      break;
6832
453k
    }
6833
6834
698k
    fr_fatal_assert_msg(vb->vb_octets, "CONSISTENCY CHECK FAILED %s[%d]: fr_value_box_t octets field "
6835
698k
            "was NULL", file, line);
6836
698k
    break;
6837
6838
0
  case FR_TYPE_VOID:
6839
0
    fr_fatal_assert_msg(vb->vb_void, "CONSISTENCY CHECK FAILED %s[%d]: fr_value_box_t ptr field "
6840
0
            "was NULL", file, line);
6841
0
    break;
6842
6843
0
  case FR_TYPE_GROUP:
6844
0
    fr_value_box_list_verify(file, line, &vb->vb_group);
6845
0
    break;
6846
6847
323k
  case FR_TYPE_ATTR:
6848
323k
    fr_fatal_assert_msg(vb->vb_attr, "CONSISTENCY CHECK FAILED %s[%d]: fr_value_box_t vb_attr field "
6849
323k
            "was NULL", file, line);
6850
323k
    break;
6851
6852
813k
  default:
6853
813k
    break;
6854
2.68M
  }
6855
2.68M
}
6856
6857
void fr_value_box_list_verify(char const *file, int line, fr_value_box_list_t const *list)
6858
0
{
6859
0
  fr_value_box_list_foreach(list, vb) fr_value_box_verify(file, line, vb);
6860
0
}
6861
6862
/** Mark a value-box as "safe", of a particular type.
6863
 *
6864
 */
6865
void _fr_value_box_mark_safe_for(fr_value_box_t *vb, fr_value_box_safe_for_t safe_for)
6866
0
{
6867
  /*
6868
   *  Don't over-ride value-boxes which are already safe, unless we want to mark them as being
6869
   *  completely unsafe.
6870
   */
6871
0
  if ((vb->safe_for == FR_VALUE_BOX_SAFE_FOR_ANY) &&
6872
0
      (safe_for != FR_VALUE_BOX_SAFE_FOR_NONE)) {
6873
0
    fr_assert(!vb->tainted);
6874
0
    return;
6875
0
  }
6876
6877
0
  vb->safe_for = safe_for;
6878
0
}
6879
6880
/** Mark a value-box as "unsafe"
6881
 *
6882
 *  This always succeeds, and there are no side effects.
6883
 */
6884
void fr_value_box_mark_unsafe(fr_value_box_t *vb)
6885
2.47k
{
6886
2.47k
  vb->safe_for = FR_VALUE_BOX_SAFE_FOR_NONE;
6887
2.47k
}
6888
6889
/** Set the escaped flag for all value boxes in a list
6890
 *
6891
 * @note Only operates on a single level.
6892
 *
6893
 * @param[in] list  to operate on.
6894
 * @param[in] safe_for  value to set.
6895
 */
6896
void fr_value_box_list_mark_safe_for(fr_value_box_list_t *list, fr_value_box_safe_for_t safe_for)
6897
0
{
6898
0
  fr_value_box_list_foreach(list, vb) {
6899
    /*
6900
     *  Don't over-ride value-boxes which are already safe.
6901
     */
6902
0
    if (vb->safe_for == FR_VALUE_BOX_SAFE_FOR_ANY) {
6903
0
      fr_assert(!vb->tainted);
6904
6905
0
    } else {
6906
0
      vb->safe_for = safe_for;
6907
0
    }
6908
0
  }
6909
0
}
6910
6911
/** Copy the safety values from one box to another.
6912
 *
6913
 */
6914
void fr_value_box_safety_copy(fr_value_box_t *out, fr_value_box_t const *in)
6915
0
{
6916
0
  if (out == in) return;
6917
6918
0
  out->safe_for = in->safe_for;
6919
0
  out->tainted = in->tainted;
6920
0
  out->secret = in->secret;
6921
0
}
6922
6923
/** Copy the safety values from one box to another.
6924
 *
6925
 *  But note that we have changed the output format, so we reset the "safe_for" value to NONE.
6926
 */
6927
void fr_value_box_safety_copy_changed(fr_value_box_t *out, fr_value_box_t const *in)
6928
2.56k
{
6929
2.56k
  out->safe_for = FR_VALUE_BOX_SAFE_FOR_NONE;
6930
2.56k
  out->tainted = in->tainted;
6931
2.56k
  out->secret = in->secret;
6932
2.56k
}
6933
6934
/** Merge safety results.
6935
 */
6936
void fr_value_box_safety_merge(fr_value_box_t *out, fr_value_box_t const *in)
6937
0
{
6938
0
  if (out == in) return;
6939
6940
  /*
6941
   *  If we're already at no safety, then we don't need to do anything.
6942
   *
6943
   *  Otherwise we update the safety only if we need to change it.
6944
   */
6945
0
  if ((out->safe_for != FR_VALUE_BOX_SAFE_FOR_NONE) &&
6946
0
      (out->safe_for != in->safe_for)) {
6947
    /*
6948
     *  If the output is anything, then the input is more restrictive, so we switch to that.
6949
     *
6950
     *  Otherwise the values are different.  Either it's X/Y, or NONE/X, or X/NONE.  In which
6951
     *  case the answer is always NONE.
6952
     */
6953
0
    if (out->safe_for == FR_VALUE_BOX_SAFE_FOR_ANY) {
6954
0
      out->safe_for = in->safe_for;
6955
6956
0
    } else {
6957
0
      out->safe_for = FR_VALUE_BOX_SAFE_FOR_NONE;
6958
0
    }
6959
0
  }
6960
6961
0
  out->tainted |= in->tainted;
6962
0
  out->secret |= in->secret;
6963
0
}
6964
6965
6966
/** Check truthiness of values.
6967
 *
6968
 *  The casting rules for expressions / conditions are slightly
6969
 *  different than fr_value_box_cast().  Largely because that
6970
 *  function is used to parse configuration files, and parses "yes
6971
 *  / no" and "true / false" strings, even if there's no
6972
 *  fr_dict_attr_t passed to it.
6973
 */
6974
bool fr_value_box_is_truthy(fr_value_box_t const *in)
6975
0
{
6976
0
  fr_value_box_t box;
6977
6978
0
  switch (in->type) {
6979
0
  case FR_TYPE_NULL:
6980
0
  case FR_TYPE_STRUCTURAL_EXCEPT_GROUP:
6981
0
  case FR_TYPE_COMBO_IP_ADDR:
6982
0
  case FR_TYPE_COMBO_IP_PREFIX:
6983
0
  case FR_TYPE_ATTR:
6984
0
  case FR_TYPE_INTERNAL:
6985
0
    break;
6986
6987
0
  case FR_TYPE_GROUP:
6988
0
    return (fr_value_box_list_num_elements(&in->vb_group) > 0);
6989
6990
0
  case FR_TYPE_BOOL:
6991
0
    return in->vb_bool;
6992
6993
0
  case FR_TYPE_STRING:
6994
0
  case FR_TYPE_OCTETS:
6995
0
    return (in->vb_length > 0);
6996
6997
0
  case FR_TYPE_IPV4_ADDR:
6998
0
  case FR_TYPE_IPV6_ADDR:
6999
0
    return !fr_ipaddr_is_inaddr_any(&in->vb_ip);
7000
7001
0
  case FR_TYPE_IPV4_PREFIX:
7002
0
  case FR_TYPE_IPV6_PREFIX:
7003
0
    return !((in->vb_ip.prefix == 0) && fr_ipaddr_is_inaddr_any(&in->vb_ip));
7004
7005
0
  case FR_TYPE_INTEGER_EXCEPT_BOOL:
7006
0
  case FR_TYPE_FLOAT32:
7007
0
  case FR_TYPE_FLOAT64:
7008
0
  case FR_TYPE_IFID:
7009
0
  case FR_TYPE_ETHERNET:
7010
0
    fr_value_box_init_null(&box);
7011
0
    if (fr_value_box_cast(NULL, &box, FR_TYPE_BOOL, NULL, in) < 0) return false;
7012
0
    return box.vb_bool;
7013
0
  }
7014
7015
0
  return false;
7016
0
}
7017
7018
0
#define INFO_INDENT(_fmt, ...)  fprintf(fp, "%*s" _fmt "\n", depth * 2, " ", ## __VA_ARGS__)
7019
7020
static void _fr_value_box_debug(FILE *fp, fr_value_box_t const *vb, int depth, int idx);
7021
static void _fr_value_box_list_debug(FILE *fp, fr_value_box_list_t const *head, int depth)
7022
0
{
7023
0
  int i = 0;
7024
7025
0
  INFO_INDENT("{");
7026
0
  fr_value_box_list_foreach(head, vb) _fr_value_box_debug(fp, vb, depth + 1, i++);
7027
0
  INFO_INDENT("}");
7028
0
}
7029
7030
/** Print a list of value boxes as info messages
7031
 *
7032
 * @note Call directly from the debugger
7033
 */
7034
void fr_value_box_list_debug(FILE *fp, fr_value_box_list_t const *head)
7035
0
{
7036
0
  _fr_value_box_list_debug(fp, head, 0);
7037
0
}
7038
7039
static void _fr_value_box_debug(FILE *fp, fr_value_box_t const *vb, int depth, int idx)
7040
0
{
7041
0
  char *value;
7042
0
  char buffer[64];
7043
7044
0
  if (fr_type_is_structural(vb->type)) {
7045
0
    _fr_value_box_list_debug(fp, &vb->vb_group, depth + 1);
7046
0
    return;
7047
0
  }
7048
7049
0
  buffer[0] = '\0';
7050
0
  if (vb->type == FR_TYPE_TIME_DELTA) {
7051
0
    if (!vb->enumv) {
7052
0
      snprintf(buffer, sizeof(buffer), " (sec!) %" PRId64, fr_time_delta_unwrap(vb->vb_time_delta));
7053
0
    } else {
7054
0
      snprintf(buffer, sizeof(buffer), " (%s) %" PRId64,
7055
0
         fr_table_str_by_value(fr_time_precision_table, vb->enumv->flags.flag_time_res, "?"),
7056
0
         fr_time_delta_unwrap(vb->vb_time_delta));
7057
0
    }
7058
0
  }
7059
7060
0
  fr_value_box_aprint(NULL, &value, vb, NULL);
7061
0
  if (idx >= 0) {
7062
0
    INFO_INDENT("[%d] (%s) %s", idx, fr_type_to_str(vb->type), value);
7063
0
    INFO_INDENT("          %s %s %lx%s",
7064
0
          vb->secret ? "s" : "-",
7065
0
          vb->tainted ? "t" : "-",
7066
0
          vb->safe_for, buffer);
7067
0
  } else {
7068
0
    INFO_INDENT("(%s) %s", fr_type_to_str(vb->type), value);
7069
0
    INFO_INDENT("     %s %s %lx%s",
7070
0
          vb->secret ? "s" : "-",
7071
0
          vb->tainted ? "t" : "-",
7072
0
          vb->safe_for, buffer);
7073
0
  }
7074
0
  talloc_free(value);
7075
0
}
7076
7077
/** Print the value of a box as info messages
7078
 *
7079
 * @note Call directly from the debugger
7080
 */
7081
void fr_value_box_debug(FILE *fp, fr_value_box_t const *vb)
7082
0
{
7083
0
  _fr_value_box_debug(fp, vb, 0, -1);
7084
0
}