Coverage Report

Created: 2023-12-08 06:56

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