26RCSIDH(cf_parse_h,
"$Id: b7a3496ac94f0ac08ffcea07762945608cb05e29 $")
35#include <freeradius-devel/util/rb.h>
36#include <freeradius-devel/util/table.h>
37#include <freeradius-devel/util/value.h>
38#include <freeradius-devel/server/cf_util.h>
44#ifdef HAVE_BUILTIN_CHOOSE_EXPR
45typedef void _mismatch_abinary_m;
46typedef void _mismatch_abinary;
47typedef void _mismatch_bool_m;
48typedef void _mismatch_bool;
49typedef void _mismatch_char_m;
50typedef void _mismatch_char;
51typedef void _mismatch_double_m;
52typedef void _mismatch_double;
53typedef void _mismatch_ethernet_m;
54typedef void _mismatch_ethernet;
55typedef void _mismatch_float_m;
56typedef void _mismatch_float;
57typedef void _mismatch_fripaddr_m;
58typedef void _mismatch_fripaddr;
59typedef void _mismatch_ifid_m;
60typedef void _mismatch_ifid;
61typedef void _mismatch_int32_m;
62typedef void _mismatch_int32;
63typedef void _mismatch_size_m;
64typedef void _mismatch_size;
65typedef void _mismatch_time_delta_m;
66typedef void _mismatch_time_delta;
67typedef void _mismatch_time_m;
68typedef void _mismatch_time;
69typedef void _mismatch_uint16_m;
70typedef void _mismatch_uint16;
71typedef void _mismatch_uint32_m;
72typedef void _mismatch_uint32;
73typedef void _mismatch_uint64_m;
74typedef void _mismatch_uint64;
75typedef void _mismatch_uint8_m_m;
76typedef void _mismatch_uint8_m;
77typedef void _mismatch_uint8;
78typedef void _mismatch_void_m;
79typedef void _mismatch_void;
80typedef void _mismatch_tmpl_m;
81typedef void _mismatch_vp_tmpl;
84typedef void _mismatch_default;
85typedef void conf_type_mismatch;
86typedef void conf_type_invalid;
103# define FR_CONF_FLAG_CHECK(_t, _f, _ct, _p) \
104__builtin_choose_expr(((_f) & CONF_FLAG_SUBSECTION), _p, \
105__builtin_choose_expr((_t == FR_TYPE_VOID), _p, \
106__builtin_choose_expr((_t == FR_TYPE_SIZE) && !((_f) & CONF_FLAG_MULTI), \
107 __builtin_choose_expr(IS_COMPATIBLE((_ct), size_t *), _p, (_mismatch_size) 0), \
108__builtin_choose_expr((_t == FR_TYPE_SIZE) && ((_f) & CONF_FLAG_MULTI), \
109 __builtin_choose_expr(IS_COMPATIBLE((_ct), size_t **), _p, (_mismatch_size_m) 0), \
111 fr_time_t * : __builtin_choose_expr((_t == FR_TYPE_DATE) && !((_f) & CONF_FLAG_MULTI), \
112 _p, (_mismatch_time) 0), \
113 fr_time_t ** : __builtin_choose_expr((_t == FR_TYPE_DATE) && ((_f) & CONF_FLAG_MULTI), \
114 _p, (_mismatch_time_m) 0), \
115 fr_ethernet_t * : __builtin_choose_expr((_t == FR_TYPE_ETHERNET) && !((_f) & CONF_FLAG_MULTI), \
116 _p, (_mismatch_ethernet) 0), \
117 fr_ethernet_t ** : __builtin_choose_expr((_t == FR_TYPE_ETHERNET) && ((_f) & CONF_FLAG_MULTI), \
118 _p, (_mismatch_ethernet_m) 0), \
119 fr_ifid_t * : __builtin_choose_expr((_t == FR_TYPE_IFID) && !((_f) & CONF_FLAG_MULTI), \
120 _p, (_mismatch_ifid) 0), \
121 fr_ifid_t ** : __builtin_choose_expr((_t == FR_TYPE_IFID) && ((_f) & CONF_FLAG_MULTI), \
122 _p, (_mismatch_ifid_m) 0), \
123 fr_time_delta_t *: __builtin_choose_expr((_t == FR_TYPE_TIME_DELTA) && !((_f) & CONF_FLAG_MULTI), \
124 _p, (_mismatch_time_delta) 0), \
125 fr_time_delta_t **: __builtin_choose_expr((_t == FR_TYPE_TIME_DELTA) && ((_f) & CONF_FLAG_MULTI), \
126 _p, (_mismatch_time_delta_m) 0), \
127 tmpl_t ** : __builtin_choose_expr(((_f) & CONF_FLAG_TMPL) && !((_f) & CONF_FLAG_MULTI), \
128 _p, (_mismatch_vp_tmpl) 0), \
129 tmpl_t *** : __builtin_choose_expr(((_f) & CONF_FLAG_TMPL) && ((_f) & CONF_FLAG_MULTI), \
130 _p, (_mismatch_tmpl_m) 0), \
131 char const ** : __builtin_choose_expr((_t == FR_TYPE_STRING) && !((_f) & CONF_FLAG_MULTI), \
132 _p, (_mismatch_char) 0), \
133 char const *** : __builtin_choose_expr((_t == FR_TYPE_STRING) && ((_f) & CONF_FLAG_MULTI), \
134 _p, (_mismatch_char_m) 0), \
135 bool * : __builtin_choose_expr((_t == FR_TYPE_BOOL) && !((_f) & CONF_FLAG_MULTI), \
136 _p, (_mismatch_bool) 0), \
137 bool ** : __builtin_choose_expr((_t == FR_TYPE_BOOL) && ((_f) & CONF_FLAG_MULTI), \
138 _p, (_mismatch_bool_m) 0), \
139 uint32_t * : __builtin_choose_expr((_t == FR_TYPE_UINT32) && !((_f) & CONF_FLAG_MULTI), \
140 _p, (_mismatch_uint32) 0), \
141 uint32_t ** : __builtin_choose_expr((_t == FR_TYPE_UINT32) && ((_f) & CONF_FLAG_MULTI), \
142 _p, (_mismatch_uint32_m) 0), \
143 fr_ipaddr_t * : __builtin_choose_expr(((_t == FR_TYPE_IPV4_ADDR) || \
144 (_t == FR_TYPE_IPV4_PREFIX) || \
145 (_t == FR_TYPE_IPV6_ADDR) || \
146 (_t == FR_TYPE_IPV6_PREFIX) || \
147 (_t == FR_TYPE_COMBO_IP_PREFIX) || \
148 (_t == FR_TYPE_COMBO_IP_ADDR)) || \
149 !((_f) & CONF_FLAG_MULTI), _p, (_mismatch_fripaddr) 0), \
150 fr_ipaddr_t ** : __builtin_choose_expr(((_t == FR_TYPE_IPV4_ADDR) || \
151 (_t == FR_TYPE_IPV4_PREFIX) || \
152 (_t == FR_TYPE_IPV6_ADDR) || \
153 (_t == FR_TYPE_IPV6_PREFIX) || \
154 (_t == FR_TYPE_COMBO_IP_PREFIX) || \
155 (_t == FR_TYPE_COMBO_IP_ADDR)) && \
156 ((_f) & CONF_FLAG_MULTI), _p, (_mismatch_fripaddr_m) 0), \
157 uint8_t const ** : __builtin_choose_expr((_t == FR_TYPE_OCTETS) && !((_f) & CONF_FLAG_MULTI), \
158 _p, (_mismatch_uint8) 0), \
159 uint8_t const ***: __builtin_choose_expr((_t == FR_TYPE_OCTETS) && ((_f) & CONF_FLAG_MULTI), \
160 _p, (_mismatch_uint8_m) 0), \
161 uint8_t * : __builtin_choose_expr((_t == FR_TYPE_UINT8) && !((_f) & CONF_FLAG_MULTI), \
162 _p, (_mismatch_uint8) 0), \
163 uint8_t ** : __builtin_choose_expr((_t == FR_TYPE_UINT8) && ((_f) & CONF_FLAG_MULTI), \
164 _p, (_mismatch_uint8_m) 0), \
165 uint16_t * : __builtin_choose_expr((_t == FR_TYPE_UINT16) && !((_f) & CONF_FLAG_MULTI), \
166 _p, (_mismatch_uint16) 0), \
167 uint16_t ** : __builtin_choose_expr((_t == FR_TYPE_UINT16) && ((_f) & CONF_FLAG_MULTI), \
168 _p, (_mismatch_uint16_m) 0), \
169 int32_t * : __builtin_choose_expr((_t == FR_TYPE_INT32) && !((_f) & CONF_FLAG_MULTI), \
170 _p, (_mismatch_int32) 0), \
171 int32_t ** : __builtin_choose_expr((_t == FR_TYPE_INT32) && ((_f) & CONF_FLAG_MULTI), \
172 _p, (_mismatch_int32_m) 0), \
173 uint64_t * : __builtin_choose_expr((_t == FR_TYPE_UINT64) && !((_f) & CONF_FLAG_MULTI), \
174 _p, (_mismatch_uint64) 0), \
175 uint64_t ** : __builtin_choose_expr((_t == FR_TYPE_UINT64) && ((_f) & CONF_FLAG_MULTI), \
176 _p, (_mismatch_uint64_m) 0), \
177 float * : __builtin_choose_expr((_t == FR_TYPE_FLOAT32) && !((_f) & CONF_FLAG_MULTI), \
178 _p, (_mismatch_float) 0), \
179 float ** : __builtin_choose_expr((_t == FR_TYPE_FLOAT32) && ((_f) & CONF_FLAG_MULTI), \
180 _p, (_mismatch_float_m) 0), \
181 double * : __builtin_choose_expr((_t == FR_TYPE_FLOAT64) && !((_f) & CONF_FLAG_MULTI), \
182 _p, (_mismatch_double) 0), \
183 double ** : __builtin_choose_expr((_t == FR_TYPE_FLOAT64) && ((_f) & CONF_FLAG_MULTI), \
184 _p, (_mismatch_double_m) 0), \
185 default: (conf_type_mismatch)0)))))
187# define FR_CONF_FLAG_CHECK(_type, _flags, _c_type, _ptr_or_offset) _ptr_or_offset
190#define CONF_CTYPE_TO_FLAGS(_ct) \
192 tmpl_t ** : CONF_FLAG_TMPL, \
193 tmpl_t *** : CONF_FLAG_TMPL | CONF_FLAG_MULTI, \
194 xlat_t ** : CONF_FLAG_XLAT, \
195 xlat_t *** : CONF_FLAG_XLAT | CONF_FLAG_MULTI, \
196 fr_ethernet_t * : 0, \
197 fr_ethernet_t ** : CONF_FLAG_MULTI, \
199 fr_ifid_t ** : CONF_FLAG_MULTI, \
201 fr_time_t ** : CONF_FLAG_MULTI, \
202 fr_time_delta_t * : 0, \
203 fr_time_delta_t ** : CONF_FLAG_MULTI, \
205 char const *** : CONF_FLAG_MULTI, \
207 bool ** : CONF_FLAG_MULTI, \
208 uint8_t const ** : 0, \
209 uint8_t const *** : CONF_FLAG_MULTI, \
211 uint8_t ** : CONF_FLAG_MULTI, \
213 uint16_t ** : CONF_FLAG_MULTI, \
215 uint32_t ** : CONF_FLAG_MULTI, \
217 uint64_t ** : CONF_FLAG_MULTI, \
219 int8_t ** : CONF_FLAG_MULTI, \
221 int16_t ** : CONF_FLAG_MULTI, \
223 int32_t ** : CONF_FLAG_MULTI, \
225 int64_t ** : CONF_FLAG_MULTI, \
227 float ** : CONF_FLAG_MULTI, \
229 double ** : CONF_FLAG_MULTI)
241# define FR_CONF_OFFSET_TYPE_FLAGS(_name, _type, _flags, _struct, _field) \
245 .offset = FR_CONF_FLAG_CHECK((_type), (_flags), &(((_struct *)NULL)->_field), offsetof(_struct, _field))
256# define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field) \
257 FR_CONF_OFFSET_TYPE_FLAGS(_name, \
258 FR_CTYPE_TO_TYPE((((_struct *)NULL)->_field)), \
259 (_flags) | CONF_CTYPE_TO_FLAGS((((_struct *)NULL)->_field)),\
268# define FR_CONF_OFFSET(_name, _struct, _field) \
269 FR_CONF_OFFSET_TYPE_FLAGS(_name, \
270 FR_CTYPE_TO_TYPE((((_struct *)NULL)->_field)), \
271 CONF_CTYPE_TO_FLAGS((((_struct *)NULL)->_field)),\
282# define FR_CONF_OFFSET_IS_SET(_name, _type, _flags, _struct, _field) \
285 .flags = CONF_FLAG_IS_SET | (_flags), \
286 .offset = FR_CONF_FLAG_CHECK((_type), (_flags), &(((_struct *)NULL)->_field), offsetof(_struct, _field)), \
287 .is_set_offset = offsetof(_struct, _field ## _is_set)
297# define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs) \
299 .flags = CONF_FLAG_SUBSECTION | (_flags), \
300 .offset = offsetof(_struct, _field), \
310# define FR_CONF_OFFSET_REF(_struct, _field, _subcs) \
311 .name1 = CF_IDENT_ANY, \
312 .flags = CONF_FLAG_REF, \
313 .offset = offsetof(_struct, _field), \
323# define FR_CONF_POINTER(_name, _type, _flags, _res_p) \
327 .data = FR_CONF_FLAG_CHECK((_type), (_flags), (_res_p), _res_p)
338# define FR_CONF_POINTER_IS_SET(_name, _type, _flags, _res_p) \
341 .flags = CONF_FLAG_IS_SET | (_flags), \
342 .data = FR_CONF_FLAG_CHECK((_type), (_flags), (_res_p), _res_p), \
343 .is_set_ptr = _res_p ## _is_set
344# define FR_ITEM_POINTER(_type, _res_p) _type, FR_CONF_FLAG_CHECK((_type), 0, (_res_p), _res_p)
358# define FR_CONF_SUBSECTION_ALLOC(_name, _type, _flags, _struct, _field, _subcs) \
362 .offset = FR_CONF_FLAG_CHECK((_type), (_flags), &(((_struct *)NULL)->_field), offsetof(_struct, _field)), \
364 .subcs_size = sizeof(**(((_struct *)0)->_field))
374# define FR_CONF_FUNC(_name, _type, _flags, _func, _dflt_func) \
379 .dflt_func = _dflt_func
387# define FR_CONF_SUBSECTION_GLOBAL(_name, _flags, _subcs) \
389 .flags = CONF_FLAG_SUBSECTION | (_flags), \
398#define FR_CONF_DEPRECATED(_name, _struct, _field) \
400 .flags = CONF_FLAG_DEPRECATED
410typedef enum CC_HINT(flag_enum) {
454#define fr_rule_deprecated(_rule) ((_rule)->flags & CONF_FLAG_DEPRECATED)
456#define fr_rule_required(_rule) ((_rule)->flags & CONF_FLAG_REQUIRED)
458#define fr_rule_secret(_rule) ((_rule)->flags & CONF_FLAG_SECRET)
460#define fr_rule_file_input(_rule) ((_rule)->flags & CONF_FLAG_FILE_INPUT)
462#define fr_rule_file_output(_rule) ((_rule)->flags & CONF_FLAG_FILE_OUTPUT)
465#define fr_rule_multi(_rule) ((_rule)->flags & CONF_FLAG_MULTI)
467#define fr_rule_not_empty(_rule) ((_rule)->flags & CONF_FLAG_NOT_EMPTY)
469#define fr_rule_is_set(_rule) ((_rule)->flags & CONF_FLAG_IS_SET)
471#define fr_rule_ok_missing(_rule) ((_rule)->flags & CONF_FLAG_OK_MISSING)
473#define fr_rule_file_exists(_rule) ((_rule)->flags & CONF_FLAG_FILE_EXISTS)
475#define fr_rule_dflt(_rule) ((_rule)->dflt || (_rule)->dflt_func)
477#define fr_rule_is_attribute(_rule) ((_rule)->flags & CONF_FLAG_ATTRIBUTE)
479#define fr_rule_is_xlat(_rule) ((_rule)->flags & CONF_FLAG_XLAT)
481#define fr_rule_is_tmpl(_rule) ((_rule)->flags & CONF_FLAG_TMPL)
484#define FR_SIZE_COND_CHECK(_name, _var, _cond, _new)\
487 WARN("Ignoring \"" _name " = %zu\", forcing to \"" _name " = %zu\"", _var, _new);\
492#define FR_SIZE_BOUND_CHECK(_name, _var, _op, _bound) FR_SIZE_COND_CHECK(_name, _var, (_var _op _bound), _bound)
494#define FR_INTEGER_COND_CHECK(_name, _var, _cond, _new)\
497 WARN("Ignoring \"" _name " = %u\", forcing to \"" _name " = %u\"", (unsigned int) (_var), (unsigned int) (_new));\
502#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound) FR_INTEGER_COND_CHECK(_name, _var, (_var _op _bound), _bound)
504#define FR_TIME_DELTA_COND_CHECK(_name, _var, _cond, _new)\
507 WARN("Ignoring \"" _name " = %pV\", forcing to \"" _name " = %pV\"", \
508 fr_box_time_delta(_var), fr_box_time_delta(_new));\
513#define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)\
515 if (!fr_time_delta_cond(_var, _op, _bound)) { \
516 WARN("Ignoring \"" _name " = %pV\", forcing to \"" _name " = %pV\"",\
517 fr_box_time_delta(_var),\
518 fr_box_time_delta(_bound));\
611 size_t is_set_offset;
630 char const *subcs_type;
642#define CONF_PARSER_TERMINATOR { .name1 = NULL, .type = ~(UINT32_MAX - 1), \
643 .offset = 0, .data = NULL, .dflt = NULL, .quote = T_INVALID }
645#define CONF_PARSER_PARTIAL_TERMINATOR { .name1 = NULL, .type = ~(UINT32_MAX - 1), \
646 .offset = 1, .data = NULL, .dflt = NULL, .quote = T_INVALID }
648#define CF_FILE_NONE (0)
649#define CF_FILE_ERROR (1)
650#define CF_FILE_CONFIG (1 << 2)
651#define CF_FILE_MODULE (1 << 3)
672#define cf_section_rule_push(_cs, _rule) _cf_section_rule_push(_cs, _rule, __FILE__, __LINE__)
674#define cf_section_rules_push(_cs, _rule) _cf_section_rules_push(_cs, _rule, __FILE__, __LINE__)
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
int cf_table_parse_uint32(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int32_t (FR_TYPE_UINT32)
int(* cf_dflt_t)(CONF_PAIR **out, void *parent, CONF_SECTION *cs, fr_token_t quote, conf_parser_t const *rule)
Callback for producing dynamic defaults from 3rd party libraries.
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
void const * uctx
User data accessible by the cf_parse_t func.
void * data
Pointer to a static variable to write the parsed value to.
int cf_table_parse_int32(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int32_t (FR_TYPE_INT32)
int cf_pair_parse(TALLOC_CTX *ctx, CONF_SECTION *cs, char const *name, unsigned int type, void *data, char const *dflt, fr_token_t dflt_quote))
Parses a CONF_PAIR into a C data type, with a default value.
int cf_parse_uid(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
conf_parser_flags_t flags
Flags which control parsing behaviour.
int cf_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int.
int cf_parse_permissions(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
fr_type_t type
An fr_type_t value, controls the output type.
size_t offset
Relative offset of field or structure to write the parsed value to.
char const * name2
Second identifier for CONF_SECTION.
void cf_pair_debug_log(CONF_SECTION const *cs, CONF_PAIR *cp, conf_parser_t const *rule)
fr_token_t quote
Quoting around the default value. Only used for templates.
fr_table_num_sorted_t const * table
int(* cf_parse_t)(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Callback for performing custom parsing of a CONF_SECTION or CONF_PAIR.
int cf_pair_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *out, CONF_PAIR *cp, conf_parser_t const *rule))
Parses a CONF_PAIR into a boxed value.
char const * name1
Name of the CONF_ITEM to parse.
int cf_parse_gid(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
int cf_section_parse_pass2(void *base, CONF_SECTION *cs)
Fixup xlat expansions and attributes.
int _cf_section_rule_push(CONF_SECTION *cs, conf_parser_t const *rule, char const *filename, int lineno)
Add a single rule to a CONF_SECTION.
int _cf_section_rules_push(CONF_SECTION *cs, conf_parser_t const *rules, char const *filename, int lineno)
Add an array of parse rules to a CONF_SECTION.
cf_parse_t on_read
Function to call as the item is being read, just after it has been allocated and initialized.
int cf_pair_parse_value(TALLOC_CTX *ctx, void *out, void *base, CONF_ITEM *ci, conf_parser_t const *rule))
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
@ CONF_FLAG_FILE_OUTPUT
File matching value must exist, and must be writable.
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
@ CONF_FLAG_REF
reference another conf_parser_t inline in this one
@ CONF_FLAG_SECRET
Only print value if debug level >= 3.
@ CONF_FLAG_IS_SET
Write whether this config item was left as the default to is_set_offset or is_set_ptr.
@ CONF_FLAG_ATTRIBUTE
Value must resolve to attribute in dict (deprecated, use CONF_FLAG_TMPL).
@ CONF_FLAG_FILE_INPUT
File matching value must exist, and must be readable.
@ CONF_FLAG_DEPRECATED
If a matching CONF_PAIR is found, error out with a deprecated message.
@ CONF_FLAG_NONE
No special flags.
@ CONF_FLAG_NOT_EMPTY
CONF_PAIR is required to have a non zero length value.
@ CONF_FLAG_XLAT
string will be dynamically expanded.
@ CONF_FLAG_OPTIONAL
subsection is pushed only if a non-optional matching one is pushed
@ CONF_FLAG_OK_MISSING
OK if it's missing.
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
@ CONF_FLAG_FILE_EXISTS
File matching value must exist.
@ CONF_FLAG_TMPL
CONF_PAIR should be parsed as a template.
@ CONF_FLAG_HIDDEN
Used by scripts to omit items from the generated documentation.
Defines a CONF_PAIR to C data type mapping.
Common header for all CONF_* types.
Configuration AVP similar to a fr_pair_t.
A section grouping multiple CONF_PAIR.
fr_aka_sim_id_type_t type
An element in a lexicographically sorted array of name to num mappings.
static size_t char ** out