The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
cf_parse.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: a818e4f92a8f2d5bb1583a8ebcf735e3289db139 $
19 * @file cf_parse.c
20 * @brief Convert internal format configuration values into native C types.
21 *
22 * @copyright 2017 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23 * @copyright 2000,2006 The FreeRADIUS server project
24 * @copyright 2000 Miquel van Smoorenburg (miquels@cistron.nl)
25 * @copyright 2000 Alan DeKok (aland@freeradius.org)
26 */
27RCSID("$Id: a818e4f92a8f2d5bb1583a8ebcf735e3289db139 $")
28
29#include <string.h>
30
31#include <freeradius-devel/server/cf_file.h>
32#include <freeradius-devel/server/cf_parse.h>
33#include <freeradius-devel/server/cf_priv.h>
34#include <freeradius-devel/server/log.h>
35#include <freeradius-devel/server/tmpl.h>
36#include <freeradius-devel/server/virtual_servers.h>
37#include <freeradius-devel/util/debug.h>
38#include <freeradius-devel/util/inet.h>
39#include <freeradius-devel/util/misc.h>
40#include <freeradius-devel/util/perm.h>
41#include <freeradius-devel/util/types.h>
42
44static char const parse_spaces[] = " ";
45
46#define PAIR_SPACE(_cs) ((_cs->depth + 1) * 2)
47#define SECTION_SPACE(_cs) (_cs->depth * 2)
48
49void cf_pair_debug_log(CONF_SECTION const *cs, CONF_PAIR *cp, conf_parser_t const *rule)
50{
51 char const *value;
52 char *tmp = NULL;
53 char const *quote = "";
54 bool secret = (rule->flags & CONF_FLAG_SECRET);
56
57 if (cp->printed) return;
58
59 /*
60 * tmpls are special, they just need to get printed as string
61 */
62 if (rule->flags & CONF_FLAG_TMPL) {
64 } else {
65 type = rule->type;
66 }
67
68 if (secret && (fr_debug_lvl < L_DBG_LVL_3)) {
69 cf_log_debug(cs, "%.*s%s = <<< secret >>>", PAIR_SPACE(cs), parse_spaces, cp->attr);
70 return;
71 }
72
73 /*
74 * Print the strings with the correct quotation character and escaping.
75 */
77 value = tmp = fr_asprint(NULL, cp->value, talloc_array_length(cp->value) - 1, fr_token_quote[cp->rhs_quote]);
78
79 } else {
80 value = cf_pair_value(cp);
81 }
82
84 switch (cf_pair_value_quote(cp)) {
85 default:
86 break;
87
89 quote = "\"";
90 break;
91
93 quote = "'";
94 break;
95
97 quote = "`";
98 break;
99
101 quote = "/";
102 break;
103 }
104 }
105
106 cf_log_debug(cs, "%.*s%s = %s%s%s", PAIR_SPACE(cs), parse_spaces, cp->attr, quote, value, quote);
107
108 talloc_free(tmp);
109
110 cp->printed = true;
111}
112
113/** Parses a #CONF_PAIR into a boxed value
114 *
115 * @copybrief cf_pair_value
116 * @see cf_pair_value
117 *
118 * @param[in] ctx to allocate any dynamic buffers in.
119 * @param[out] out Where to write the parsed value.
120 * @param[in] cp to parse.
121 * @param[in] rule to parse to. May contain flags.
122 * @return
123 * - 0 on success.
124 * - -1 on failure.
125 */
126int cf_pair_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *out, CONF_PAIR *cp, conf_parser_t const *rule)
127{
128 if (fr_value_box_from_str(ctx, out, rule->type, NULL, cp->value, talloc_array_length(cp->value) - 1, NULL, false) < 0) {
129 cf_log_perr(cp, "Invalid value \"%s\" for config item %s",
130 cp->value, cp->attr);
131
132 return -1;
133 }
134
135 /*
136 * Strings can be file paths...
137 */
138 if (fr_type_is_string(rule->type)) {
139 /*
140 * If there's out AND it's an input file, check
141 * that we can read it. This check allows errors
142 * to be caught as early as possible, during
143 * server startup.
144 */
145 if (fr_rule_file_input(rule) && !cf_file_check(cp, true)) {
146 error:
148 return -1;
149 }
150 if (fr_rule_file_exists(rule) && !cf_file_check(cp, false)) goto error;
151 }
152
153 return 0;
154}
155
156/** Parses a #CONF_PAIR into a C data type
157 *
158 * @copybrief cf_pair_value
159 * @see cf_pair_value
160 *
161 * @param[in] ctx to allocate any dynamic buffers in.
162 * @param[out] out Where to write the parsed value.
163 * @param[in] base address of the structure out points into.
164 * May be NULL in the case of manual parsing.
165 * @param[in] ci to parse.
166 * @param[in] rule to parse to. May contain flags.
167 * @return
168 * - 0 on success.
169 * - -1 on failure.
170 */
171int cf_pair_parse_value(TALLOC_CTX *ctx, void *out, UNUSED void *base, CONF_ITEM *ci, conf_parser_t const *rule)
172{
173 int ret = 0;
174 bool cant_be_empty, tmpl;
175
176 ssize_t slen;
177
178 CONF_PAIR *cp = cf_item_to_pair(ci);
179
180 cant_be_empty = fr_rule_not_empty(rule);
181 tmpl = fr_rule_is_tmpl(rule);
182
183 fr_assert(cp);
184 fr_assert(!fr_rule_is_attribute(rule) || tmpl); /* Attribute flag only valid for templates */
185
186 if (fr_rule_required(rule)) cant_be_empty = true; /* May want to review this in the future... */
187
188 /*
189 * Everything except templates must have a base type.
190 */
191 if (!rule->type && !tmpl) {
192 cf_log_err(cp, "Configuration pair \"%s\" must have a data type", cp->attr);
193 return -1;
194 }
195
196 /*
197 * Catch crazy errors.
198 */
199 if (!cp->value) {
200 cf_log_err(cp, "Configuration pair \"%s\" must have a value", cp->attr);
201 return -1;
202 }
203
204 /*
205 * Check for zero length strings
206 */
207 if ((cp->value[0] == '\0') && cant_be_empty) {
208 cf_log_err(cp, "Configuration pair \"%s\" must not be empty (zero length)", cp->attr);
209 if (!fr_rule_required(rule)) cf_log_err(cp, "Comment item to silence this message");
210 error:
211 ret = -1;
212 return ret;
213 }
214
215 if (tmpl) {
216 tmpl_t *vpt;
217 static tmpl_rules_t rules = {
218 .attr = {
219 .allow_unknown = true,
220 .allow_unresolved = true,
221 .allow_foreign = true,
222 }
223 };
224 fr_sbuff_t sbuff = FR_SBUFF_IN(cp->value, strlen(cp->value));
225
227 /*
228 * Parse the cast operator for barewords
229 */
230 if (cp->rhs_quote == T_BARE_WORD) {
231 slen = tmpl_cast_from_substr(&rules, &sbuff);
232 if (slen < 0) {
233 tmpl_error:
234 cf_canonicalize_error(cp, slen, "Failed parsing attribute reference",
235 cp->value);
236 goto error;
237 }
238 fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX, NULL);
239
240 } else if (fr_rule_is_attribute(rule)) {
241 cf_log_err(cp, "Invalid quoting. Unquoted attribute reference is required");
242 goto error;
243 }
244
245 slen = tmpl_afrom_substr(cp, &vpt, &sbuff, cp->rhs_quote,
247 &rules);
248 if (!vpt) goto tmpl_error;
249
251 cf_log_err(cp, "Expected attr got %s",
252 tmpl_type_to_str(vpt->type));
253 return -1;
254 }
255
256 *(tmpl_t **)out = vpt;
257
258 goto finish;
259 }
260
261 /*
262 * Parse as a boxed value out of sheer laziness...
263 *
264 * Then we get all the internal types for free, and only need to add
265 * one set of printing and parsing functions for new types...
266 */
267 {
269
270 if (cf_pair_to_value_box(ctx, &vb, cf_item_to_pair(ci), rule) < 0) goto error;
271
272 if (fr_value_box_memcpy_out(out, &vb) < 0) {
273 cf_log_perr(cp, "Failed unboxing parsed configuration item value");
275 goto error;
276 }
277 }
278
279finish:
280
281 return ret;
282}
283
284/** Allocate a pair using the dflt value and quotation
285 *
286 * The pair created by this function should fed to #cf_pair_parse for parsing.
287 *
288 * @param[out] out Where to write the CONF_PAIR we created with the default value.
289 * @param[in] parent being populated.
290 * @param[in] cs to parent the CONF_PAIR from.
291 * @param[in] rule to use to create the default.
292 * @return
293 * - 0 on success.
294 * - -1 on failure.
295 */
296static int cf_pair_default(CONF_PAIR **out, void *parent, CONF_SECTION *cs, conf_parser_t const *rule)
297
298{
299 int lineno = 0;
300 char const *expanded;
301 CONF_PAIR *cp;
302 char buffer[8192];
303 fr_token_t dflt_quote = rule->quote;
304
305 fr_assert(rule->dflt || rule->dflt_func);
306
307 if (fr_rule_required(rule)) {
308 cf_log_err(cs, "Configuration pair \"%s\" must have a value", rule->name1);
309 return -1;
310 }
311
312 /*
313 * If no default quote was set, determine it from the type
314 */
315 if (dflt_quote == T_INVALID) {
316 if (fr_type_is_quoted(rule->type)) {
317 dflt_quote = T_DOUBLE_QUOTED_STRING;
318 } else {
319 dflt_quote = T_BARE_WORD;
320 }
321 }
322
323 /*
324 * Use the dynamic default function if set
325 */
326 if (rule->dflt_func) {
327 if (rule->dflt_func(out, parent, cs, dflt_quote, rule) < 0) {
328 cf_log_perr(cs, "Failed producing default for \"%s\"", rule->name1);
329 return -1;
330 }
331
332 return 0;
333 }
334
335 expanded = cf_expand_variables("<internal>", lineno, cs, buffer, sizeof(buffer), rule->dflt, -1, NULL);
336 if (!expanded) {
337 cf_log_err(cs, "Failed expanding variable %s", rule->name1);
338 return -1;
339 }
340
341 cp = cf_pair_alloc(cs, rule->name1, expanded, T_OP_EQ, T_BARE_WORD, dflt_quote);
342 if (!cp) return -1;
343
344 /*
345 * Set the ret to indicate we used a default value
346 */
347 *out = cp;
348
349 return 1;
350}
351
352static int cf_pair_unescape(CONF_PAIR *cp, conf_parser_t const *rule)
353{
354 char const *p;
355 char *str, *unescaped, *q;
356
357 if (!cp->value) return 0;
358
359 if (cp->rhs_quote != T_DOUBLE_QUOTED_STRING) return 0;
360
361 if (!(rule->flags & CONF_FLAG_TMPL)) {
362 if (rule->type != FR_TYPE_STRING) return 0;
363 }
364
365 if (strchr(cp->value, '\\') == NULL) return 0;
366
367 str = talloc_strdup(cp, cp->value);
368 if (!str) return -1;
369
370 p = cp->value;
371 q = str;
372 while (*p) {
373 unsigned int x;
374
375 if (*p != '\\') {
376 *(q++) = *(p++);
377 continue;
378 }
379
380 p++;
381 switch (*p) {
382 case 'r':
383 *q++ = '\r';
384 break;
385 case 'n':
386 *q++ = '\n';
387 break;
388 case 't':
389 *q++ = '\t';
390 break;
391
392 default:
393 if (*p >= '0' && *p <= '9' &&
394 sscanf(p, "%3o", &x) == 1) {
395 if (!x) {
396 cf_log_err(cp, "Cannot have embedded zeros in value for %s", cp->attr);
397 return -1;
398 }
399
400 *q++ = x;
401 p += 2;
402 } else {
403 *q++ = *p;
404 }
405 break;
406 }
407 p++;
408 }
409 *q = '\0';
410
411 unescaped = talloc_typed_strdup(cp, str); /* no embedded NUL */
412 if (!unescaped) return -1;
413
414 talloc_free(str);
415
416 /*
417 * Replace the old value with the new one.
418 */
420 cp->value = unescaped;
421
422 return 0;
423}
424
425/** Parses a #CONF_PAIR into a C data type, with a default value.
426 *
427 * @param[in] ctx To allocate arrays and values in.
428 * @param[out] out Where to write the result.
429 * Must not be NULL unless rule->runc is provided.
430 * @param[in] base address of the structure out points into.
431 * May be NULL in the case of manual parsing.
432 * @param[in] cs to search for matching #CONF_PAIR in.
433 * @param[in] rule to parse #CONF_PAIR with.
434 * @return
435 * - 1 if default value was used, or if there was no CONF_PAIR or dflt.
436 * - 0 on success.
437 * - -1 on error.
438 * - -2 if deprecated.
439 */
440static int CC_HINT(nonnull(4,5)) cf_pair_parse_internal(TALLOC_CTX *ctx, void *out, void *base,
441 CONF_SECTION *cs, conf_parser_t const *rule)
442{
443 bool required, deprecated;
444 size_t count = 0;
445 CONF_PAIR *cp = NULL, *dflt_cp = NULL;
446
447#ifndef NDEBUG
448 char const *dflt = rule->dflt;
449 fr_token_t dflt_quote = rule->quote;
450#endif
451 cf_parse_t func = rule->func ? rule->func : cf_pair_parse_value;
452
453 fr_assert(!fr_rule_is_tmpl(rule) || !dflt || (dflt_quote != T_INVALID)); /* We ALWAYS need a quoting type for templates */
454
455 /*
456 * Functions don't necessarily *need* to write
457 * anywhere, so their data pointer can be NULL.
458 */
459 if (!out) {
460 if (!rule->func) {
461 cf_log_err(cs, "Rule doesn't specify output destination");
462 return -1;
463 }
464 }
465
466 required = fr_rule_required(rule);
467 deprecated = fr_rule_deprecated(rule);
468
469 /*
470 * If the item is multi-valued we allocate an array
471 * to hold the multiple values.
472 */
473 if (fr_rule_multi(rule)) {
474 void **array;
475 size_t i = 0;
476
477 /*
478 * Easier than re-allocing
479 */
480 count = cf_pair_count(cs, rule->name1);
481
482 /*
483 * Multivalued, but there's no value, create a
484 * default pair.
485 */
486 if (!count) {
487 if (deprecated) return 0;
488
489 if (!fr_rule_dflt(rule)) {
490 if (required) {
491 need_value:
492 cf_log_err(cs, "Configuration item \"%s\" must have a value", rule->name1);
493 return -1;
494 }
495 return 1;
496 }
497
498 if (cf_pair_default(&dflt_cp, base, cs, rule) < 0) return -1;
499 count = cf_pair_count(cs, rule->name1); /* Dynamic functions can add multiple defaults */
500 if (!count) {
501 if (fr_rule_not_empty(rule)) {
502 cf_log_err(cs, "Configuration item \"%s\" cannot be empty", rule->name1);
503 return -1;
504 }
505 return 0;
506 }
507 }
508
509 if (deprecated) {
510 /*
511 * Emit the deprecated warning in the
512 * context of the first pair.
513 */
514 cp = cf_pair_find(cs, rule->name1);
515 fr_assert(cp);
516
517 deprecated:
518 cf_log_err(cp, "Configuration pair \"%s\" is deprecated", cp->attr);
519 return -2;
520 }
521
522 /*
523 * No output, so don't bother allocing the array
524 */
525 if (!out) {
526 array = NULL;
527
528 /*
529 * Tmpl is outside normal range
530 */
531 } else if (fr_rule_is_tmpl(rule)) {
532 MEM(array = (void **)talloc_zero_array(ctx, tmpl_t *, count));
533
534 /*
535 * Allocate an array of values.
536 *
537 * We don't NULL terminate. Consumer must use
538 * talloc_array_length().
539 */
540 } else {
541 array = fr_type_array_alloc(ctx, rule->type, count);
542 if (unlikely(array == NULL)) {
543 cf_log_perr(cp, "Failed allocating value array");
544 return -1;
545 }
546 }
547
548 while ((cp = cf_pair_find_next(cs, cp, rule->name1))) {
549 int ret;
550 void *entry;
551 TALLOC_CTX *value_ctx = array;
552
553 /*
554 * Figure out where to write the output
555 */
556 if (!array) {
557 entry = NULL;
558 } else if ((rule->type == FR_TYPE_VOID) || (rule->flags & CONF_FLAG_TMPL)) {
559 entry = &array[i++];
560 } else {
561 entry = ((uint8_t *) array) + (i++ * fr_value_box_field_sizes[rule->type]);
562 }
563
564 if (cf_pair_unescape(cp, rule) < 0) return -1;
565
566 /*
567 * Switch between custom parsing function
568 * and the standard value parsing function.
569 */
570 cf_pair_debug_log(cs, cp, rule);
571
572 if (cf_pair_is_parsed(cp)) continue;
573 ret = func(value_ctx, entry, base, cf_pair_to_item(cp), rule);
574 if (ret < 0) {
575 talloc_free(array);
576 return -1;
577 }
579 }
580 if (array) *(void **)out = array;
581 /*
582 * Single valued config item gets written to
583 * the data pointer directly.
584 */
585 } else {
586 CONF_PAIR *next;
587 int ret;
588
589 cp = cf_pair_find(cs, rule->name1);
590 if (!cp) {
591 if (deprecated) return 0;
592
593 if (!fr_rule_dflt(rule)) {
594 if (required) goto need_value;
595 return 1;
596 }
597
598 if (cf_pair_default(&dflt_cp, base, cs, rule) < 0) return -1;
599 cp = dflt_cp;
600 if (!cp) {
601 if (fr_rule_not_empty(rule)) {
602 cf_log_err(cs, "Configuration item \"%s\" cannot be empty", rule->name1);
603 return -1;
604 }
605
606 return 0;
607 }
608 } else {
609 if (cf_pair_unescape(cp, rule) < 0) return -1;
610 }
611
612 next = cf_pair_find_next(cs, cp, rule->name1);
613 if (next) {
614 cf_log_err(cf_pair_to_item(next), "Invalid duplicate configuration item '%s'", rule->name1);
615 return -1;
616 }
617 if (deprecated) goto deprecated;
618
619 cf_pair_debug_log(cs, cp, rule);
620
621 if (cf_pair_is_parsed(cp)) return 0;
622 ret = func(ctx, out, base, cf_pair_to_item(cp), rule);
623 if (ret < 0) return -1;
625 }
626
627 return 0;
628}
629
630/** Parses a #CONF_PAIR into a C data type, with a default value.
631 *
632 * Takes fields from a #conf_parser_t struct and uses them to parse the string value
633 * of a #CONF_PAIR into a C data type matching the type argument.
634 *
635 * The format of the types are the same as #fr_value_box_t types.
636 *
637 * @note The dflt value will only be used if no matching #CONF_PAIR is found. Empty strings will not
638 * result in the dflt value being used.
639 *
640 * **fr_type_t to data type mappings**
641 * | fr_type_t | Data type | Dynamically allocated |
642 * | ----------------------- | ------------------ | ---------------------- |
643 * | FR_TYPE_BOOL | ``bool`` | No |
644 * | FR_TYPE_UINT32 | ``uint32_t`` | No |
645 * | FR_TYPE_UINT16 | ``uint16_t`` | No |
646 * | FR_TYPE_UINT64 | ``uint64_t`` | No |
647 * | FR_TYPE_INT32 | ``int32_t`` | No |
648 * | FR_TYPE_STRING | ``char const *`` | Yes |
649 * | FR_TYPE_IPV4_ADDR | ``fr_ipaddr_t`` | No |
650 * | FR_TYPE_IPV4_PREFIX | ``fr_ipaddr_t`` | No |
651 * | FR_TYPE_IPV6_ADDR | ``fr_ipaddr_t`` | No |
652 * | FR_TYPE_IPV6_PREFIX | ``fr_ipaddr_t`` | No |
653 * | FR_TYPE_COMBO_IP_ADDR | ``fr_ipaddr_t`` | No |
654 * | FR_TYPE_COMBO_IP_PREFIX | ``fr_ipaddr_t`` | No |
655 * | FR_TYPE_TIME_DELTA | ``fr_time_delta_t``| No |
656 *
657 * @param[in] ctx To allocate arrays and values in.
658 * @param[in] cs to search for matching #CONF_PAIR in.
659 * @param[in] name of #CONF_PAIR to search for.
660 * @param[in] type Data type to parse #CONF_PAIR value as.
661 * Should be one of the following ``data`` types,
662 * and one or more of the following ``flag`` types or'd together:
663
664 * - ``data`` #FR_TYPE_BOOL - @copybrief FR_TYPE_BOOL
665 * - ``data`` #FR_TYPE_UINT32 - @copybrief FR_TYPE_UINT32
666 * - ``data`` #FR_TYPE_UINT16 - @copybrief FR_TYPE_UINT16
667 * - ``data`` #FR_TYPE_UINT64 - @copybrief FR_TYPE_UINT64
668 * - ``data`` #FR_TYPE_INT32 - @copybrief FR_TYPE_INT32
669 * - ``data`` #FR_TYPE_STRING - @copybrief FR_TYPE_STRING
670 * - ``data`` #FR_TYPE_IPV4_ADDR - @copybrief FR_TYPE_IPV4_ADDR (IPv4 address with prefix 32).
671 * - ``data`` #FR_TYPE_IPV4_PREFIX - @copybrief FR_TYPE_IPV4_PREFIX (IPv4 address with variable prefix).
672 * - ``data`` #FR_TYPE_IPV6_ADDR - @copybrief FR_TYPE_IPV6_ADDR (IPv6 address with prefix 128).
673 * - ``data`` #FR_TYPE_IPV6_PREFIX - @copybrief FR_TYPE_IPV6_PREFIX (IPv6 address with variable prefix).
674 * - ``data`` #FR_TYPE_COMBO_IP_ADDR - @copybrief FR_TYPE_COMBO_IP_ADDR (IPv4/IPv6 address with
675 * prefix 32/128).
676 * - ``data`` #FR_TYPE_COMBO_IP_PREFIX - @copybrief FR_TYPE_COMBO_IP_PREFIX (IPv4/IPv6 address with
677 * variable prefix).
678 * - ``data`` #FR_TYPE_TIME_DELTA - @copybrief FR_TYPE_TIME_DELTA
679 * - ``flag`` #CONF_FLAG_TMPL - @copybrief CONF_FLAG_TMPL
680 * Feeds the value into #tmpl_afrom_substr. Value can be
681 * obtained when processing requests, with #tmpl_expand or #tmpl_aexpand.
682 * - ``flag`` #FR_TYPE_DEPRECATED - @copybrief FR_TYPE_DEPRECATED
683 * - ``flag`` #CONF_FLAG_REQUIRED - @copybrief CONF_FLAG_REQUIRED
684 * - ``flag`` #CONF_FLAG_ATTRIBUTE - @copybrief CONF_FLAG_ATTRIBUTE
685 * - ``flag`` #CONF_FLAG_SECRET - @copybrief CONF_FLAG_SECRET
686 * - ``flag`` #CONF_FLAG_FILE_INPUT - @copybrief CONF_FLAG_FILE_INPUT
687 * - ``flag`` #CONF_FLAG_FILE_OUTPUT - @copybrief CONF_FLAG_FILE_OUTPUT
688 * - ``flag`` #CONF_FLAG_NOT_EMPTY - @copybrief CONF_FLAG_NOT_EMPTY
689 * - ``flag`` #CONF_FLAG_MULTI - @copybrief CONF_FLAG_MULTI
690 * - ``flag`` #CONF_FLAG_IS_SET - @copybrief CONF_FLAG_IS_SET
691 * @param[out] data Pointer to a global variable, or pointer to a field in the struct being populated with values.
692 * @param[in] dflt value to use, if no #CONF_PAIR is found.
693 * @param[in] dflt_quote around the dflt value.
694 * @return
695 * - 1 if default value was used, or if there was no CONF_PAIR or dflt.
696 * - 0 on success.
697 * - -1 on error.
698 * - -2 if deprecated.
699 */
700int cf_pair_parse(TALLOC_CTX *ctx, CONF_SECTION *cs, char const *name,
701 unsigned int type, void *data, char const *dflt, fr_token_t dflt_quote)
702{
703 conf_parser_t rule = {
704 .name1 = name,
705 .type = type,
706 .dflt = dflt,
707 .quote = dflt_quote
708 };
709
710 return cf_pair_parse_internal(ctx, data, NULL, cs, &rule);
711}
712
713/** Pre-allocate a config section structure to allow defaults to be set
714 *
715 * @param cs The parent subsection.
716 * @param base pointer or variable.
717 * @param rule that may have defaults in this config section.
718 * @return
719 * - 0 on success.
720 * - -1 on failure.
721 */
722static int cf_section_parse_init(CONF_SECTION *cs, void *base, conf_parser_t const *rule)
723{
724 CONF_PAIR *cp;
725
726 /*
727 * This rule refers to a named subsection
728 */
729 if ((rule->flags & CONF_FLAG_SUBSECTION)) {
730 char const *name2 = NULL;
731 CONF_SECTION *subcs;
732
733 /*
734 * Optional MUST be listed before required ones
735 */
736 if ((rule->flags & CONF_FLAG_OPTIONAL) != 0) {
737 return 0;
738 }
739
740 subcs = cf_section_find(cs, rule->name1, rule->name2);
741
742 /*
743 * Set the is_set field for the subsection.
744 */
745 if (rule->flags & CONF_FLAG_IS_SET) {
746 bool *is_set;
747
748 is_set = rule->data ? rule->is_set_ptr : ((uint8_t *)base) + rule->is_set_offset;
749 if (is_set) *is_set = (subcs != NULL);
750 }
751
752 /*
753 * It exists, we don't have to do anything else.
754 */
755 if (subcs) return 0;
756
757 /*
758 * If there is no subsection, either complain,
759 * allow it, or create it with default values.
760 */
761 if (rule->flags & CONF_FLAG_REQUIRED) {
762 cf_log_err(cs, "Missing %s {} subsection", rule->name1);
763 return -1;
764 }
765
766 /*
767 * It's OK for this to be missing. Don't
768 * initialize it.
769 */
770 if ((rule->flags & CONF_FLAG_OK_MISSING) != 0) return 0;
771
772 /*
773 * If there's no subsection in the
774 * config, BUT the conf_parser_t wants one,
775 * then create an empty one. This is so
776 * that we can track the strings,
777 * etc. allocated in the subsection.
778 */
779 if (DEBUG_ENABLED4) cf_log_debug(cs, "Allocating fake section \"%s\"", rule->name1);
780
781 /*
782 * If name1 is CF_IDENT_ANY, then don't
783 * alloc the section as we have no idea
784 * what it should be called.
785 */
786 if (rule->name1 == CF_IDENT_ANY) return 0;
787
788 /*
789 * Don't specify name2 if it's CF_IDENT_ANY
790 */
791 if (rule->name2 != CF_IDENT_ANY) name2 = rule->name2;
792 subcs = cf_section_alloc(cs, cs, rule->name1, name2);
793 if (!subcs) return -1;
794
795 return 0;
796 }
797
798 /*
799 * This rule refers to another conf_parse_t which is included in-line in
800 * this section.
801 */
802 if ((rule->flags & CONF_FLAG_REF) != 0) {
803 conf_parser_t const *rule_p;
804 uint8_t *sub_base = base;
805
806 fr_assert(rule->subcs != NULL);
807
808 sub_base += rule->offset;
809
810 for (rule_p = rule->subcs; rule_p->name1; rule_p++) {
811 int ret = cf_section_parse_init(cs, sub_base, rule_p);
812 if (ret < 0) return ret;
813 }
814 return 0;
815 }
816
817 /*
818 * Don't re-initialize data which was already parsed.
819 */
820 cp = cf_pair_find(cs, rule->name1);
821 if (cp && cp->parsed) return 0;
822
823 if ((rule->type != FR_TYPE_STRING) &&
824 (!(rule->flags & CONF_FLAG_FILE_INPUT)) &&
825 (!(rule->flags & CONF_FLAG_FILE_OUTPUT))) {
826 return 0;
827 }
828
829 if (rule->data) {
830 *(char **) rule->data = NULL;
831 } else if (base) {
832 *(char **) (((char *)base) + rule->offset) = NULL;
833 } else {
834 return 0;
835 }
836
837 return 0;
838}
839
841{
842 cf_item_foreach(&cs->item, ci) {
843 /*
844 * Don't recurse on sections. We can only safely
845 * check conf pairs at the same level as the
846 * section that was just parsed.
847 */
848 if (ci->type == CONF_ITEM_SECTION) continue;
849 if (ci->type == CONF_ITEM_PAIR) {
850 CONF_PAIR *cp;
851
852 cp = cf_item_to_pair(ci);
853 if (cp->parsed || cp->referenced || (ci->lineno < 0)) continue;
854
855 WARN("%s[%d]: The item '%s' is defined, but is unused by the configuration",
856 ci->filename, ci->lineno,
857 cp->attr);
858 }
859
860 /*
861 * Skip everything else.
862 */
863 }
864}
865
866/** Parse a subsection
867 *
868 * @note Turns out using nested structures (instead of pointers) for subsections, was actually
869 * a pretty bad design decision, and will need to be fixed at some future point.
870 * For now we have a horrible hack where only multi-subsections get an array of structures
871 * of the appropriate size.
872 *
873 * @param[in] ctx to allocate any additional structures under.
874 * @param[out] out pointer to a struct/pointer to fill with data.
875 * @param[in] base address of the structure out points into.
876 * May be NULL in the case of manual parsing.
877 * @param[in] cs to parse.
878 * @param[in] rule to parse the subcs with.
879 * @return
880 * - 0 on success.
881 * - -1 on general error.
882 * - -2 if a deprecated #CONF_ITEM was found.
883 */
884static int cf_subsection_parse(TALLOC_CTX *ctx, void *out, void *base, CONF_SECTION *cs, conf_parser_t const *rule)
885{
886 CONF_SECTION *subcs = NULL;
887 int count = 0, i = 0, ret;
888
889 size_t subcs_size = rule->subcs_size;
890 conf_parser_t const *rules = rule->subcs;
891
892 uint8_t **array = NULL;
893
895
896 subcs = cf_section_find(cs, rule->name1, rule->name2);
897 if (!subcs) return 0;
898
899 /*
900 * Handle the single subsection case (which is simple)
901 */
902 if (!(rule->flags & CONF_FLAG_MULTI)) {
903 uint8_t *buff = NULL;
904
905 if (DEBUG_ENABLED4) cf_log_debug(cs, "Evaluating rules for %s section. Output %p",
906 cf_section_name1(subcs), out);
907
908 /*
909 * Add any rules, so the func can just call cf_section_parse
910 * if it wants to continue after doing its stuff.
911 */
912 if (cf_section_rules_push(subcs, rules) < 0) return -1;
913 if (rule->func) return rule->func(ctx, out, base, cf_section_to_item(subcs), rule);
914
915 /*
916 * FIXME: We shouldn't allow nested structures like this.
917 * Each subsection struct should be allocated separately so
918 * we have a clean talloc hierarchy.
919 */
920 if (!subcs_size) return cf_section_parse(ctx, out, subcs);
921
922 if (out) {
923 MEM(buff = talloc_zero_array(ctx, uint8_t, subcs_size));
924 if (rule->subcs_type) talloc_set_name_const(buff, rule->subcs_type);
925 }
926
927 ret = cf_section_parse(buff, buff, subcs);
928 if (ret < 0) {
930 return ret;
931 }
932
933 if (out) *((uint8_t **)out) = buff;
934
935 return 0;
936 }
937
938 fr_assert(subcs_size);
939
940 /*
941 * Handle the multi subsection case (which is harder)
942 */
943 subcs = NULL;
944 while ((subcs = cf_section_find_next(cs, subcs, rule->name1, rule->name2))) count++;
945
946 /*
947 * Allocate an array to hold the subsections
948 */
949 if (out) {
950 MEM(array = talloc_zero_array(ctx, uint8_t *, count));
951 if (rule->subcs_type) talloc_set_name(array, "%s *", rule->subcs_type);
952 }
953 /*
954 * Start parsing...
955 *
956 * Note, we allocate each subsection structure individually
957 * so that they can be used as talloc contexts and we can
958 * keep the talloc hierarchy clean.
959 */
960 subcs = NULL;
961 while ((subcs = cf_section_find_next(cs, subcs, rule->name1, rule->name2))) {
962 uint8_t *buff = NULL;
963
964 if (DEBUG_ENABLED4) cf_log_debug(cs, "Evaluating rules for %s[%i] section. Output %p",
965 cf_section_name1(subcs),
966 i, out);
967
968 if (array) {
969 MEM(buff = talloc_zero_array(array, uint8_t, subcs_size));
970 if (rule->subcs_type) talloc_set_name_const(buff, rule->subcs_type);
971 array[i++] = buff;
972 }
973
974 /*
975 * Add any rules, so the func can just call cf_section_parse
976 * if it wants to continue after doing its stuff.
977 */
978 if (cf_section_rules_push(subcs, rules) < 0) {
979 talloc_free(array);
980 return -1;
981 }
982 if (rule->func) {
983 ret = rule->func(ctx, buff, base, cf_section_to_item(subcs), rule);
984 if (ret < 0) {
985 talloc_free(array);
986 return ret;
987 }
988 continue;
989 }
990
991 ret = cf_section_parse(buff, buff, subcs);
992 if (ret < 0) {
993 talloc_free(array);
994 return ret;
995 }
996 }
997
998 if (out) *((uint8_t ***)out) = array;
999
1000 return 0;
1001}
1002
1003static int cf_section_parse_rule(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs, conf_parser_t const *rule)
1004{
1005 int ret;
1006 bool *is_set = NULL;
1007 void *data = NULL;
1008
1009 /*
1010 * Ignore ON_READ parse rules if there's no subsequent
1011 * parse functions.
1012 */
1013 if (!rule->func && rule->on_read) return 0;
1014
1015 /*
1016 * Pre-allocate the config structure to hold default values
1017 */
1018 if (cf_section_parse_init(cs, base, rule) < 0) return -1;
1019
1020 if (rule->data) {
1021 data = rule->data; /* prefer this. */
1022 } else if (base) {
1023 data = ((uint8_t *)base) + rule->offset;
1024 }
1025
1026 /*
1027 * Handle subsections specially
1028 */
1029 if (rule->flags & CONF_FLAG_SUBSECTION) {
1030 return cf_subsection_parse(ctx, data, base, cs, rule);
1031 }
1032
1033 /*
1034 * Ignore this rule if it's a reference, as the
1035 * rules it points to have been pushed by the
1036 * above function.
1037 */
1038 if ((rule->flags & CONF_FLAG_REF) != 0) {
1039 conf_parser_t const *rule_p;
1040 uint8_t *sub_base = base;
1041
1042 fr_assert(rule->subcs != NULL);
1043
1044 sub_base += rule->offset;
1045
1046 for (rule_p = rule->subcs; rule_p->name1; rule_p++) {
1047 if (rule_p->flags & CONF_FLAG_DEPRECATED) continue; /* Skip deprecated */
1048
1049 ret = cf_section_parse_rule(ctx, sub_base, cs, rule_p);
1050 if (ret < 0) return ret;
1051 }
1052
1053 /*
1054 * Ensure we have a proper terminator, type so we catch
1055 * missing terminators reliably
1056 */
1057 fr_cond_assert(rule_p->type == conf_term.type);
1058
1059 return 0;
1060 }
1061
1062 /*
1063 * Else it's a CONF_PAIR
1064 */
1065
1066 /*
1067 * Pair either needs an output destination or
1068 * there needs to be a function associated with
1069 * it.
1070 */
1071 if (!data && !rule->func) {
1072 cf_log_err(cs, "Rule doesn't specify output destination");
1073 return -1;
1074 }
1075
1076 /*
1077 * Get pointer to where we need to write out
1078 * whether the pointer was set.
1079 */
1080 if (rule->flags & CONF_FLAG_IS_SET) {
1081 is_set = rule->data ? rule->is_set_ptr : ((uint8_t *)base) + rule->is_set_offset;
1082 }
1083
1084 /*
1085 * Parse the pair we found, or a default value.
1086 */
1087 ret = cf_pair_parse_internal(ctx, data, base, cs, rule);
1088 switch (ret) {
1089 case 1: /* Used default (or not present) */
1090 if (is_set) *is_set = false;
1091 ret = 0;
1092 break;
1093
1094 case 0: /* OK */
1095 if (is_set) *is_set = true;
1096 break;
1097
1098 case -1: /* Parse error */
1099 break;
1100
1101 case -2: /* Deprecated CONF ITEM */
1102 if (((rule + 1)->offset && ((rule + 1)->offset == rule->offset)) ||
1103 ((rule + 1)->data && ((rule + 1)->data == rule->data))) {
1104 cf_log_err(cs, "Replace \"%s\" with \"%s\"", rule->name1,
1105 (rule + 1)->name1);
1106 }
1107 break;
1108 }
1109
1110 return ret;
1111}
1112
1113/** Parse a configuration section into user-supplied variables
1114 *
1115 * @param[in] ctx to allocate any strings, or additional structures in.
1116 * Usually the same as base, unless base is a nested struct.
1117 * @param[out] base pointer to a struct to fill with data.
1118 * @param[in] cs to parse.
1119 * @return
1120 * - 0 on success.
1121 * - -1 on general error.
1122 * - -2 if a deprecated #CONF_ITEM was found.
1123 */
1124int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
1125{
1126 CONF_DATA const *rule_cd = NULL;
1127
1128 if (!cs->name2) {
1129 cf_log_debug(cs, "%.*s%s {", SECTION_SPACE(cs), parse_spaces, cs->name1);
1130 } else {
1131 cf_log_debug(cs, "%.*s%s %s {", SECTION_SPACE(cs), parse_spaces, cs->name1, cs->name2);
1132 }
1133
1134 /*
1135 * Loop over all the child rules of the section
1136 */
1137 while ((rule_cd = cf_data_find_next(cs, rule_cd, conf_parser_t, CF_IDENT_ANY))) {
1138 int ret;
1139 conf_parser_t *rule;
1140
1141 rule = cf_data_value(rule_cd);
1142
1143 ret = cf_section_parse_rule(ctx, base, cs, rule);
1144 if (ret < 0) return ret;
1145 }
1146
1147 cs->base = base;
1148
1149 /*
1150 * Warn about items in the configuration which weren't
1151 * checked during parsing.
1152 */
1154
1155 cf_log_debug(cs, "%.*s}", SECTION_SPACE(cs), parse_spaces);
1156
1157 return 0;
1158}
1159
1160/*
1161 * Pass2 fixups on tmpl_t
1162 *
1163 * We don't have (or need yet) cf_pair_parse_pass2(), so we just
1164 * do it for tmpls.
1165 */
1167 bool attribute, fr_dict_t const *dict_def)
1168{
1169 tmpl_t *vpt = *out;
1170
1171 fr_assert(vpt); /* We need something to resolve */
1172
1173 if (tmpl_resolve(vpt, &(tmpl_res_rules_t){ .dict_def = dict_def, .force_dict_def = (dict_def != NULL)}) < 0) {
1174 cf_log_perr(cp, "Failed processing configuration item '%s'", cp->attr);
1175 return -1;
1176 }
1177
1178 if (attribute && !tmpl_is_attr(vpt)) {
1179 cf_log_err(cp, "Expected attr got %s",
1180 tmpl_type_to_str(vpt->type));
1181 return -1;
1182 }
1183
1184 switch (vpt->type) {
1185 /*
1186 * All attributes should have been defined by this point.
1187 */
1189 cf_log_err(cp, "Unknown attribute '%s'", tmpl_attr_tail_unresolved(vpt));
1190 return -1;
1191
1193 /*
1194 * Try to realize the underlying type, if at all possible.
1195 */
1196 if (!attribute && type && (tmpl_cast_in_place(vpt, type, NULL) < 0)) {
1197 cf_log_perr(cp, "Failed processing configuration item '%s'", cp->attr);
1198 return -1;
1199 }
1200 break;
1201
1202 case TMPL_TYPE_ATTR:
1203 case TMPL_TYPE_DATA:
1204 case TMPL_TYPE_EXEC:
1206 case TMPL_TYPE_XLAT:
1208 break;
1209
1211 case TMPL_TYPE_REGEX:
1215 case TMPL_TYPE_NULL:
1216 case TMPL_TYPE_MAX:
1217 fr_assert(0);
1218 /* Don't add default */
1219 }
1220
1221 return 0;
1222}
1223
1224/** Fixup xlat expansions and attributes
1225 *
1226 * @param[out] base start of structure to write #tmpl_t s to.
1227 * @param[in] cs CONF_SECTION to fixup.
1228 * @return
1229 * - 0 on success.
1230 * - -1 on failure (parse errors etc...).
1231 */
1233{
1234 CONF_DATA const *rule_cd = NULL;
1235
1236 while ((rule_cd = cf_data_find_next(cs, rule_cd, conf_parser_t, CF_IDENT_ANY))) {
1237 bool attribute, multi, is_tmpl, is_xlat;
1238 CONF_PAIR *cp;
1239 conf_parser_t *rule = cf_data_value(rule_cd);
1240 void *data;
1241 fr_type_t type = rule->type;
1242 conf_parser_flags_t flags = rule->flags;
1243 fr_dict_t const *dict = NULL;
1244
1245 is_tmpl = (flags & CONF_FLAG_TMPL);
1246 is_xlat = (flags & CONF_FLAG_XLAT);
1247 attribute = (flags & CONF_FLAG_ATTRIBUTE);
1248 multi = (flags & CONF_FLAG_MULTI);
1249
1250 /*
1251 * It's a section, recurse!
1252 */
1253 if (flags & CONF_FLAG_SUBSECTION) {
1254 uint8_t *subcs_base;
1255 CONF_SECTION *subcs = cf_section_find(cs, rule->name1, rule->name2);
1256
1257 /*
1258 * Select base by whether this is a nested struct,
1259 * or a pointer to another struct.
1260 */
1261 if (!base) {
1262 subcs_base = NULL;
1263 } else if (multi) {
1264 size_t j, len;
1265 uint8_t **array;
1266
1267 array = *(uint8_t ***)(((uint8_t *)base) + rule->offset);
1268 len = talloc_array_length(array);
1269
1270 for (j = 0; j < len; j++) if (cf_section_parse_pass2(array[j], subcs) < 0) return -1;
1271 continue;
1272 } else {
1273 subcs_base = (uint8_t *)base + rule->offset;
1274 }
1275
1276 if (cf_section_parse_pass2(subcs_base, subcs) < 0) return -1;
1277
1278 continue;
1279 }
1280
1281 /*
1282 * Find the CONF_PAIR, may still not exist if there was
1283 * no default set for the conf_parser_t.
1284 */
1285 cp = cf_pair_find(cs, rule->name1);
1286 if (!cp) continue;
1287
1288 /*
1289 * Figure out which data we need to fix.
1290 */
1291 data = rule->data; /* prefer this. */
1292 if (!data && base) data = ((char *)base) + rule->offset;
1293 if (!data) continue;
1294
1295 /*
1296 * Non-xlat expansions shouldn't have xlat!
1297 *
1298 * Except other libraries like libkafka may be the ones
1299 * doing the actual expansion, so we don't _know_
1300 * if the xlatlike value is destined for use in FreeRADIUS
1301 * or not, so we can't definitely determine if this is an
1302 * error.
1303 *
1304 * Code left in place to warn other people off re-adding
1305 * this check in future.
1306 */
1307#if 0
1308 if (!is_xlat && !is_tmpl) {
1309 /*
1310 * Ignore %{... in shared secrets.
1311 * They're never dynamically expanded.
1312 */
1313 if ((rule->flags & CONF_FLAG_SECRET) != 0) continue;
1314
1315 if (strstr(cp->value, "%{") != NULL) {
1316 cf_log_err(cp, "Found dynamic expansion in string which "
1317 "will not be dynamically expanded");
1318 return -1;
1319 }
1320 continue;
1321 }
1322#endif
1323
1324 /*
1325 * Search for dictionary data somewhere in the virtual
1326 * server.
1327 */
1329
1330 /*
1331 * Parse (and throw away) the xlat string (for validation).
1332 *
1333 * FIXME: All of these should be converted from CONF_FLAG_XLAT
1334 * to CONF_FLAG_TMPL.
1335 */
1336 if (is_xlat) {
1337 ssize_t slen;
1338 xlat_exp_head_t *xlat;
1339
1340 redo:
1341 xlat = NULL;
1342
1343 /*
1344 * xlat expansions should be parseable.
1345 */
1346 slen = xlat_tokenize(cs, &xlat,
1347 &FR_SBUFF_IN(cp->value, talloc_array_length(cp->value) - 1), NULL,
1348 &(tmpl_rules_t) {
1349 .attr = {
1350 .dict_def = dict,
1351 .list_def = request_attr_request,
1352 .allow_unknown = false,
1353 .allow_unresolved = false,
1354 .allow_foreign = (dict == NULL)
1355 },
1356 }, 0);
1357 if (slen < 0) {
1358 char *spaces, *text;
1359
1360 fr_canonicalize_error(cs, &spaces, &text, slen, cp->value);
1361
1362 cf_log_err(cp, "Failed parsing expansion string:");
1363 cf_log_err(cp, "%s", text);
1364 cf_log_perr(cp, "%s^", spaces);
1365
1367 talloc_free(text);
1368 talloc_free(xlat);
1369 return -1;
1370 }
1371
1372 talloc_free(xlat);
1373
1374 /*
1375 * If the "multi" flag is set, check all of them.
1376 */
1377 if (multi) {
1378 cp = cf_pair_find_next(cs, cp, cp->attr);
1379 if (cp) goto redo;
1380 }
1381 continue;
1382
1383 /*
1384 * Parse the pair into a template
1385 */
1386 } else if (is_tmpl && !multi) {
1387 if (cf_parse_tmpl_pass2(cs, (tmpl_t **)data, cp, type, attribute, dict) < 0) {
1388 return -1;
1389 }
1390
1391 } else if (is_tmpl) {
1392 size_t i;
1393 char const *name = cp->attr;
1394 tmpl_t **array = *(tmpl_t ***) data;
1395
1396 for (i = 0; i < talloc_array_length(array); i++, cp = cf_pair_find_next(cs, cp, name)) {
1397 if (!cp) break;
1398
1399 if (cf_parse_tmpl_pass2(cs, &array[i], cp, type, attribute, dict) < 0) {
1400 return -1;
1401 }
1402 }
1403 }
1404 }
1405
1406 return 0;
1407}
1408
1409
1410/** Add a single rule to a #CONF_SECTION
1411 *
1412 * @param[in] cs to add rules to.
1413 * @param[in] rule to add.
1414 * @param[in] filename where the rule was pushed.
1415 * @param[in] lineno where the rule was pushed.
1416 * @return
1417 * - 0 on success.
1418 * - -1 if the rules added conflict.
1419 */
1420int _cf_section_rule_push(CONF_SECTION *cs, conf_parser_t const *rule, char const *filename, int lineno)
1421{
1422 char const *name1, *name2;
1423
1424 if (!cs || !rule) return 0;
1425
1426 name1 = rule->name1 == CF_IDENT_ANY ? "__any__" : rule->name1;
1427 name2 = rule->name2 == CF_IDENT_ANY ? "__any__" : rule->name2;
1428
1429 if (DEBUG_ENABLED4) {
1430 cf_log_debug(cs, "Pushed parse rule to %s section: %s %s",
1431 cf_section_name1(cs),
1432 name1, rule->flags & CONF_FLAG_SUBSECTION ? "{}": "");
1433 }
1434
1435 /*
1436 * Qualifying with name prevents duplicate rules being added
1437 *
1438 * Fixme maybe?.. Can't have a section and pair with the same name.
1439 */
1440 if (!_cf_data_add_static(CF_TO_ITEM(cs), rule, "conf_parser_t", name1, filename, lineno)) {
1441 CONF_DATA const *cd;
1442 conf_parser_t *old;
1443
1444 cd = cf_data_find(CF_TO_ITEM(cs), conf_parser_t, name1);
1445 old = cf_data_value(cd);
1446 fr_assert(old != NULL);
1447
1448 /*
1449 * Shut up about duplicates.
1450 */
1451 if (memcmp(rule, old, sizeof(*rule)) == 0) {
1452 return 0;
1453 }
1454
1455 /*
1456 * Remove any ON_READ callbacks, and add the new
1457 * rule in its place.
1458 */
1459 if (old->on_read) {
1460 CONF_DATA *cd1;
1461
1462 /*
1463 * Over-write the rule in place.
1464 *
1465 * We'd like to call cf_item_remove(), but
1466 * that apparently doesn't work for
1467 * CONF_DATA. We don't need to
1468 * free/alloc one, so re-using this is
1469 * fine.
1470 */
1471 memcpy(&cd1, &cd, sizeof(cd1));
1472 cd1->data = rule;
1473 cd1->item.filename = filename;
1474 cd1->item.lineno = lineno;
1475 return 0;
1476 }
1477
1478 /*
1479 * If we have a duplicate sub-section, just
1480 * recurse and add the new sub-rules to the
1481 * existing sub-section.
1482 */
1483 if (rule->flags & CONF_FLAG_SUBSECTION) {
1484 CONF_SECTION *subcs;
1485
1486 subcs = cf_section_find(cs, name1, name2);
1487 if (!subcs) {
1488 cf_log_err(cs, "Failed finding '%s' subsection", name1);
1489 cf_item_debug(cs);
1490 return -1;
1491 }
1492
1493 /*
1494 * The old rules were delayed until we pushed a matching subsection which is actually used.
1495 */
1496 if ((old->flags & CONF_FLAG_OPTIONAL) != 0) {
1497 if (cf_section_rules_push(subcs, old->subcs) < 0) return -1;
1498 }
1499
1500 return cf_section_rules_push(subcs, rule->subcs);
1501 }
1502
1503 cf_log_err(cs, "Data of type %s with name \"%s\" already exists. "
1504 "Existing data added %s[%i]", "conf_parser_t",
1505 name1, cd->item.filename, cd->item.lineno);
1506
1507 cf_item_debug(cs);
1508 return -1;
1509 }
1510
1511 return 0;
1512}
1513
1514/** Add an array of parse rules to a #CONF_SECTION
1515 *
1516 * @param[in] cs to add rules to.
1517 * @param[in] rules to add. Last element should have NULL name field.
1518 * @param[in] filename where the rule was pushed.
1519 * @param[in] lineno where the rule was pushed.
1520 * @return
1521 * - 0 on success.
1522 * - -1 on failure.
1523 */
1524int _cf_section_rules_push(CONF_SECTION *cs, conf_parser_t const *rules, char const *filename, int lineno)
1525{
1526 conf_parser_t const *rule_p;
1527
1528 if (!cs || !rules) return 0;
1529
1530 for (rule_p = rules; rule_p->name1; rule_p++) {
1531 if (rule_p->flags & CONF_FLAG_DEPRECATED) continue; /* Skip deprecated */
1532 if (_cf_section_rule_push(cs, rule_p, filename, lineno) < 0) return -1;
1533 }
1534
1535 /*
1536 * Ensure we have a proper terminator, type so we catch
1537 * missing terminators reliably
1538 */
1539 fr_cond_assert(rule_p->type == conf_term.type);
1540
1541 return 0;
1542}
1543
1544/** Generic function for parsing conf pair values as int
1545 *
1546 * @note This should be used for enum types as c99 6.4.4.3 states that the enumeration
1547 * constants are of type int.
1548 *
1549 */
1550int cf_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
1551 CONF_ITEM *ci, conf_parser_t const *rule)
1552{
1553 int num;
1554 cf_table_parse_ctx_t const *parse_ctx = rule->uctx;
1555
1556 if (cf_pair_in_table(&num, parse_ctx->table, *parse_ctx->len, cf_item_to_pair(ci)) < 0) return -1;
1557
1558 *((int *)out) = num;
1559
1560 return 0;
1561}
1562
1563/** Generic function for parsing conf pair values as int32_t (FR_TYPE_INT32)
1564 *
1565 */
1566int cf_table_parse_int32(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
1567 CONF_ITEM *ci, conf_parser_t const *rule)
1568{
1569 int32_t num;
1570 cf_table_parse_ctx_t const *parse_ctx = rule->uctx;
1571
1572 if (cf_pair_in_table(&num, parse_ctx->table, *parse_ctx->len, cf_item_to_pair(ci)) < 0) return -1;
1573
1574 *((int32_t *)out) = num;
1575
1576 return 0;
1577}
1578
1579/** Generic function for parsing conf pair values as int32_t (FR_TYPE_UINT32)
1580 *
1581 */
1582int cf_table_parse_uint32(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
1583 CONF_ITEM *ci, conf_parser_t const *rule)
1584{
1585 int32_t num;
1586 cf_table_parse_ctx_t const *parse_ctx = rule->uctx;
1587
1588 if (cf_pair_in_table(&num, parse_ctx->table, *parse_ctx->len, cf_item_to_pair(ci)) < 0) return -1;
1589 if (num < 0) {
1590 cf_log_err(ci, "Resolved value must be a positive integer, got %i", num);
1591 return -1;
1592 }
1593 *((uint32_t *)out) = (uint32_t)num;
1594
1595 return 0;
1596}
1597
1598/** Generic function for resolving UID strings to uid_t values
1599 *
1600 * Type should be FR_TYPE_VOID, struct field should be a uid_t.
1601 */
1602int cf_parse_uid(TALLOC_CTX *ctx, void *out, UNUSED void *parent,
1603 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
1604{
1605 if (fr_perm_uid_from_str(ctx, (uid_t *)out, cf_pair_value(cf_item_to_pair(ci))) < 0) {
1606 cf_log_perr(ci, "Failed resolving UID");
1607 return -1;
1608 }
1609
1610 return 0;
1611}
1612
1613/** Generic function for resolving GID strings to uid_t values
1614 *
1615 * Type should be FR_TYPE_VOID, struct field should be a gid_t.
1616 */
1617int cf_parse_gid(TALLOC_CTX *ctx, void *out, UNUSED void *parent,
1618 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
1619{
1620 if (fr_perm_gid_from_str(ctx, (gid_t *)out, cf_pair_value(cf_item_to_pair(ci))) < 0) {
1621 cf_log_perr(ci, "Failed resolving GID");
1622 return -1;
1623 }
1624
1625 return 0;
1626}
1627
1628/** Generic function for resolving permissions to a mode-t
1629 *
1630 * Type should be FR_TYPE_VOID, struct field should be a gid_t.
1631 */
1632int cf_parse_permissions(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
1633 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
1634{
1635 mode_t mode;
1636 char const *name = cf_pair_value(cf_item_to_pair(ci));
1637
1638 if (fr_perm_mode_from_str(&mode, name) < 0) {
1639 cf_log_perr(ci, "Invalid permissions string");
1640 return -1;
1641 }
1642
1643 *(mode_t *) out = mode;
1644
1645 return 0;
1646}
static int const char char buffer[256]
Definition acutest.h:576
#define RCSID(id)
Definition build.h:483
#define unlikely(_x)
Definition build.h:381
#define UNUSED
Definition build.h:315
char const * cf_expand_variables(char const *cf, int lineno, CONF_SECTION *outer_cs, char *output, size_t outsize, char const *input, ssize_t inlen, bool *soft_fail)
Definition cf_file.c:172
bool cf_file_check(CONF_PAIR *cp, bool check_perms)
Do some checks on the file as an "input" file.
Definition cf_file.c:656
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_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
Definition cf_parse.c:1124
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
static int cf_pair_default(CONF_PAIR **out, void *parent, CONF_SECTION *cs, conf_parser_t const *rule)
Allocate a pair using the dflt value and quotation.
Definition cf_parse.c:296
#define PAIR_SPACE(_cs)
Definition cf_parse.c:46
static char const parse_spaces[]
Definition cf_parse.c:44
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_pair_parse_value(TALLOC_CTX *ctx, void *out, UNUSED void *base, CONF_ITEM *ci, conf_parser_t const *rule)
Parses a CONF_PAIR into a C data type.
Definition cf_parse.c:171
static int cf_pair_unescape(CONF_PAIR *cp, conf_parser_t const *rule)
Definition cf_parse.c:352
static void cf_section_parse_warn(CONF_SECTION *cs)
Definition cf_parse.c:840
static conf_parser_t conf_term
Definition cf_parse.c:43
int cf_parse_gid(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Generic function for resolving GID strings to uid_t values.
Definition cf_parse.c:1617
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
void cf_pair_debug_log(CONF_SECTION const *cs, CONF_PAIR *cp, conf_parser_t const *rule)
Definition cf_parse.c:49
static int cf_pair_parse_internal(TALLOC_CTX *ctx, void *out, void *base, CONF_SECTION *cs, conf_parser_t const *rule)
Parses a CONF_PAIR into a C data type, with a default value.
Definition cf_parse.c:440
int cf_parse_permissions(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Generic function for resolving permissions to a mode-t.
Definition cf_parse.c:1632
int cf_section_parse_pass2(void *base, CONF_SECTION *cs)
Fixup xlat expansions and attributes.
Definition cf_parse.c:1232
static int cf_section_parse_init(CONF_SECTION *cs, void *base, conf_parser_t const *rule)
Pre-allocate a config section structure to allow defaults to be set.
Definition cf_parse.c:722
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
#define SECTION_SPACE(_cs)
Definition cf_parse.c:47
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
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
static int cf_subsection_parse(TALLOC_CTX *ctx, void *out, void *base, CONF_SECTION *cs, conf_parser_t const *rule)
Parse a subsection.
Definition cf_parse.c:884
int cf_parse_uid(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Generic function for resolving UID strings to uid_t values.
Definition cf_parse.c:1602
static int cf_parse_tmpl_pass2(UNUSED CONF_SECTION *cs, tmpl_t **out, CONF_PAIR *cp, fr_type_t type, bool attribute, fr_dict_t const *dict_def)
Definition cf_parse.c:1166
static int cf_section_parse_rule(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs, conf_parser_t const *rule)
Definition cf_parse.c:1003
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:642
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition cf_parse.h:596
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
#define fr_rule_dflt(_rule)
Definition cf_parse.h:475
conf_parser_flags_t flags
Flags which control parsing behaviour.
Definition cf_parse.h:585
#define fr_rule_not_empty(_rule)
Definition cf_parse.h:467
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
#define fr_rule_multi(_rule)
Definition cf_parse.h:465
char const * name2
Second identifier for CONF_SECTION.
Definition cf_parse.h:581
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
#define fr_rule_file_exists(_rule)
Definition cf_parse.h:473
#define fr_rule_deprecated(_rule)
Definition cf_parse.h:454
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
#define fr_rule_file_input(_rule)
Definition cf_parse.h:460
#define cf_section_rules_push(_cs, _rule)
Definition cf_parse.h:674
#define fr_rule_is_tmpl(_rule)
Definition cf_parse.h:481
char const * name1
Name of the CONF_ITEM to parse.
Definition cf_parse.h:580
#define fr_rule_is_attribute(_rule)
Definition cf_parse.h:477
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
#define fr_rule_required(_rule)
Definition cf_parse.h:456
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_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_TMPL
CONF_PAIR should be parsed as a template.
Definition cf_parse.h:430
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:579
bool printed
Was this item printed already in debug mode?
Definition cf_priv.h:82
CONF_ITEM item
Common set of fields.
Definition cf_priv.h:102
void * base
Definition cf_priv.h:113
char const * name2
Second name token. Given foo bar {} would be bar.
Definition cf_priv.h:105
char const * attr
Attribute name.
Definition cf_priv.h:73
fr_token_t rhs_quote
Value Quoting style T_(DOUBLE|SINGLE|BACK)_QUOTE_STRING or T_BARE_WORD.
Definition cf_priv.h:78
char const * value
Attribute value.
Definition cf_priv.h:74
#define cf_item_foreach(_ci, _iter)
Iterate over the contents of a list.
Definition cf_priv.h:149
char const * name1
First name token. Given foo bar {} would be foo.
Definition cf_priv.h:104
void const * data
User data.
Definition cf_priv.h:130
char const * filename
The file the config item was parsed from.
Definition cf_priv.h:64
@ CONF_ITEM_PAIR
Definition cf_priv.h:41
@ CONF_ITEM_SECTION
Definition cf_priv.h:42
bool referenced
Was this item referenced in the config?
Definition cf_priv.h:83
CONF_ITEM item
Common set of fields.
Definition cf_priv.h:125
bool parsed
Was this item used during parsing?
Definition cf_priv.h:81
int lineno
The line number the config item began on.
Definition cf_priv.h:63
Internal data that is associated with a configuration section.
Definition cf_priv.h:124
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
CONF_PAIR * cf_pair_find_next(CONF_SECTION const *cs, CONF_PAIR const *prev, char const *attr)
Find a pair with a name matching attr, after specified pair.
Definition cf_util.c:1453
unsigned int cf_pair_count(CONF_SECTION const *cs, char const *attr)
Count the number of times an attribute occurs in a parent section.
Definition cf_util.c:1520
int cf_pair_in_table(int32_t *out, fr_table_num_sorted_t const *table, size_t table_len, CONF_PAIR *cp)
Check to see if the CONF_PAIR value is present in the specified table.
Definition cf_util.c:1966
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
Definition cf_util.c:1763
CONF_ITEM * cf_section_to_item(CONF_SECTION const *cs)
Cast a CONF_SECTION to a CONF_ITEM.
Definition cf_util.c:738
CONF_PAIR * cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value, fr_token_t op, fr_token_t lhs_quote, fr_token_t rhs_quote)
Allocate a CONF_PAIR.
Definition cf_util.c:1279
void cf_pair_mark_parsed(CONF_PAIR *cp)
Mark a pair as parsed.
Definition cf_util.c:1376
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1171
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition cf_util.c:1028
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
Definition cf_util.c:1439
CONF_DATA const * _cf_data_add_static(CONF_ITEM *ci, void const *data, char const *type, char const *name, char const *filename, int lineno)
Add non-talloced user data to a config section.
Definition cf_util.c:1828
bool cf_pair_is_parsed(CONF_PAIR *cp)
Return whether a pair has already been parsed.
Definition cf_util.c:1388
fr_token_t cf_pair_value_quote(CONF_PAIR const *pair)
Return the value (rhs) quoting of a pair.
Definition cf_util.c:1638
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:664
CONF_SECTION * cf_section_find_next(CONF_SECTION const *cs, CONF_SECTION const *prev, char const *name1, char const *name2)
Return the next matching section.
Definition cf_util.c:1049
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1594
CONF_ITEM * cf_pair_to_item(CONF_PAIR const *cp)
Cast a CONF_PAIR to a CONF_ITEM.
Definition cf_util.c:722
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:289
#define cf_data_find(_cf, _type, _name)
Definition cf_util.h:244
#define cf_canonicalize_error(_ci, _slen, _msg, _str)
Definition cf_util.h:367
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:296
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition cf_util.h:140
#define CF_TO_ITEM(_cf)
Auto cast from the input type to CONF_ITEM (which is the base type)
Definition cf_util.h:65
#define cf_log_debug(_cf, _fmt,...)
Definition cf_util.h:292
#define cf_data_find_next(_cf, _prev, _type, _name)
Definition cf_util.h:247
#define cf_item_debug(_cf)
Definition cf_util.h:361
#define CF_IDENT_ANY
Definition cf_util.h:78
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:139
#define MEM(x)
Definition debug.h:36
static char const * spaces
Definition dependency.c:371
Test enumeration values.
Definition dict_test.h:92
#define DEBUG_ENABLED4
True if global debug level 1-3 messages are enabled.
Definition log.h:260
talloc_free(reap)
int fr_debug_lvl
Definition log.c:43
void fr_canonicalize_error(TALLOC_CTX *ctx, char **sp, char **text, ssize_t slen, char const *fmt)
Canonicalize error strings, removing tabs, and generate spaces for error marker.
Definition log.c:90
@ L_DBG_LVL_3
3rd highest priority debug messages (-xxx | -Xx).
Definition log.h:72
fr_type_t
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_VOID
User data.
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
unsigned int mode_t
int fr_perm_mode_from_str(mode_t *out, char const *str)
Definition perm.c:62
int fr_perm_uid_from_str(TALLOC_CTX *ctx, uid_t *out, char const *name)
Resolve a user name to a GID.
Definition perm.c:451
int fr_perm_gid_from_str(TALLOC_CTX *ctx, gid_t *out, char const *name)
Resolve a group name to a GID.
Definition perm.c:473
char * fr_asprint(TALLOC_CTX *ctx, char const *in, ssize_t inlen, char quote)
Escape string that may contain binary data, and write it to a new buffer.
Definition print.c:428
#define fr_assert(_expr)
Definition rad_assert.h:38
static char * secret
#define WARN(fmt,...)
Definition radclient.h:47
fr_dict_attr_t const * request_attr_request
Definition request.c:45
static char const * name
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_adv_past_whitespace(_sbuff, _len, _tt)
static char const * tmpl_type_to_str(tmpl_type_t type)
Return a static string containing the type name.
Definition tmpl.h:645
#define tmpl_is_attr_unresolved(vpt)
Definition tmpl.h:224
static fr_slen_t vpt
Definition tmpl.h:1272
int tmpl_resolve(tmpl_t *vpt, tmpl_res_rules_t const *tr_rules))
Attempt to resolve functions and attributes in xlats and attribute references.
#define tmpl_is_attr(vpt)
Definition tmpl.h:213
@ TMPL_TYPE_REGEX_UNCOMPILED
Regex where compilation is possible but hasn't been performed yet.
Definition tmpl.h:162
@ TMPL_TYPE_MAX
Marker for the last tmpl type.
Definition tmpl.h:203
@ TMPL_TYPE_ATTR_UNRESOLVED
An attribute reference that we couldn't resolve but looked valid.
Definition tmpl.h:189
@ TMPL_TYPE_ATTR
Reference to one or more attributes.
Definition tmpl.h:146
@ TMPL_TYPE_XLAT
Pre-parsed xlat expansion.
Definition tmpl.h:150
@ TMPL_TYPE_NULL
Has no value.
Definition tmpl.h:138
@ TMPL_TYPE_EXEC
Callout to an external script or program.
Definition tmpl.h:154
@ TMPL_TYPE_REGEX_XLAT_UNRESOLVED
A regular expression with unresolved xlat functions or attribute references.
Definition tmpl.h:201
@ TMPL_TYPE_DATA
Value in native boxed format.
Definition tmpl.h:142
@ TMPL_TYPE_REGEX
Compiled (and possibly JIT'd) regular expression.
Definition tmpl.h:158
@ TMPL_TYPE_DATA_UNRESOLVED
Unparsed literal string.
Definition tmpl.h:183
@ TMPL_TYPE_XLAT_UNRESOLVED
A xlat expansion with unresolved xlat functions or attribute references.
Definition tmpl.h:197
@ TMPL_TYPE_REGEX_XLAT
A regex containing xlat expansions.
Definition tmpl.h:166
@ TMPL_TYPE_EXEC_UNRESOLVED
An exec with unresolved xlat function or attribute references.
Definition tmpl.h:193
@ TMPL_TYPE_UNINITIALISED
Uninitialised.
Definition tmpl.h:134
ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_token_t quote, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Convert an arbitrary string into a tmpl_t.
static char const * tmpl_attr_tail_unresolved(tmpl_t const *vpt)
Return the last attribute reference unresolved da.
Definition tmpl.h:880
int tmpl_cast_in_place(tmpl_t *vpt, fr_type_t type, fr_dict_attr_t const *enumv))
Convert tmpl_t of type TMPL_TYPE_DATA_UNRESOLVED or TMPL_TYPE_DATA to TMPL_TYPE_DATA of type specifie...
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition tmpl.h:344
ssize_t tmpl_cast_from_substr(tmpl_rules_t *t_rules, fr_sbuff_t *in))
Parse a cast specifier.
Similar to tmpl_rules_t, but used to specify parameters that may change during subsequent resolution ...
Definition tmpl.h:373
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:341
static char buff[sizeof("18446744073709551615")+3]
Definition size_tests.c:41
return count
Definition module.c:163
fr_aka_sim_id_type_t type
fr_dict_attr_t const * list_def
Default list to use with unqualified attribute reference.
Definition tmpl.h:307
uint8_t allow_unknown
Allow unknown attributes i.e.
Definition tmpl.h:316
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition talloc.c:445
static int talloc_const_free(void const *ptr)
Free const'd memory.
Definition talloc.h:224
const char fr_token_quote[T_TOKEN_LAST]
Convert tokens back to a quoting character.
Definition token.c:156
enum fr_token fr_token_t
@ T_INVALID
Definition token.h:39
@ T_SINGLE_QUOTED_STRING
Definition token.h:122
@ T_BARE_WORD
Definition token.h:120
@ T_OP_EQ
Definition token.h:83
@ T_BACK_QUOTED_STRING
Definition token.h:123
@ T_DOUBLE_QUOTED_STRING
Definition token.h:121
@ T_SOLIDUS_QUOTED_STRING
Definition token.h:124
fr_slen_t xlat_tokenize(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, fr_value_box_safe_for_t literals_safe_for)
Tokenize an xlat expansion.
static fr_slen_t parent
Definition pair.h:851
void ** fr_type_array_alloc(TALLOC_CTX *ctx, fr_type_t type, size_t count)
Allocate an array of a given type.
Definition types.c:631
#define fr_type_is_string(_x)
Definition types.h:327
#define fr_type_is_quoted(_x)
Definition types.h:368
size_t const fr_value_box_field_sizes[]
How many bytes wide each of the value data fields are.
Definition value.c:149
ssize_t fr_value_box_from_str(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, char const *in, size_t inlen, fr_sbuff_unescape_rules_t const *erules, bool tainted)
Definition value.c:5315
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
Definition value.c:3681
fr_sbuff_parse_rules_t const * value_parse_rules_unquoted[T_TOKEN_LAST]
Parse rules for non-quoted strings.
Definition value.c:508
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition value.c:3723
static int fr_value_box_memcpy_out(void *out, fr_value_box_t const *vb)
Copy the value of a value box to a field in a C struct.
Definition value.h:764
static fr_slen_t data
Definition value.h:1265
int nonnull(2, 5))
static size_t char ** out
Definition value.h:997
fr_dict_t const * virtual_server_dict_by_child_ci(CONF_ITEM const *ci)
Return the namespace for a given virtual server specified by a CONF_ITEM within the virtual server.