The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
cf_parse.h
Go to the documentation of this file.
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 /**
19  * $Id: 4f43843c4762c64109a2138cd33d3975ddc4160c $
20  *
21  * @file lib/server/cf_parse.h
22  * @brief API to parse internal format configuration items into native C types.
23  *
24  * @copyright 2015 The FreeRADIUS server project
25  */
26 RCSIDH(cf_parse_h, "$Id: 4f43843c4762c64109a2138cd33d3975ddc4160c $")
27 
28 typedef struct conf_parser_s conf_parser_t;
29 
30 #include <stddef.h>
31 #include <stdint.h>
32 #include <stdbool.h>
33 #include <unistd.h>
34 #include <sys/time.h>
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>
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 #ifdef HAVE_BUILTIN_CHOOSE_EXPR
45 typedef void _mismatch_abinary_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
46 typedef void _mismatch_abinary; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
47 typedef void _mismatch_bool_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
48 typedef void _mismatch_bool; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
49 typedef void _mismatch_char_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
50 typedef void _mismatch_char; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
51 typedef void _mismatch_double_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
52 typedef void _mismatch_double; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
53 typedef void _mismatch_ethernet_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
54 typedef void _mismatch_ethernet; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
55 typedef void _mismatch_float_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
56 typedef void _mismatch_float; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
57 typedef void _mismatch_fripaddr_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
58 typedef void _mismatch_fripaddr; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
59 typedef void _mismatch_ifid_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
60 typedef void _mismatch_ifid; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
61 typedef void _mismatch_int32_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
62 typedef void _mismatch_int32; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
63 typedef void _mismatch_size_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
64 typedef void _mismatch_size; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
65 typedef void _mismatch_time_delta_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
66 typedef void _mismatch_time_delta; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
67 typedef void _mismatch_time_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
68 typedef void _mismatch_time; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
69 typedef void _mismatch_uint16_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
70 typedef void _mismatch_uint16; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
71 typedef void _mismatch_uint32_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
72 typedef void _mismatch_uint32; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
73 typedef void _mismatch_uint64_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
74 typedef void _mismatch_uint64; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
75 typedef void _mismatch_uint8_m_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
76 typedef void _mismatch_uint8_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
77 typedef void _mismatch_uint8; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
78 typedef void _mismatch_void_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
79 typedef void _mismatch_void; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
80 typedef void _mismatch_tmpl_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
81 typedef void _mismatch_vp_tmpl; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
82 
83 
84 typedef void _mismatch_default; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
85 typedef void conf_type_mismatch; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
86 typedef void conf_type_invalid; //!< Dummy type used to indicate invalid FR_TYPE_*.
87 
88 /** Check the #fr_type_t matches the destination data type
89  *
90  * Validation macro to check the type of the pointer or offset _p passed in
91  * matches the #fr_type_t of the configuration item.
92  *
93  * Uses various magic builtin precompilation functions, so will likely only
94  * work with recent versions of clang and gcc.
95  *
96  * @note The warnings/errors emitted are usually awful.
97  *
98  * @param[in] _t a #fr_type_t value.
99  * @param[in] _f additional flags that control parsing.
100  * @param[in] _ct data type of global or struct field, obtained with ``__typeof__``.
101  * @param[in] _p Pointer or offset.
102  */
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), \
110 _Generic((_ct), \
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)))))
186 #else
187 # define FR_CONF_FLAG_CHECK(_type, _flags, _c_type, _ptr_or_offset) _ptr_or_offset
188 #endif
189 
190 #define CONF_CTYPE_TO_FLAGS(_ct) \
191 _Generic(&(_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, \
198  fr_ifid_t * : 0, \
199  fr_ifid_t ** : CONF_FLAG_MULTI, \
200  fr_time_t * : 0, \
201  fr_time_t ** : CONF_FLAG_MULTI, \
202  fr_time_delta_t * : 0, \
203  fr_time_delta_t ** : CONF_FLAG_MULTI, \
204  char const ** : 0, \
205  char const *** : CONF_FLAG_MULTI, \
206  bool * : 0, \
207  bool ** : CONF_FLAG_MULTI, \
208  uint8_t const ** : 0, \
209  uint8_t const *** : CONF_FLAG_MULTI, \
210  uint8_t * : 0, \
211  uint8_t ** : CONF_FLAG_MULTI, \
212  uint16_t * : 0, \
213  uint16_t ** : CONF_FLAG_MULTI, \
214  uint32_t * : 0, \
215  uint32_t ** : CONF_FLAG_MULTI, \
216  uint64_t * : 0, \
217  uint64_t ** : CONF_FLAG_MULTI, \
218  int8_t * : 0, \
219  int8_t ** : CONF_FLAG_MULTI, \
220  int16_t * : 0, \
221  int16_t ** : CONF_FLAG_MULTI, \
222  int32_t * : 0, \
223  int32_t ** : CONF_FLAG_MULTI, \
224  int64_t * : 0, \
225  int64_t ** : CONF_FLAG_MULTI, \
226  float * : 0, \
227  float ** : CONF_FLAG_MULTI, \
228  double * : 0, \
229  double ** : CONF_FLAG_MULTI)
230 
231 /** conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
232  *
233  * This variant takes output type and flags manually, instead of determining them automatically.
234  *
235  * @param[in] _name of the CONF_PAIR to search for.
236  * @param[in] _type to parse the CONF_PAIR as.
237  * @param[in] _flags controlling parsing behaviour.
238  * @param[in] _struct containing the field to write the result to.
239  * @param[in] _field to write the result to.
240  */
241 # define FR_CONF_OFFSET_TYPE_FLAGS(_name, _type, _flags, _struct, _field) \
242  .name1 = _name, \
243  .type = (_type), \
244  .flags = (_flags), \
245  .offset = FR_CONF_FLAG_CHECK((_type), (_flags), &(((_struct *)NULL)->_field), offsetof(_struct, _field))
246 
247 /** conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
248  *
249  * This variant takes additional flags, and will add CONF_FLAG_MULTI automatically if the field is an array.
250  *
251  * @param[in] _name of the CONF_PAIR to search for.
252  * @param[in] _flags controlling parsing behaviour.
253  * @param[in] _struct containing the field to write the result to.
254  * @param[in] _field to write the result to.
255  */
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)),\
260  _struct, _field)
261 
262 /** conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
263  *
264  * @param[in] _name of the CONF_PAIR to search for.
265  * @param[in] _struct containing the field to write the result to.
266  * @param[in] _field to write the result to.
267  */
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)),\
272  _struct, _field)
273 
274 /** conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct, recording if a default was used in `<_field>`_is_set
275  *
276  * @param[in] _name of the CONF_PAIR to search for.
277  * @param[in] _type to parse the CONF_PAIR as.
278  * @param[in] _flags controlling parsing behaviour.
279  * @param[in] _struct containing the field to write the result to.
280  * @param[in] _field to write the result to.
281  */
282 # define FR_CONF_OFFSET_IS_SET(_name, _type, _flags, _struct, _field) \
283  .name1 = _name, \
284  .type = (_type), \
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)
288 
289 /** conf_parser_t which populates a sub-struct using a CONF_SECTION
290  *
291  * @param[in] _name of the CONF_SECTION to search for.
292  * @param[in] _flags controlling parsing behaviour.
293  * @param[in] _struct containing the sub-struct to populate.
294  * @param[in] _field containing the sub-struct to populate.
295  * @param[in] _subcs CONF_SECTION to parse.
296  */
297 # define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs) \
298  .name1 = _name, \
299  .flags = CONF_FLAG_SUBSECTION | (_flags), \
300  .offset = offsetof(_struct, _field), \
301  .subcs = _subcs
302 
303 /** conf_parser_t which parses a single CONF_PAIR producing a single global result
304  *
305  * @param[in] _name of the CONF_PAIR to search for.
306  * @param[in] _type to parse the CONF_PAIR as.
307  * @param[in] _flags controlling parsing behaviour.
308  * @param[out] _res_p pointer to a global var, where the result will be written.
309  */
310 # define FR_CONF_POINTER(_name, _type, _flags, _res_p) \
311  .name1 = _name, \
312  .type = (_type), \
313  .flags = (_flags), \
314  .data = FR_CONF_FLAG_CHECK((_type), (_flags), (_res_p), _res_p)
315 
316 /** conf_parser_t which parses a single CONF_PAIR producing a single global result, recording if a default was used in `<_res_p>`_is_set
317  *
318  * @note is set state is recorded in variable `<_res_p>`_is_set.
319  *
320  * @param[in] _name of the CONF_PAIR to search for.
321  * @param[in] _type to parse the CONF_PAIR as.
322  * @param[in] _flags controlling parsing behaviour.
323  * @param[out] _res_p pointer to a global var, where the result will be written.
324  */
325 # define FR_CONF_POINTER_IS_SET(_name, _type, _flags, _res_p) \
326  .name1 = _name, \
327  .type = (_type), \
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)
332 
333 /** A conf_parser_t multi-subsection
334  *
335  * Parse multiple instance of a subsection, allocating an array of structs
336  * to hold the result.
337  *
338  * @param[in] _name name of subsection to search for.
339  * @param[in] _type the output type.
340  * @param[in] _flags flags controlling parsing behaviour.
341  * @param[in] _struct instance data struct.
342  * @param[in] _field field in instance data struct.
343  * @param[in] _subcs conf_parser_t array to use to parse subsection data.
344  */
345 # define FR_CONF_SUBSECTION_ALLOC(_name, _type, _flags, _struct, _field, _subcs) \
346  .name1 = _name, \
347  .type = (_type), \
348  .flags = (_flags), \
349  .offset = FR_CONF_FLAG_CHECK((_type), (_flags), &(((_struct *)NULL)->_field), offsetof(_struct, _field)), \
350  .subcs = _subcs, \
351  .subcs_size = sizeof(**(((_struct *)0)->_field))
352 
353 /** conf_parser_t entry which doesn't fill in a pointer or offset, but relies on functions to record values
354  *
355  * @param[in] _name name of pair to search for.
356  * @param[in] _type base type to parse pair as.
357  * @param[in] _flags f lags controlling parsing behaviour.
358  * @param[in] _func to use to record value.
359  * @param[in] _dflt_func to use to get defaults from a 3rd party library.
360  */
361 # define FR_CONF_FUNC(_name, _type, _flags, _func, _dflt_func) \
362  .name1 = _name, \
363  .type = (_type), \
364  .flags = (_flags), \
365  .func = _func, \
366  .dflt_func = _dflt_func
367 
368 /** conf_parser_t entry which runs conf_parser_t entries for a subsection without any output
369  *
370  * @param[in] _name of pair to search for.
371  * @param[in] _flags flags controlling parsing behaviour.
372  * @param[in] _subcs to use to get defaults from a 3rd party library.
373  */
374 # define FR_CONF_SUBSECTION_GLOBAL(_name, _flags, _subcs) \
375  .name1 = _name, \
376  .flags = CONF_FLAG_SUBSECTION | (_flags), \
377  .subcs = _subcs
378 
379 /** conf_parser_t entry which raises an error if a matching CONF_PAIR is found
380  *
381  * @param[in] _name of pair to search for.
382  * @param[in] _struct where the result was previously written.
383  * @param[in] _field in the struct where the result was previously written.
384  */
385 #define FR_CONF_DEPRECATED(_name, _struct, _field) \
386  .name1 = _name, \
387  .flags = CONF_FLAG_DEPRECATED
388 
389 /** @name #conf_parser_t type flags
390  *
391  * These flags should be or'd with another FR_TYPE_* value to create validation
392  * rules for the #cf_pair_parse function.
393  *
394  * @{
395  */
396 DIAG_OFF(attributes)
397 typedef enum CC_HINT(flag_enum) {
398  CONF_FLAG_HIDDEN = 0, //!< Used by scripts to omit items from the
399  ///< generated documentation.
400  CONF_FLAG_SUBSECTION = (1 << 1), //!< Instead of putting the information into a
401  ///< configuration structure, the configuration
402  ///< file routines MAY just parse it directly into
403  ///< user-supplied variables.
404  CONF_FLAG_DEPRECATED = (1 << 10), //!< If a matching #CONF_PAIR is found,
405  //!< error out with a deprecated message.
406  CONF_FLAG_REQUIRED = (1 << 11), //!< Error out if no matching #CONF_PAIR
407  //!< is found, and no dflt value is set.
408  CONF_FLAG_ATTRIBUTE = (1 << 12), //!< Value must resolve to attribute in dict
409  //!< (deprecated, use #CONF_FLAG_TMPL).
410  CONF_FLAG_SECRET = (1 << 13), //!< Only print value if debug level >= 3.
411 
412  CONF_FLAG_FILE_INPUT = (1 << 14), //!< File matching value must exist,
413  //!< and must be readable.
414  CONF_FLAG_FILE_OUTPUT = (1 << 15), //!< File matching value must exist,
415  //!< and must be writable.
416 
417  CONF_FLAG_XLAT = (1 << 16), //!< string will be dynamically expanded.
418  CONF_FLAG_TMPL = (1 << 17), //!< CONF_PAIR should be parsed as a template.
419 
420  CONF_FLAG_MULTI = (1 << 18), //!< CONF_PAIR can have multiple copies.
421  CONF_FLAG_NOT_EMPTY = (1 << 19), //!< CONF_PAIR is required to have a non zero
422  //!< length value.
423  CONF_FLAG_FILE_EXISTS = (1 << 20), //!< File matching value must exist
424 
425  CONF_FLAG_IS_SET = (1 << 21), //!< Write whether this config item was
426  //!< left as the default to is_set_offset
427  //!< or is_set_ptr.
428  CONF_FLAG_OK_MISSING = (1 << 22), //!< OK if it's missing
430 DIAG_ON(attributes)
431 
432 /** @} */
433 
434 /** @name #conf_parser_t flags checks
435  *
436  * @{
437  */
438 #define fr_rule_deprecated(_rule) ((_rule)->flags & CONF_FLAG_DEPRECATED)
439 
440 #define fr_rule_required(_rule) ((_rule)->flags & CONF_FLAG_REQUIRED)
441 
442 #define fr_rule_secret(_rule) ((_rule)->flags & CONF_FLAG_SECRET)
443 
444 #define fr_rule_file_input(_rule) ((_rule)->flags & CONF_FLAG_FILE_INPUT)
445 
446 #define fr_rule_file_output(_rule) ((_rule)->flags & CONF_FLAG_FILE_OUTPUT)
447 
448 
449 #define fr_rule_multi(_rule) ((_rule)->flags & CONF_FLAG_MULTI)
450 
451 #define fr_rule_not_empty(_rule) ((_rule)->flags & CONF_FLAG_NOT_EMPTY)
452 
453 #define fr_rule_is_set(_rule) ((_rule)->flags & CONF_FLAG_IS_SET)
454 
455 #define fr_rule_ok_missing(_rule) ((_rule)->flags & CONF_FLAG_OK_MISSING)
456 
457 #define fr_rule_file_exists(_rule) ((_rule)->flags & CONF_FLAG_FILE_EXISTS)
458 
459 #define fr_rule_dflt(_rule) ((_rule)->dflt || (_rule)->dflt_func)
460 
461 #define fr_rule_is_attribute(_rule) ((_rule)->flags & CONF_FLAG_ATTRIBUTE)
462 
463 #define fr_rule_is_xlat(_rule) ((_rule)->flags & CONF_FLAG_XLAT)
464 
465 #define fr_rule_is_tmpl(_rule) ((_rule)->flags & CONF_FLAG_TMPL)
466 /** @} */
467 
468 #define FR_SIZE_COND_CHECK(_name, _var, _cond, _new)\
469 do {\
470  if (!(_cond)) {\
471  WARN("Ignoring \"" _name " = %zu\", forcing to \"" _name " = %zu\"", _var, _new);\
472  _var = _new;\
473  }\
474 } while (0)
475 
476 #define FR_SIZE_BOUND_CHECK(_name, _var, _op, _bound) FR_SIZE_COND_CHECK(_name, _var, (_var _op _bound), _bound)
477 
478 #define FR_INTEGER_COND_CHECK(_name, _var, _cond, _new)\
479 do {\
480  if (!(_cond)) {\
481  WARN("Ignoring \"" _name " = %i\", forcing to \"" _name " = %i\"", _var, _new);\
482  _var = _new;\
483  }\
484 } while (0)
485 
486 #define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound) FR_INTEGER_COND_CHECK(_name, _var, (_var _op _bound), _bound)
487 
488 #define FR_TIME_DELTA_COND_CHECK(_name, _var, _cond, _new)\
489 do {\
490  if (!(_cond)) {\
491  WARN("Ignoring \"" _name " = %pV\", forcing to \"" _name " = %pV\"", \
492  fr_box_time_delta(_var), fr_box_time_delta(_new));\
493  _var = _new;\
494  }\
495 } while (0)
496 
497 #define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)\
498 do {\
499  if (!fr_time_delta_cond(_var, _op, _bound)) { \
500  WARN("Ignoring \"" _name " = %pV\", forcing to \"" _name " = %pV\"",\
501  fr_box_time_delta(_var),\
502  fr_box_time_delta(_bound));\
503  _var = _bound;\
504  }\
505 } while (0)
506 
507 extern bool check_config;
508 
509 /** Callback for performing custom parsing of a #CONF_SECTION or CONF_PAIR
510  *
511  * @param[in] ctx to allocate any data in.
512  * @param[out] out Where to write the result of parsing.
513  * @param[in] parent The base address of the structure.
514  * @param[in] ci The #CONF_SECTION or #CONF_PAIR to parse.
515  * @param[in] rule Parse rules - How the #CONF_PAIR or #CONF_SECTION should be converted.
516  * @return
517  * - 0 on success.
518  * - -1 on failure.
519  */
520 typedef int (*cf_parse_t)(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
521 
522 /** Callback for producing dynamic defaults from 3rd party libraries
523  *
524  * @param[out] out Where to write default conf pair.
525  * @param[in] parent being populated.
526  * @param[in] cs to allocate pair in.
527  * @param[in] quote to use when allocing the pair. Provided as a convenience.
528  * @param[in] rule to produce default for.
529  * @return
530  * - 0 on success.
531  * - -1 on failure.
532  */
533 typedef int (*cf_dflt_t)(CONF_PAIR **out, void *parent, CONF_SECTION *cs, fr_token_t quote, conf_parser_t const *rule);
534 
535 /** Defines a #CONF_PAIR to C data type mapping
536  *
537  * Is typically used to define mappings between module sections, and module instance structs.
538  * May also be used to set global configuration options.
539  *
540  * Offset/data values should be set using #FR_CONF_OFFSET or #FR_CONF_POINTER.
541  *
542  * Example with #FR_CONF_OFFSET :
543  @code{.c}
544  static conf_parser_t module_config[] = {
545  { FR_CONF_OFFSET_TYPE_FLAGS("example", FR_TYPE_STRING | CONF_FLAG_NOT_EMPTY, 0, 0, example_instance_t, example), .dflt = "default_value" },
546  CONF_PARSER_TERMINATOR
547  }
548  @endcode
549  *
550  * Example with #FR_CONF_POINTER :
551  @code{.c}
552  static conf_parser_t global_config[] = {
553  { FR_CONF_POINTER("example", FR_TYPE_STRING | CONF_FLAG_NOT_EMPTY, 0, 0, 0, &my_global), .dflt = "default_value" },
554  CONF_PARSER_TERMINATOR
555  }
556  @endcode
557  *
558  * @see FR_CONF_OFFSET
559  * @see FR_CONF_POINTER
560  * @see cf_section_parse
561  * @see cf_pair_parse
562  */
564  char const *name1; //!< Name of the #CONF_ITEM to parse.
565  char const *name2; //!< Second identifier for #CONF_SECTION.
566 
567  fr_type_t type; //!< An #fr_type_t value, controls the output type.
568 
569  conf_parser_flags_t flags; //!< Flags which control parsing behaviour.
570 
571  size_t offset; //!< Relative offset of field or structure to write the parsed value to.
572  //!< When #flags is set to #CONF_FLAG_SUBSECTION, may be used to specify
573  //!< a base offset to add to all offsets contained within the
574  //!< subsection.
575  //!< @note Must be used exclusively to #data.
576 
577  void *data; //!< Pointer to a static variable to write the parsed value to.
578  //!< @note Must be used exclusively to #offset.
579 
580  cf_parse_t func; //!< Override default parsing behaviour for the specified type with
581  //!< a custom parsing function.
582 
583  cf_parse_t on_read; //!< Function to call as the item is being read, just after
584  //!< it has been allocated and initialized.
585 
586  void const *uctx; //!< User data accessible by the #cf_parse_t func. Useful for
587  ///< building reusable functions.
588 
589  /** Where to write status if FR_TYPE_IS_DEFAULT is set
590  *
591  * @note Which field is used, is determined by whether
592  * data ptr is set.
593  */
594  union {
595  size_t is_set_offset; //!< If type contains FR_TYPE_IS_DEFAULT write status to bool.
596  //!< at this address.
597  void *is_set_ptr; //!< If type contains FR_TYPE_IS_DEFAULT write status to ptr
598  //!< at this address.
599  };
600 
601  union {
602  struct {
603  char const *dflt; //!< Default as it would appear in radiusd.conf.
604 
605  cf_dflt_t dflt_func; //!< Function to produce dynamic defaults.
606  };
607 
608  struct {
609  conf_parser_t const *subcs; //!< When #CONF_FLAG_SUBSECTION is set, should
610  //!< be a pointer to the start of another array of
611  //!< #conf_parser_t structs, forming the subsection.
612  size_t subcs_size; //!< If non-zero, allocate structs of this size to hold
613  //!< the parsed data.
614  char const *subcs_type; //!< Set a specific talloc type for subcs structures.
615  };
616  };
617 
618  fr_token_t quote; //!< Quoting around the default value. Only used for templates.
619 };
620 
621 typedef struct {
623  size_t *len;
625 
626 #define CONF_PARSER_TERMINATOR { .name1 = NULL, .type = ~(UINT32_MAX - 1), \
627  .offset = 0, .data = NULL, .dflt = NULL, .quote = T_INVALID }
628 
629 #define CONF_PARSER_PARTIAL_TERMINATOR { .name1 = NULL, .type = ~(UINT32_MAX - 1), \
630  .offset = 1, .data = NULL, .dflt = NULL, .quote = T_INVALID }
631 
632 #define CF_FILE_NONE (0)
633 #define CF_FILE_ERROR (1)
634 #define CF_FILE_CONFIG (1 << 2)
635 #define CF_FILE_MODULE (1 << 3)
636 
637 void cf_pair_debug(CONF_SECTION const *cs, CONF_PAIR *cp, conf_parser_t const *rule);
638 
639 /*
640  * Type validation and conversion
641  */
642 int cf_pair_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *out, CONF_PAIR *cp, conf_parser_t const *rule)
643  CC_HINT(nonnull(2, 3, 4));
644 
645 int cf_pair_parse_value(TALLOC_CTX *ctx, void *out, void *base, CONF_ITEM *ci, conf_parser_t const *rule)
646  CC_HINT(nonnull(2, 4, 5));
647 
648 int cf_pair_parse(TALLOC_CTX *ctx, CONF_SECTION *cs, char const *name,
649  unsigned int type, void *data, char const *dflt, fr_token_t dflt_quote) CC_HINT(nonnull(2,3));
650 int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs);
651 int cf_section_parse_pass2(void *base, CONF_SECTION *cs);
652 
653 /*
654  * Runtime parse rules
655  */
656 #define cf_section_rule_push(_cs, _rule) _cf_section_rule_push(_cs, _rule, __FILE__, __LINE__)
657 int _cf_section_rule_push(CONF_SECTION *cs, conf_parser_t const *rule, char const *filename, int lineno);
658 #define cf_section_rules_push(_cs, _rule) _cf_section_rules_push(_cs, _rule, __FILE__, __LINE__)
659 int _cf_section_rules_push(CONF_SECTION *cs, conf_parser_t const *rules, char const *filename, int lineno);
660 
661 /*
662  * Generic parsing callback functions
663  */
664 int cf_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
665  CONF_ITEM *ci, conf_parser_t const *rule);
666 
667 int cf_table_parse_uint32(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
668  CONF_ITEM *ci, conf_parser_t const *rule);
669 
670 int cf_table_parse_int32(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
671  CONF_ITEM *ci, conf_parser_t const *rule);
672 
673 int cf_parse_uid(TALLOC_CTX *ctx, void *out, UNUSED void *parent,
674  CONF_ITEM *ci, conf_parser_t const *rule);
675 
676 int cf_parse_gid(TALLOC_CTX *ctx, void *out, UNUSED void *parent,
677  CONF_ITEM *ci, conf_parser_t const *rule);
678 
679 #ifdef __cplusplus
680 }
681 #endif
#define DIAG_ON(_x)
Definition: build.h:419
#define RCSIDH(h, id)
Definition: build.h:445
#define UNUSED
Definition: build.h:313
#define DIAG_OFF(_x)
Definition: build.h:418
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition: cf_parse.h:580
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)
Definition: cf_parse.c:1506
void cf_pair_debug(CONF_SECTION const *cs, CONF_PAIR *cp, conf_parser_t const *rule)
Definition: cf_parse.c:49
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.
Definition: cf_parse.h:533
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
Definition: cf_parse.c:985
void const * uctx
User data accessible by the cf_parse_t func.
Definition: cf_parse.h:586
void * data
Pointer to a static variable to write the parsed value to.
Definition: cf_parse.h:577
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)
Definition: cf_parse.c:1490
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.
Definition: cf_parse.c:700
bool check_config
Definition: cf_file.c:66
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.
Definition: cf_parse.h:569
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.
Definition: cf_parse.c:1474
fr_type_t type
An fr_type_t value, controls the output type.
Definition: cf_parse.h:567
size_t offset
Relative offset of field or structure to write the parsed value to.
Definition: cf_parse.h:571
char const * name2
Second identifier for CONF_SECTION.
Definition: cf_parse.h:565
fr_token_t quote
Quoting around the default value. Only used for templates.
Definition: cf_parse.h:618
fr_table_num_sorted_t const * table
Definition: cf_parse.h:622
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.
Definition: cf_parse.h:520
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.
Definition: cf_parse.c:126
char const * name1
Name of the CONF_ITEM to parse.
Definition: cf_parse.h:564
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.
Definition: cf_parse.c:1163
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.
Definition: cf_parse.c:1351
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.
Definition: cf_parse.c:1448
cf_parse_t on_read
Function to call as the item is being read, just after it has been allocated and initialized.
Definition: cf_parse.h:583
int cf_pair_parse_value(TALLOC_CTX *ctx, void *out, void *base, CONF_ITEM *ci, conf_parser_t const *rule))
conf_parser_flags_t
Definition: cf_parse.h:397
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition: cf_parse.h:406
@ CONF_FLAG_FILE_OUTPUT
File matching value must exist, and must be writable.
Definition: cf_parse.h:414
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
Definition: cf_parse.h:420
@ CONF_FLAG_SECRET
Only print value if debug level >= 3.
Definition: cf_parse.h:410
@ CONF_FLAG_IS_SET
Write whether this config item was left as the default to is_set_offset or is_set_ptr.
Definition: cf_parse.h:425
@ CONF_FLAG_ATTRIBUTE
Value must resolve to attribute in dict (deprecated, use CONF_FLAG_TMPL).
Definition: cf_parse.h:408
@ CONF_FLAG_FILE_INPUT
File matching value must exist, and must be readable.
Definition: cf_parse.h:412
@ CONF_FLAG_DEPRECATED
If a matching CONF_PAIR is found, error out with a deprecated message.
Definition: cf_parse.h:404
@ CONF_FLAG_NOT_EMPTY
CONF_PAIR is required to have a non zero length value.
Definition: cf_parse.h:421
@ CONF_FLAG_XLAT
string will be dynamically expanded.
Definition: cf_parse.h:417
@ CONF_FLAG_OK_MISSING
OK if it's missing.
Definition: cf_parse.h:428
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition: cf_parse.h:400
@ CONF_FLAG_FILE_EXISTS
File matching value must exist.
Definition: cf_parse.h:423
@ CONF_FLAG_TMPL
CONF_PAIR should be parsed as a template.
Definition: cf_parse.h:418
@ CONF_FLAG_HIDDEN
Used by scripts to omit items from the generated documentation.
Definition: cf_parse.h:398
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:563
Common header for all CONF_* types.
Definition: cf_priv.h:49
Configuration AVP similar to a fr_pair_t.
Definition: cf_priv.h:70
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:89
fr_type_t
Definition: merged_model.c:80
static char const * name
fr_aka_sim_id_type_t type
An element in a lexicographically sorted array of name to num mappings.
Definition: table.h:45
enum fr_token fr_token_t
static fr_slen_t parent
Definition: pair.h:844
static fr_slen_t data
Definition: value.h:1259
int nonnull(2, 5))
static size_t char ** out
Definition: value.h:984