24 RCSID(
"$Id: 41fd75b4250a3c3da8b7b928d5962396e557787e $")
26 #include <freeradius-devel/radius/defs.h>
27 #include <freeradius-devel/util/conf.h>
28 #include <freeradius-devel/util/dict_fixup_priv.h>
29 #include <freeradius-devel/util/dict_priv.h>
30 #include <freeradius-devel/util/dict.h>
31 #include <freeradius-devel/util/file.h>
32 #include <freeradius-devel/util/rand.h>
33 #include <freeradius-devel/util/strerror.h>
34 #include <freeradius-devel/util/syserror.h>
35 #include <freeradius-devel/util/table.h>
36 #include <freeradius-devel/util/types.h>
37 #include <freeradius-devel/util/value.h>
55 #define MAX_STACK (32)
80 #define CURRENT_FRAME(_dctx) (&(_dctx)->stack[(_dctx)->stack_depth])
91 if (argc >= max_argc)
break;
101 while ((*str ==
' ') ||
125 int unsigned ret = 0;
127 static char const *tab =
"0123456789";
129 if ((str[0] ==
'0') &&
130 ((str[1] ==
'x') || (str[1] ==
'X'))) {
131 tab =
"0123456789abcdef";
140 if (*str ==
'.')
break;
142 c = memchr(tab, tolower((
uint8_t)*str), base);
199 p = strchr(
name,
'[');
205 q = strchr(p + 1,
']');
225 if ((length == 0) || (length > 255)) {
233 if (strcmp(
name,
"octets") == 0) {
236 }
else if (strcmp(
name,
"string") == 0) {
239 }
else if (strcmp(
name,
"struct") == 0) {
242 }
else if (strcmp(
name,
"bit") == 0) {
248 (*da_p)->flags.extra = 1;
253 }
else if (length <= 8) {
255 }
else if (length <= 16) {
257 }
else if (length <= 32) {
259 }
else if (length <= 56) {
273 (*da_p)->flags.flag_byte_offset = length;
276 fr_strerror_const(
"Only 'octets', 'string', 'struct', or 'bit' types can have a 'length' parameter");
280 (*da_p)->flags.is_known_width =
true;
281 (*da_p)->flags.length = length;
302 #define FLAG_FUNC(_name) \
303 static int dict_flag_##_name(fr_dict_attr_t **da_p, UNUSED char const *value, UNUSED fr_dict_flag_parser_rule_t const *rules)\
305 (*da_p)->flags._name = 1; \
314 fr_strerror_const(
"'clone=...' references can only be used for 'tlv' and 'struct' types");
356 fr_strerror_const(
"The 'key' flag can only be used for attributes of type 'uint8', 'uint16', or 'uint32'");
360 if (da->flags.extra) {
375 if (strcmp(
value,
"uint8") == 0) {
379 }
else if (strcmp(
value,
"uint16") == 0) {
387 da->flags.type_size = 0;
403 fr_strerror_const(
"The 'offset' flag can only be used in combination with 'length=uint8' or 'length=uint16'");
407 offset = atoi(
value);
408 if ((offset <= 0) || (offset > 255)) {
412 da->flags.type_size = offset;
428 fr_strerror_const(
"The 'precision' flag can only be used with data types 'date' or 'time'");
437 da->flags.flag_time_res = precision;
446 if (da->flags.extra) {
466 da->flags.secret = 1;
469 fr_strerror_const(
"The 'secret' flag can only be used with data types 'string' or 'octets'");
487 fr_strerror_const(
"The 'subtype' flag can only be used with data types 'date' or 'time'");
506 da->flags.length = 2;
510 da->flags.is_unsigned =
true;
511 da->flags.length = 2;
516 da->flags.length = 4;
520 da->flags.is_unsigned =
true;
521 da->flags.length = 4;
526 da->flags.length = 8;
530 da->flags.is_unsigned =
true;
531 da->flags.length = 8;
547 {
L(
"array"), { .func = dict_flag_array } },
549 {
L(
"counter"), { .func = dict_flag_counter } },
551 {
L(
"internal"), { .func = dict_flag_internal } },
560 static size_t dict_common_flags_len =
NUM_ELEMENTS(dict_common_flags);
562 char *p, *
next = NULL;
569 for (p =
name; p && *p !=
'\0' ; p =
next) {
611 if (!((ctx->
dict->proto->attr.flags.table &&
612 fr_dict_attr_flag_to_parser(&parser, ctx->
dict->proto->attr.flags.table,
613 ctx->
dict->proto->attr.flags.table_len, key, NULL)) ||
614 fr_dict_attr_flag_to_parser(&parser, dict_common_flags, dict_common_flags_len, key, NULL))) {
700 if (strncmp(argv[0],
"Attr-", 5) == 0) {
708 if (argv[1][0] ==
'.') {
714 ref_namespace = ctx->
dict->root;
736 static inline CC_HINT(always_inline)
739 da->filename = dctx->stack[dctx->stack_depth].filename;
740 da->line = dctx->stack[dctx->stack_depth].line;
828 if (!da->parent)
return 1;
836 found = dup_name ? dup_name : dup_num;
856 fr_strerror_printf(
"Duplicate attribute name '%s' in namespace '%s'. Originally defined %s[%u]",
857 da->name, da->parent->name, dup_name->filename, dup_name->line);
861 fr_strerror_printf(
"Duplicate attribute number %u in parent '%s'. Originally defined %s[%u]",
862 da->attr, da->parent->name, dup_num->filename, dup_num->line);
886 char const *type_name,
char *flag_name,
894 if (strncmp(
name,
"Attr-", 5) == 0) {
904 if (
unlikely(da == NULL))
return -1;
910 memcpy(&da->flags, base_flags,
sizeof(da->flags));
928 if (flag_name)
if (dict_process_flag_field(ctx, flag_name, &da) < 0)
goto error;
939 bool set_relative_attr;
947 if ((argc < 3) || (argc > 4)) {
953 (argc > 3) ? argv[3] : NULL, base_flags) < 0) {
967 if (argv[1][0] !=
'.') {
974 if (strchr(argv[1],
'.') == 0) {
982 if (slen <= 0)
goto error;
999 if (slen <= 0)
goto error;
1001 set_relative_attr =
false;
1017 fr_strerror_printf(
"Member %s of ATTRIBUTE %s type 'struct' MUST use the \"MEMBER\" keyword",
1029 #ifdef WITH_DICTIONARY_WARNINGS
1034 if (!vendor && (attr < 256) &&
1035 !strstr(fn,
"rfc") && !strstr(fn,
"illegal")) {
1036 fprintf(stderr,
"WARNING: Illegal attribute %s in %s\n",
1041 #ifdef STATIC_ANALYZER
1042 if (!ctx->
dict)
return -1;
1080 if (
parent->flags.is_root) ctx->
dict->vsa_parent = attr;
1120 if ((argc < 2) || (argc > 3)) {
1126 (argc > 2) ? argv[2] : NULL, base_flags) < 0) {
1158 fr_strerror_printf(
"Member %s of parent %s type 'struct' MUST use the \"MEMBER\" keyword",
1163 #ifdef STATIC_ANALYZER
1164 if (!ctx->
dict)
goto error;
1171 da->flags.name_only =
true;
1244 if (strncmp(argv[0],
"Attr-", 5) == 0) {
1254 if (
unlikely(da == NULL))
return -1;
1260 memcpy(&da->flags, base_flags,
sizeof(da->flags));
1262 da->flags.name_only =
true;
1263 da->flags.internal =
true;
1265 flags.is_enum =
true;
1304 #ifdef STATIC_ANALYZER
1305 if (!ctx->
dict)
goto error;
1330 char const *dir_name,
char const *filename,
1331 char const *src_file,
int src_line);
1345 if ((argv[0][8] !=
'\0') && ((argv[0][8] !=
'-') || (argv[0][9] !=
'\0'))) {
1360 if (strncmp(argv[1],
"${dictdir}/", 11) != 0) {
1366 if ((rcode == -2) && (argv[0][8] ==
'-')) {
1409 if ((argc < 2) || (argc > 3)) {
1420 (argc > 2) ? argv[2] : NULL, base_flags) < 0) {
1424 #ifdef STATIC_ANALYZER
1425 if (!ctx->
dict)
goto error;
1448 if (previous && previous->flags.extra && (previous->flags.subtype ==
FLAG_BIT_FIELD)) {
1455 da->flags.flag_byte_offset = (da->flags.length + previous->flags.flag_byte_offset) & 0x07;
1458 if (previous->flags.flag_byte_offset != 0) {
1474 fr_strerror_printf(
"Cannot add MEMBER to 'struct' %s after a variable sized member %s",
1501 fr_strerror_printf(
"'struct' %s has a 'length' field %s, and cannot end with a TLV %s",
1557 if (!da->flags.is_known_width) {
1558 fr_strerror_printf(
"'struct' %s has fixed size %u, but member %s is of unknown size",
1573 fr_strerror_printf(
"'struct' %s has fixed size %u, but member %s overflows that length",
1659 argv[0], strlen(argv[0]),
1660 argv[1], strlen(argv[1]),
1661 argv[2], strlen(argv[2]),
parent) < 0) {
1678 argv[2], strlen(argv[2]),
1713 if (strcmp(p,
"internal") == 0) {
1736 char *key_attr = argv[1];
1737 char *
name = argv[0];
1740 if ((argc < 3) || (argc > 4)) {
1795 if (
unlikely(da == NULL))
return -1;
1809 if (dict_process_flag_field(ctx, argv[3], &da) < 0)
goto error;
1817 attr =
value.vb_uint8;
1821 attr =
value.vb_uint16;
1825 attr =
value.vb_uint32;
1893 bool continuation =
false;
1902 if ((strlen(p) < 3) ||
1906 (p[3] && (p[3] !=
','))) {
1912 type = (int)(p[0] -
'0');
1913 length = (int)(p[2] -
'0');
1920 if ((length != 0) && (length != 1) && (length != 2)) {
1932 if ((p[4] !=
'c') ||
1938 continuation =
true;
1940 if ((
type != 1) || (length != 1)) {
1948 *pcontinuation = continuation;
1959 unsigned int type_size = 0;
1962 bool require_dl =
false;
1963 bool string_based =
false;
1965 if ((argc < 2) || (argc > 3)) {
1966 fr_strerror_const(
"Missing arguments after PROTOCOL. Expected PROTOCOL <num> <name>");
1999 if (strcmp(argv[2],
"verify=lib") == 0) {
2004 if (strcmp(argv[2],
"format=string") == 0) {
2006 string_based =
true;
2011 fr_strerror_printf(
"Invalid format for PROTOCOL. Expected 'format=', got '%s'", argv[2]);
2016 type_size = strtoul(p, &q, 10);
2017 if (q != (p + strlen(p))) {
2029 #ifdef STATIC_ANALYZER
2030 if (!
dict->root)
return -1;
2040 #ifdef STATIC_ANALYZER
2041 if (!
dict->root || !
dict->root->name || !argv[0])
return -1;
2046 dict->root->name, argv[0],
dict->root->attr);
2055 if (type_size && (
dict->root->flags.type_size != type_size)) {
2056 fr_strerror_printf(
"Conflicting flags for PROTOCOL \"%s\" (current %d versus new %d)",
2057 dict->root->name,
dict->root->flags.type_size, type_size);
2084 dict->string_based = string_based;
2086 mutable->flags.type_size =
dict->proto->default_type_size;
2087 mutable->flags.length =
dict->proto->default_type_length;
2089 mutable->flags.type_size = type_size;
2090 mutable->flags.length = 1;
2103 bool continuation =
false;
2107 if ((argc < 2) || (argc > 3)) {
2140 mutable->type =
type;
2141 mutable->length = length;
2142 mutable->continuation = continuation;
2174 if (
unlikely(*filename_out == NULL))
goto oom;
2192 if (strcmp(
file->filename, filename) == 0)
return true;
2214 char const *dir_name,
char const *filename,
2215 char const *src_file,
int src_line)
2218 char dir[256], fn[256];
2222 bool was_member =
false;
2224 struct stat statbuf;
2236 if ((strlen(dir_name) + 3 + strlen(filename)) >
sizeof(dir)) {
2248 if (!FR_DIR_IS_RELATIVE(filename)) {
2249 strlcpy(dir, filename,
sizeof(dir));
2250 p = strrchr(dir, FR_DIR_SEP);
2254 strlcat(dir,
"/",
sizeof(dir));
2257 strlcpy(fn, filename,
sizeof(fn));
2259 strlcpy(dir, dir_name,
sizeof(dir));
2260 p = strrchr(dir, FR_DIR_SEP);
2262 if (p[1])
strlcat(dir,
"/",
sizeof(dir));
2264 strlcat(dir,
"/",
sizeof(dir));
2266 strlcat(dir, filename,
sizeof(dir));
2267 p = strrchr(dir, FR_DIR_SEP);
2271 strlcat(dir,
"/",
sizeof(dir));
2274 p = strrchr(filename, FR_DIR_SEP);
2276 snprintf(fn,
sizeof(fn),
"%s%s", dir, p);
2278 snprintf(fn,
sizeof(fn),
"%s%s", dir, filename);
2287 fr_strerror_printf(
"ERROR - we have a recursive $INCLUDE or load of dictionary %s", fn);
2292 if ((fp = fopen(fn,
"r")) == NULL) {
2306 if (fstat(fileno(fp), &statbuf) < 0) {
2314 if (!S_ISREG(statbuf.st_mode)) {
2326 "Refusing to start due to insecure configuration", fn);
2341 memset(&base_flags, 0,
sizeof(base_flags));
2343 while (fgets(buf,
sizeof(buf), fp) != NULL) {
2360 p = strchr(buf,
'#');
2364 if (argc == 0)
continue;
2392 &base_flags) == -1)
goto error;
2414 if (da->flags.length &&
2416 fr_strerror_printf(
"MEMBERs of %s struct[%u] do not exactly fill the fixed-size structure",
2417 da->name, da->flags.length);
2443 argv + 1, argc - 1) == -1)
goto error;
2453 &base_flags) == -1)
goto error;
2463 &base_flags) == -1)
goto error;
2473 &base_flags) == -1)
goto error;
2541 if (
strcasecmp(argv[0],
"BEGIN-PROTOCOL") == 0) {
2583 found->loading =
true;
2595 if (
strcasecmp(argv[0],
"END-PROTOCOL") == 0) {
2609 if (found != ctx->
dict) {
2611 argv[1], found->root->name);
2734 if (
strcasecmp(argv[0],
"BEGIN-VENDOR") == 0) {
2759 if (strncmp(argv[2],
"parent=", 7) != 0) {
2773 "Attribute '%s' should be 'vsa' but is '%s'", p,
2780 }
else if (ctx->
dict->vsa_parent) {
2791 }
else if (ctx->
dict->string_based) {
2792 vsa_da = ctx->
dict->root;
2796 ctx->
dict->root->name);
2813 memset(&flags, 0,
sizeof(flags));
2816 flags.
length = ctx->
dict->proto->default_type_length;
2826 (vsa_da->parent->flags.is_root)) {
2861 if (
strcasecmp(argv[0],
"END-VENDOR") == 0) {
2922 char const *dir_name,
char const *filename,
2923 char const *src_file,
int src_line)
2928 memset(&ctx, 0,
sizeof(ctx));
2969 char *dict_path = NULL;
2977 fr_strerror_const(
"fr_dict_global_ctx_init() must be called before loading dictionary files");
2990 dict_path = dict_subdir ?
3011 TALLOC_FREE(dict_path);
3078 box.vb_uint8 = p->
value;
3105 char *dict_dir = NULL;
3112 fr_strerror_const(
"fr_dict_global_ctx_init() must be called before loading dictionary files");
3117 fr_strerror_const(
"Internal dictionary must be initialised before loading protocol dictionaries");
3148 dict->loaded =
true;
3180 fr_strerror_printf(
"Dictionary \"%s\" missing \"BEGIN-PROTOCOL %s\" declaration", dict_dir, proto_name);
3187 dict->loaded =
true;
3188 if (
dict->proto &&
dict->proto->init) {
3189 if (
dict->proto->init() < 0)
goto error;
3191 dict->loading =
false;
3217 fr_strerror_printf(
"fr_dict_global_ctx_init() must be called before loading dictionary files");
3225 if (!
dict)
return NULL;
3256 if (!
dict->vendors_by_name) {
3257 fr_strerror_printf(
"%s: Must initialise dictionary before calling fr_dict_read()", __FUNCTION__);
3278 if (argc == 0)
return 0;
3281 memset(&ctx, 0,
sizeof(ctx));
3299 argv[1],
dict->root->name);
3303 if (ret < 0)
goto error;
3305 }
else if (
strcasecmp(argv[0],
"ATTRIBUTE") == 0) {
3308 memset(&base_flags, 0,
sizeof(base_flags));
3311 argv + 1, argc - 1, &base_flags);
3312 if (ret < 0)
goto error;
3313 }
else if (
strcasecmp(argv[0],
"VENDOR") == 0) {
3315 if (ret < 0)
goto error;
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define L(_str)
Helper for initialising arrays of string literals.
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
size_t type
Length of type data.
fr_dict_attr_t const * fr_dict_attr_by_oid(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *oid))
Resolve an attribute using an OID string.
char const * fr_dict_global_ctx_dir(void)
int fr_dict_attr_add_initialised(fr_dict_attr_t *da)
A variant of fr_dict_attr_t that allows a pre-allocated, populated fr_dict_attr_t to be added.
@ FLAG_LENGTH_UINT8
string / octets type is prefixed by uint8 of length
@ FLAG_LENGTH_UINT16
string / octets type is prefixed by uint16 of length
@ FLAG_KEY_FIELD
this is a key field for a subsequent struct
@ FLAG_BIT_FIELD
bit field inside of a struct
fr_slen_t fr_dict_enum_name_from_substr(fr_sbuff_t *out, fr_sbuff_parse_error_t *err, fr_sbuff_t *in, fr_sbuff_term_t const *tt)
Extract an enumeration name from a string.
int fr_dict_enum_add_name(fr_dict_attr_t *da, char const *name, fr_value_box_t const *value, bool coerce, bool replace)
Add a value name.
char const * name
Vendor name.
fr_dict_attr_t * fr_dict_attr_unconst(fr_dict_attr_t const *da)
Coerce to non-const.
fr_dict_vendor_t const * fr_dict_vendor_by_num(fr_dict_t const *dict, uint32_t vendor_pen)
Look up a vendor by its PEN.
unsigned int is_root
Is root of a dictionary.
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *attr))
Locate a fr_dict_attr_t by its name.
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)
Find a common ancestor that two TLV type attributes share.
fr_dict_flag_parse_func_t func
Custom parsing function to convert a flag value string to a C type value.
unsigned int internal
Internal attribute, should not be received in protocol packets, should not be encoded.
fr_slen_t fr_dict_attr_by_oid_legacy(fr_dict_t const *dict, fr_dict_attr_t const **parent, unsigned int *attr, char const *oid)
Get the leaf attribute of an OID string.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
uint32_t pen
Private enterprise number.
#define da_is_length_field(_da)
uint8_t type_size
For TLV2 and root attributes.
size_t length
Length of length data.
@ FR_DICT_ATTR_EXT_REF
Attribute references another attribute and/or dictionary.
bool needs_value
This parsing flag must have a value. Else we error.
fr_dict_attr_t const * fr_dict_attr_child_by_num(fr_dict_attr_t const *parent, unsigned int attr)
Check if a child attribute exists in a parent using an attribute number.
fr_dict_vendor_t const * fr_dict_vendor_by_name(fr_dict_t const *dict, char const *name)
Look up a vendor by its name.
#define fr_dict_attr_is_key_field(_da)
static int8_t fr_dict_attr_cmp_fields(const fr_dict_attr_t *a, const fr_dict_attr_t *b)
Compare two dictionary attributes by their contents.
uint8_t length
length of the attribute
Values of the encryption flags.
Protocol specific custom flag definitnion.
#define fr_dict_attr_ref_type(_type)
static void * fr_dict_attr_ext(fr_dict_attr_t const *da, fr_dict_attr_ext_t ext)
fr_dict_attr_ref_type_t type
The state of the reference.
#define fr_dict_attr_ref_is_unresolved(_type)
@ FR_DICT_ATTR_REF_ENUM
The attribute is an enumeration value.
@ FR_DICT_ATTR_REF_ALIAS
The attribute is an alias for another attribute.
@ FR_DICT_ATTR_REF_CLONE
The attribute is a "copy" of another attribute.
Attribute extension - Holds a reference to an attribute in another dictionary.
static int dict_attr_ref_aunresolved(fr_dict_attr_t **da_p, char const *ref, fr_dict_attr_ref_type_t type)
int dict_fixup_apply(dict_fixup_ctx_t *fctx)
Apply all outstanding fixes to a set of dictionaries.
int dict_fixup_enumv_enqueue(dict_fixup_ctx_t *fctx, char const *filename, int line, char const *attr, size_t attr_len, char const *name, size_t name_len, char const *value, size_t value_len, fr_dict_attr_t const *parent)
Add an enumeration value to an attribute which has not yet been defined.
int dict_fixup_alias_enqueue(dict_fixup_ctx_t *fctx, char const *filename, int line, fr_dict_attr_t *alias_parent, char const *alias, fr_dict_attr_t *ref_parent, char const *ref)
Resolve a group reference.
int dict_fixup_clone_enqueue(dict_fixup_ctx_t *fctx, fr_dict_attr_t *da, char const *ref)
Clone one area of a tree into another.
int dict_fixup_init(TALLOC_CTX *ctx, dict_fixup_ctx_t *fctx)
Initialise a fixup ctx.
int dict_fixup_clone_enum_enqueue(dict_fixup_ctx_t *fctx, fr_dict_attr_t *da, char const *ref)
Clone enumeration values from one attribute to another.
fr_dict_attr_t const * dict_protocol_reference(fr_dict_attr_t const *root, char const *ref)
Resolve a ref= or copy= value to a dictionary.
int dict_fixup_vsa_enqueue(dict_fixup_ctx_t *fctx, fr_dict_attr_t *da)
Push a fixup for a VSA.
int dict_fixup_clone(fr_dict_attr_t **dst_p, fr_dict_attr_t const *src)
Clone a dictionary attribute from a ref.
int dict_fixup_group_enqueue(dict_fixup_ctx_t *fctx, fr_dict_attr_t *da, char const *ref)
Resolve a group reference.
TALLOC_CTX * pool
Temporary pool for fixups, reduces holes.
int dict_attr_enum_add_name(fr_dict_attr_t *da, char const *name, fr_value_box_t const *value, bool coerce, bool replace, fr_dict_attr_t const *child_struct)
int dict_attr_type_init(fr_dict_attr_t **da_p, fr_type_t type)
Initialise type specific fields within the dictionary attribute.
int dict_attr_parent_init(fr_dict_attr_t **da_p, fr_dict_attr_t const *parent)
Initialise fields which depend on a parent attribute.
#define dict_attr_alloc(_ctx, _parent, _name, _attr, _type, _args)
#define INTERNAL_IF_NULL(_dict, _ret)
Set the internal dictionary if none was provided.
fr_dict_t * dict_by_protocol_num(unsigned int num)
Internal version of fr_dict_by_protocol_num.
int dict_attr_add_to_namespace(fr_dict_attr_t const *parent, fr_dict_attr_t *da)
Add an attribute to the name table for an attribute.
fr_dict_t * dict_by_protocol_name(char const *name)
Internal version of fr_dict_by_protocol_name.
int dict_attr_child_add(fr_dict_attr_t *parent, fr_dict_attr_t *child)
Add a child to a parent.
fr_dict_t * dict_alloc(TALLOC_CTX *ctx)
Allocate a new dictionary.
int dict_vendor_add(fr_dict_t *dict, char const *name, unsigned int num)
Add a vendor to the dictionary.
int dict_attr_alias_add(fr_dict_attr_t const *parent, char const *alias, fr_dict_attr_t const *ref)
Add an alias to an existing attribute.
int dict_attr_finalise(fr_dict_attr_t **da_p, char const *name)
Set remaining fields in a dictionary attribute before insertion.
fr_dict_attr_t * dict_attr_child_by_num(fr_dict_attr_t const *parent, unsigned int attr)
Internal version of fr_dict_attr_child_by_num.
int dict_attr_num_init(fr_dict_attr_t *da, unsigned int num)
Set the attribute number (if any)
int dict_attr_num_init_name_only(fr_dict_attr_t *da)
Set the attribute number (if any)
int dict_dlopen(fr_dict_t *dict, char const *name)
fr_dict_t * internal
Magic internal dictionary.
int dict_dependent_add(fr_dict_t *dict, char const *dependent)
Record a new dependency on a dictionary.
fr_dict_attr_t * dict_attr_alloc_null(TALLOC_CTX *ctx, fr_dict_protocol_t const *dict)
Partial initialisation functions.
#define dict_attr_alloc_root(_ctx, _dict, _name, _attr, _args)
int dict_protocol_add(fr_dict_t *dict)
Add a protocol to the global protocol table.
fr_dict_gctx_t * dict_gctx
Top level structure containing global dictionary state.
bool perm_check
Whether we should check dictionary file permissions as they're loaded.
fr_dict_attr_t * dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *name)
Optional arguments for initialising/allocating attributes.
Entry in the filename list of files associated with this dictionary.
static fr_dict_attr_t const * dict_gctx_unwind(dict_tokenize_ctx_t *ctx)
static int dict_read_process_common(dict_tokenize_ctx_t *ctx, fr_dict_attr_t **da_p, char const *name, char const *type_name, char *flag_name, fr_dict_attr_flags_t const *base_flags)
static bool dict_filename_loaded(fr_dict_t *dict, char const *filename)
See if we have already loaded the file,.
dict_nest_t nest
for manual vs automatic begin / end things
fr_dict_attr_t * value_attr
Cache of last attribute to speed up value processing.
static int dict_set_value_attr(dict_tokenize_ctx_t *ctx, fr_dict_attr_t *da)
dict_tokenize_frame_t stack[MAX_STACK]
stack of attributes to track
int member_num
structure member numbers
static int dict_read_process_define(dict_tokenize_ctx_t *ctx, char **argv, int argc, fr_dict_attr_flags_t const *base_flags)
static int dict_attr_allow_dup(fr_dict_attr_t const *da)
Check if this definition is a duplicate, and if it is, whether we should skip it error out.
static int dict_gctx_push(dict_tokenize_ctx_t *ctx, fr_dict_attr_t const *da)
static int dict_flag_ref(fr_dict_attr_t **da_p, char const *value, UNUSED fr_dict_flag_parser_rule_t const *rule)
static int dict_flag_precision(fr_dict_attr_t **da_p, char const *value, UNUSED fr_dict_flag_parser_rule_t const *rule)
fr_dict_t * fr_dict_alloc(char const *proto_name, unsigned int proto_number)
ssize_t struct_size
size of the struct.
fr_dict_attr_t const * struct_is_closed
no more members are allowed
int fr_dict_protocol_afrom_file(fr_dict_t **out, char const *proto_name, char const *proto_dir, char const *dependent)
(Re)-initialize a protocol dictionary
int fr_dict_str_to_argv(char *str, char **argv, int max_argc)
static int dict_read_sscanf_i(unsigned int *pvalue, char const *str)
static int dict_read_process_attribute(dict_tokenize_ctx_t *ctx, char **argv, int argc, fr_dict_attr_flags_t const *base_flags)
static int dict_process_type_field(dict_tokenize_ctx_t *ctx, char const *name, fr_dict_attr_t **da_p)
static int dict_read_parse_format(char const *format, int *ptype, int *plength, bool *pcontinuation)
static dict_tokenize_frame_t const * dict_gctx_find_frame(dict_tokenize_ctx_t *ctx, dict_nest_t nest)
static int dict_from_file(fr_dict_t *dict, char const *dir_name, char const *filename, char const *src_file, int src_line)
fr_dict_attr_t const * da
the da we care about
static int _dict_from_file(dict_tokenize_ctx_t *ctx, char const *dir_name, char const *filename, char const *src_file, int src_line)
Parse a dictionary file.
fr_dict_t * dict
The dictionary before the current BEGIN-PROTOCOL block.
static int dict_filename_add(char **filename_out, fr_dict_t *dict, char const *filename)
Maintain a linked list of filenames which we've seen loading this dictionary.
#define FLAG_FUNC(_name)
Define a flag setting function, which sets one bit in a fr_dict_attr_flags_t.
char * filename
name of the file we're reading
static int dict_read_process_value(dict_tokenize_ctx_t *ctx, char **argv, int argc)
Process a value alias.
static int dict_flag_offset(fr_dict_attr_t **da_p, char const *value, UNUSED fr_dict_flag_parser_rule_t const *rule)
fr_dict_t * dict
Protocol dictionary we're inserting attributes into.
static int dict_read_process_struct(dict_tokenize_ctx_t *ctx, char **argv, int argc)
Process a STRUCT name attr value.
fr_dict_attr_t const * relative_attr
for ".82" instead of "1.2.3.82".
static int dict_flag_clone(fr_dict_attr_t **da_p, char const *value, UNUSED fr_dict_flag_parser_rule_t const *rules)
int line
line number of this file
static int dict_flag_enum(fr_dict_attr_t **da_p, char const *value, UNUSED fr_dict_flag_parser_rule_t const *rule)
static int dict_finalise(dict_tokenize_ctx_t *ctx)
static int dict_read_process_enum(dict_tokenize_ctx_t *ctx, char **argv, int argc, fr_dict_attr_flags_t const *base_flags)
static int dict_flag_length(fr_dict_attr_t **da_p, char const *value, UNUSED fr_dict_flag_parser_rule_t const *rule)
int fr_dict_read(fr_dict_t *dict, char const *dir, char const *filename)
Read supplementary attribute definitions into an existing dictionary.
static int dict_read_process_vendor(fr_dict_t *dict, char **argv, int argc)
int fr_dict_parse_str(fr_dict_t *dict, char *buf, fr_dict_attr_t const *parent)
static int dict_read_process_include(dict_tokenize_ctx_t *ctx, char **argv, int argc, char const *dir, char *fn, int line)
static int dict_flag_subtype(fr_dict_attr_t **da_p, char const *value, UNUSED fr_dict_flag_parser_rule_t const *rule)
static int dict_flag_key(fr_dict_attr_t **da_p, UNUSED char const *value, UNUSED fr_dict_flag_parser_rule_t const *rule)
static int dict_read_process_alias(dict_tokenize_ctx_t *ctx, char **argv, int argc)
int fr_dict_internal_afrom_file(fr_dict_t **out, char const *dict_subdir, char const *dependent)
(Re-)Initialize the special internal dictionary
static int dict_attr_add_or_fixup(dict_fixup_ctx_t *fixup, fr_dict_attr_t **da_p)
Add an attribute to the dictionary, or add it to a list of attributes to clone later.
#define CURRENT_FRAME(_dctx)
static void dict_attr_location_set(dict_tokenize_ctx_t *dctx, fr_dict_attr_t *da)
static int dict_read_process_member(dict_tokenize_ctx_t *ctx, char **argv, int argc, fr_dict_attr_flags_t const *base_flags)
static TABLE_TYPE_NAME_FUNC_RPTR(table_sorted_value_by_str, fr_dict_flag_parser_t const *, fr_dict_attr_flag_to_parser, fr_dict_flag_parser_rule_t const *, fr_dict_flag_parser_rule_t const *)
A lookup function for dictionary attribute flags.
static int dict_read_process_protocol(char **argv, int argc)
Register the specified dictionary as a protocol dictionary.
static int dict_flag_secret(fr_dict_attr_t **da_p, UNUSED char const *value, UNUSED fr_dict_flag_parser_rule_t const *rule)
#define MAX_STACK
Parser context for dict_from_file.
static int dict_read_process_flags(UNUSED fr_dict_t *dict, char **argv, int argc, fr_dict_attr_flags_t *base_flags)
int stack_depth
points to the last used stack frame
static int dict_root_set(fr_dict_t *dict, char const *name, unsigned int proto_number)
Set a new root dictionary attribute.
static void * fr_dlist_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
static void * fr_dlist_head(fr_dlist_head_t const *list_head)
Return the HEAD item of a list or NULL if the list is empty.
static int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
char const * fr_cwd_strip(char const *filename)
Intended to be used in logging functions to make output more readable.
static char * stack[MAX_STACK]
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_INT64
64 Bit signed integer.
@ FR_TYPE_INT16
16 Bit signed integer.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_STRUCT
like TLV, but without T or L, and fixed-width children
@ FR_TYPE_INT32
32 Bit signed integer.
@ FR_TYPE_VENDOR
Attribute that represents a vendor in the attribute tree.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_VSA
Vendor-Specific, for RADIUS attribute 26.
@ FR_TYPE_OCTETS
Raw octets.
@ FR_TYPE_GROUP
A grouping of other attributes.
static size_t array[MY_ARRAY_SIZE]
int strncasecmp(char *s1, char *s2, int n)
int strcasecmp(char *s1, char *s2)
#define FR_SBUFF_IN(_start, _len_or_end)
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
fr_aka_sim_id_type_t type
size_t strlcat(char *dst, char const *src, size_t siz)
size_t strlcpy(char *dst, char const *src, size_t siz)
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
char const * str
Literal string.
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
static void const * table_sorted_value_by_str(void const *table, size_t table_len, size_t element_size, char const *name)
Convert a string to a value using a lexicographically sorted table.
fr_table_elem_name_t name
An element in an arbitrarily ordered array of name to num mappings.
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
fr_table_num_ordered_t const fr_time_precision_table[]
#define FR_DICTIONARY_FILE
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
#define fr_strerror_const_push(_msg)
#define fr_strerror_const(_msg)
fr_table_num_ordered_t const fr_type_table[]
Map data types to names representing those types.
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
#define fr_type_is_null(_x)
#define fr_type_is_leaf(_x)
static fr_type_t fr_type_from_str(char const *type)
Return the constant value representing a type.
ssize_t fr_value_box_from_str(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, char const *in, size_t inlen, fr_sbuff_unescape_rules_t const *erules, bool tainted)
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
#define FR_VALUE_BOX_INITIALISER_NULL(_vb)
A static initialiser for stack/globally allocated boxes.
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
int format(printf, 5, 0))
static size_t char ** out