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