Coverage Report

Created: 2026-09-28 06:27

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