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: b30974bcbe2a9ef4556bdcdd6b6b19db57ffff71 $
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: b30974bcbe2a9ef4556bdcdd6b6b19db57ffff71 $")
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_NONE = 0, //!< No special flags.
399  CONF_FLAG_SUBSECTION = (1 << 1), //!< Instead of putting the information into a
400  ///< configuration structure, the configuration
401  ///< file routines MAY just parse it directly into
402  ///< user-supplied variables.
403  CONF_FLAG_DEPRECATED = (1 << 10), //!< If a matching #CONF_PAIR is found,
404  //!< error out with a deprecated message.
405  CONF_FLAG_REQUIRED = (1 << 11), //!< Error out if no matching #CONF_PAIR
406  //!< is found, and no dflt value is set.
407  CONF_FLAG_ATTRIBUTE = (1 << 12), //!< Value must resolve to attribute in dict
408  //!< (deprecated, use #CONF_FLAG_TMPL).
409  CONF_FLAG_SECRET = (1 << 13), //!< Only print value if debug level >= 3.
410 
411  CONF_FLAG_FILE_INPUT = (1 << 14), //!< File matching value must exist,
412  //!< and must be readable.
413  CONF_FLAG_FILE_OUTPUT = (1 << 15), //!< File matching value must exist,
414  //!< and must be writable.
415 
416  CONF_FLAG_XLAT = (1 << 16), //!< string will be dynamically expanded.
417  CONF_FLAG_TMPL = (1 << 17), //!< CONF_PAIR should be parsed as a template.
418 
419  CONF_FLAG_MULTI = (1 << 18), //!< CONF_PAIR can have multiple copies.
420  CONF_FLAG_NOT_EMPTY = (1 << 19), //!< CONF_PAIR is required to have a non zero
421  //!< length value.
422  CONF_FLAG_FILE_EXISTS = (1 << 20), //!< File matching value must exist
423 
424  CONF_FLAG_IS_SET = (1 << 21), //!< Write whether this config item was
425  //!< left as the default to is_set_offset
426  //!< or is_set_ptr.
427  CONF_FLAG_OK_MISSING = (1 << 22), //!< OK if it's missing
428  CONF_FLAG_HIDDEN = (1 << 23), //!< Used by scripts to omit items from the
429  ///< generated documentation.
431 DIAG_ON(attributes)
432 
433 /** @} */
434 
435 /** @name #conf_parser_t flags checks
436  *
437  * @{
438  */
439 #define fr_rule_deprecated(_rule) ((_rule)->flags & CONF_FLAG_DEPRECATED)
440 
441 #define fr_rule_required(_rule) ((_rule)->flags & CONF_FLAG_REQUIRED)
442 
443 #define fr_rule_secret(_rule) ((_rule)->flags & CONF_FLAG_SECRET)
444 
445 #define fr_rule_file_input(_rule) ((_rule)->flags & CONF_FLAG_FILE_INPUT)
446 
447 #define fr_rule_file_output(_rule) ((_rule)->flags & CONF_FLAG_FILE_OUTPUT)
448 
449 
450 #define fr_rule_multi(_rule) ((_rule)->flags & CONF_FLAG_MULTI)
451 
452 #define fr_rule_not_empty(_rule) ((_rule)->flags & CONF_FLAG_NOT_EMPTY)
453 
454 #define fr_rule_is_set(_rule) ((_rule)->flags & CONF_FLAG_IS_SET)
455 
456 #define fr_rule_ok_missing(_rule) ((_rule)->flags & CONF_FLAG_OK_MISSING)
457 
458 #define fr_rule_file_exists(_rule) ((_rule)->flags & CONF_FLAG_FILE_EXISTS)
459 
460 #define fr_rule_dflt(_rule) ((_rule)->dflt || (_rule)->dflt_func)
461 
462 #define fr_rule_is_attribute(_rule) ((_rule)->flags & CONF_FLAG_ATTRIBUTE)
463 
464 #define fr_rule_is_xlat(_rule) ((_rule)->flags & CONF_FLAG_XLAT)
465 
466 #define fr_rule_is_tmpl(_rule) ((_rule)->flags & CONF_FLAG_TMPL)
467 /** @} */
468 
469 #define FR_SIZE_COND_CHECK(_name, _var, _cond, _new)\
470 do {\
471  if (!(_cond)) {\
472  WARN("Ignoring \"" _name " = %zu\", forcing to \"" _name " = %zu\"", _var, _new);\
473  _var = _new;\
474  }\
475 } while (0)
476 
477 #define FR_SIZE_BOUND_CHECK(_name, _var, _op, _bound) FR_SIZE_COND_CHECK(_name, _var, (_var _op _bound), _bound)
478 
479 #define FR_INTEGER_COND_CHECK(_name, _var, _cond, _new)\
480 do {\
481  if (!(_cond)) {\
482  WARN("Ignoring \"" _name " = %i\", forcing to \"" _name " = %i\"", _var, _new);\
483  _var = _new;\
484  }\
485 } while (0)
486 
487 #define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound) FR_INTEGER_COND_CHECK(_name, _var, (_var _op _bound), _bound)
488 
489 #define FR_TIME_DELTA_COND_CHECK(_name, _var, _cond, _new)\
490 do {\
491  if (!(_cond)) {\
492  WARN("Ignoring \"" _name " = %pV\", forcing to \"" _name " = %pV\"", \
493  fr_box_time_delta(_var), fr_box_time_delta(_new));\
494  _var = _new;\
495  }\
496 } while (0)
497 
498 #define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)\
499 do {\
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));\
504  _var = _bound;\
505  }\
506 } while (0)
507 
508 extern bool check_config;
509 
510 /** Callback for performing custom parsing of a #CONF_SECTION or CONF_PAIR
511  *
512  * @param[in] ctx to allocate any data in.
513  * @param[out] out Where to write the result of parsing.
514  * @param[in] parent The base address of the structure.
515  * @param[in] ci The #CONF_SECTION or #CONF_PAIR to parse.
516  * @param[in] rule Parse rules - How the #CONF_PAIR or #CONF_SECTION should be converted.
517  * @return
518  * - 0 on success.
519  * - -1 on failure.
520  */
521 typedef int (*cf_parse_t)(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
522 
523 /** Callback for producing dynamic defaults from 3rd party libraries
524  *
525  * @param[out] out Where to write default conf pair.
526  * @param[in] parent being populated.
527  * @param[in] cs to allocate pair in.
528  * @param[in] quote to use when allocing the pair. Provided as a convenience.
529  * @param[in] rule to produce default for.
530  * @return
531  * - 0 on success.
532  * - -1 on failure.
533  */
534 typedef int (*cf_dflt_t)(CONF_PAIR **out, void *parent, CONF_SECTION *cs, fr_token_t quote, conf_parser_t const *rule);
535 
536 /** Defines a #CONF_PAIR to C data type mapping
537  *
538  * Is typically used to define mappings between module sections, and module instance structs.
539  * May also be used to set global configuration options.
540  *
541  * Offset/data values should be set using #FR_CONF_OFFSET or #FR_CONF_POINTER.
542  *
543  * Example with #FR_CONF_OFFSET :
544  @code{.c}
545  static conf_parser_t module_config[] = {
546  { FR_CONF_OFFSET_TYPE_FLAGS("example", FR_TYPE_STRING | CONF_FLAG_NOT_EMPTY, 0, 0, example_instance_t, example), .dflt = "default_value" },
547  CONF_PARSER_TERMINATOR
548  }
549  @endcode
550  *
551  * Example with #FR_CONF_POINTER :
552  @code{.c}
553  static conf_parser_t global_config[] = {
554  { FR_CONF_POINTER("example", FR_TYPE_STRING | CONF_FLAG_NOT_EMPTY, 0, 0, 0, &my_global), .dflt = "default_value" },
555  CONF_PARSER_TERMINATOR
556  }
557  @endcode
558  *
559  * @see FR_CONF_OFFSET
560  * @see FR_CONF_POINTER
561  * @see cf_section_parse
562  * @see cf_pair_parse
563  */
565  char const *name1; //!< Name of the #CONF_ITEM to parse.
566  char const *name2; //!< Second identifier for #CONF_SECTION.
567 
568  fr_type_t type; //!< An #fr_type_t value, controls the output type.
569 
570  conf_parser_flags_t flags; //!< Flags which control parsing behaviour.
571 
572  size_t offset; //!< Relative offset of field or structure to write the parsed value to.
573  //!< When #flags is set to #CONF_FLAG_SUBSECTION, may be used to specify
574  //!< a base offset to add to all offsets contained within the
575  //!< subsection.
576  //!< @note Must be used exclusively to #data.
577 
578  void *data; //!< Pointer to a static variable to write the parsed value to.
579  //!< @note Must be used exclusively to #offset.
580 
581  cf_parse_t func; //!< Override default parsing behaviour for the specified type with
582  //!< a custom parsing function.
583 
584  cf_parse_t on_read; //!< Function to call as the item is being read, just after
585  //!< it has been allocated and initialized.
586 
587  void const *uctx; //!< User data accessible by the #cf_parse_t func. Useful for
588  ///< building reusable functions.
589 
590  /** Where to write status if FR_TYPE_IS_DEFAULT is set
591  *
592  * @note Which field is used, is determined by whether
593  * data ptr is set.
594  */
595  union {
596  size_t is_set_offset; //!< If type contains FR_TYPE_IS_DEFAULT write status to bool.
597  //!< at this address.
598  void *is_set_ptr; //!< If type contains FR_TYPE_IS_DEFAULT write status to ptr
599  //!< at this address.
600  };
601 
602  union {
603  struct {
604  char const *dflt; //!< Default as it would appear in radiusd.conf.
605 
606  cf_dflt_t dflt_func; //!< Function to produce dynamic defaults.
607  };
608 
609  struct {
610  conf_parser_t const *subcs; //!< When #CONF_FLAG_SUBSECTION is set, should
611  //!< be a pointer to the start of another array of
612  //!< #conf_parser_t structs, forming the subsection.
613  size_t subcs_size; //!< If non-zero, allocate structs of this size to hold
614  //!< the parsed data.
615  char const *subcs_type; //!< Set a specific talloc type for subcs structures.
616  };
617  };
618 
619  fr_token_t quote; //!< Quoting around the default value. Only used for templates.
620 };
621 
622 typedef struct {
624  size_t *len;
626 
627 #define CONF_PARSER_TERMINATOR { .name1 = NULL, .type = ~(UINT32_MAX - 1), \
628  .offset = 0, .data = NULL, .dflt = NULL, .quote = T_INVALID }
629 
630 #define CONF_PARSER_PARTIAL_TERMINATOR { .name1 = NULL, .type = ~(UINT32_MAX - 1), \
631  .offset = 1, .data = NULL, .dflt = NULL, .quote = T_INVALID }
632 
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)
637 
638 void cf_pair_debug_log(CONF_SECTION const *cs, CONF_PAIR *cp, conf_parser_t const *rule);
639 
640 /*
641  * Type validation and conversion
642  */
643 int cf_pair_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *out, CONF_PAIR *cp, conf_parser_t const *rule)
644  CC_HINT(nonnull(2, 3, 4));
645 
646 int cf_pair_parse_value(TALLOC_CTX *ctx, void *out, void *base, CONF_ITEM *ci, conf_parser_t const *rule)
647  CC_HINT(nonnull(2, 4, 5));
648 
649 int cf_pair_parse(TALLOC_CTX *ctx, CONF_SECTION *cs, char const *name,
650  unsigned int type, void *data, char const *dflt, fr_token_t dflt_quote) CC_HINT(nonnull(2,3));
651 int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs);
652 int cf_section_parse_pass2(void *base, CONF_SECTION *cs);
653 
654 /*
655  * Runtime parse rules
656  */
657 #define cf_section_rule_push(_cs, _rule) _cf_section_rule_push(_cs, _rule, __FILE__, __LINE__)
658 int _cf_section_rule_push(CONF_SECTION *cs, conf_parser_t const *rule, char const *filename, int lineno);
659 #define cf_section_rules_push(_cs, _rule) _cf_section_rules_push(_cs, _rule, __FILE__, __LINE__)
660 int _cf_section_rules_push(CONF_SECTION *cs, conf_parser_t const *rules, char const *filename, int lineno);
661 
662 /*
663  * Generic parsing callback functions
664  */
665 int cf_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
666  CONF_ITEM *ci, conf_parser_t const *rule);
667 
668 int cf_table_parse_uint32(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
669  CONF_ITEM *ci, conf_parser_t const *rule);
670 
671 int cf_table_parse_int32(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
672  CONF_ITEM *ci, conf_parser_t const *rule);
673 
674 int cf_parse_uid(TALLOC_CTX *ctx, void *out, UNUSED void *parent,
675  CONF_ITEM *ci, conf_parser_t const *rule);
676 
677 int cf_parse_gid(TALLOC_CTX *ctx, void *out, UNUSED void *parent,
678  CONF_ITEM *ci, conf_parser_t const *rule);
679 
680 #ifdef __cplusplus
681 }
682 #endif
#define DIAG_ON(_x)
Definition: build.h:456
#define RCSIDH(h, id)
Definition: build.h:482
#define UNUSED
Definition: build.h:313
#define DIAG_OFF(_x)
Definition: build.h:455
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition: cf_parse.h:581
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
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:534
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:587
void * data
Pointer to a static variable to write the parsed value to.
Definition: cf_parse.h:578
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:67
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:570
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:568
size_t offset
Relative offset of field or structure to write the parsed value to.
Definition: cf_parse.h:572
char const * name2
Second identifier for CONF_SECTION.
Definition: cf_parse.h:566
void cf_pair_debug_log(CONF_SECTION const *cs, CONF_PAIR *cp, conf_parser_t const *rule)
Definition: cf_parse.c:49
fr_token_t quote
Quoting around the default value. Only used for templates.
Definition: cf_parse.h:619
fr_table_num_sorted_t const * table
Definition: cf_parse.h:623
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:521
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:565
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:584
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:405
@ CONF_FLAG_FILE_OUTPUT
File matching value must exist, and must be writable.
Definition: cf_parse.h:413
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
Definition: cf_parse.h:419
@ CONF_FLAG_SECRET
Only print value if debug level >= 3.
Definition: cf_parse.h:409
@ 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:424
@ CONF_FLAG_ATTRIBUTE
Value must resolve to attribute in dict (deprecated, use CONF_FLAG_TMPL).
Definition: cf_parse.h:407
@ CONF_FLAG_FILE_INPUT
File matching value must exist, and must be readable.
Definition: cf_parse.h:411
@ CONF_FLAG_DEPRECATED
If a matching CONF_PAIR is found, error out with a deprecated message.
Definition: cf_parse.h:403
@ CONF_FLAG_NONE
No special flags.
Definition: cf_parse.h:398
@ CONF_FLAG_NOT_EMPTY
CONF_PAIR is required to have a non zero length value.
Definition: cf_parse.h:420
@ CONF_FLAG_XLAT
string will be dynamically expanded.
Definition: cf_parse.h:416
@ CONF_FLAG_OK_MISSING
OK if it's missing.
Definition: cf_parse.h:427
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition: cf_parse.h:399
@ CONF_FLAG_FILE_EXISTS
File matching value must exist.
Definition: cf_parse.h:422
@ CONF_FLAG_TMPL
CONF_PAIR should be parsed as a template.
Definition: cf_parse.h:417
@ CONF_FLAG_HIDDEN
Used by scripts to omit items from the generated documentation.
Definition: cf_parse.h:428
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:564
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:101
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:49
enum fr_token fr_token_t
static fr_slen_t parent
Definition: pair.h:851
static fr_slen_t data
Definition: value.h:1265
int nonnull(2, 5))
static size_t char ** out
Definition: value.h:997