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: aada8f866edabf5329af3a20783f7f5620805235 $
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: aada8f866edabf5329af3a20783f7f5620805235 $")
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 output hint type. If the type is a bare word, it MUST be of the relevant data type.
250 *
251 * @param[in] _name of the CONF_PAIR to search for.
252 * @param[in] _type to parse the CONF_PAIR as.
253 * @param[in] _flags controlling parsing behaviour.
254 * @param[in] _struct containing the field to write the result to.
255 * @param[in] _field to write the result to.
256 */
257# define FR_CONF_OFFSET_HINT_TYPE(_name, _type, _struct, _field) \
258 .name1 = _name, \
259 .type = (_type), \
260 .flags = CONF_FLAG_TMPL, \
261 .offset = FR_CONF_FLAG_CHECK(FR_TYPE_VOID, CONF_FLAG_TMPL, &(((_struct *)NULL)->_field), offsetof(_struct, _field))
262
263/** conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
264 *
265 * This variant takes additional flags, and will add CONF_FLAG_MULTI automatically if the field is an array.
266 *
267 * @param[in] _name of the CONF_PAIR to search for.
268 * @param[in] _flags controlling parsing behaviour.
269 * @param[in] _struct containing the field to write the result to.
270 * @param[in] _field to write the result to.
271 */
272# define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field) \
273 FR_CONF_OFFSET_TYPE_FLAGS(_name, \
274 FR_CTYPE_TO_TYPE((((_struct *)NULL)->_field)), \
275 (_flags) | CONF_CTYPE_TO_FLAGS((((_struct *)NULL)->_field)),\
276 _struct, _field)
277
278/** conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
279 *
280 * @param[in] _name of the CONF_PAIR to search for.
281 * @param[in] _struct containing the field to write the result to.
282 * @param[in] _field to write the result to.
283 */
284# define FR_CONF_OFFSET(_name, _struct, _field) \
285 FR_CONF_OFFSET_TYPE_FLAGS(_name, \
286 FR_CTYPE_TO_TYPE((((_struct *)NULL)->_field)), \
287 CONF_CTYPE_TO_FLAGS((((_struct *)NULL)->_field)),\
288 _struct, _field)
289
290/** 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
291 *
292 * @param[in] _name of the CONF_PAIR to search for.
293 * @param[in] _type to parse the CONF_PAIR as.
294 * @param[in] _flags controlling parsing behaviour.
295 * @param[in] _struct containing the field to write the result to.
296 * @param[in] _field to write the result to.
297 */
298# define FR_CONF_OFFSET_IS_SET(_name, _type, _flags, _struct, _field) \
299 .name1 = _name, \
300 .type = (_type), \
301 .flags = CONF_FLAG_IS_SET | (_flags), \
302 .offset = FR_CONF_FLAG_CHECK((_type), (_flags), &(((_struct *)NULL)->_field), offsetof(_struct, _field)), \
303 .is_set_offset = offsetof(_struct, _field ## _is_set)
304
305/** conf_parser_t which populates a sub-struct using a CONF_SECTION
306 *
307 * @param[in] _name of the CONF_SECTION to search for.
308 * @param[in] _flags controlling parsing behaviour.
309 * @param[in] _struct containing the sub-struct to populate.
310 * @param[in] _field containing the sub-struct to populate.
311 * @param[in] _subcs CONF_SECTION to parse.
312 */
313# define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs) \
314 .name1 = _name, \
315 .flags = CONF_FLAG_SUBSECTION | (_flags), \
316 .offset = offsetof(_struct, _field), \
317 .subcs = _subcs
318
319/** conf_parser_t which populates a sub-struct using a CONF_SECTION
320 *
321 * @param[in] _name of the CONF_SECTION to search for.
322 * @param[in] _struct containing the sub-struct to populate.
323 * @param[in] _field containing the sub-struct to populate.
324 * @param[in] _subcs conf_parser_t to include in-line in this section
325 */
326# define FR_CONF_OFFSET_REF(_struct, _field, _subcs) \
327 .name1 = CF_IDENT_ANY, \
328 .flags = CONF_FLAG_REF, \
329 .offset = offsetof(_struct, _field), \
330 .subcs = _subcs
331
332/** conf_parser_t which parses a single CONF_PAIR producing a single global result
333 *
334 * @param[in] _name of the CONF_PAIR to search for.
335 * @param[in] _type to parse the CONF_PAIR as.
336 * @param[in] _flags controlling parsing behaviour.
337 * @param[out] _res_p pointer to a global var, where the result will be written.
338 */
339# define FR_CONF_POINTER(_name, _type, _flags, _res_p) \
340 .name1 = _name, \
341 .type = (_type), \
342 .flags = (_flags), \
343 .data = FR_CONF_FLAG_CHECK((_type), (_flags), (_res_p), _res_p)
344
345/** 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
346 *
347 * @note is set state is recorded in variable `<_res_p>`_is_set.
348 *
349 * @param[in] _name of the CONF_PAIR to search for.
350 * @param[in] _type to parse the CONF_PAIR as.
351 * @param[in] _flags controlling parsing behaviour.
352 * @param[out] _res_p pointer to a global var, where the result will be written.
353 */
354# define FR_CONF_POINTER_IS_SET(_name, _type, _flags, _res_p) \
355 .name1 = _name, \
356 .type = (_type), \
357 .flags = CONF_FLAG_IS_SET | (_flags), \
358 .data = FR_CONF_FLAG_CHECK((_type), (_flags), (_res_p), _res_p), \
359 .is_set_ptr = _res_p ## _is_set
360# define FR_ITEM_POINTER(_type, _res_p) _type, FR_CONF_FLAG_CHECK((_type), 0, (_res_p), _res_p)
361
362/** A conf_parser_t multi-subsection
363 *
364 * Parse multiple instance of a subsection, allocating an array of structs
365 * to hold the result.
366 *
367 * @param[in] _name name of subsection to search for.
368 * @param[in] _type the output type.
369 * @param[in] _flags flags controlling parsing behaviour.
370 * @param[in] _struct instance data struct.
371 * @param[in] _field field in instance data struct.
372 * @param[in] _subcs conf_parser_t array to use to parse subsection data.
373 */
374# define FR_CONF_SUBSECTION_ALLOC(_name, _type, _flags, _struct, _field, _subcs) \
375 .name1 = _name, \
376 .type = (_type), \
377 .flags = (_flags), \
378 .offset = FR_CONF_FLAG_CHECK((_type), (_flags), &(((_struct *)NULL)->_field), offsetof(_struct, _field)), \
379 .subcs = _subcs, \
380 .subcs_size = sizeof(**(((_struct *)0)->_field))
381
382/** conf_parser_t entry which doesn't fill in a pointer or offset, but relies on functions to record values
383 *
384 * @param[in] _name name of pair to search for.
385 * @param[in] _type base type to parse pair as.
386 * @param[in] _flags flags controlling parsing behaviour.
387 * @param[in] _func to use to record value.
388 * @param[in] _dflt_func to use to get defaults from a 3rd party library.
389 */
390# define FR_CONF_FUNC(_name, _type, _flags, _func, _dflt_func) \
391 .name1 = _name, \
392 .type = (_type), \
393 .flags = (_flags), \
394 .func = _func, \
395 .dflt_func = _dflt_func
396
397/** conf_parser_t entry which runs conf_parser_t entries for a subsection without any output
398 *
399 * @param[in] _name of pair to search for.
400 * @param[in] _flags flags controlling parsing behaviour.
401 * @param[in] _subcs to use to get defaults from a 3rd party library.
402 */
403# define FR_CONF_SUBSECTION_GLOBAL(_name, _flags, _subcs) \
404 .name1 = _name, \
405 .flags = CONF_FLAG_SUBSECTION | (_flags), \
406 .subcs = _subcs
407
408/** conf_parser_t entry which raises an error if a matching CONF_PAIR is found
409 *
410 * @param[in] _name of pair to search for.
411 * @param[in] _struct where the result was previously written.
412 * @param[in] _field in the struct where the result was previously written.
413 */
414#define FR_CONF_DEPRECATED(_name, _struct, _field) \
415 .name1 = _name, \
416 .flags = CONF_FLAG_DEPRECATED
417
418/** @name #conf_parser_t type flags
419 *
420 * These flags should be or'd with another FR_TYPE_* value to create validation
421 * rules for the #cf_pair_parse function.
422 *
423 * @{
424 */
425DIAG_OFF(attributes)
426typedef enum CC_HINT(flag_enum) {
427 CONF_FLAG_NONE = 0, //!< No special flags.
428 CONF_FLAG_SUBSECTION = (1 << 1), //!< Instead of putting the information into a
429 ///< configuration structure, the configuration
430 ///< file routines MAY just parse it directly into
431 ///< user-supplied variables.
432 CONF_FLAG_DEPRECATED = (1 << 10), //!< If a matching #CONF_PAIR is found,
433 //!< error out with a deprecated message.
434 CONF_FLAG_REQUIRED = (1 << 11), //!< Error out if no matching #CONF_PAIR
435 //!< is found, and no dflt value is set.
436 CONF_FLAG_ATTRIBUTE = (1 << 12), //!< Value must resolve to attribute in dict
437 //!< (deprecated, use #CONF_FLAG_TMPL).
438 CONF_FLAG_SECRET = (1 << 13), //!< Only print value if debug level >= 3.
439
440 CONF_FLAG_FILE_INPUT = (1 << 14), //!< File matching value must exist,
441 //!< and must be readable.
442 CONF_FLAG_FILE_OUTPUT = (1 << 15), //!< File matching value must exist,
443 //!< and must be writable.
444
445 CONF_FLAG_XLAT = (1 << 16), //!< string will be dynamically expanded.
446 CONF_FLAG_TMPL = (1 << 17), //!< CONF_PAIR should be parsed as a template.
447
448 CONF_FLAG_MULTI = (1 << 18), //!< CONF_PAIR can have multiple copies.
449 CONF_FLAG_NOT_EMPTY = (1 << 19), //!< CONF_PAIR is required to have a non zero
450 //!< length value.
451 CONF_FLAG_FILE_EXISTS = (1 << 20), //!< File matching value must exist
452
453 CONF_FLAG_IS_SET = (1 << 21), //!< Write whether this config item was
454 //!< left as the default to is_set_offset
455 //!< or is_set_ptr.
456 CONF_FLAG_OK_MISSING = (1 << 22), //!< OK if it's missing
457 CONF_FLAG_HIDDEN = (1 << 23), //!< Used by scripts to omit items from the
458 ///< generated documentation.
459 CONF_FLAG_REF = (1 << 24), //!< reference another conf_parser_t inline in this one
460 CONF_FLAG_OPTIONAL = (1 << 25), //!< subsection is pushed only if a non-optional matching one is pushed
462DIAG_ON(attributes)
463
464/** @} */
465
466/** @name #conf_parser_t flags checks
467 *
468 * @{
469 */
470#define fr_rule_deprecated(_rule) ((_rule)->flags & CONF_FLAG_DEPRECATED)
471
472#define fr_rule_required(_rule) ((_rule)->flags & CONF_FLAG_REQUIRED)
473
474#define fr_rule_secret(_rule) ((_rule)->flags & CONF_FLAG_SECRET)
475
476#define fr_rule_file_input(_rule) ((_rule)->flags & CONF_FLAG_FILE_INPUT)
477
478#define fr_rule_file_output(_rule) ((_rule)->flags & CONF_FLAG_FILE_OUTPUT)
479
480
481#define fr_rule_multi(_rule) ((_rule)->flags & CONF_FLAG_MULTI)
482
483#define fr_rule_not_empty(_rule) ((_rule)->flags & CONF_FLAG_NOT_EMPTY)
484
485#define fr_rule_is_set(_rule) ((_rule)->flags & CONF_FLAG_IS_SET)
486
487#define fr_rule_ok_missing(_rule) ((_rule)->flags & CONF_FLAG_OK_MISSING)
488
489#define fr_rule_file_exists(_rule) ((_rule)->flags & CONF_FLAG_FILE_EXISTS)
490
491#define fr_rule_dflt(_rule) ((_rule)->dflt || (_rule)->dflt_func)
492
493#define fr_rule_is_attribute(_rule) ((_rule)->flags & CONF_FLAG_ATTRIBUTE)
494
495#define fr_rule_is_xlat(_rule) ((_rule)->flags & CONF_FLAG_XLAT)
496
497#define fr_rule_is_tmpl(_rule) ((_rule)->flags & CONF_FLAG_TMPL)
498/** @} */
499
500#define FR_SIZE_COND_CHECK(_name, _var, _cond, _new)\
501do {\
502 if (!(_cond)) {\
503 WARN("Ignoring \"" _name " = %zu\", forcing to \"" _name " = %zu\"", _var, _new);\
504 _var = _new;\
505 }\
506} while (0)
507
508#define FR_SIZE_BOUND_CHECK(_name, _var, _op, _bound) FR_SIZE_COND_CHECK(_name, _var, (_var _op _bound), _bound)
509
510#define FR_INTEGER_COND_CHECK(_name, _var, _cond, _new)\
511do {\
512 if (!(_cond)) {\
513 WARN("Ignoring \"" _name " = %u\", forcing to \"" _name " = %u\"", (unsigned int) (_var), (unsigned int) (_new));\
514 _var = _new;\
515 }\
516} while (0)
517
518#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound) FR_INTEGER_COND_CHECK(_name, _var, (_var _op _bound), _bound)
519
520#define FR_TIME_DELTA_COND_CHECK(_name, _var, _cond, _new)\
521do {\
522 if (!(_cond)) {\
523 WARN("Ignoring \"" _name " = %pV\", forcing to \"" _name " = %pV\"", \
524 fr_box_time_delta(_var), fr_box_time_delta(_new));\
525 _var = _new;\
526 }\
527} while (0)
528
529#define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)\
530do {\
531 if (!fr_time_delta_cond(_var, _op, _bound)) { \
532 WARN("Ignoring \"" _name " = %pV\", forcing to \"" _name " = %pV\"",\
533 fr_box_time_delta(_var),\
534 fr_box_time_delta(_bound));\
535 _var = _bound;\
536 }\
537} while (0)
538
539extern bool check_config;
540
541/** Callback for performing custom parsing of a #CONF_SECTION or CONF_PAIR
542 *
543 * @param[in] ctx to allocate any data in.
544 * @param[out] out Where to write the result of parsing.
545 * @param[in] parent The base address of the structure.
546 * @param[in] ci The #CONF_SECTION or #CONF_PAIR to parse.
547 * @param[in] rule Parse rules - How the #CONF_PAIR or #CONF_SECTION should be converted.
548 * @return
549 * - 0 on success.
550 * - -1 on failure.
551 */
552typedef int (*cf_parse_t)(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
553
554/** Callback for producing dynamic defaults from 3rd party libraries
555 *
556 * @param[out] out Where to write default conf pair.
557 * @param[in] parent being populated.
558 * @param[in] cs to allocate pair in.
559 * @param[in] quote to use when allocing the pair. Provided as a convenience.
560 * @param[in] rule to produce default for.
561 * @return
562 * - 0 on success.
563 * - -1 on failure.
564 */
565typedef int (*cf_dflt_t)(CONF_PAIR **out, void *parent, CONF_SECTION *cs, fr_token_t quote, conf_parser_t const *rule);
566
567/** Defines a #CONF_PAIR to C data type mapping
568 *
569 * Is typically used to define mappings between module sections, and module instance structs.
570 * May also be used to set global configuration options.
571 *
572 * Offset/data values should be set using #FR_CONF_OFFSET or #FR_CONF_POINTER.
573 *
574 * Example with #FR_CONF_OFFSET :
575 @code{.c}
576 static conf_parser_t module_config[] = {
577 { FR_CONF_OFFSET_TYPE_FLAGS("example", FR_TYPE_STRING | CONF_FLAG_NOT_EMPTY, 0, 0, example_instance_t, example), .dflt = "default_value" },
578 CONF_PARSER_TERMINATOR
579 }
580 @endcode
581 *
582 * Example with #FR_CONF_POINTER :
583 @code{.c}
584 static conf_parser_t global_config[] = {
585 { FR_CONF_POINTER("example", FR_TYPE_STRING | CONF_FLAG_NOT_EMPTY, 0, 0, 0, &my_global), .dflt = "default_value" },
586 CONF_PARSER_TERMINATOR
587 }
588 @endcode
589 *
590 * @see FR_CONF_OFFSET
591 * @see FR_CONF_POINTER
592 * @see cf_section_parse
593 * @see cf_pair_parse
594 */
596 char const *name1; //!< Name of the #CONF_ITEM to parse.
597 char const *name2; //!< Second identifier for #CONF_SECTION.
598
599 fr_type_t type; //!< An #fr_type_t value, controls the output type.
600
601 conf_parser_flags_t flags; //!< Flags which control parsing behaviour.
602
603 size_t offset; //!< Relative offset of field or structure to write the parsed value to.
604 //!< When #flags is set to #CONF_FLAG_SUBSECTION, may be used to specify
605 //!< a base offset to add to all offsets contained within the
606 //!< subsection.
607 //!< @note Must be used exclusively to #data.
608
609 void *data; //!< Pointer to a static variable to write the parsed value to.
610 //!< @note Must be used exclusively to #offset.
611
612 cf_parse_t func; //!< Override default parsing behaviour for the specified type with
613 //!< a custom parsing function.
614
615 cf_parse_t on_read; //!< Function to call as the item is being read, just after
616 //!< it has been allocated and initialized.
617
618 void const *uctx; //!< User data accessible by the #cf_parse_t func. Useful for
619 ///< building reusable functions.
620
621 /** Where to write status if FR_TYPE_IS_DEFAULT is set
622 *
623 * @note Which field is used, is determined by whether
624 * data ptr is set.
625 */
626 union {
627 size_t is_set_offset; //!< If type contains FR_TYPE_IS_DEFAULT write status to bool.
628 //!< at this address.
629 void *is_set_ptr; //!< If type contains FR_TYPE_IS_DEFAULT write status to ptr
630 //!< at this address.
631 };
632
633 union {
634 struct {
635 char const *dflt; //!< Default as it would appear in radiusd.conf.
636
637 cf_dflt_t dflt_func; //!< Function to produce dynamic defaults.
638 };
639
640 struct {
641 conf_parser_t const *subcs; //!< When #CONF_FLAG_SUBSECTION is set, should
642 //!< be a pointer to the start of another array of
643 //!< #conf_parser_t structs, forming the subsection.
644 size_t subcs_size; //!< If non-zero, allocate structs of this size to hold
645 //!< the parsed data.
646 char const *subcs_type; //!< Set a specific talloc type for subcs structures.
647 };
648 };
649
650 fr_token_t quote; //!< Quoting around the default value. Only used for templates.
651};
652
653typedef struct {
655 size_t *len;
657
658#define CONF_PARSER_TERMINATOR { .name1 = NULL, .type = ~(UINT32_MAX - 1), \
659 .offset = 0, .data = NULL, .dflt = NULL, .quote = T_INVALID }
660
661#define CONF_PARSER_PARTIAL_TERMINATOR { .name1 = NULL, .type = ~(UINT32_MAX - 1), \
662 .offset = 1, .data = NULL, .dflt = NULL, .quote = T_INVALID }
663
664#define CF_FILE_NONE (0)
665#define CF_FILE_ERROR (1)
666#define CF_FILE_CONFIG (1 << 2)
667#define CF_FILE_MODULE (1 << 3)
668
669void cf_pair_debug_log(CONF_SECTION const *cs, CONF_PAIR *cp, conf_parser_t const *rule);
670
671/*
672 * Type validation and conversion
673 */
674int cf_pair_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *out, CONF_PAIR *cp, conf_parser_t const *rule)
675 CC_HINT(nonnull(2, 3, 4));
676
677int cf_pair_parse_value(TALLOC_CTX *ctx, void *out, void *base, CONF_ITEM *ci, conf_parser_t const *rule)
678 CC_HINT(nonnull(2, 4, 5));
679
680int cf_pair_parse(TALLOC_CTX *ctx, CONF_SECTION *cs, char const *name,
681 unsigned int type, void *data, char const *dflt, fr_token_t dflt_quote) CC_HINT(nonnull(2,3));
682int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs);
683int cf_section_parse_pass2(void *base, CONF_SECTION *cs);
684
685/*
686 * Runtime parse rules
687 */
688#define cf_section_rule_push(_cs, _rule) _cf_section_rule_push(_cs, _rule, __FILE__, __LINE__)
689int _cf_section_rule_push(CONF_SECTION *cs, conf_parser_t const *rule, char const *filename, int lineno);
690#define cf_section_rules_push(_cs, _rule) _cf_section_rules_push(_cs, _rule, __FILE__, __LINE__)
691int _cf_section_rules_push(CONF_SECTION *cs, conf_parser_t const *rules, char const *filename, int lineno);
692
693/*
694 * Generic parsing callback functions
695 */
696int cf_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
697 CONF_ITEM *ci, conf_parser_t const *rule);
698
699int cf_table_parse_uint32(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
700 CONF_ITEM *ci, conf_parser_t const *rule);
701
702int cf_table_parse_int32(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
703 CONF_ITEM *ci, conf_parser_t const *rule);
704
705int cf_parse_uid(TALLOC_CTX *ctx, void *out, UNUSED void *parent,
706 CONF_ITEM *ci, conf_parser_t const *rule);
707
708int cf_parse_gid(TALLOC_CTX *ctx, void *out, UNUSED void *parent,
709 CONF_ITEM *ci, conf_parser_t const *rule);
710
711int cf_parse_permissions(TALLOC_CTX *ctx, void *out, UNUSED void *parent,
712 CONF_ITEM *ci, conf_parser_t const *rule);
713
714int cf_null_on_read(TALLOC_CTX *ctx, void *out, void *parent,
715 CONF_ITEM *ci, conf_parser_t const *rule);
716
717#ifdef __cplusplus
718}
719#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:612
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:1609
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:565
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
Definition cf_parse.c:1151
void const * uctx
User data accessible by the cf_parse_t func.
Definition cf_parse.h:618
void * data
Pointer to a static variable to write the parsed value to.
Definition cf_parse.h:609
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:1593
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:727
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:601
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:1577
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:599
size_t offset
Relative offset of field or structure to write the parsed value to.
Definition cf_parse.h:603
char const * name2
Second identifier for CONF_SECTION.
Definition cf_parse.h:597
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:650
fr_table_num_sorted_t const * table
Definition cf_parse.h:654
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:552
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:126
char const * name1
Name of the CONF_ITEM to parse.
Definition cf_parse.h:596
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:1259
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:1447
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:1551
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:615
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:426
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:434
@ CONF_FLAG_FILE_OUTPUT
File matching value must exist, and must be writable.
Definition cf_parse.h:442
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
Definition cf_parse.h:448
@ CONF_FLAG_REF
reference another conf_parser_t inline in this one
Definition cf_parse.h:459
@ CONF_FLAG_SECRET
Only print value if debug level >= 3.
Definition cf_parse.h:438
@ 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:453
@ CONF_FLAG_ATTRIBUTE
Value must resolve to attribute in dict (deprecated, use CONF_FLAG_TMPL).
Definition cf_parse.h:436
@ CONF_FLAG_FILE_INPUT
File matching value must exist, and must be readable.
Definition cf_parse.h:440
@ CONF_FLAG_DEPRECATED
If a matching CONF_PAIR is found, error out with a deprecated message.
Definition cf_parse.h:432
@ CONF_FLAG_NONE
No special flags.
Definition cf_parse.h:427
@ CONF_FLAG_NOT_EMPTY
CONF_PAIR is required to have a non zero length value.
Definition cf_parse.h:449
@ CONF_FLAG_XLAT
string will be dynamically expanded.
Definition cf_parse.h:445
@ CONF_FLAG_OPTIONAL
subsection is pushed only if a non-optional matching one is pushed
Definition cf_parse.h:460
@ CONF_FLAG_OK_MISSING
OK if it's missing.
Definition cf_parse.h:456
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:428
@ CONF_FLAG_FILE_EXISTS
File matching value must exist.
Definition cf_parse.h:451
@ CONF_FLAG_TMPL
CONF_PAIR should be parsed as a template.
Definition cf_parse.h:446
@ CONF_FLAG_HIDDEN
Used by scripts to omit items from the generated documentation.
Definition cf_parse.h:457
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:595
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