26 RCSIDH(cf_parse_h,
"$Id: b30974bcbe2a9ef4556bdcdd6b6b19db57ffff71 $")
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
45 typedef void _mismatch_abinary_m;
46 typedef void _mismatch_abinary;
47 typedef void _mismatch_bool_m;
48 typedef void _mismatch_bool;
49 typedef void _mismatch_char_m;
50 typedef void _mismatch_char;
51 typedef void _mismatch_double_m;
52 typedef void _mismatch_double;
53 typedef void _mismatch_ethernet_m;
54 typedef void _mismatch_ethernet;
55 typedef void _mismatch_float_m;
56 typedef void _mismatch_float;
57 typedef void _mismatch_fripaddr_m;
58 typedef void _mismatch_fripaddr;
59 typedef void _mismatch_ifid_m;
60 typedef void _mismatch_ifid;
61 typedef void _mismatch_int32_m;
62 typedef void _mismatch_int32;
63 typedef void _mismatch_size_m;
64 typedef void _mismatch_size;
65 typedef void _mismatch_time_delta_m;
66 typedef void _mismatch_time_delta;
67 typedef void _mismatch_time_m;
68 typedef void _mismatch_time;
69 typedef void _mismatch_uint16_m;
70 typedef void _mismatch_uint16;
71 typedef void _mismatch_uint32_m;
72 typedef void _mismatch_uint32;
73 typedef void _mismatch_uint64_m;
74 typedef void _mismatch_uint64;
75 typedef void _mismatch_uint8_m_m;
76 typedef void _mismatch_uint8_m;
77 typedef void _mismatch_uint8;
78 typedef void _mismatch_void_m;
79 typedef void _mismatch_void;
80 typedef void _mismatch_tmpl_m;
81 typedef void _mismatch_vp_tmpl;
84 typedef void _mismatch_default;
85 typedef void conf_type_mismatch;
86 typedef 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_POINTER(_name, _type, _flags, _res_p) \
314 .data = FR_CONF_FLAG_CHECK((_type), (_flags), (_res_p), _res_p)
325 # define FR_CONF_POINTER_IS_SET(_name, _type, _flags, _res_p) \
328 .flags = CONF_FLAG_IS_SET | (_flags), \
329 .data = FR_CONF_FLAG_CHECK((_type), (_flags), (_res_p), _res_p), \
330 .is_set_ptr = _res_p ## _is_set
331 # define FR_ITEM_POINTER(_type, _res_p) _type, FR_CONF_FLAG_CHECK((_type), 0, (_res_p), _res_p)
345 # define FR_CONF_SUBSECTION_ALLOC(_name, _type, _flags, _struct, _field, _subcs) \
349 .offset = FR_CONF_FLAG_CHECK((_type), (_flags), &(((_struct *)NULL)->_field), offsetof(_struct, _field)), \
351 .subcs_size = sizeof(**(((_struct *)0)->_field))
361 # define FR_CONF_FUNC(_name, _type, _flags, _func, _dflt_func) \
366 .dflt_func = _dflt_func
374 # define FR_CONF_SUBSECTION_GLOBAL(_name, _flags, _subcs) \
376 .flags = CONF_FLAG_SUBSECTION | (_flags), \
385 #define FR_CONF_DEPRECATED(_name, _struct, _field) \
387 .flags = CONF_FLAG_DEPRECATED
397 typedef enum CC_HINT(flag_enum) {
439 #define fr_rule_deprecated(_rule) ((_rule)->flags & CONF_FLAG_DEPRECATED)
441 #define fr_rule_required(_rule) ((_rule)->flags & CONF_FLAG_REQUIRED)
443 #define fr_rule_secret(_rule) ((_rule)->flags & CONF_FLAG_SECRET)
445 #define fr_rule_file_input(_rule) ((_rule)->flags & CONF_FLAG_FILE_INPUT)
447 #define fr_rule_file_output(_rule) ((_rule)->flags & CONF_FLAG_FILE_OUTPUT)
450 #define fr_rule_multi(_rule) ((_rule)->flags & CONF_FLAG_MULTI)
452 #define fr_rule_not_empty(_rule) ((_rule)->flags & CONF_FLAG_NOT_EMPTY)
454 #define fr_rule_is_set(_rule) ((_rule)->flags & CONF_FLAG_IS_SET)
456 #define fr_rule_ok_missing(_rule) ((_rule)->flags & CONF_FLAG_OK_MISSING)
458 #define fr_rule_file_exists(_rule) ((_rule)->flags & CONF_FLAG_FILE_EXISTS)
460 #define fr_rule_dflt(_rule) ((_rule)->dflt || (_rule)->dflt_func)
462 #define fr_rule_is_attribute(_rule) ((_rule)->flags & CONF_FLAG_ATTRIBUTE)
464 #define fr_rule_is_xlat(_rule) ((_rule)->flags & CONF_FLAG_XLAT)
466 #define fr_rule_is_tmpl(_rule) ((_rule)->flags & CONF_FLAG_TMPL)
469 #define FR_SIZE_COND_CHECK(_name, _var, _cond, _new)\
472 WARN("Ignoring \"" _name " = %zu\", forcing to \"" _name " = %zu\"", _var, _new);\
477 #define FR_SIZE_BOUND_CHECK(_name, _var, _op, _bound) FR_SIZE_COND_CHECK(_name, _var, (_var _op _bound), _bound)
479 #define FR_INTEGER_COND_CHECK(_name, _var, _cond, _new)\
482 WARN("Ignoring \"" _name " = %i\", forcing to \"" _name " = %i\"", _var, _new);\
487 #define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound) FR_INTEGER_COND_CHECK(_name, _var, (_var _op _bound), _bound)
489 #define FR_TIME_DELTA_COND_CHECK(_name, _var, _cond, _new)\
492 WARN("Ignoring \"" _name " = %pV\", forcing to \"" _name " = %pV\"", \
493 fr_box_time_delta(_var), fr_box_time_delta(_new));\
498 #define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)\
500 if (!fr_time_delta_cond(_var, _op, _bound)) { \
501 WARN("Ignoring \"" _name " = %pV\", forcing to \"" _name " = %pV\"",\
502 fr_box_time_delta(_var),\
503 fr_box_time_delta(_bound));\
596 size_t is_set_offset;
615 char const *subcs_type;
627 #define CONF_PARSER_TERMINATOR { .name1 = NULL, .type = ~(UINT32_MAX - 1), \
628 .offset = 0, .data = NULL, .dflt = NULL, .quote = T_INVALID }
630 #define CONF_PARSER_PARTIAL_TERMINATOR { .name1 = NULL, .type = ~(UINT32_MAX - 1), \
631 .offset = 1, .data = NULL, .dflt = NULL, .quote = T_INVALID }
633 #define CF_FILE_NONE (0)
634 #define CF_FILE_ERROR (1)
635 #define CF_FILE_CONFIG (1 << 2)
636 #define CF_FILE_MODULE (1 << 3)
657 #define cf_section_rule_push(_cs, _rule) _cf_section_rule_push(_cs, _rule, __FILE__, __LINE__)
659 #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.
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_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_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