Coverage Report

Created: 2024-08-28 06:17

/src/freeradius-server/src/freeradius-devel/util/dict.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
/*
3
 *  This program is free software; you can redistribute it and/or modify
4
 *  it under the terms of the GNU General Public License as published by
5
 *  the Free Software Foundation; either version 2 of the License, or
6
 *  (at your option) any later version.
7
 *
8
 *  This program is distributed in the hope that it will be useful,
9
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 *  GNU General Public License for more details.
12
 *
13
 *  You should have received a copy of the GNU General Public License
14
 *  along with this program; if not, write to the Free Software
15
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16
 */
17
18
/** Multi-protocol AVP dictionary API
19
 *
20
 * @file src/lib/util/dict.h
21
 *
22
 * @copyright 2015 The FreeRADIUS server project
23
 */
24
RCSIDH(dict_h, "$Id: 0ad1bda348c50556e9d12359321a6485794c017c $")
25
26
#ifdef __cplusplus
27
extern "C" {
28
#endif
29
30
#include <freeradius-devel/build.h>
31
#include <freeradius-devel/missing.h>
32
#include <freeradius-devel/util/dl.h>
33
#include <freeradius-devel/util/ext.h>
34
#include <freeradius-devel/util/rb.h>
35
#include <freeradius-devel/util/sbuff.h>
36
#include <freeradius-devel/util/table.h>
37
#include <freeradius-devel/util/talloc.h>
38
#include <freeradius-devel/util/types.h>
39
40
#include <stdbool.h>
41
#include <stdint.h>
42
43
/*
44
 *  Avoid circular type references.
45
 */
46
typedef struct dict_attr_s fr_dict_attr_t;
47
typedef struct fr_dict fr_dict_t;
48
49
typedef struct value_box_s fr_value_box_t;
50
51
/*
52
 *  Allow public and private versions of the same structures
53
 */
54
#ifdef _CONST
55
#  error _CONST can only be defined in the local header
56
#endif
57
#ifndef _DICT_PRIVATE
58
#  define _CONST const
59
#else
60
#  define _CONST
61
#endif
62
63
#ifdef WITH_VERIFY_PTR
64
5.24M
#  define DA_VERIFY(_x)   fr_dict_attr_verify(__FILE__, __LINE__, _x)
65
#else
66
#  define DA_VERIFY(_x)   fr_cond_assert(_x)
67
#endif
68
69
typedef struct fr_dict_autoload_talloc_s fr_dict_autoload_talloc_t;
70
71
/** Values of the encryption flags
72
 */
73
typedef struct {
74
  unsigned int    is_root : 1;      //!< Is root of a dictionary.
75
76
  unsigned int    is_unknown : 1;     //!< This dictionary attribute is ephemeral
77
                ///< and not part of the main dictionary.
78
79
  unsigned int    is_raw : 1;     //!< This dictionary attribute was constructed
80
                ///< from a known attribute to allow the user
81
                ///< to assign octets values directly.
82
                ///< See .is_unknown to determine if it is
83
                ///< ephemeral.
84
  unsigned int    is_alias : 1;     //!< This isn't a real attribute, it's a reference to
85
                ///< to one.
86
  unsigned int    internal : 1;     //!< Internal attribute, should not be received
87
                ///< in protocol packets, should not be encoded.
88
  unsigned int    array : 1;      //!< Pack multiples into 1 attr.
89
90
  unsigned int    is_known_width : 1;   //!< is treated as if it has a known width for structs
91
92
  unsigned int    has_value : 1;      //!< Has a value.
93
94
  unsigned int    is_unsigned : 1;          //!< hackity hack for dates and time deltas
95
96
  unsigned int    counter : 1;          //!< integer attribute is actually an impulse / counter
97
98
  unsigned int    name_only : 1;      //!< this attribute should always be referred to by name, not by number
99
100
  unsigned int    secret : 1;     //!< this attribute should be omitted in debug mode
101
102
  /*
103
   *  @todo - if we want to clean these fields up, make
104
   *  "subtype" and "type_size" both 4-bit bitfields.  That
105
   *  gives us an extra 8 bits for adding new flags, and we
106
   *  can likely get rid of "extra", in order to save one
107
   *  more bit.
108
   */
109
  unsigned int    extra : 1;      //!< really "subtype is used by dict, not by protocol"
110
111
  unsigned int    local : 1;          //!< is a local variable
112
113
  /*
114
   *  main: extra is set, then this field is is key, bit, or a uint16 length field.
115
   *  radius: is one of 9 options for flags
116
   *  dhcp v4/v6: DNS label, or partial DNS label
117
   */
118
  uint8_t     subtype;      //!< protocol-specific values, OR key fields
119
120
  /*
121
   *  Length in bytes for most attributes.
122
   *  Length in bits for da_is_bit_field(da)
123
   */
124
  uint8_t     length;       //!< length of the attribute
125
126
  /*
127
   *  TLVs: 1, 2, or 4.
128
   *  date / time types: fr_time_res_t, which has 4 possible values.
129
   *  bit fields: offset in the byte where this bit field ends, which is only
130
   *    used as a caching mechanism during parsing of the dictionaries.
131
   */
132
  uint8_t     type_size;      //!< For TLV2 and root attributes.
133
} fr_dict_attr_flags_t;
134
135
23.0k
#define flag_time_res type_size
136
1.04k
#define flag_byte_offset type_size
137
138
/** subtype values for the dictionary when extra=1
139
 *
140
 */
141
enum {
142
  FLAG_EXTRA_NONE = 0,        //!< no extra meaning, should be invalid
143
  FLAG_KEY_FIELD,         //!< this is a key field for a subsequent struct
144
  FLAG_BIT_FIELD,               //!< bit field inside of a struct
145
  FLAG_LENGTH_UINT8,        //!< string / octets type is prefixed by uint8 of length
146
  FLAG_LENGTH_UINT16,       //!< string / octets type is prefixed by uint16 of length
147
};
148
149
312k
#define fr_dict_attr_is_key_field(_da) ((_da)->flags.extra && ((_da)->flags.subtype == FLAG_KEY_FIELD))
150
265k
#define da_is_bit_field(_da) ((_da)->flags.extra && ((_da)->flags.subtype == FLAG_BIT_FIELD))
151
1.59M
#define da_is_length_field(_da) ((_da)->flags.extra && (((_da)->flags.subtype == FLAG_LENGTH_UINT8) || ((_da)->flags.subtype == FLAG_LENGTH_UINT16)))
152
19.4k
#define da_length_offset(_da) ((_da)->flags.type_size)
153
154
155
/** Extension identifier
156
 *
157
 * @note New extension structures should also be added to the to the appropriate table in dict_ext.c
158
 */
159
typedef enum {
160
  FR_DICT_ATTR_EXT_NAME = 0,        //!< Name of the attribute.
161
  FR_DICT_ATTR_EXT_CHILDREN,        //!< Attribute has children.
162
  FR_DICT_ATTR_EXT_REF,         //!< Attribute references another
163
                ///< attribute and/or dictionary.
164
  FR_DICT_ATTR_EXT_VENDOR,        //!< Cached vendor pointer.
165
  FR_DICT_ATTR_EXT_DA_STACK,        //!< Cached da stack.
166
  FR_DICT_ATTR_EXT_ENUMV,         //!< Enumeration values.
167
  FR_DICT_ATTR_EXT_NAMESPACE,       //!< Attribute has its own namespace.
168
  FR_DICT_ATTR_EXT_PROTOCOL_SPECIFIC,     //!< Protocol specific extensions
169
  FR_DICT_ATTR_EXT_MAX
170
} fr_dict_attr_ext_t;
171
172
/** Dictionary attribute
173
 */
174
struct dict_attr_s {
175
  fr_dict_t _CONST* _CONST dict;        //!< Dict attribute belongs to.
176
177
  char const    *name;        //!< Attribute name.
178
  size_t      name_len;     //!< Length of the name.
179
180
  unsigned int    attr;       //!< Attribute number.
181
  unsigned int    depth;        //!< Depth of nesting for this attribute.
182
183
  unsigned int    last_child_attr;    //!< highest value of last child attribute.
184
185
  fr_type_t   type;       //!< Value type.
186
187
  fr_dict_attr_t const  *parent;      //!< Immediate parent of this attribute.
188
  fr_dict_attr_t const  *next;        //!< Next child in bin.
189
  fr_dict_attr_t    *fixup;       //!< Attribute has been marked up for fixups.
190
191
  fr_dict_attr_flags_t  flags;        //!< Flags.
192
193
  uint8_t     ext[FR_DICT_ATTR_EXT_MAX];  //!< Extensions to the dictionary attribute.
194
} CC_HINT(aligned(FR_EXT_ALIGNMENT));
195
196
/** Extension identifier
197
 *
198
 * @note New extension structures should also be added to the appropriate table in dict_ext.c
199
 */
200
typedef enum {
201
  FR_DICT_ENUM_EXT_UNION_REF = 0,       //!< Reference to a union/subs-struct.
202
  FR_DICT_ENUM_EXT_MAX
203
} fr_dict_enum_ext_t;
204
205
/** Value of an enumerated attribute
206
 *
207
 * Maps one of more string values to integers and vice versa.
208
 */
209
typedef struct {
210
  char const    *name;        //!< Enum name.
211
  size_t      name_len;     //!< Allows for efficient name lookups when operating
212
                ///< on partial buffers.
213
  fr_value_box_t const  *value;       //!< Enum value (what name maps to).
214
215
  uint8_t     ext[FR_DICT_ENUM_EXT_MAX];  //!< Extensions to the dictionary attribute.
216
217
  fr_dict_attr_t const  *child_struct[];    //!< for key fields
218
} fr_dict_enum_value_t CC_HINT(aligned(FR_EXT_ALIGNMENT));
219
220
/** Private enterprise
221
 *
222
 * Represents an IANA private enterprise allocation.
223
 *
224
 * The width of the private enterprise number must be the same for all protocols
225
 * so we can represent a vendor with a single struct.
226
 */
227
typedef struct {
228
  uint32_t    pen;        //!< Private enterprise number.
229
  bool      continuation;     //!< we only have one flag for now, for WiMAX
230
  size_t      type;         //!< Length of type data
231
  size_t      length;       //!< Length of length data
232
  char const    *name;        //!< Vendor name.
233
} fr_dict_vendor_t;
234
235
/** Specifies a value which must be present for the module to function
236
 *
237
 */
238
typedef struct {
239
  fr_value_box_t const  **out;        //!< Enumeration value.
240
  fr_dict_attr_t const  **attr;       //!< The protocol dictionary the attribute should
241
                ///< be resolved in. ** so it's a compile time
242
                ///< constant.
243
  char const    *name;        //!< of the attribute.
244
} fr_dict_enum_autoload_t;
245
246
/** Specifies an attribute which must be present for the module to function
247
 *
248
 */
249
typedef struct {
250
  fr_dict_attr_t const  **out;        //!< Where to write a pointer to the resolved
251
                //!< #fr_dict_attr_t.
252
  fr_dict_t const   **dict;       //!< The protocol dictionary the attribute should
253
                ///< be resolved in. ** so it's a compile time
254
                ///< constant.
255
  char const    *name;        //!< of the attribute.
256
  fr_type_t   type;       //!< of the attribute.  Mismatch is a fatal error.
257
} fr_dict_attr_autoload_t;
258
259
/** Specifies a dictionary which must be loaded/loadable for the module to function
260
 *
261
 */
262
typedef struct {
263
  fr_dict_t const   **out;        //!< Where to write a pointer to the loaded/resolved
264
                //!< #fr_dict_t.
265
  char const    *base_dir;      //!< Directory structure beneath share.
266
  char const    *proto;       //!< The protocol dictionary name.
267
} fr_dict_autoload_t;
268
269
/** Errors returned by attribute lookup functions
270
 *
271
 */
272
typedef enum {
273
  FR_DICT_ATTR_OK     = 0,      //!< No error.
274
  FR_DICT_ATTR_NOTFOUND   = -1,     //!< Attribute couldn't be found.
275
  FR_DICT_ATTR_PROTOCOL_NOTFOUND  = -2,     //!< Protocol couldn't be found.
276
  FR_DICT_ATTR_PARSE_ERROR  = -3,     //!< Attribute string couldn't be parsed
277
  FR_DICT_ATTR_INTERNAL_ERROR = -4,     //!< Internal error occurred.
278
  FR_DICT_ATTR_OOM    = -5,     //!< Memory allocation error.
279
  FR_DICT_ATTR_NOT_DESCENDENT = -6,     //!< Attribute is not a descendent of the parent
280
                ///< attribute.
281
  FR_DICT_ATTR_NOT_ANCESTOR = -7,     //!< Attribute is not an ancestor of the child
282
                ///< attribute.
283
  FR_DICT_ATTR_NO_CHILDREN  = -8,     //!< Child lookup in attribute with no children.
284
  FR_DICT_ATTR_EINVAL   = -9      //!< Invalid arguments.
285
286
} fr_dict_attr_err_t;
287
288
typedef bool (*fr_dict_attr_valid_func_t)(fr_dict_t *dict, fr_dict_attr_t const *parent,
289
            char const *name, int attr, fr_type_t type, fr_dict_attr_flags_t *flags);
290
291
/*
292
 *  Forward declarations to avoid circular references.
293
 */
294
typedef struct pair_list_s fr_pair_list_t;
295
typedef struct fr_dbuff_s fr_dbuff_t;
296
297
/** A generic interface for decoding packets to fr_pair_ts
298
 *
299
 * A decoding function should decode a single top level packet from wire format.
300
 *
301
 * Note that unlike #fr_tp_proto_decode_t, this function is NOT passed an encode_ctx.  That is because when we
302
 * do cross-protocol encoding, the "outer" protocol has no information it can share with the "inner" protocol.
303
 *
304
 * @param[in] ctx   to allocate new pairs in.
305
 * @param[in] vps   where new VPs will be added
306
 * @param[in] data    to decode.
307
 * @param[in] data_len    The length of the incoming data.
308
 * @return
309
 *  - <= 0 on error.  May be the offset (as a negative value) where the error occurred.
310
 *  - > 0 on success.  How many bytes were decoded.
311
 */
312
typedef ssize_t (*fr_dict_attr_decode_func_t)(TALLOC_CTX *ctx, fr_pair_list_t *vps,
313
                uint8_t const *data, size_t data_len);
314
315
/** A generic interface for encoding fr_pair_ts to packets
316
 *
317
 * An encoding function should encode multiple VPs to a wire format packet
318
 *
319
 * Note that unlike #fr_tp_proto_encode_t, this function is NOT passed an encode_ctx.  That is because when we
320
 * do cross-protocol encoding, the "outer" protocol has no information it can share with the "inner" protocol.
321
 *
322
 * @param[in] vps   vps to encode
323
 * @param[in] dbuff   buffer where data can be written
324
 * @return
325
 *  - <= 0 on error.  May be the offset (as a negative value) where the error occurred.
326
 *  - > 0 on success.  How many bytes were encoded
327
 */
328
typedef ssize_t(*fr_dict_attr_encode_func_t)(fr_dbuff_t *dbuff, fr_pair_list_t const *vps);
329
330
/** Init / free callbacks
331
 *
332
 *  Only for "autoref" usage.
333
 */
334
typedef int (*fr_dict_protocol_init_t)(void);
335
typedef void (*fr_dict_protocol_free_t)(void);
336
337
338
/** Protocol-specific callbacks in libfreeradius-PROTOCOL
339
 *
340
 */
341
typedef struct {
342
  char const    *name;        //!< name of this protocol
343
  int     default_type_size;    //!< how many octets are in "type" field
344
  int     default_type_length;    //!< how many octets are in "length" field
345
  fr_table_num_ordered_t  const *subtype_table;   //!< for "encrypt=1", etc.
346
  size_t      subtype_table_len;    //!< length of subtype_table
347
  fr_dict_attr_valid_func_t attr_valid;     //!< validation function for new attributes
348
349
  fr_dict_protocol_init_t init;       //!< initialize the library
350
  fr_dict_protocol_free_t free;       //!< free the library
351
352
  fr_dict_attr_decode_func_t decode;      //!< for decoding attributes
353
  fr_dict_attr_encode_func_t encode;      //!< for encoding attributes
354
} fr_dict_protocol_t;
355
356
typedef struct fr_dict_gctx_s fr_dict_gctx_t;
357
358
/*
359
 *  Dictionary constants
360
 */
361
#define FR_DICT_PROTO_MAX_NAME_LEN  (128)     //!< Maximum length of a protocol name.
362
37.3k
#define FR_DICT_ENUM_MAX_NAME_LEN (128)      //!< Maximum length of a enum value.
363
751
#define FR_DICT_VENDOR_MAX_NAME_LEN (128)      //!< Maximum length of a vendor name.
364
245k
#define FR_DICT_ATTR_MAX_NAME_LEN (128)      //!< Maximum length of a attribute name.
365
366
/** Maximum level of TLV nesting allowed
367
 */
368
13.1M
#define FR_DICT_TLV_NEST_MAX    (24)
369
370
/** Maximum level of da stack caching
371
 */
372
2.08M
#define FR_DICT_DA_STACK_CACHE_MAX  (5)
373
374
/** Maximum TLV stack size
375
 *
376
 * The additional attributes are to account for
377
 *
378
 * Root + Vendor + NULL (top frame).
379
 * Root + Embedded protocol + Root + Vendor + NULL.
380
 *
381
 * Code should ensure that it doesn't run off the end of the stack,
382
 * as this could be remotely exploitable, using odd nesting.
383
 */
384
13.1M
#define FR_DICT_MAX_TLV_STACK   (FR_DICT_TLV_NEST_MAX + 5)
385
386
/** Characters that are allowed in dictionary attribute names
387
 *
388
 */
389
extern bool const fr_dict_attr_allowed_chars[UINT8_MAX + 1];
390
391
/** Characters that are allowed in dictionary enumeration value names
392
 *
393
 */
394
extern bool const fr_dict_enum_allowed_chars[UINT8_MAX + 1];
395
396
/** @name Dictionary structure extensions
397
 *
398
 * @{
399
 */
400
#include <freeradius-devel/util/dict_ext.h>
401
/** @} */
402
403
/** @name Programmatically create dictionary attributes and values
404
 *
405
 * @{
406
 */
407
int     fr_dict_attr_add(fr_dict_t *dict, fr_dict_attr_t const *parent, char const *name, int attr,
408
           fr_type_t type, fr_dict_attr_flags_t const *flags) CC_HINT(nonnull(1,2,3));
409
410
int     fr_dict_enum_add_name(fr_dict_attr_t *da, char const *name,
411
                fr_value_box_t const *value, bool coerce, bool replace);
412
413
int     fr_dict_enum_add_name_next(fr_dict_attr_t *da, char const *name) CC_HINT(nonnull);
414
415
int     fr_dict_str_to_argv(char *str, char **argv, int max_argc);
416
/** @} */
417
418
/** @name Unknown ephemeral attributes
419
 *
420
 * @{
421
 */
422
fr_dict_attr_t const  *fr_dict_unknown_add(fr_dict_t *dict, fr_dict_attr_t const *old) CC_HINT(nonnull);
423
424
void      fr_dict_unknown_free(fr_dict_attr_t const **da);
425
426
fr_dict_attr_t    *fr_dict_unknown_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da);
427
428
static inline fr_dict_attr_t *fr_dict_unknown_copy(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
429
503k
{
430
503k
  fr_assert(da->flags.is_unknown);
431
432
503k
  return fr_dict_unknown_afrom_da(ctx, da);
433
503k
}
Unexecuted instantiation: fuzzer_tacacs.c:fr_dict_unknown_copy
Unexecuted instantiation: fuzzer_vmps.c:fr_dict_unknown_copy
Unexecuted instantiation: fuzzer_tftp.c:fr_dict_unknown_copy
Unexecuted instantiation: fuzzer_dns.c:fr_dict_unknown_copy
Unexecuted instantiation: fuzzer_dhcpv6.c:fr_dict_unknown_copy
Unexecuted instantiation: fuzzer_radius.c:fr_dict_unknown_copy
Unexecuted instantiation: fuzzer_util.c:fr_dict_unknown_copy
Unexecuted instantiation: fuzzer_dhcpv4.c:fr_dict_unknown_copy
Unexecuted instantiation: fuzzer_bfd.c:fr_dict_unknown_copy
Unexecuted instantiation: base32.c:fr_dict_unknown_copy
Unexecuted instantiation: base64.c:fr_dict_unknown_copy
Unexecuted instantiation: calc.c:fr_dict_unknown_copy
Unexecuted instantiation: decode.c:fr_dict_unknown_copy
Unexecuted instantiation: dict_ext.c:fr_dict_unknown_copy
Unexecuted instantiation: dict_fixup.c:fr_dict_unknown_copy
Unexecuted instantiation: dict_print.c:fr_dict_unknown_copy
Unexecuted instantiation: dict_test.c:fr_dict_unknown_copy
Unexecuted instantiation: dict_tokenize.c:fr_dict_unknown_copy
dict_unknown.c:fr_dict_unknown_copy
Line
Count
Source
429
35.6k
{
430
35.6k
  fr_assert(da->flags.is_unknown);
431
432
35.6k
  return fr_dict_unknown_afrom_da(ctx, da);
433
35.6k
}
Unexecuted instantiation: dict_util.c:fr_dict_unknown_copy
Unexecuted instantiation: dict_validate.c:fr_dict_unknown_copy
Unexecuted instantiation: dl.c:fr_dict_unknown_copy
Unexecuted instantiation: dns.c:fr_dict_unknown_copy
Unexecuted instantiation: edit.c:fr_dict_unknown_copy
Unexecuted instantiation: encode.c:fr_dict_unknown_copy
Unexecuted instantiation: file.c:fr_dict_unknown_copy
Unexecuted instantiation: inet.c:fr_dict_unknown_copy
Unexecuted instantiation: log.c:fr_dict_unknown_copy
Unexecuted instantiation: packet.c:fr_dict_unknown_copy
pair.c:fr_dict_unknown_copy
Line
Count
Source
429
467k
{
430
467k
  fr_assert(da->flags.is_unknown);
431
432
467k
  return fr_dict_unknown_afrom_da(ctx, da);
433
467k
}
Unexecuted instantiation: pair_inline.c:fr_dict_unknown_copy
Unexecuted instantiation: pair_legacy.c:fr_dict_unknown_copy
Unexecuted instantiation: pair_print.c:fr_dict_unknown_copy
Unexecuted instantiation: pair_tokenize.c:fr_dict_unknown_copy
Unexecuted instantiation: print.c:fr_dict_unknown_copy
Unexecuted instantiation: proto.c:fr_dict_unknown_copy
Unexecuted instantiation: regex.c:fr_dict_unknown_copy
Unexecuted instantiation: socket.c:fr_dict_unknown_copy
Unexecuted instantiation: stats.c:fr_dict_unknown_copy
Unexecuted instantiation: struct.c:fr_dict_unknown_copy
Unexecuted instantiation: trie.c:fr_dict_unknown_copy
Unexecuted instantiation: types.c:fr_dict_unknown_copy
Unexecuted instantiation: uri.c:fr_dict_unknown_copy
Unexecuted instantiation: value.c:fr_dict_unknown_copy
Unexecuted instantiation: fuzzer.c:fr_dict_unknown_copy
Unexecuted instantiation: base.c:fr_dict_unknown_copy
Unexecuted instantiation: vmps.c:fr_dict_unknown_copy
Unexecuted instantiation: list.c:fr_dict_unknown_copy
Unexecuted instantiation: tcp.c:fr_dict_unknown_copy
Unexecuted instantiation: abinary.c:fr_dict_unknown_copy
Unexecuted instantiation: raw.c:fr_dict_unknown_copy
Unexecuted instantiation: udp.c:fr_dict_unknown_copy
434
435
fr_dict_attr_t    *fr_dict_unknown_vendor_afrom_num(TALLOC_CTX *ctx,
436
                fr_dict_attr_t const *parent, unsigned int vendor)
437
                CC_HINT(nonnull(2));
438
439
fr_dict_attr_t    *fr_dict_unknown_tlv_afrom_num(TALLOC_CTX *ctx,
440
                   fr_dict_attr_t const *parent, unsigned int num)
441
                   CC_HINT(nonnull(2));
442
443
fr_dict_attr_t    *fr_dict_unknown_attr_afrom_num(TALLOC_CTX *ctx,
444
              fr_dict_attr_t const *parent, unsigned int num)
445
              CC_HINT(nonnull(2));
446
447
fr_dict_attr_t    *fr_dict_unknown_attr_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
448
                   CC_HINT(nonnull(2));
449
450
451
fr_slen_t   fr_dict_unknown_afrom_oid_substr(TALLOC_CTX *ctx,
452
               fr_dict_attr_t const **out,
453
               fr_dict_attr_t const *parent,
454
               fr_sbuff_t *in)
455
               CC_HINT(nonnull(2,3,4));
456
457
int     fr_dict_attr_unknown_parent_to_known(fr_dict_attr_t *da, fr_dict_attr_t const *parent);
458
459
fr_dict_attr_t const  *fr_dict_attr_unknown_resolve(fr_dict_t const *dict, fr_dict_attr_t const *da);
460
/** @} */
461
462
/** @name Attribute comparisons
463
 *
464
 * @{
465
 */
466
static inline  CC_HINT(nonnull) int8_t fr_dict_attr_cmp(fr_dict_attr_t const *a, fr_dict_attr_t const *b)
467
0
{
468
0
  int8_t ret;
469
0
470
0
  /*
471
0
   *  Comparing unknowns or raws is expensive
472
0
   *  because we need to check the lineage.
473
0
   */
474
0
  if (a->flags.is_unknown | a->flags.is_raw | b->flags.is_unknown | b->flags.is_raw) {
475
0
    ret = CMP(a->depth, b->depth);
476
0
    if (ret != 0) return ret;
477
0
478
0
    ret = CMP(a->attr, b->attr);
479
0
    if (ret != 0) return ret;
480
0
481
0
    ret = (a->parent == NULL) - (b->parent == NULL);
482
0
    if ((ret != 0) || !a->parent) return ret;
483
0
484
0
    return fr_dict_attr_cmp(a->parent, b->parent);
485
0
  }
486
0
487
0
  /*
488
0
   *  Comparing knowns is cheap because the
489
0
   *  DAs are unique.
490
0
   */
491
0
  return CMP(a, b);
492
0
}
Unexecuted instantiation: fuzzer_tacacs.c:fr_dict_attr_cmp
Unexecuted instantiation: fuzzer_vmps.c:fr_dict_attr_cmp
Unexecuted instantiation: fuzzer_tftp.c:fr_dict_attr_cmp
Unexecuted instantiation: fuzzer_dns.c:fr_dict_attr_cmp
Unexecuted instantiation: fuzzer_dhcpv6.c:fr_dict_attr_cmp
Unexecuted instantiation: fuzzer_radius.c:fr_dict_attr_cmp
Unexecuted instantiation: fuzzer_util.c:fr_dict_attr_cmp
Unexecuted instantiation: fuzzer_dhcpv4.c:fr_dict_attr_cmp
Unexecuted instantiation: fuzzer_bfd.c:fr_dict_attr_cmp
Unexecuted instantiation: base32.c:fr_dict_attr_cmp
Unexecuted instantiation: base64.c:fr_dict_attr_cmp
Unexecuted instantiation: calc.c:fr_dict_attr_cmp
Unexecuted instantiation: decode.c:fr_dict_attr_cmp
Unexecuted instantiation: dict_ext.c:fr_dict_attr_cmp
Unexecuted instantiation: dict_fixup.c:fr_dict_attr_cmp
Unexecuted instantiation: dict_print.c:fr_dict_attr_cmp
Unexecuted instantiation: dict_test.c:fr_dict_attr_cmp
Unexecuted instantiation: dict_tokenize.c:fr_dict_attr_cmp
Unexecuted instantiation: dict_unknown.c:fr_dict_attr_cmp
Unexecuted instantiation: dict_util.c:fr_dict_attr_cmp
Unexecuted instantiation: dict_validate.c:fr_dict_attr_cmp
Unexecuted instantiation: dl.c:fr_dict_attr_cmp
Unexecuted instantiation: dns.c:fr_dict_attr_cmp
Unexecuted instantiation: edit.c:fr_dict_attr_cmp
Unexecuted instantiation: encode.c:fr_dict_attr_cmp
Unexecuted instantiation: file.c:fr_dict_attr_cmp
Unexecuted instantiation: inet.c:fr_dict_attr_cmp
Unexecuted instantiation: log.c:fr_dict_attr_cmp
Unexecuted instantiation: packet.c:fr_dict_attr_cmp
Unexecuted instantiation: pair.c:fr_dict_attr_cmp
Unexecuted instantiation: pair_inline.c:fr_dict_attr_cmp
Unexecuted instantiation: pair_legacy.c:fr_dict_attr_cmp
Unexecuted instantiation: pair_print.c:fr_dict_attr_cmp
Unexecuted instantiation: pair_tokenize.c:fr_dict_attr_cmp
Unexecuted instantiation: print.c:fr_dict_attr_cmp
Unexecuted instantiation: proto.c:fr_dict_attr_cmp
Unexecuted instantiation: regex.c:fr_dict_attr_cmp
Unexecuted instantiation: socket.c:fr_dict_attr_cmp
Unexecuted instantiation: stats.c:fr_dict_attr_cmp
Unexecuted instantiation: struct.c:fr_dict_attr_cmp
Unexecuted instantiation: trie.c:fr_dict_attr_cmp
Unexecuted instantiation: types.c:fr_dict_attr_cmp
Unexecuted instantiation: uri.c:fr_dict_attr_cmp
Unexecuted instantiation: value.c:fr_dict_attr_cmp
Unexecuted instantiation: fuzzer.c:fr_dict_attr_cmp
Unexecuted instantiation: base.c:fr_dict_attr_cmp
Unexecuted instantiation: vmps.c:fr_dict_attr_cmp
Unexecuted instantiation: list.c:fr_dict_attr_cmp
Unexecuted instantiation: tcp.c:fr_dict_attr_cmp
Unexecuted instantiation: abinary.c:fr_dict_attr_cmp
Unexecuted instantiation: raw.c:fr_dict_attr_cmp
Unexecuted instantiation: udp.c:fr_dict_attr_cmp
493
/** @} */
494
495
/** @name Debugging functions
496
 *
497
 * @{
498
 */
499
void      fr_dict_namespace_debug(fr_dict_attr_t const *da);
500
501
void      fr_dict_attr_debug(fr_dict_attr_t const *da);
502
503
void      fr_dict_debug(fr_dict_t const *dict);
504
505
void      fr_dict_export(fr_dict_t const *dict);
506
/** @} */
507
508
/** @name Attribute lineage
509
 *
510
 * @{
511
 */
512
fr_dict_attr_t const  *fr_dict_attr_common_parent(fr_dict_attr_t const *a, fr_dict_attr_t const *b, bool is_ancestor);
513
514
int     fr_dict_oid_component_legacy(unsigned int *out, char const **oid);
515
516
fr_slen_t   fr_dict_attr_flags_print(fr_sbuff_t *out, fr_dict_t const *dict,
517
             fr_type_t type, fr_dict_attr_flags_t const *flags);
518
519
fr_slen_t   fr_dict_attr_oid_print(fr_sbuff_t *out,
520
                 fr_dict_attr_t const *ancestor, fr_dict_attr_t const *da, bool numeric);
521
0
#define     FR_DICT_ATTR_OID_PRINT_RETURN(...) FR_SBUFF_RETURN(fr_dict_attr_oid_print, ##__VA_ARGS__)
522
523
fr_slen_t   fr_dict_attr_by_oid_legacy(fr_dict_t const *dict, fr_dict_attr_t const **parent,
524
                     unsigned int *attr, char const *oid) CC_HINT(nonnull);
525
526
fr_slen_t   fr_dict_oid_component(fr_dict_attr_err_t *err,
527
                fr_dict_attr_t const **out, fr_dict_attr_t const *parent,
528
                fr_sbuff_t *in, fr_sbuff_term_t const *tt)
529
                CC_HINT(nonnull(2,3,4));
530
531
fr_slen_t   fr_dict_attr_by_oid_substr(fr_dict_attr_err_t *err,
532
               fr_dict_attr_t const **out, fr_dict_attr_t const *parent,
533
               fr_sbuff_t *in, fr_sbuff_term_t const *tt)
534
               CC_HINT(nonnull(2,3,4));
535
536
fr_dict_attr_t const  *fr_dict_attr_by_oid(fr_dict_attr_err_t *err,
537
               fr_dict_attr_t const *parent, char const *oid)
538
               CC_HINT(nonnull(2,3));
539
540
bool      fr_dict_attr_can_contain(fr_dict_attr_t const *parent, fr_dict_attr_t const *child) CC_HINT(nonnull);
541
542
/** @} */
543
544
/** @name Attribute, vendor and dictionary lookup
545
 *
546
 * @{
547
 */
548
549
/** @hidecallergraph */
550
fr_dict_attr_t const  *fr_dict_root(fr_dict_t const *dict) CC_HINT(nonnull);
551
552
bool      fr_dict_is_read_only(fr_dict_t const *dict);
553
554
dl_t      *fr_dict_dl(fr_dict_t const *dict);
555
556
fr_slen_t   fr_dict_by_protocol_substr(fr_dict_attr_err_t *err,
557
               fr_dict_t const **out, fr_sbuff_t *name, fr_dict_t const *dict_def);
558
559
fr_dict_t const   *fr_dict_by_protocol_name(char const *name);
560
561
fr_dict_t const   *fr_dict_by_protocol_num(unsigned int num);
562
563
fr_dict_protocol_t const *fr_dict_protocol(fr_dict_t const *dict);
564
565
fr_dict_t const   *fr_dict_by_da(fr_dict_attr_t const *da) CC_HINT(nonnull);
566
567
fr_dict_t const   *fr_dict_by_attr_name(fr_dict_attr_t const **found, char const *name);
568
569
bool      fr_dict_compatible(fr_dict_t const *dict1, fr_dict_t const *dict2) CC_HINT(nonnull);
570
571
/** Return true if this attribute is parented directly off the dictionary root
572
 *
573
 * @param[in] da    to check.
574
 * @return
575
 *  - true if attribute is top level.
576
 *  - false if attribute is not top level.
577
 */
578
static inline bool fr_dict_attr_is_top_level(fr_dict_attr_t const *da)
579
0
{
580
0
  if (unlikely(!da) || unlikely(!da->parent)) return false;
581
0
  return da->parent->flags.is_root;
582
0
}
Unexecuted instantiation: fuzzer_tacacs.c:fr_dict_attr_is_top_level
Unexecuted instantiation: fuzzer_vmps.c:fr_dict_attr_is_top_level
Unexecuted instantiation: fuzzer_tftp.c:fr_dict_attr_is_top_level
Unexecuted instantiation: fuzzer_dns.c:fr_dict_attr_is_top_level
Unexecuted instantiation: fuzzer_dhcpv6.c:fr_dict_attr_is_top_level
Unexecuted instantiation: fuzzer_radius.c:fr_dict_attr_is_top_level
Unexecuted instantiation: fuzzer_util.c:fr_dict_attr_is_top_level
Unexecuted instantiation: fuzzer_dhcpv4.c:fr_dict_attr_is_top_level
Unexecuted instantiation: fuzzer_bfd.c:fr_dict_attr_is_top_level
Unexecuted instantiation: base32.c:fr_dict_attr_is_top_level
Unexecuted instantiation: base64.c:fr_dict_attr_is_top_level
Unexecuted instantiation: calc.c:fr_dict_attr_is_top_level
Unexecuted instantiation: decode.c:fr_dict_attr_is_top_level
Unexecuted instantiation: dict_ext.c:fr_dict_attr_is_top_level
Unexecuted instantiation: dict_fixup.c:fr_dict_attr_is_top_level
Unexecuted instantiation: dict_print.c:fr_dict_attr_is_top_level
Unexecuted instantiation: dict_test.c:fr_dict_attr_is_top_level
Unexecuted instantiation: dict_tokenize.c:fr_dict_attr_is_top_level
Unexecuted instantiation: dict_unknown.c:fr_dict_attr_is_top_level
Unexecuted instantiation: dict_util.c:fr_dict_attr_is_top_level
Unexecuted instantiation: dict_validate.c:fr_dict_attr_is_top_level
Unexecuted instantiation: dl.c:fr_dict_attr_is_top_level
Unexecuted instantiation: dns.c:fr_dict_attr_is_top_level
Unexecuted instantiation: edit.c:fr_dict_attr_is_top_level
Unexecuted instantiation: encode.c:fr_dict_attr_is_top_level
Unexecuted instantiation: file.c:fr_dict_attr_is_top_level
Unexecuted instantiation: inet.c:fr_dict_attr_is_top_level
Unexecuted instantiation: log.c:fr_dict_attr_is_top_level
Unexecuted instantiation: packet.c:fr_dict_attr_is_top_level
Unexecuted instantiation: pair.c:fr_dict_attr_is_top_level
Unexecuted instantiation: pair_inline.c:fr_dict_attr_is_top_level
Unexecuted instantiation: pair_legacy.c:fr_dict_attr_is_top_level
Unexecuted instantiation: pair_print.c:fr_dict_attr_is_top_level
Unexecuted instantiation: pair_tokenize.c:fr_dict_attr_is_top_level
Unexecuted instantiation: print.c:fr_dict_attr_is_top_level
Unexecuted instantiation: proto.c:fr_dict_attr_is_top_level
Unexecuted instantiation: regex.c:fr_dict_attr_is_top_level
Unexecuted instantiation: socket.c:fr_dict_attr_is_top_level
Unexecuted instantiation: stats.c:fr_dict_attr_is_top_level
Unexecuted instantiation: struct.c:fr_dict_attr_is_top_level
Unexecuted instantiation: trie.c:fr_dict_attr_is_top_level
Unexecuted instantiation: types.c:fr_dict_attr_is_top_level
Unexecuted instantiation: uri.c:fr_dict_attr_is_top_level
Unexecuted instantiation: value.c:fr_dict_attr_is_top_level
Unexecuted instantiation: fuzzer.c:fr_dict_attr_is_top_level
Unexecuted instantiation: base.c:fr_dict_attr_is_top_level
Unexecuted instantiation: vmps.c:fr_dict_attr_is_top_level
Unexecuted instantiation: list.c:fr_dict_attr_is_top_level
Unexecuted instantiation: tcp.c:fr_dict_attr_is_top_level
Unexecuted instantiation: abinary.c:fr_dict_attr_is_top_level
Unexecuted instantiation: raw.c:fr_dict_attr_is_top_level
Unexecuted instantiation: udp.c:fr_dict_attr_is_top_level
583
584
fr_dict_vendor_t const  *fr_dict_vendor_by_da(fr_dict_attr_t const *da);
585
586
fr_dict_vendor_t const  *fr_dict_vendor_by_name(fr_dict_t const *dict, char const *name);
587
588
fr_dict_vendor_t const  *fr_dict_vendor_by_num(fr_dict_t const *dict, uint32_t vendor_pen);
589
590
fr_dict_attr_t const  *fr_dict_vendor_da_by_num(fr_dict_attr_t const *vendor_root, uint32_t vendor_pen);
591
592
fr_slen_t   fr_dict_attr_search_by_qualified_name_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
593
                     fr_dict_t const *dict_def,
594
                     fr_sbuff_t *name, fr_sbuff_term_t const *tt,
595
                     bool internal, bool foreign)
596
                     CC_HINT(nonnull(2, 4));
597
598
fr_slen_t   fr_dict_attr_search_by_name_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
599
                   fr_dict_t const *dict_def,
600
                 fr_sbuff_t *name, fr_sbuff_term_t const *tt,
601
                 bool internal, bool foreign)
602
                 CC_HINT(nonnull(2, 4));
603
604
fr_slen_t   fr_dict_attr_search_by_qualified_oid_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
605
                        fr_dict_t const *dict_def,
606
                    fr_sbuff_t *in, fr_sbuff_term_t const *tt,
607
                    bool internal, bool foreign)
608
                    CC_HINT(nonnull(2, 4));
609
610
fr_dict_attr_t const  *fr_dict_attr_search_by_qualified_oid(fr_dict_attr_err_t *err,
611
                          fr_dict_t const *dict_def, char const *attr,
612
                          bool internal, bool foreign)
613
                    CC_HINT(nonnull(3));
614
615
fr_slen_t   fr_dict_attr_search_by_oid_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
616
                fr_dict_t const *dict_def,
617
                fr_sbuff_t *in, fr_sbuff_term_t const *tt,
618
                bool internal, bool foreign)
619
                CC_HINT(nonnull(2, 4));
620
621
fr_slen_t   fr_dict_attr_by_name_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out,
622
                fr_dict_attr_t const *parent,
623
                fr_sbuff_t *name, fr_sbuff_term_t const *tt)
624
                CC_HINT(nonnull(2,3,4));
625
626
fr_dict_attr_t const  *fr_dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent,
627
                char const *attr)
628
                CC_HINT(nonnull(2,3));
629
630
fr_dict_attr_t const  *fr_dict_attr_child_by_num(fr_dict_attr_t const *parent, unsigned int attr);
631
632
fr_dict_enum_value_t    *fr_dict_enum_by_value(fr_dict_attr_t const *da, fr_value_box_t const *value);
633
634
char const    *fr_dict_enum_name_by_value(fr_dict_attr_t const *da, fr_value_box_t const *value);
635
636
fr_dict_enum_value_t    *fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len);
637
638
fr_slen_t   fr_dict_enum_by_name_substr(fr_dict_enum_value_t **out, fr_dict_attr_t const *da, fr_sbuff_t *in);
639
640
fr_slen_t   fr_dict_enum_name_from_substr(fr_sbuff_t *out, fr_sbuff_parse_error_t *err,
641
                  fr_sbuff_t *in, fr_sbuff_term_t const *tt);
642
643
static inline fr_slen_t fr_dict_enum_name_afrom_substr(TALLOC_CTX *ctx, char **out, fr_sbuff_parse_error_t *err,
644
                   fr_sbuff_t *in, fr_sbuff_term_t const *tt)
645
      SBUFF_OUT_TALLOC_FUNC_NO_LEN_DEF(fr_dict_enum_name_from_substr, err, in, tt)
646
/** @} */
647
648
/** @name Dictionary and protocol loading
649
 *
650
 * @{
651
 */
652
int     fr_dict_internal_afrom_file(fr_dict_t **out, char const *internal_name,
653
                char const *dependent);
654
655
int     fr_dict_protocol_afrom_file(fr_dict_t **out, char const *proto_name, char const *proto_dir,
656
                char const *dependent);
657
658
fr_dict_t   *fr_dict_protocol_alloc(fr_dict_t const *parent);
659
660
int     fr_dict_read(fr_dict_t *dict, char const *dict_dir, char const *filename);
661
/** @} */
662
663
/** @name Autoloader interface
664
 *
665
 * @{
666
 */
667
int     fr_dict_enum_autoload(fr_dict_enum_autoload_t const *to_load);
668
669
int     fr_dict_attr_autoload(fr_dict_attr_autoload_t const *to_load);
670
671
5.48k
#define     fr_dict_autoload(_to_load) _fr_dict_autoload(_to_load, __FILE__)
672
int     _fr_dict_autoload(fr_dict_autoload_t const *to_load, char const *dependent);
673
674
5.48k
#define     fr_dict_autofree(_to_free) _fr_dict_autofree(_to_free, __FILE__)
675
int     _fr_dict_autofree(fr_dict_autoload_t const *to_free, char const *dependent);
676
677
#define     fr_dict_autoload_talloc(_ctx, _dict_out, _proto) _fr_dict_autoload_talloc(_ctx, _dict_out, _proto, __FILE__)
678
fr_dict_autoload_talloc_t *_fr_dict_autoload_talloc(TALLOC_CTX *ctx, fr_dict_t const **out, char const *proto, char const *dependent);
679
680
int     fr_dl_dict_enum_autoload(dl_t const *module, void *symbol, void *user_ctx);
681
682
int     fr_dl_dict_attr_autoload(dl_t const *module, void *symbol, void *user_ctx);
683
684
int     fr_dl_dict_autoload(dl_t const *module, void *symbol, void *user_ctx);
685
686
void      fr_dl_dict_autofree(dl_t const *module, void *symbol, void *user_ctx);
687
/** @} */
688
689
/** @name Allocating and freeing
690
 *
691
 * @{
692
 */
693
fr_dict_t     *fr_dict_alloc(char const *proto_name, unsigned int proto_number) CC_HINT(nonnull);
694
695
int     fr_dict_dependent_add(fr_dict_t const *dict, char const *dependent) CC_HINT(nonnull);
696
697
int     fr_dict_free(fr_dict_t **dict, char const *dependent) CC_HINT(nonnull);
698
699
int     fr_dict_const_free(fr_dict_t const **dict, char const *dependent) CC_HINT(nonnull);
700
/** @} */
701
702
/** @name Global dictionary management
703
 *
704
 * @{
705
 */
706
fr_dict_gctx_t    *fr_dict_global_ctx_init(TALLOC_CTX *ctx, bool free_at_exit, char const *dict_dir);
707
708
void      fr_dict_global_ctx_perm_check(fr_dict_gctx_t *gctx, bool enable);
709
710
void      fr_dict_global_ctx_set(fr_dict_gctx_t const *gctx);
711
712
int     fr_dict_global_ctx_free(fr_dict_gctx_t const *gctx);
713
714
int     fr_dict_global_ctx_dir_set(char const *dict_dir);
715
716
void      fr_dict_global_ctx_read_only(void);
717
718
void      fr_dict_global_ctx_debug(fr_dict_gctx_t const *gctx);
719
720
char const    *fr_dict_global_ctx_dir(void);
721
722
typedef struct fr_hash_iter_s fr_dict_global_ctx_iter_t;
723
724
fr_dict_t   *fr_dict_global_ctx_iter_init(fr_dict_global_ctx_iter_t *iter) CC_HINT(nonnull);
725
726
fr_dict_t   *fr_dict_global_ctx_iter_next(fr_dict_global_ctx_iter_t *iter) CC_HINT(nonnull);
727
728
fr_dict_t   *fr_dict_unconst(fr_dict_t const *dict);
729
730
fr_dict_attr_t    *fr_dict_attr_unconst(fr_dict_attr_t const *da);
731
732
fr_dict_t const   *fr_dict_internal(void);
733
734
/** @} */
735
736
/** @name Dictionary testing and validation
737
 *
738
 * @{
739
 */
740
int     fr_dict_parse_str(fr_dict_t *dict, char *buf,
741
            fr_dict_attr_t const *parent);
742
743
ssize_t     fr_dict_valid_name(char const *name, ssize_t len);
744
745
ssize_t     fr_dict_valid_oid_str(char const *name, ssize_t len);
746
747
fr_dict_attr_t const  *fr_dict_attr_iterate_children(fr_dict_attr_t const *parent, fr_dict_attr_t const **prev);
748
749
typedef int   (*fr_dict_walk_t)(fr_dict_attr_t const *da, void *uctx);
750
751
int     fr_dict_walk(fr_dict_attr_t const *da, fr_dict_walk_t callback, void *uctx);
752
753
void      fr_dict_attr_verify(char const *file, int line, fr_dict_attr_t const *da);
754
/** @} */
755
756
#undef _CONST
757
758
#ifdef __cplusplus
759
}
760
#endif