The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
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: b7a3496ac94f0ac08ffcea07762945608cb05e29 $
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 */
26RCSIDH(cf_parse_h, "$Id: b7a3496ac94f0ac08ffcea07762945608cb05e29 $")
27
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
41extern "C" {
42#endif
43
44#ifdef HAVE_BUILTIN_CHOOSE_EXPR
45typedef void _mismatch_abinary_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
46typedef void _mismatch_abinary; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
47typedef void _mismatch_bool_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
48typedef void _mismatch_bool; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
49typedef void _mismatch_char_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
50typedef void _mismatch_char; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
51typedef void _mismatch_double_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
52typedef void _mismatch_double; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
53typedef void _mismatch_ethernet_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
54typedef void _mismatch_ethernet; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
55typedef void _mismatch_float_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
56typedef void _mismatch_float; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
57typedef void _mismatch_fripaddr_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
58typedef void _mismatch_fripaddr; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
59typedef void _mismatch_ifid_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
60typedef void _mismatch_ifid; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
61typedef void _mismatch_int32_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
62typedef void _mismatch_int32; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
63typedef void _mismatch_size_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
64typedef void _mismatch_size; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
65typedef void _mismatch_time_delta_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
66typedef void _mismatch_time_delta; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
67typedef void _mismatch_time_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
68typedef void _mismatch_time; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
69typedef void _mismatch_uint16_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
70typedef void _mismatch_uint16; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
71typedef void _mismatch_uint32_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
72typedef void _mismatch_uint32; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
73typedef void _mismatch_uint64_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
74typedef void _mismatch_uint64; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
75typedef void _mismatch_uint8_m_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
76typedef void _mismatch_uint8_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
77typedef void _mismatch_uint8; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
78typedef void _mismatch_void_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
79typedef void _mismatch_void; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
80typedef void _mismatch_tmpl_m; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
81typedef void _mismatch_vp_tmpl; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
82
83
84typedef void _mismatch_default; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
85typedef void conf_type_mismatch; //!< Dummy type used to indicate FR_TYPE_*/C type mismatch.
86typedef 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 populates a sub-struct using a CONF_SECTION
304 *
305 * @param[in] _name of the CONF_SECTION to search for.
306 * @param[in] _struct containing the sub-struct to populate.
307 * @param[in] _field containing the sub-struct to populate.
308 * @param[in] _subcs conf_parser_t to include in-line in this section
309 */
310# define FR_CONF_OFFSET_REF(_struct, _field, _subcs) \
311 .name1 = CF_IDENT_ANY, \
312 .flags = CONF_FLAG_REF, \
313 .offset = offsetof(_struct, _field), \
314 .subcs = _subcs
315
316/** conf_parser_t which parses a single CONF_PAIR producing a single global result
317 *
318 * @param[in] _name of the CONF_PAIR to search for.
319 * @param[in] _type to parse the CONF_PAIR as.
320 * @param[in] _flags controlling parsing behaviour.
321 * @param[out] _res_p pointer to a global var, where the result will be written.
322 */
323# define FR_CONF_POINTER(_name, _type, _flags, _res_p) \
324 .name1 = _name, \
325 .type = (_type), \
326 .flags = (_flags), \
327 .data = FR_CONF_FLAG_CHECK((_type), (_flags), (_res_p), _res_p)
328
329/** 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
330 *
331 * @note is set state is recorded in variable `<_res_p>`_is_set.
332 *
333 * @param[in] _name of the CONF_PAIR to search for.
334 * @param[in] _type to parse the CONF_PAIR as.
335 * @param[in] _flags controlling parsing behaviour.
336 * @param[out] _res_p pointer to a global var, where the result will be written.
337 */
338# define FR_CONF_POINTER_IS_SET(_name, _type, _flags, _res_p) \
339 .name1 = _name, \
340 .type = (_type), \
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)
345
346/** A conf_parser_t multi-subsection
347 *
348 * Parse multiple instance of a subsection, allocating an array of structs
349 * to hold the result.
350 *
351 * @param[in] _name name of subsection to search for.
352 * @param[in] _type the output type.
353 * @param[in] _flags flags controlling parsing behaviour.
354 * @param[in] _struct instance data struct.
355 * @param[in] _field field in instance data struct.
356 * @param[in] _subcs conf_parser_t array to use to parse subsection data.
357 */
358# define FR_CONF_SUBSECTION_ALLOC(_name, _type, _flags, _struct, _field, _subcs) \
359 .name1 = _name, \
360 .type = (_type), \
361 .flags = (_flags), \
362 .offset = FR_CONF_FLAG_CHECK((_type), (_flags), &(((_struct *)NULL)->_field), offsetof(_struct, _field)), \
363 .subcs = _subcs, \
364 .subcs_size = sizeof(**(((_struct *)0)->_field))
365
366/** conf_parser_t entry which doesn't fill in a pointer or offset, but relies on functions to record values
367 *
368 * @param[in] _name name of pair to search for.
369 * @param[in] _type base type to parse pair as.
370 * @param[in] _flags flags controlling parsing behaviour.
371 * @param[in] _func to use to record value.
372 * @param[in] _dflt_func to use to get defaults from a 3rd party library.
373 */
374# define FR_CONF_FUNC(_name, _type, _flags, _func, _dflt_func) \
375 .name1 = _name, \
376 .type = (_type), \
377 .flags = (_flags), \
378 .func = _func, \
379 .dflt_func = _dflt_func
380
381/** conf_parser_t entry which runs conf_parser_t entries for a subsection without any output
382 *
383 * @param[in] _name of pair to search for.
384 * @param[in] _flags flags controlling parsing behaviour.
385 * @param[in] _subcs to use to get defaults from a 3rd party library.
386 */
387# define FR_CONF_SUBSECTION_GLOBAL(_name, _flags, _subcs) \
388 .name1 = _name, \
389 .flags = CONF_FLAG_SUBSECTION | (_flags), \
390 .subcs = _subcs
391
392/** conf_parser_t entry which raises an error if a matching CONF_PAIR is found
393 *
394 * @param[in] _name of pair to search for.
395 * @param[in] _struct where the result was previously written.
396 * @param[in] _field in the struct where the result was previously written.
397 */
398#define FR_CONF_DEPRECATED(_name, _struct, _field) \
399 .name1 = _name, \
400 .flags = CONF_FLAG_DEPRECATED
401
402/** @name #conf_parser_t type flags
403 *
404 * These flags should be or'd with another FR_TYPE_* value to create validation
405 * rules for the #cf_pair_parse function.
406 *
407 * @{
408 */
409DIAG_OFF(attributes)
410typedef enum CC_HINT(flag_enum) {
411 CONF_FLAG_NONE = 0, //!< No special flags.
412 CONF_FLAG_SUBSECTION = (1 << 1), //!< Instead of putting the information into a
413 ///< configuration structure, the configuration
414 ///< file routines MAY just parse it directly into
415 ///< user-supplied variables.
416 CONF_FLAG_DEPRECATED = (1 << 10), //!< If a matching #CONF_PAIR is found,
417 //!< error out with a deprecated message.
418 CONF_FLAG_REQUIRED = (1 << 11), //!< Error out if no matching #CONF_PAIR
419 //!< is found, and no dflt value is set.
420 CONF_FLAG_ATTRIBUTE = (1 << 12), //!< Value must resolve to attribute in dict
421 //!< (deprecated, use #CONF_FLAG_TMPL).
422 CONF_FLAG_SECRET = (1 << 13), //!< Only print value if debug level >= 3.
423
424 CONF_FLAG_FILE_INPUT = (1 << 14), //!< File matching value must exist,
425 //!< and must be readable.
426 CONF_FLAG_FILE_OUTPUT = (1 << 15), //!< File matching value must exist,
427 //!< and must be writable.
428
429 CONF_FLAG_XLAT = (1 << 16), //!< string will be dynamically expanded.
430 CONF_FLAG_TMPL = (1 << 17), //!< CONF_PAIR should be parsed as a template.
431
432 CONF_FLAG_MULTI = (1 << 18), //!< CONF_PAIR can have multiple copies.
433 CONF_FLAG_NOT_EMPTY = (1 << 19), //!< CONF_PAIR is required to have a non zero
434 //!< length value.
435 CONF_FLAG_FILE_EXISTS = (1 << 20), //!< File matching value must exist
436
437 CONF_FLAG_IS_SET = (1 << 21), //!< Write whether this config item was
438 //!< left as the default to is_set_offset
439 //!< or is_set_ptr.
440 CONF_FLAG_OK_MISSING = (1 << 22), //!< OK if it's missing
441 CONF_FLAG_HIDDEN = (1 << 23), //!< Used by scripts to omit items from the
442 ///< generated documentation.
443 CONF_FLAG_REF = (1 << 24), //!< reference another conf_parser_t inline in this one
444 CONF_FLAG_OPTIONAL = (1 << 25), //!< subsection is pushed only if a non-optional matching one is pushed
446DIAG_ON(attributes)
447
448/** @} */
449
450/** @name #conf_parser_t flags checks
451 *
452 * @{
453 */
454#define fr_rule_deprecated(_rule) ((_rule)->flags & CONF_FLAG_DEPRECATED)
455
456#define fr_rule_required(_rule) ((_rule)->flags & CONF_FLAG_REQUIRED)
457
458#define fr_rule_secret(_rule) ((_rule)->flags & CONF_FLAG_SECRET)
459
460#define fr_rule_file_input(_rule) ((_rule)->flags & CONF_FLAG_FILE_INPUT)
461
462#define fr_rule_file_output(_rule) ((_rule)->flags & CONF_FLAG_FILE_OUTPUT)
463
464
465#define fr_rule_multi(_rule) ((_rule)->flags & CONF_FLAG_MULTI)
466
467#define fr_rule_not_empty(_rule) ((_rule)->flags & CONF_FLAG_NOT_EMPTY)
468
469#define fr_rule_is_set(_rule) ((_rule)->flags & CONF_FLAG_IS_SET)
470
471#define fr_rule_ok_missing(_rule) ((_rule)->flags & CONF_FLAG_OK_MISSING)
472
473#define fr_rule_file_exists(_rule) ((_rule)->flags & CONF_FLAG_FILE_EXISTS)
474
475#define fr_rule_dflt(_rule) ((_rule)->dflt || (_rule)->dflt_func)
476
477#define fr_rule_is_attribute(_rule) ((_rule)->flags & CONF_FLAG_ATTRIBUTE)
478
479#define fr_rule_is_xlat(_rule) ((_rule)->flags & CONF_FLAG_XLAT)
480
481#define fr_rule_is_tmpl(_rule) ((_rule)->flags & CONF_FLAG_TMPL)
482/** @} */
483
484#define FR_SIZE_COND_CHECK(_name, _var, _cond, _new)\
485do {\
486 if (!(_cond)) {\
487 WARN("Ignoring \"" _name " = %zu\", forcing to \"" _name " = %zu\"", _var, _new);\
488 _var = _new;\
489 }\
490} while (0)
491
492#define FR_SIZE_BOUND_CHECK(_name, _var, _op, _bound) FR_SIZE_COND_CHECK(_name, _var, (_var _op _bound), _bound)
493
494#define FR_INTEGER_COND_CHECK(_name, _var, _cond, _new)\
495do {\
496 if (!(_cond)) {\
497 WARN("Ignoring \"" _name " = %u\", forcing to \"" _name " = %u\"", (unsigned int) (_var), (unsigned int) (_new));\
498 _var = _new;\
499 }\
500} while (0)
501
502#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound) FR_INTEGER_COND_CHECK(_name, _var, (_var _op _bound), _bound)
503
504#define FR_TIME_DELTA_COND_CHECK(_name, _var, _cond, _new)\
505do {\
506 if (!(_cond)) {\
507 WARN("Ignoring \"" _name " = %pV\", forcing to \"" _name " = %pV\"", \
508 fr_box_time_delta(_var), fr_box_time_delta(_new));\
509 _var = _new;\
510 }\
511} while (0)
512
513#define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)\
514do {\
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));\
519 _var = _bound;\
520 }\
521} while (0)
522
523extern bool check_config;
524
525/** Callback for performing custom parsing of a #CONF_SECTION or CONF_PAIR
526 *
527 * @param[in] ctx to allocate any data in.
528 * @param[out] out Where to write the result of parsing.
529 * @param[in] parent The base address of the structure.
530 * @param[in] ci The #CONF_SECTION or #CONF_PAIR to parse.
531 * @param[in] rule Parse rules - How the #CONF_PAIR or #CONF_SECTION should be converted.
532 * @return
533 * - 0 on success.
534 * - -1 on failure.
535 */
536typedef int (*cf_parse_t)(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
537
538/** Callback for producing dynamic defaults from 3rd party libraries
539 *
540 * @param[out] out Where to write default conf pair.
541 * @param[in] parent being populated.
542 * @param[in] cs to allocate pair in.
543 * @param[in] quote to use when allocing the pair. Provided as a convenience.
544 * @param[in] rule to produce default for.
545 * @return
546 * - 0 on success.
547 * - -1 on failure.
548 */
549typedef int (*cf_dflt_t)(CONF_PAIR **out, void *parent, CONF_SECTION *cs, fr_token_t quote, conf_parser_t const *rule);
550
551/** Defines a #CONF_PAIR to C data type mapping
552 *
553 * Is typically used to define mappings between module sections, and module instance structs.
554 * May also be used to set global configuration options.
555 *
556 * Offset/data values should be set using #FR_CONF_OFFSET or #FR_CONF_POINTER.
557 *
558 * Example with #FR_CONF_OFFSET :
559 @code{.c}
560 static conf_parser_t module_config[] = {
561 { FR_CONF_OFFSET_TYPE_FLAGS("example", FR_TYPE_STRING | CONF_FLAG_NOT_EMPTY, 0, 0, example_instance_t, example), .dflt = "default_value" },
562 CONF_PARSER_TERMINATOR
563 }
564 @endcode
565 *
566 * Example with #FR_CONF_POINTER :
567 @code{.c}
568 static conf_parser_t global_config[] = {
569 { FR_CONF_POINTER("example", FR_TYPE_STRING | CONF_FLAG_NOT_EMPTY, 0, 0, 0, &my_global), .dflt = "default_value" },
570 CONF_PARSER_TERMINATOR
571 }
572 @endcode
573 *
574 * @see FR_CONF_OFFSET
575 * @see FR_CONF_POINTER
576 * @see cf_section_parse
577 * @see cf_pair_parse
578 */
580 char const *name1; //!< Name of the #CONF_ITEM to parse.
581 char const *name2; //!< Second identifier for #CONF_SECTION.
582
583 fr_type_t type; //!< An #fr_type_t value, controls the output type.
584
585 conf_parser_flags_t flags; //!< Flags which control parsing behaviour.
586
587 size_t offset; //!< Relative offset of field or structure to write the parsed value to.
588 //!< When #flags is set to #CONF_FLAG_SUBSECTION, may be used to specify
589 //!< a base offset to add to all offsets contained within the
590 //!< subsection.
591 //!< @note Must be used exclusively to #data.
592
593 void *data; //!< Pointer to a static variable to write the parsed value to.
594 //!< @note Must be used exclusively to #offset.
595
596 cf_parse_t func; //!< Override default parsing behaviour for the specified type with
597 //!< a custom parsing function.
598
599 cf_parse_t on_read; //!< Function to call as the item is being read, just after
600 //!< it has been allocated and initialized.
601
602 void const *uctx; //!< User data accessible by the #cf_parse_t func. Useful for
603 ///< building reusable functions.
604
605 /** Where to write status if FR_TYPE_IS_DEFAULT is set
606 *
607 * @note Which field is used, is determined by whether
608 * data ptr is set.
609 */
610 union {
611 size_t is_set_offset; //!< If type contains FR_TYPE_IS_DEFAULT write status to bool.
612 //!< at this address.
613 void *is_set_ptr; //!< If type contains FR_TYPE_IS_DEFAULT write status to ptr
614 //!< at this address.
615 };
616
617 union {
618 struct {
619 char const *dflt; //!< Default as it would appear in radiusd.conf.
620
621 cf_dflt_t dflt_func; //!< Function to produce dynamic defaults.
622 };
623
624 struct {
625 conf_parser_t const *subcs; //!< When #CONF_FLAG_SUBSECTION is set, should
626 //!< be a pointer to the start of another array of
627 //!< #conf_parser_t structs, forming the subsection.
628 size_t subcs_size; //!< If non-zero, allocate structs of this size to hold
629 //!< the parsed data.
630 char const *subcs_type; //!< Set a specific talloc type for subcs structures.
631 };
632 };
633
634 fr_token_t quote; //!< Quoting around the default value. Only used for templates.
635};
636
637typedef struct {
639 size_t *len;
641
642#define CONF_PARSER_TERMINATOR { .name1 = NULL, .type = ~(UINT32_MAX - 1), \
643 .offset = 0, .data = NULL, .dflt = NULL, .quote = T_INVALID }
644
645#define CONF_PARSER_PARTIAL_TERMINATOR { .name1 = NULL, .type = ~(UINT32_MAX - 1), \
646 .offset = 1, .data = NULL, .dflt = NULL, .quote = T_INVALID }
647
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)
652
653void cf_pair_debug_log(CONF_SECTION const *cs, CONF_PAIR *cp, conf_parser_t const *rule);
654
655/*
656 * Type validation and conversion
657 */
658int cf_pair_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *out, CONF_PAIR *cp, conf_parser_t const *rule)
659 CC_HINT(nonnull(2, 3, 4));
660
661int cf_pair_parse_value(TALLOC_CTX *ctx, void *out, void *base, CONF_ITEM *ci, conf_parser_t const *rule)
662 CC_HINT(nonnull(2, 4, 5));
663
664int cf_pair_parse(TALLOC_CTX *ctx, CONF_SECTION *cs, char const *name,
665 unsigned int type, void *data, char const *dflt, fr_token_t dflt_quote) CC_HINT(nonnull(2,3));
666int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs);
667int cf_section_parse_pass2(void *base, CONF_SECTION *cs);
668
669/*
670 * Runtime parse rules
671 */
672#define cf_section_rule_push(_cs, _rule) _cf_section_rule_push(_cs, _rule, __FILE__, __LINE__)
673int _cf_section_rule_push(CONF_SECTION *cs, conf_parser_t const *rule, char const *filename, int lineno);
674#define cf_section_rules_push(_cs, _rule) _cf_section_rules_push(_cs, _rule, __FILE__, __LINE__)
675int _cf_section_rules_push(CONF_SECTION *cs, conf_parser_t const *rules, char const *filename, int lineno);
676
677/*
678 * Generic parsing callback functions
679 */
680int cf_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
681 CONF_ITEM *ci, conf_parser_t const *rule);
682
683int cf_table_parse_uint32(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
684 CONF_ITEM *ci, conf_parser_t const *rule);
685
686int cf_table_parse_int32(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
687 CONF_ITEM *ci, conf_parser_t const *rule);
688
689int cf_parse_uid(TALLOC_CTX *ctx, void *out, UNUSED void *parent,
690 CONF_ITEM *ci, conf_parser_t const *rule);
691
692int cf_parse_gid(TALLOC_CTX *ctx, void *out, UNUSED void *parent,
693 CONF_ITEM *ci, conf_parser_t const *rule);
694
695int cf_parse_permissions(TALLOC_CTX *ctx, void *out, UNUSED void *parent,
696 CONF_ITEM *ci, conf_parser_t const *rule);
697
698#ifdef __cplusplus
699}
700#endif
#define DIAG_ON(_x)
Definition build.h:458
#define RCSIDH(h, id)
Definition build.h:484
#define UNUSED
Definition build.h:315
#define DIAG_OFF(_x)
Definition build.h:457
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition cf_parse.h:596
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:1582
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:549
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
Definition cf_parse.c:1124
void const * uctx
User data accessible by the cf_parse_t func.
Definition cf_parse.h:602
void * data
Pointer to a static variable to write the parsed value to.
Definition cf_parse.h:593
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:1566
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:585
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:1550
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.
Definition cf_parse.h:583
size_t offset
Relative offset of field or structure to write the parsed value to.
Definition cf_parse.h:587
char const * name2
Second identifier for CONF_SECTION.
Definition cf_parse.h:581
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:634
fr_table_num_sorted_t const * table
Definition cf_parse.h:638
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:536
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:580
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:1232
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:1420
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:1524
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:599
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:410
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:418
@ CONF_FLAG_FILE_OUTPUT
File matching value must exist, and must be writable.
Definition cf_parse.h:426
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
Definition cf_parse.h:432
@ CONF_FLAG_REF
reference another conf_parser_t inline in this one
Definition cf_parse.h:443
@ CONF_FLAG_SECRET
Only print value if debug level >= 3.
Definition cf_parse.h:422
@ 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:437
@ CONF_FLAG_ATTRIBUTE
Value must resolve to attribute in dict (deprecated, use CONF_FLAG_TMPL).
Definition cf_parse.h:420
@ CONF_FLAG_FILE_INPUT
File matching value must exist, and must be readable.
Definition cf_parse.h:424
@ CONF_FLAG_DEPRECATED
If a matching CONF_PAIR is found, error out with a deprecated message.
Definition cf_parse.h:416
@ CONF_FLAG_NONE
No special flags.
Definition cf_parse.h:411
@ CONF_FLAG_NOT_EMPTY
CONF_PAIR is required to have a non zero length value.
Definition cf_parse.h:433
@ CONF_FLAG_XLAT
string will be dynamically expanded.
Definition cf_parse.h:429
@ CONF_FLAG_OPTIONAL
subsection is pushed only if a non-optional matching one is pushed
Definition cf_parse.h:444
@ CONF_FLAG_OK_MISSING
OK if it's missing.
Definition cf_parse.h:440
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:412
@ CONF_FLAG_FILE_EXISTS
File matching value must exist.
Definition cf_parse.h:435
@ CONF_FLAG_TMPL
CONF_PAIR should be parsed as a template.
Definition cf_parse.h:430
@ CONF_FLAG_HIDDEN
Used by scripts to omit items from the generated documentation.
Definition cf_parse.h:441
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:579
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
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