The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
cf_util.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: d8757fa6af2e6ca3e2002b09bf62d81dd2372bff $
19  * @file cf_util.c
20  * @brief Functions for building and managing the structure of internal format config items.
21  *
22  * @copyright 2017 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23  */
24 RCSID("$Id: d8757fa6af2e6ca3e2002b09bf62d81dd2372bff $")
25 
26 #include <string.h>
27 
28 #include <freeradius-devel/server/cf_file.h>
29 #include <freeradius-devel/server/cf_priv.h>
30 #include <freeradius-devel/server/cf_util.h>
31 #include <freeradius-devel/server/log.h>
32 #include <freeradius-devel/util/debug.h>
33 #include <freeradius-devel/util/atexit.h>
34 
35 static inline int8_t cf_ident2_cmp(void const *a, void const *b);
36 static int8_t _cf_ident1_cmp(void const *a, void const *b);
37 static int8_t _cf_ident2_cmp(void const *a, void const *b);
38 
39 /** Return the next child that's of the specified type
40  *
41  * @param[in] parent to return children from.
42  * @param[in] prev child to start searching from.
43  * @param[in] type to search for.
44  * @return
45  * - The next #CONF_ITEM that's a child of ci matching type.
46  * - NULL if no #CONF_ITEM matches that criteria.
47  */
49 {
51  if (ci->type == type) return ci;
52  }
53 
54  return NULL;
55 }
56 
57 #define IS_WILDCARD(_ident) (_ident == CF_IDENT_ANY)
58 
59 /** Return the next child that's of the specified type with the specified identifiers
60  *
61  * @param[in] parent The section we're searching in.
62  * @param[in] type of #CONF_ITEM we're searching for.
63  * @param[in] ident1 The first identifier.
64  * @param[in] ident2 The second identifier. Special value CF_IDENT_ANY
65  * can be used to match any ident2 value.
66  * @return
67  * - The first matching item.
68  * - NULL if no items matched.
69  */
70 static CONF_ITEM *cf_find(CONF_ITEM const *parent, CONF_ITEM_TYPE type, char const *ident1, char const *ident2)
71 {
72  CONF_SECTION cs_find;
73  CONF_PAIR cp_find;
74  CONF_DATA cd_find;
75  CONF_ITEM *find;
76 
77  if (!parent) return NULL;
78  if (cf_item_has_no_children(parent)) return NULL;
79 
80  if (!ident1) return cf_next(parent, NULL, type);
81 
82  switch (type) {
83  case CONF_ITEM_SECTION:
84  memset(&cs_find, 0, sizeof(cs_find));
85  cs_find.item.type = CONF_ITEM_SECTION;
86  cs_find.name1 = ident1;
87  if (!IS_WILDCARD(ident2)) cs_find.name2 = ident2;
88 
89  find = (CONF_ITEM *)&cs_find;
90  break;
91 
92  case CONF_ITEM_PAIR:
93  fr_assert((ident2 == NULL) || IS_WILDCARD(ident2));
94 
95  memset(&cp_find, 0, sizeof(cp_find));
96  cp_find.item.type = CONF_ITEM_PAIR;
97  cp_find.attr = ident1;
98 
99  find = (CONF_ITEM *)&cp_find;
100  break;
101 
102  case CONF_ITEM_DATA:
103  memset(&cd_find, 0, sizeof(cd_find));
104  cd_find.item.type = CONF_ITEM_DATA;
105  cd_find.type = ident1;
106  if (!IS_WILDCARD(ident2)) cd_find.name = ident2;
107 
108  find = (CONF_ITEM *)&cd_find;
109  break;
110 
111  default:
112  fr_assert_fail(NULL);
113  return NULL;
114  }
115 
116  /*
117  * No ident1, iterate over the child list
118  */
119  if (IS_WILDCARD(ident1)) {
120  cf_item_foreach(parent, ci) {
121  if (find->type != ci->type) continue;
122 
123  if (cf_ident2_cmp(find, ci) == 0) return ci;
124  }
125 
126  return NULL;
127  }
128 
129  /*
130  * No ident2, use the ident1 tree.
131  */
132  if (IS_WILDCARD(ident2)) return fr_rb_find(parent->ident1, find);
133 
134  /*
135  * Only sections have an ident2 tree.
136  */
137  if (parent->type != CONF_ITEM_SECTION) return NULL;
138 
139  /*
140  * Both ident1 and ident2 use the ident2 tree.
141  */
142  return fr_rb_find(parent->ident2, find);
143 }
144 
145 /** Return the next child that's of the specified type with the specified identifiers
146  *
147  * @param[in] parent The section we're searching in.
148  * @param[in] prev item we found, or NULL to start from the beginning.
149  * @param[in] type of #CONF_ITEM we're searching for.
150  * @param[in] ident1 The first identifier.
151  * @param[in] ident2 The second identifier. Special value CF_IDENT_ANY
152  * can be used to match any ident2 value.
153  * @return
154  * - The first matching item.
155  * - NULL if no items matched.
156  */
157 static CONF_ITEM *cf_find_next(CONF_ITEM const *parent, CONF_ITEM const *prev,
158  CONF_ITEM_TYPE type, char const *ident1, char const *ident2)
159 {
160  CONF_SECTION cs_find;
161  CONF_PAIR cp_find;
162  CONF_DATA cd_find;
163  CONF_ITEM *find;
164 
165  if (!parent) return NULL;
166 
167  if (!prev) {
168  if (!ident1) return cf_next(parent, NULL, type);
169  return cf_find(parent, type, ident1, ident2);
170  }
171  if (!ident1) return cf_next(parent, prev, type);
172 
173  switch (type) {
174  case CONF_ITEM_SECTION:
175  memset(&cs_find, 0, sizeof(cs_find));
176  cs_find.item.type = CONF_ITEM_SECTION;
177  cs_find.name1 = ident1;
178  if (!IS_WILDCARD(ident2)) cs_find.name2 = ident2;
179 
180  find = (CONF_ITEM *)&cs_find;
181  break;
182 
183  case CONF_ITEM_PAIR:
184  fr_assert((ident2 == NULL) || IS_WILDCARD(ident2));
185 
186  memset(&cp_find, 0, sizeof(cp_find));
187  cp_find.item.type = CONF_ITEM_PAIR;
188  cp_find.attr = ident1;
189 
190  find = (CONF_ITEM *)&cp_find;
191  break;
192 
193  case CONF_ITEM_DATA:
194  memset(&cd_find, 0, sizeof(cd_find));
195  cd_find.item.type = CONF_ITEM_DATA;
196  cd_find.type = ident1;
197  if (!IS_WILDCARD(ident2)) cd_find.name = ident2;
198 
199  find = (CONF_ITEM *)&cd_find;
200  break;
201 
202  default:
203  fr_assert_fail(NULL);
204  return NULL;
205  }
206 
207  if (IS_WILDCARD(ident1)) {
208  cf_item_foreach_prev(parent, ci, prev) {
209  if (cf_ident2_cmp(ci, find) == 0) return ci;
210  }
211 
212  return NULL;
213  }
214 
215  if (IS_WILDCARD(ident2)) {
216  cf_item_foreach_prev(parent, ci, prev) {
217  if (_cf_ident1_cmp(ci, find) == 0) return ci;
218 
219  }
220 
221  return NULL;
222  }
223 
224  cf_item_foreach_prev(parent, ci, prev) {
225  if (_cf_ident2_cmp(ci, find) == 0) return ci;
226  }
227 
228  return NULL;
229 }
230 
231 /** Compare the first identifier of a child
232  *
233  * For CONF_ITEM_PAIR this is 'attr'.
234  * For CONF_ITEM_SECTION this is 'name1'.
235  * For CONF_ITEM_DATA this is 'type'.
236  *
237  * @param[in] one First CONF_ITEM to compare.
238  * @param[in] two Second CONF_ITEM to compare.
239  * @return CMP(one, two)
240  */
241 static inline int8_t _cf_ident1_cmp(void const *one, void const *two)
242 {
243  int ret;
244 
246 
247  {
248  CONF_ITEM const *a = one;
249  CONF_ITEM const *b = two;
250 
251  CMP_RETURN(a, b, type);
252  type = a->type;
253  }
254 
255  switch (type) {
256  case CONF_ITEM_PAIR:
257  {
258  CONF_PAIR const *a = one;
259  CONF_PAIR const *b = two;
260 
261  ret = strcmp(a->attr, b->attr);
262  return CMP(ret, 0);
263  }
264 
265  case CONF_ITEM_SECTION:
266  {
267  CONF_SECTION const *a = one;
268  CONF_SECTION const *b = two;
269 
270  ret = strcmp(a->name1, b->name1);
271  return CMP(ret, 0);
272  }
273 
274  case CONF_ITEM_DATA:
275  {
276  CONF_DATA const *a = one;
277  CONF_DATA const *b = two;
278 
279  ret = strcmp(a->type, b->type);
280  return CMP(ret, 0);
281  }
282 
283  default:
284  fr_assert_fail(NULL);
285  return 0;
286  }
287 }
288 
289 /** Compare only the second identifier of a child
290  *
291  * For CONF_ITEM_SECTION this is 'name2'.
292  * For CONF_ITEM_DATA this is 'name'.
293  *
294  * @param[in] one First CONF_ITEM to compare.
295  * @param[in] two Second CONF_ITEM to compare.
296  * @return CMP(one,two)
297  */
298 static inline int8_t cf_ident2_cmp(void const *one, void const *two)
299 {
300  CONF_ITEM const *ci = one;
301  int ret;
302 
303  switch (ci->type) {
304  case CONF_ITEM_PAIR:
305  return 0;
306 
307  case CONF_ITEM_SECTION:
308  {
309  CONF_SECTION const *a = one;
310  CONF_SECTION const *b = two;
311 
312  if (!b->name2 && a->name2) return +1;
313  if (b->name2 && !a->name2) return -1;
314  if (!b->name2 && !a->name2) return 0;
315 
316  ret = strcmp(a->name2, b->name2);
317  return CMP(ret, 0);
318  }
319 
320  case CONF_ITEM_DATA:
321  {
322  CONF_DATA const *a = one;
323  CONF_DATA const *b = two;
324 
325  if (!b->name && a->name) return +1;
326  if (b->name && !a->name) return -1;
327  if (!b->name && !a->name) return 0;
328 
329  ret = strcmp(a->name, b->name);
330  return CMP(ret, 0);
331  }
332 
333  default:
334  fr_assert_fail(NULL);
335  return 0;
336  }
337 }
338 
339 /** Compare the first and second identifiers of a child
340  *
341  * For CONF_ITEM_SECTION this is 'name2'.
342  * For CONF_ITEM_DATA this is 'name'.
343  *
344  * @param[in] a First CONF_ITEM to compare.
345  * @param[in] b Second CONF_ITEM to compare.
346  * @return CMP(a, b)
347  */
348 static int8_t _cf_ident2_cmp(void const *a, void const *b)
349 {
350  int ret;
351 
352  ret = _cf_ident1_cmp(a, b);
353  if (ret != 0) return ret;
354 
355  return cf_ident2_cmp(a, b);
356 }
357 
358 /** Add a child
359  *
360  * @param[in] parent to add child to.
361  * @param[in] child to add.
362  */
364 {
365  fr_assert(parent != child);
366 
367  if (!parent || !child) return;
368 
369  /*
370  * New child, add child trees.
371  */
372  if (!parent->ident1) parent->ident1 = fr_rb_inline_alloc(parent, CONF_ITEM, ident1_node,
373  _cf_ident1_cmp, NULL);
374  fr_rb_insert(parent->ident1, child);
375  fr_dlist_insert_tail(&parent->children, child); /* Append to the list of children */
376 
377  if (parent->type != CONF_ITEM_SECTION) return; /* Only sections can have ident2 trees */
378 
379  if (!parent->ident2) parent->ident2 = fr_rb_inline_alloc(parent, CONF_ITEM, ident2_node,
380  _cf_ident2_cmp, NULL);
381  fr_rb_insert(parent->ident2, child); /* NULL ident2 is still a value */
382 }
383 
384 /** Insert a child after a given one
385  *
386  * @param[in] parent to add child to.
387  * @param[in] prev previous
388  * @param[in] child to add.
389  */
391 {
392  fr_assert(parent != child);
393  fr_assert(prev != child);
394 
395  /*
396  * Must be given something. Can't insert at HEAD.
397  */
398  if (!parent || !child) return;
399 
400  if (!prev) {
401  cf_item_add(parent, child);
402  return;
403  }
404 
405  /*
406  * If there's a prev, then the ident trees must be there.
407  */
408  fr_assert(parent->ident1 != NULL);
409 
410  fr_rb_insert(parent->ident1, child);
411  fr_dlist_insert_after(&parent->children, prev, child); /* insert in the list of children */
412 
413  if (parent->type != CONF_ITEM_SECTION) return; /* only sections can have ident2 trees */
414 
415  fr_assert(parent->ident2 != NULL);
416  fr_rb_insert(parent->ident2, child); /* NULL ident2 is still a value */
417 }
418 
419 
420 /** Remove item from parent and fixup trees
421  *
422  * @param[in] parent to remove child from.
423  * @param[in] child to remove.
424  * @return
425  * - The item removed.
426  * - NULL if the item wasn't set.
427  */
429 {
430  CONF_ITEM *found = NULL;
431  bool in_ident1, in_ident2;
432 
433  if (!parent || cf_item_has_no_children(parent)) return NULL;
434  if (parent != child->parent) return NULL;
435 
436  cf_item_foreach(parent, ci) {
437  if (ci == child) {
438  found = ci;
439  break;
440  }
441  }
442 
443  if (!found) return NULL;
444 
445  /*
446  * Fixup the linked list
447  */
448  fr_dlist_remove(&parent->children, child);
449 
450  in_ident1 = (fr_rb_remove_by_inline_node(parent->ident1, &child->ident1_node) != NULL);
451 
452  /*
453  * Only sections can have ident2 trees.
454  */
455  if (parent->type != CONF_ITEM_SECTION) {
456  in_ident2 = false;
457  } else {
458  in_ident2 = (fr_rb_remove_by_inline_node(parent->ident2, &child->ident2_node) != NULL);
459  }
460 
461  /*
462  * Look for twins. They weren't in the tree initially,
463  * because "child" was there.
464  */
465  cf_item_foreach(parent, ci) {
466  if (!in_ident1 && !in_ident2) break;
467 
468  if (in_ident1 && (_cf_ident1_cmp(ci, child) == 0)) {
469  fr_rb_insert(parent->ident1, ci);
470  in_ident1 = false;
471  }
472 
473  if (in_ident2 && (_cf_ident2_cmp(ci, child) == 0)) {
474  fr_rb_insert(parent->ident2, ci);
475  in_ident2 = false;
476  }
477  }
478 
479  return child;
480 }
481 
482 /** Return the next child of cs
483  *
484  * @param[in] ci to return children from.
485  * @param[in] prev child to start searching from.
486  * @return
487  * - The next #CONF_ITEM that's a child of cs.
488  * - NULL if no more #CONF_ITEM.
489  */
490 CONF_ITEM *_cf_item_next(CONF_ITEM const *ci, CONF_ITEM const *prev)
491 {
492  if (!ci) return NULL;
493 
494  return fr_dlist_next(&ci->children, prev);
495 }
496 
497 /** Initialize a CONF_ITEM, so we don't have repeated code
498  *
499  * @param[in] ci the CONF_ITEM to initialize
500  * @param[in] type the type to set
501  * @param[in] parent the parent node hosting this one
502  * @param[in] filename which caused this node to be created
503  * @param[in] lineno where in the filename
504  */
505 static void cf_item_init(CONF_ITEM *ci, CONF_ITEM_TYPE type, CONF_ITEM *parent, char const *filename, int lineno)
506 {
507  ci->type = type;
508  ci->parent = parent;
509 
510  fr_dlist_init(&ci->children, CONF_ITEM, entry);
511 
512  if (filename) cf_filename_set(ci, filename);
513  if (lineno) cf_lineno_set(ci, lineno);
514 }
515 
516 /** Return the top level #CONF_SECTION holding all other #CONF_ITEM
517  *
518  * @param[in] ci to traverse up from.
519  * @return
520  * - NULL if ci was NULL.
521  * - The top level #CONF_SECTION
522  */
524 {
525  CONF_ITEM const *ci_p;
526 
527  if (!ci) return NULL;
528 
529  for (ci_p = ci; ci_p->parent; ci_p = ci_p->parent);
530 
531  return cf_item_to_section(ci_p);
532 }
533 
534 /** Return the parent of a #CONF_ITEM
535  *
536  * @param[in] ci to return the parent of.
537  * @return
538  * - NULL if ci was NULL or it has no parents.
539  * - The parent of ci.
540  */
542 {
543  if (!ci) return NULL;
544 
545  return ci->parent;
546 }
547 
548 /** Return the lineno the #CONF_ITEM was parsed at
549  *
550  * @param[in] ci to return the location of.
551  * @return
552  * - -1 if the #CONF_ITEM was created programmatically.
553  * - >= 0 where in the config file the line was parsed from.
554  */
555 int _cf_lineno(CONF_ITEM const *ci)
556 {
557  if (!ci) return -1;
558 
559  return ci->lineno;
560 }
561 
562 /** Return the filename the #CONF_ITEM was parsed in
563  *
564  * @param[in] ci to return the location of.
565  * @return
566  * - NULL if the #CONF_ITEM was created programmatically.
567  * - The path of the config file the #CONF_ITEM was located in.
568  */
569 char const *_cf_filename(CONF_ITEM const *ci)
570 {
571  if (!ci) return NULL;
572 
573  return ci->filename;
574 }
575 
576 /** Determine if #CONF_ITEM is a #CONF_SECTION
577  *
578  * @param[in] ci to check.
579  * @return
580  * - true if ci is a #CONF_SECTION.
581  * - false if ci is another specialisation.
582  */
584 {
585  if (!ci) return false;
586 
587  return ci->type == CONF_ITEM_SECTION;
588 }
589 
590 /** Determine if #CONF_ITEM is a #CONF_PAIR
591  *
592  * @param[in] ci to check.
593  * @return
594  * - true if ci is a #CONF_PAIR.
595  * - false if ci is another specialisation.
596  */
597 bool cf_item_is_pair(CONF_ITEM const *ci)
598 {
599  if (!ci) return false;
600 
601  return ci->type == CONF_ITEM_PAIR;
602 }
603 
604 /** Determine if #CONF_ITEM is #CONF_DATA
605  *
606  * @param[in] ci to check.
607  * @return
608  * - true if ci is #CONF_DATA.
609  * - false if ci is another specialisation.
610  */
611 bool cf_item_is_data(CONF_ITEM const *ci)
612 {
613  if (!ci) return false;
614 
615  return ci->type == CONF_ITEM_DATA;
616 }
617 
618 /** Cast a #CONF_ITEM to a #CONF_PAIR
619  *
620  * @note Will assert if ci does not contain #CONF_PAIR.
621  *
622  * @param[in] ci to cast.
623  * @return
624  * - #CONF_PAIR.
625  * - NULL if ci was NULL.
626  *
627  * @hidecallergraph
628  */
630 {
631  if (ci == NULL) return NULL;
632 
633  fr_assert(ci->type == CONF_ITEM_PAIR);
634 
635  return UNCONST(CONF_PAIR *, ci);
636 }
637 
638 /** Cast a #CONF_ITEM to a #CONF_SECTION
639  *
640  * @note Will assert if ci does not contain #CONF_SECTION.
641  *
642  * @param[in] ci to cast.
643  * @return
644  * - #CONF_SECTION.
645  * - NULL if ci was NULL.
646  *
647  * @hidecallergraph
648  */
650 {
651  if (ci == NULL) return NULL;
652 
654 
655  return UNCONST(CONF_SECTION *, ci);
656 }
657 
658 /** Cast #CONF_ITEM to #CONF_DATA performing a type check
659  *
660  * @note Will assert if ci does not contain #CONF_DATA.
661  *
662  * @param[in] ci to cast.
663  * @return
664  * - #CONF_DATA.
665  * - NULL if ci was NULL.
666  *
667  * @hidecallergraph
668  */
670 {
671  if (ci == NULL) return NULL;
672 
673  fr_assert(ci->type == CONF_ITEM_DATA);
674 
675  return UNCONST(CONF_DATA *, ci);
676 }
677 
678 /** Cast a #CONF_PAIR to a #CONF_ITEM
679  *
680  * @param[in] cp to cast.
681  * @return
682  * - The common #CONF_ITEM header.
683  * - NULL if cp was NULL.
684  *
685  * @hidecallergraph
686  */
688 {
689  if (cp == NULL) return NULL;
690 
691  return UNCONST(CONF_ITEM *, cp);
692 }
693 
694 /** Cast a #CONF_SECTION to a #CONF_ITEM
695  *
696  * @param[in] cs to cast.
697  * @return
698  * - The common #CONF_ITEM header.
699  * - NULL if cs was NULL.
700  *
701  * @hidecallergraph
702  */
704 {
705  if (cs == NULL) return NULL;
706 
707  return UNCONST(CONF_ITEM *, cs);
708 }
709 
710 /** Cast #CONF_DATA to a #CONF_ITEM
711  *
712  * @param[in] cd to cast.
713  * @return
714  * - The common #CONF_ITEM header.
715  * - NULL if cd was NULL.
716  *
717  * @hidecallergraph
718  */
720 {
721  if (cd == NULL) return NULL;
722 
723  return UNCONST(CONF_ITEM *, cd);
724 }
725 
726 /** Free a section and associated trees
727  *
728  * @param[in] cs to free.
729  * @return 0
730  */
732 {
733  if (cs->item.ident1) TALLOC_FREE(cs->item.ident1);
734  if (cs->item.ident2) TALLOC_FREE(cs->item.ident2);
735 
736  return 0;
737 }
738 
739 /** Allocate a #CONF_SECTION
740  *
741  * @param[in] ctx to allocate
742  * @param[in] parent #CONF_SECTION to hang this #CONF_SECTION off of.
743  * If parent is not NULL, the new section will be added as a child.
744  * @param[in] name1 Primary name.
745  * @param[in] name2 Secondary name.
746  * @param[in] filename Caller file name for debugging. May be overridden later.
747  * @param[in] lineno Caller line number for debugging. May be overridden later.
748  * @return
749  * - NULL on error.
750  * - A new #CONF_SECTION parented by parent.
751  */
753  char const *name1, char const *name2,
754  char const *filename, int lineno)
755 {
756  CONF_SECTION *cs;
757  char buffer[1024];
758 
759  if (!name1) return NULL;
760 
761  if (name2 && parent) {
762  char const *p;
763 
764  p = strchr(name2, '$');
765  if (p && (p[1] != '{')) p = NULL;
766 
767  if (p) {
768  name2 = cf_expand_variables(parent->item.filename,
769  parent->item.lineno,
770  parent,
771  buffer, sizeof(buffer), name2, -1, NULL);
772 
773  if (!name2) {
774  ERROR("Failed expanding section name");
775  return NULL;
776  }
777  }
778  }
779 
780  cs = talloc_zero(ctx, CONF_SECTION);
781  if (!cs) return NULL;
782 
784 
785  MEM(cs->name1 = talloc_typed_strdup(cs, name1));
786  if (name2) {
787  MEM(cs->name2 = talloc_typed_strdup(cs, name2));
788  cs->name2_quote = T_BARE_WORD;
789  }
790  talloc_set_destructor(cs, _cf_section_free);
791 
792  cs->attr = (cs->name1[0] == '&') | (parent && parent->attr);
793 
794  if (parent) {
795  CONF_DATA const *cd;
796  conf_parser_t *rule;
797 
798  /*
799  * Look up the parents parsing rules for itself.
800  * If there are rules, then one of them might be
801  * parsing rules for this new child. If that
802  * happens, we push the child parsing rules to
803  * this new child.
804  */
806  if (cd) {
807  rule = cf_data_value(cd);
808 
809  if ((rule->flags & CONF_FLAG_SUBSECTION) &&
810  rule->on_read && rule->subcs) {
811  conf_parser_t const *rule_p;
812 
813  for (rule_p = rule->subcs; rule_p->name1; rule_p++) {
814  if ((rule_p->flags & CONF_FLAG_SUBSECTION) &&
815  rule->on_read &&
816  (strcmp(rule_p->name1, name1) == 0)) {
817  if (_cf_section_rule_push(cs, rule_p,
818  cd->item.filename, cd->item.lineno) < 0) {
819  error:
820  talloc_free(cs);
821  return NULL;
822  }
823 
824  if (rule_p->on_read(ctx, NULL, NULL,
825  cf_section_to_item(cs), rule_p) < 0) goto error;
826  goto done;
827  }
828  }
829  }
830  }
831 
832  /*
833  * Or, the parent may already have parse rules
834  * for this new child. In which case we push the
835  * child rules for this section, and then do the
836  * on_read callback.
837  */
839  if (cd) {
840  rule = cf_data_value(cd);
841  if ((rule->flags & CONF_FLAG_SUBSECTION) &&
842  rule->on_read) {
843  if (cf_section_rules_push(cs, rule->subcs) < 0) goto error;
844  if (rule->on_read(ctx, NULL, NULL, cf_section_to_item(cs), rule) < 0) goto error;
845  }
846  }
847 
848  done:
849  cs->depth = parent->depth + 1;
850  cf_item_add(parent, &(cs->item));
851  }
852 
853  return cs;
854 }
855 
856 /** Set the filename of a #CONF_ITEM
857  *
858  * @param[in] ci to set filename on.
859  * @param[in] filename to set.
860  */
861 void _cf_filename_set(CONF_ITEM *ci, char const *filename)
862 {
864 
865  ci->filename = talloc_typed_strdup(ci, filename);
866 }
867 
868 /** Set the line number of a #CONF_ITEM
869  *
870  * @param[in] ci to set the lineno for.
871  * @param[in] lineno to set.
872  */
873 void _cf_lineno_set(CONF_ITEM *ci, int lineno)
874 {
875  ci->lineno = lineno;
876 }
877 
878 /** Duplicate a configuration section
879  *
880  * @note recursively duplicates any child sections.
881  * @note does not duplicate any data associated with a section, or its child sections.
882  *
883  * @param[in] ctx to allocate memory in.
884  * @param[in] parent section (may be NULL).
885  * @param[in] cs to duplicate.
886  * @param[in] name1 of new section.
887  * @param[in] name2 of new section.
888  * @param[in] copy_meta Copy additional meta data for a section
889  * (like template, base, depth and variables).
890  * @return
891  * - A duplicate of the existing section.
892  * - NULL on error.
893  */
895  char const *name1, char const *name2, bool copy_meta)
896 {
897  CONF_SECTION *new, *subcs;
898  CONF_PAIR *cp;
899 
900  new = cf_section_alloc(ctx, parent, name1, name2);
901 
902  if (copy_meta) {
903  new->template = cs->template;
904  new->base = cs->base;
905  new->depth = cs->depth;
906  }
907 
908  cf_filename_set(new, cs->item.filename);
909  cf_lineno_set(new, cs->item.lineno);
910 
911  cf_item_foreach(&cs->item, ci) {
912  switch (ci->type) {
913  case CONF_ITEM_SECTION:
914  subcs = cf_item_to_section(ci);
915  subcs = cf_section_dup(new, new, subcs,
916  cf_section_name1(subcs), cf_section_name2(subcs),
917  copy_meta);
918  if (!subcs) {
919  talloc_free(new);
920  return NULL;
921  }
922  break;
923 
924  case CONF_ITEM_PAIR:
925  cp = cf_pair_dup(new, cf_item_to_pair(ci));
926  if (!cp) {
927  talloc_free(new);
928  return NULL;
929  }
930  break;
931 
932  case CONF_ITEM_DATA: /* Skip data */
933  break;
934 
935  case CONF_ITEM_INVALID:
936  fr_assert(0);
937  }
938  }
939 
940  return new;
941 }
942 
943 
944 /** Return the next child that's a #CONF_SECTION
945  *
946  * @param[in] cs to return children from.
947  * @param[in] prev child to start searching from.
948  * @return
949  * - The next #CONF_ITEM that's a child of cs and a CONF_SECTION.
950  * - NULL if no #CONF_ITEM matches that criteria.
951  */
953 {
955 }
956 
957 /** Find a CONF_SECTION with name1 and optionally name2.
958  *
959  * @param[in] cs The section we're searching in.
960  * @param[in] name1 of the section we're searching for. Special value CF_IDENT_ANY
961  * can be used to match any name1 value.
962  * @param[in] name2 of the section we're searching for. Special value CF_IDENT_ANY
963  * can be used to match any name2 value.
964  * @return
965  * - The first matching subsection.
966  * - NULL if no subsections match.
967  *
968  * @hidecallergraph
969  */
971  char const *name1, char const *name2)
972 {
974 }
975 
976 /** Return the next matching section
977  *
978  * @param[in] cs The section we're searching in.
979  * @param[in] prev section we found. May be NULL in which case
980  * we just return the next section after prev.
981  * @param[in] name1 of the section we're searching for. Special value CF_IDENT_ANY
982  * can be used to match any name1 value.
983  * @param[in] name2 of the section we're searching for. Special value CF_IDENT_ANY
984  * can be used to match any name2 value.
985  * @return
986  * - The next CONF_SECTION.
987  * - NULL if there are no more CONF_SECTIONs
988  *
989  * @hidecallergraph
990  */
992  char const *name1, char const *name2)
993 {
995  CONF_ITEM_SECTION, name1, name2));
996 }
997 
998 /** Find a section in the lineage of a CONF_SECTION which matches a specific name1 and optionally name2.
999  *
1000  * Will walk up the configuration tree, searching in each parent until a matching section is found or
1001  * we hit the root.
1002  *
1003  * @param[in] cs The section we're searching in.
1004  * @param[in] name1 of the section we're searching for. Special value CF_IDENT_ANY
1005  * can be used to match any name1 value.
1006  * @param[in] name2 of the section we're searching for. Special value CF_IDENT_ANY
1007  * can be used to match any name2 value.
1008  * @return
1009  * - The first matching subsection.
1010  * - NULL if no subsections match.
1011  */
1013  char const *name1, char const *name2)
1014 {
1015  CONF_ITEM const *parent = cf_section_to_item(cs);
1016 
1017  do {
1018  CONF_ITEM *found;
1019 
1020  found = cf_find(parent, CONF_ITEM_SECTION, name1, name2);
1021  if (found) return cf_item_to_section(found);
1022  } while ((parent = cf_parent(parent)));
1023 
1024  return NULL;
1025 }
1026 
1027 
1028 /** Find a parent CONF_SECTION with name1 and optionally name2.
1029  *
1030  * @param[in] cs The section we're searching in.
1031  * @param[in] name1 of the section we're searching for. Special value CF_IDENT_ANY
1032  * can be used to match any name1 value.
1033  * @param[in] name2 of the section we're searching for. Special value CF_IDENT_ANY
1034  * can be used to match any name2 value.
1035  * @return
1036  * - The first matching subsection.
1037  * - NULL if no subsections match.
1038  */
1040  char const *name1, char const *name2)
1041 {
1043 
1044  while ((parent = cf_parent(parent))) {
1046 
1047  if (cf_section_name_cmp(found, name1, name2) == 0) return found;
1048  };
1049 
1050  return NULL;
1051 }
1052 
1053 /** Find a pair in a #CONF_SECTION
1054  *
1055  * @param[in] cs the #CONF_SECTION to search in.
1056  * @param[in] attr to search for.
1057  * @return
1058  * - NULL if no pair can be found.
1059  * - The value of the pair found.
1060  */
1061 char const *cf_section_value_find(CONF_SECTION const *cs, char const *attr)
1062 {
1063  CONF_PAIR *cp;
1064 
1065  cp = cf_pair_find(cs, attr);
1066 
1067  return (cp ? cp->value : NULL);
1068 }
1069 
1070 /** Check if a given section matches the specified name1/name2 identifiers
1071  *
1072  * @param[in] cs to check.
1073  * @param[in] name1 identifier. May be CF_IDENT_ANY for wildcard matches.
1074  * @param[in] name2 identifier. May be CF_IDENT_ANY for wildcard matches.
1075  * @return
1076  * - >1 if cs is greater than the identifiers.
1077  * - 0 if cs matches the identifiers.
1078  * - <0 if cs is less than the identifiers.
1079  */
1080 int8_t cf_section_name_cmp(CONF_SECTION const *cs, char const *name1, char const *name2)
1081 {
1082  int8_t ret;
1083 
1084  if (name1 != CF_IDENT_ANY) {
1085  ret = CMP(strcmp(cf_section_name1(cs), name1), 0);
1086  if (ret != 0) return ret;
1087  }
1088 
1089  if (name2 != CF_IDENT_ANY) {
1090  char const *cs_name2 = cf_section_name2(cs);
1091 
1092  if (!cs_name2) {
1093  if (!name2) return 0;
1094  return 1;
1095  }
1096 
1097  return CMP(strcmp(cs_name2, name2), 0);
1098  }
1099 
1100  return 0;
1101 }
1102 
1103 /** Return the second identifier of a #CONF_SECTION
1104  *
1105  * @param[in] cs to return identifiers for.
1106  * @return
1107  * - The first identifier.
1108  * - NULL if cs was NULL or no name1 set.
1109  *
1110  * @hidecallergraph
1111  */
1112 char const *cf_section_name1(CONF_SECTION const *cs)
1113 {
1114  return (cs ? cs->name1 : NULL);
1115 }
1116 
1117 /** Return the second identifier of a #CONF_SECTION
1118  *
1119  * @param[in] cs to return identifiers for.
1120  * @return
1121  * - The second identifier.
1122  * - NULL if cs was NULL or no name2 set.
1123  *
1124  * @hidecallergraph
1125  */
1126 char const *cf_section_name2(CONF_SECTION const *cs)
1127 {
1128  return (cs ? cs->name2 : NULL);
1129 }
1130 
1131 /** Return name2 if set, else name1
1132  *
1133  * @param[in] cs to return identifiers for.
1134  * @return name1 or name2 identifier.
1135  *
1136  * @hidecallergraph
1137  */
1138 char const *cf_section_name(CONF_SECTION const *cs)
1139 {
1140  char const *name;
1141 
1142  name = cf_section_name2(cs);
1143  if (name) return name;
1144 
1145  return cf_section_name1(cs);
1146 }
1147 
1148 /** Return variadic argument at the specified index
1149  *
1150  * @param[in] cs containing the arguments.
1151  * @param[in] argc Argument index. Note name1 and name2 are not counted in this index.
1152  * @return the argument value or NULL.
1153  */
1154 char const *cf_section_argv(CONF_SECTION const *cs, int argc)
1155 {
1156  if (!cs || !cs->argv || (argc < 0) || (argc > cs->argc)) return NULL;
1157 
1158  return cs->argv[argc];
1159 }
1160 
1161 /** Return the quoting of the name2 identifier
1162  *
1163  * @param[in] cs containing name2.
1164  * @return
1165  * - #T_BARE_WORD.
1166  * - #T_SINGLE_QUOTED_STRING.
1167  * - #T_BACK_QUOTED_STRING.
1168  * - #T_DOUBLE_QUOTED_STRING.
1169  * - #T_INVALID if cs was NULL.
1170  */
1172 {
1173  if (!cs) return T_INVALID;
1174 
1175  return cs->name2_quote;
1176 }
1177 
1178 /** Set the quoting of the name2 identifier
1179  *
1180  * @param[in] cs containing name2.
1181  * @param[in] token the quote token
1182  */
1184 {
1185  if (!cs) return;
1186 
1187  cs->name2_quote = token;
1188 }
1189 
1190 /** Return the quoting for one of the variadic arguments
1191  *
1192  * @param[in] cs containing the arguments.
1193  * @param[in] argc Argument index. Note name1 and name2 are not counted in this index.
1194  * @return
1195  * - #T_BARE_WORD.
1196  * - #T_SINGLE_QUOTED_STRING.
1197  * - #T_BACK_QUOTED_STRING.
1198  * - #T_DOUBLE_QUOTED_STRING.
1199  * - #T_INVALID if cs was NULL or the index was invalid.
1200  */
1202 {
1203  if (!cs || !cs->argv_quote || (argc < 0) || (argc > cs->argc)) return T_INVALID;
1204 
1205  return cs->argv_quote[argc];
1206 }
1207 
1208 /** Allocate a #CONF_PAIR
1209  *
1210  * @param[in] parent #CONF_SECTION to hang this #CONF_PAIR off of.
1211  * @param[in] attr name.
1212  * @param[in] value of #CONF_PAIR.
1213  * @param[in] op #T_OP_EQ, #T_OP_SET etc.
1214  * @param[in] lhs_quote #T_BARE_WORD, #T_DOUBLE_QUOTED_STRING, #T_BACK_QUOTED_STRING.
1215  * @param[in] rhs_quote #T_BARE_WORD, #T_DOUBLE_QUOTED_STRING, #T_BACK_QUOTED_STRING.
1216  * @return
1217  * - NULL on error.
1218  * - A new #CONF_SECTION parented by parent.
1219  */
1220 CONF_PAIR *cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value,
1221  fr_token_t op, fr_token_t lhs_quote, fr_token_t rhs_quote)
1222 {
1223  CONF_PAIR *cp;
1224 
1226  if (!attr) return NULL;
1227 
1228  cp = talloc_zero(parent, CONF_PAIR);
1229  if (!cp) return NULL;
1230 
1232 
1233  cp->lhs_quote = lhs_quote;
1234  cp->rhs_quote = rhs_quote;
1235  cp->op = op;
1236 
1237  cp->attr = talloc_typed_strdup(cp, attr);
1238  if (!cp->attr) {
1239  error:
1240  talloc_free(cp);
1241  return NULL;
1242  }
1243 
1244  if (value) {
1245  cp->value = talloc_typed_strdup(cp, value);
1246  if (!cp->value) goto error;
1247  }
1248 
1249  cf_item_add(parent, &(cp->item));
1250  return cp;
1251 }
1252 
1253 /** Duplicate a #CONF_PAIR
1254  *
1255  * @param parent to allocate new pair in.
1256  * @param cp to duplicate.
1257  * @return
1258  * - NULL on error.
1259  * - A duplicate of the input pair.
1260  */
1262 {
1263  CONF_PAIR *new;
1264 
1265  fr_assert(parent);
1266  fr_assert(cp);
1267 
1268  new = cf_pair_alloc(parent, cp->attr, cf_pair_value(cp), cp->op, cp->lhs_quote, cp->rhs_quote);
1269  if (!new) return NULL;
1270 
1271  new->parsed = cp->parsed;
1272  cf_lineno_set(new, cp->item.lineno);
1273  cf_filename_set(new, cp->item.filename);
1274 
1275  return new;
1276 }
1277 
1278 /** Replace pair in a given section with a new pair, of the given value.
1279  *
1280  * @note A new pair with the same metadata as the #CONF_PAIR will be added
1281  * even if the #CONF_PAIR can't be found inside the #CONF_SECTION.
1282  *
1283  * @param[in] cs to replace pair in.
1284  * @param[in] cp to replace.
1285  * @param[in] value New value to assign to cp.
1286  * @return
1287  * - 0 on success.
1288  * - -1 on failure.
1289  */
1290 int cf_pair_replace(CONF_SECTION *cs, CONF_PAIR *cp, char const *value)
1291 {
1292  CONF_PAIR *new_cp;
1293  CONF_ITEM *ci;
1294 
1295  if (!cs || !cp || !value) return -1;
1296 
1297  /*
1298  * Remove the old CONF_PAIR
1299  */
1300  ci = cf_item_remove(cs, cp);
1301  if (!fr_cond_assert(!ci || (ci == cf_pair_to_item(cp)))) return -1;
1302 
1303  /*
1304  * Add the new CONF_PAIR
1305  */
1306  MEM(new_cp = cf_pair_dup(cs, cp));
1307  talloc_const_free(cp->value);
1308  MEM(cp->value = talloc_typed_strdup(cp, value));
1309 
1310  return 0;
1311 }
1312 
1313 
1314 /** Mark a pair as parsed
1315  *
1316  * @param[in] cp to mark as parsed.
1317  */
1319 {
1320  cp->parsed = true;
1321 }
1322 
1323 /** Return whether a pair has already been parsed
1324  *
1325  * @param[in] cp to check.
1326  * @return
1327  * - true if pair has been parsed.
1328  * - false if the pair hasn't been parsed.
1329  */
1331 {
1332  return cp->parsed;
1333 }
1334 
1335 /** Return the next child that's a #CONF_PAIR
1336  *
1337  * @param[in] cs to return children from.
1338  * @param[in] prev child to start searching from.
1339  * @return
1340  * - The next #CONF_ITEM that's a child of cs and a CONF_PAIR.
1341  * - NULL if no #CONF_ITEM matches that criteria.
1342  */
1344 {
1346 }
1347 
1348 /** Search for a #CONF_PAIR with a specific name
1349  *
1350  * @param[in] cs to search in.
1351  * @param[in] attr to find.
1352  * @return
1353  * - The next matching #CONF_PAIR.
1354  * - NULL if none matched.
1355  */
1356 CONF_PAIR *cf_pair_find(CONF_SECTION const *cs, char const *attr)
1357 {
1358  return cf_item_to_pair(cf_find(cf_section_to_item(cs), CONF_ITEM_PAIR, attr, NULL));
1359 }
1360 
1361 /** Find a pair with a name matching attr, after specified pair
1362  *
1363  * @param[in] cs to search in.
1364  * @param[in] prev Pair to search from (may be NULL).
1365  * @param[in] attr to find (may be NULL in which case any attribute matches).
1366  * @return
1367  * - The next matching #CONF_PAIR
1368  * - NULL if none matched.
1369  */
1370 CONF_PAIR *cf_pair_find_next(CONF_SECTION const *cs, CONF_PAIR const *prev, char const *attr)
1371 {
1373 }
1374 
1375 /** Find a pair with a name matching attr in the specified section or one of its parents
1376  *
1377  * @param[in] cs to search in. Will start in the current section
1378  * and work upwards.
1379  * @param[in] attr to find.
1380  * @return
1381  * - A matching #CONF_PAIR.
1382  * - NULL if none matched.
1383  */
1384 CONF_PAIR *cf_pair_find_in_parent(CONF_SECTION const *cs, char const *attr)
1385 {
1386  CONF_ITEM const *parent = cf_section_to_item(cs);
1387 
1388  do {
1389  CONF_ITEM *found;
1390 
1391  found = cf_find(parent, CONF_ITEM_PAIR, attr, NULL);
1392  if (found) return cf_item_to_pair(found);
1393  } while ((parent = cf_parent(parent)));
1394 
1395  return NULL;
1396 }
1397 
1398 /** Callback to determine the number of pairs in a section
1399  *
1400  * @param[out] count Where we store the number of pairs found.
1401  * @param[in] cs we're currently searching in.
1402  */
1403 static void _pair_count(int *count, CONF_SECTION const *cs)
1404 {
1405  CONF_ITEM const *ci = NULL;
1406 
1407  while ((ci = cf_item_next(cs, ci))) {
1408  if (cf_item_is_section(ci)) {
1410  continue;
1411  }
1412 
1413  (*count)++;
1414  }
1415 }
1416 
1417 /** Count the number of conf pairs beneath a section
1418  *
1419  * @param[in] cs to search for items in.
1420  * @return The number of pairs nested within section.
1421  */
1423 {
1424  int count = 0;
1425 
1426  _pair_count(&count, cs);
1427 
1428  return count;
1429 }
1430 
1431 /** Count the number of times an attribute occurs in a parent section
1432  *
1433  * @param[in] cs to search for items in.
1434  * @param[in] attr to search for.
1435  * @return The number of pairs of that attribute type.
1436  */
1437 unsigned int cf_pair_count(CONF_SECTION const *cs, char const *attr)
1438 {
1439  size_t i;
1440  CONF_PAIR *cp = NULL;
1441 
1442  for (i = 0; (cp = cf_pair_find_next(cs, cp, attr)); i++);
1443 
1444  return i;
1445 }
1446 
1447 /** Concatenate the values of any pairs with name attr
1448  *
1449  * @param[out] out where to write the concatenated values.
1450  * @param[in] cs to search in.
1451  * @param[in] attr to search for.
1452  * @param[in] sep to use to separate values
1453  * @return
1454  * - Length of the data written to out on success.
1455  * - < 0 on failure. Number of additional bytes required in buffer.
1456  */
1457 fr_slen_t cf_pair_values_concat(fr_sbuff_t *out, CONF_SECTION const *cs, char const *attr, char const *sep)
1458 {
1459  fr_sbuff_t our_out = FR_SBUFF(out);
1460  CONF_PAIR *cp;
1461  fr_slen_t slen = 0;
1462  fr_sbuff_escape_rules_t e_rules = {
1463  .name = __FUNCTION__,
1464  .chr = '\\'
1465  };
1466 
1467  if (sep) e_rules.subs[(uint8_t)*sep] = *sep;
1468 
1469  for (cp = cf_pair_find(cs, attr); cp;) {
1470  slen = fr_sbuff_in_escape(&our_out, cf_pair_value(cp),
1471  strlen(cf_pair_value(cp)), &e_rules);
1472  if (slen < 0) return slen;
1473 
1474  cp = cf_pair_find_next(cs, cp, attr);
1475  if (cp && sep) {
1476  slen = fr_sbuff_in_strcpy(&our_out, sep);
1477  if (slen < 0) return slen;
1478  }
1479  }
1480 
1481  FR_SBUFF_SET_RETURN(out, &our_out);
1482 }
1483 
1484 /** Return the attr of a #CONF_PAIR
1485  *
1486  * Return the LHS value of a pair (the attribute).
1487  *
1488  * @param[in] pair to return the attribute for.
1489  * @return
1490  * - NULL if the pair was NULL.
1491  * - The attribute name of the pair.
1492  *
1493  * @hidecallergraph
1494  */
1495 char const *cf_pair_attr(CONF_PAIR const *pair)
1496 {
1497  return (pair ? pair->attr : NULL);
1498 }
1499 
1500 /** Return the value of a #CONF_PAIR
1501  *
1502  * Return the RHS value of a pair (the value).
1503  *
1504  * @param[in] pair to return the value of.
1505  * @return
1506  * - NULL if pair was NULL or the pair has no value.
1507  * - The string value of the pair.
1508  *
1509  * @hidecallergraph
1510  */
1511 char const *cf_pair_value(CONF_PAIR const *pair)
1512 {
1513  return (pair ? pair->value : NULL);
1514 }
1515 
1516 /** Return the operator of a pair
1517  *
1518  * @param[in] pair to return the operator of.
1519  * @return
1520  * - T_INVALID if pair was NULL.
1521  * - T_OP_* (one of the operator constants).
1522  *
1523  * @hidecallergraph
1524  */
1526 {
1527  return (pair ? pair->op : T_INVALID);
1528 }
1529 
1530 /** Return the value (lhs) quoting of a pair
1531  *
1532  * @param pair to extract value type from.
1533  * @return
1534  * - #T_BARE_WORD.
1535  * - #T_SINGLE_QUOTED_STRING.
1536  * - #T_BACK_QUOTED_STRING.
1537  * - #T_DOUBLE_QUOTED_STRING.
1538  * - #T_INVALID if the pair is NULL.
1539  */
1541 {
1542  return (pair ? pair->lhs_quote : T_INVALID);
1543 }
1544 
1545 /** Return the value (rhs) quoting of a pair
1546  *
1547  * @param pair to extract value type from.
1548  * @return
1549  * - #T_BARE_WORD.
1550  * - #T_SINGLE_QUOTED_STRING.
1551  * - #T_BACK_QUOTED_STRING.
1552  * - #T_DOUBLE_QUOTED_STRING.
1553  * - #T_INVALID if the pair is NULL.
1554  */
1556 {
1557  return (pair ? pair->rhs_quote : T_INVALID);
1558 }
1559 
1560 /** Free user data associated with #CONF_DATA
1561  *
1562  * @param[in] cd being freed.
1563  * @return 0
1564  */
1565 static int _cd_free(CONF_DATA *cd)
1566 {
1567  void *to_free;
1568 
1569  memcpy(&to_free, &cd->data, sizeof(to_free));
1570 
1571  if (cd->free) talloc_decrease_ref_count(to_free); /* Also works OK for non-reference counted chunks */
1572 
1573  return 0;
1574 }
1575 
1576 /** Allocate a new user data container
1577  *
1578  * @param[in] parent #CONF_PAIR, or #CONF_SECTION to hang CONF_DATA off of.
1579  * @param[in] data being added.
1580  * @param[in] type of data being added.
1581  * @param[in] name String identifier of the user data.
1582  * @param[in] do_free function, called when the parent #CONF_SECTION is being freed.
1583  * @return
1584  * - CONF_DATA on success.
1585  * - NULL on error.
1586  */
1587 static CONF_DATA *cf_data_alloc(CONF_ITEM *parent, void const *data, char const *type, char const *name, bool do_free)
1588 {
1589  CONF_DATA *cd;
1590 
1591  cd = talloc_zero(parent, CONF_DATA);
1592  if (!cd) return NULL;
1593 
1595 
1596  /*
1597  * strdup so if the data is freed, we can
1598  * still remove it from the section without
1599  * explosions.
1600  */
1601  if (data) {
1602  cd->type = talloc_typed_strdup(cd, type);
1603  cd->data = data;
1604  }
1605  if (name) cd->name = talloc_typed_strdup(cd, name);
1606 
1607  if (do_free) {
1608  cd->free = true;
1609  talloc_set_destructor(cd, _cd_free);
1610  }
1611 
1612  cf_item_add(parent, cd);
1613  return cd;
1614 }
1615 
1616 /** Find user data in a config section
1617  *
1618  * @param[in] ci The section to search for data in.
1619  * @param[in] type of user data. Used for name spacing and walking over a specific
1620  * type of user data.
1621  * @param[in] name String identifier of the user data. Special value CF_IDENT_ANY
1622  * may be used to match on type only.
1623  * @return
1624  * - The user data.
1625  * - NULL if no user data exists.
1626  */
1627 CONF_DATA const *_cf_data_find(CONF_ITEM const *ci, char const *type, char const *name)
1628 {
1630 }
1631 
1632 /** Return the next item of user data
1633  *
1634  * @param[in] ci The section to search for data in.
1635  * @param[in] prev section we found. May be NULL in which case
1636  * we just return the next section after prev.
1637  * @param[in] type of user data. Used for name spacing and walking over a specific
1638  * type of user data.
1639  * @param[in] name String identifier of the user data. Special value CF_IDENT_ANY
1640  * can be used to match any name2 value.
1641  * @return
1642  * - The next matching #CONF_DATA.
1643  * - NULL if there is no more matching #CONF_DATA.
1644  */
1645 CONF_DATA const *_cf_data_find_next(CONF_ITEM const *ci, CONF_ITEM const *prev, char const *type, char const *name)
1646 {
1647  return cf_item_to_data(cf_find_next(ci, prev, CONF_ITEM_DATA, type, name));
1648 }
1649 
1650 /** Find matching data in the specified section or one of its parents
1651  *
1652  * @param[in] ci The section to search for data in.
1653  * @param[in] type of user data. Used for name spacing and walking over a specific
1654  * type of user data.
1655  * @param[in] name String identifier of the user data. Special value CF_IDENT_ANY
1656  * may be used to match on type only.
1657  * @return
1658  * - The next matching #CONF_DATA.
1659  * - NULL if there is no more matching #CONF_DATA.
1660  */
1661 CONF_DATA *_cf_data_find_in_parent(CONF_ITEM const *ci, char const *type, char const *name)
1662 {
1663  CONF_ITEM const *parent = ci;
1664 
1665  do {
1666  CONF_ITEM *found;
1667 
1668  found = cf_find(parent, CONF_ITEM_DATA, type, name);
1669  if (found) return cf_item_to_data(found);
1670  } while ((parent = cf_parent(parent)));
1671 
1672  return NULL;
1673 }
1674 
1675 /** Return the user assigned value of #CONF_DATA
1676  *
1677  * @param[in] cd to return value of.
1678  * @return the user data stored within the #CONF_DATA.
1679  */
1680 void *cf_data_value(CONF_DATA const *cd)
1681 {
1682  void *to_return;
1683 
1684  if (!cd) return NULL;
1685 
1686  memcpy(&to_return, &cd->data, sizeof(to_return));
1687 
1688  return to_return;
1689 }
1690 
1691 /** Add talloced user data to a config section
1692  *
1693  * @param[in] ci to add data to.
1694  * @param[in] data to add.
1695  * @param[in] name String identifier of the user data.
1696  * @param[in] do_free Function to free user data when the CONF_SECTION is freed.
1697  * @param[in] filename Source file the #CONF_DATA was added in.
1698  * @param[in] lineno the #CONF_DATA was added at.
1699  * @return
1700  * - #CONF_DATA - opaque handle to the stored data - on success.
1701  * - NULL error.
1702  */
1703 CONF_DATA const *_cf_data_add(CONF_ITEM *ci, void const *data, char const *name, bool do_free,
1704  char const *filename, int lineno)
1705 {
1706  CONF_DATA *cd;
1707  CONF_DATA const *found;
1708  char const *type = NULL;
1709 
1710  if (!ci) return NULL;
1711 
1712  if (data) type = talloc_get_name(data);
1713 
1714  /*
1715  * Already exists. Can't add it.
1716  */
1717  found = _cf_data_find(ci, type, name);
1718  if (found) {
1719  return NULL;
1720  }
1721 
1722  cd = cf_data_alloc(ci, data, type, name, do_free);
1723  if (!cd) {
1724  cf_log_err(ci, "Failed allocating data");
1725  return NULL;
1726  }
1727  cd->is_talloced = true;
1728  cf_filename_set(cd, filename);
1729  cf_lineno_set(cd, lineno);
1730 
1731  return cd;
1732 }
1733 
1734 /** Add non-talloced user data to a config section
1735  *
1736  * @param[in] ci to add data to.
1737  * @param[in] data to add.
1738  * @param[in] type identifier of the user data.
1739  * @param[in] name String identifier of the user data.
1740  * @param[in] filename Source file the #CONF_DATA was added in.
1741  * @param[in] lineno the #CONF_DATA was added at.
1742  * - #CONF_DATA - opaque handle to the stored data - on success.
1743  * - NULL error.
1744  */
1745 CONF_DATA const *_cf_data_add_static(CONF_ITEM *ci, void const *data, char const *type, char const *name,
1746  char const *filename, int lineno)
1747 {
1748  CONF_DATA *cd;
1749  CONF_DATA const *found;
1750 
1751  /*
1752  * Already exists. Can't add it.
1753  */
1754  found = _cf_data_find(ci, type, name);
1755  if (found) {
1756  /*
1757  * Suppress these, as it's OK for the conf_parser_t in main_config.c
1758  */
1759  if (strcmp(type, "conf_parser_t") == 0) return NULL;
1760 
1761  cf_log_err(ci, "Data of type %s with name \"%s\" already exists. Existing data added %s[%i]", type,
1762  name, found->item.filename, found->item.lineno);
1763  return NULL;
1764  }
1765 
1766  cd = cf_data_alloc(ci, data, type, name, false);
1767  if (!cd) {
1768  cf_log_err(ci, "Failed allocating data");
1769  return NULL;
1770  }
1771  cd->is_talloced = false;
1772  cf_filename_set(cd, filename);
1773  cf_lineno_set(cd, lineno);
1774 
1775  return cd;
1776 }
1777 
1778 /** Remove data from a configuration section
1779  *
1780  * @note If cd was not found it will not be freed, and it is the caller's responsibility
1781  * to free it explicitly, or free the section it belongs to.
1782  *
1783  * @param[in] parent to remove data from.
1784  * @param[in] cd opaque handle of the stored data.
1785  * @return
1786  * - The value stored within the data (if cd is valid and was found and removed).
1787  * - NULL if not found.
1788  */
1790 {
1791  void *data;
1792  CONF_ITEM *ci;
1793 
1794  if (!cd) return NULL;
1795 
1796  ci = cf_item_remove(parent, cd);
1797  if (!fr_cond_assert(!ci || (ci == cf_data_to_item(cd)))) return NULL;
1798  if (!ci) return NULL;
1799 
1800  talloc_set_destructor(cd, NULL); /* Disarm the destructor */
1801  memcpy(&data, &cd->data, sizeof(data));
1802  talloc_const_free(cd);
1803 
1804  return data;
1805 }
1806 
1807 /** Walk over a specific type of CONF_DATA
1808  *
1809  * @param[in] ci containing the CONF_DATA to walk over.
1810  * @param[in] type of CONF_DATA to walk over.
1811  * @param[in] cb to call when we find CONF_DATA of the specified type.
1812  * @param[in] ctx to pass to cb.
1813  * @return
1814  * - 0 on success.
1815  * - -1 on failure.
1816  */
1817 int _cf_data_walk(CONF_ITEM *ci, char const *type, cf_walker_t cb, void *ctx)
1818 {
1819  CONF_DATA *cd;
1820  fr_rb_iter_inorder_t iter;
1821  int ret = 0;
1822 
1823  if (!ci->ident2) return 0;
1824 
1825  for (ci = fr_rb_iter_init_inorder(&iter, ci->ident2);
1826  ci;
1827  ci = fr_rb_iter_next_inorder(&iter)) {
1828  /*
1829  * We're walking ident2, not all of the items will be data
1830  */
1831  if (ci->type != CONF_ITEM_DATA) continue;
1832 
1833  cd = (void *) ci;
1834  if ((cd->type != type) && (strcmp(cd->type, type) != 0)) continue;
1835 
1836  ret = cb(UNCONST(void *, cd->data), ctx);
1837  if (ret) {
1838  break;
1839  }
1840  }
1841 
1842  return ret;
1843 }
1844 
1845 static inline CC_HINT(nonnull) void truncate_filename(char const **e, char const **p, int *len, char const *filename)
1846 {
1847  size_t flen;
1848  char const *q;
1849 
1850  #define FILENAME_TRUNCATE 60
1851 
1852  *p = filename;
1853  *e = "";
1854 
1855  flen = talloc_array_length(filename) - 1;
1856  if (flen <= FILENAME_TRUNCATE) {
1857  *len = (int)flen;
1858  return;
1859  }
1860 
1861  *p += flen - FILENAME_TRUNCATE;
1862  *len = FILENAME_TRUNCATE;
1863 
1864  q = strchr(*p, FR_DIR_SEP);
1865  if (q) {
1866  q++;
1867  *p += (q - *p);
1868  *len -= (q - *p);
1869  }
1870 
1871  *e = "...";
1872 }
1873 
1874 /** Check to see if the CONF_PAIR value is present in the specified table
1875  *
1876  * If it's not present, return an error and produce a helpful log message
1877  *
1878  * @param[out] out The result of parsing the pair value.
1879  * @param[in] table to look for string values in.
1880  * @param[in] table_len Length of the table.
1881  * @param[in] cp to parse.
1882  * @return
1883  * - 0 on success.
1884  * - -1 on failure.
1885  */
1886 int cf_pair_in_table(int32_t *out, fr_table_num_sorted_t const *table, size_t table_len, CONF_PAIR *cp)
1887 {
1888  char *list = NULL;
1889  int32_t res;
1890  size_t i;
1891 
1893  if (res != FR_TABLE_NOT_FOUND) {
1894  *out = res;
1895  return 0;
1896  }
1897 
1898  for (i = 0; i < table_len; i++) MEM(list = talloc_asprintf_append_buffer(list, "'%s', ", table[i].name.str));
1899 
1900  if (!list) {
1901  cf_log_err(cp, "Internal error parsing %s: Table was empty", cf_pair_attr(cp));
1902  return -1;
1903  }
1904 
1905  /*
1906  * Trim the final ", "
1907  */
1908  MEM(list = talloc_bstr_realloc(NULL, list, talloc_array_length(list) - 3));
1909 
1910  cf_log_err(cp, "Invalid value \"%s\". Expected one of %s", cf_pair_value(cp), list);
1911 
1912  talloc_free(list);
1913 
1914  return -1;
1915 }
1916 
1917 /** Log an error message relating to a #CONF_ITEM
1918  *
1919  * @param[in] type of log message.
1920  * @param[in] ci #CONF_ITEM to print file/lineno for.
1921  * @param[in] file src file the log message was generated in.
1922  * @param[in] line number the log message was generated on.
1923  * @param[in] fmt of the message.
1924  * @param[in] ap Message args.
1925  */
1926 void _cf_vlog(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, char const *fmt, va_list ap)
1927 {
1928  va_list aq;
1929 
1930  if ((type == L_DBG) && !DEBUG_ENABLED) return;
1931 
1932  if (!ci || !ci->filename || !*ci->filename || (*ci->filename == '<') ||
1933  (((type == L_DBG) || (type == L_INFO)) && !DEBUG_ENABLED4)) {
1934  va_copy(aq, ap);
1935  fr_vlog(LOG_DST, type, file, line, fmt, aq);
1936  va_end(aq);
1937  return;
1938  }
1939 
1940  {
1941  char const *e, *p;
1942  int len;
1943  char *msg;
1944 
1945  truncate_filename(&e, &p, &len, ci->filename);
1946 
1947  va_copy(aq, ap);
1948  msg = fr_vasprintf(NULL, fmt, aq);
1949  va_end(aq);
1950 
1951  fr_log(LOG_DST, type, file, line, "%s%.*s[%d]: %s", e, len, p, ci->lineno, msg);
1952  talloc_free(msg);
1953  }
1954 }
1955 
1956 /** Log an error message relating to a #CONF_ITEM
1957  *
1958  * @param[in] type of log message.
1959  * @param[in] file src file the log message was generated in.
1960  * @param[in] line number the log message was generated on.
1961  * @param[in] ci #CONF_ITEM to print file/lineno for.
1962  * @param[in] fmt of the message.
1963  * @param[in] ... Message args.
1964  */
1965 void _cf_log(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, char const *fmt, ...)
1966 {
1967  va_list ap;
1968 
1969  if ((type == L_DBG) && !DEBUG_ENABLED) return;
1970 
1971  va_start(ap, fmt);
1972  _cf_vlog(type, ci, file, line, fmt, ap);
1973  va_end(ap);
1974 }
1975 
1976 /** Log an error message relating to a #CONF_ITEM
1977  *
1978  * Drains the fr_strerror() stack emitting one or more error messages.
1979  *
1980  * @param[in] type of log message.
1981  * @param[in] file src file the log message was generated in.
1982  * @param[in] line number the log message was generated on.
1983  * @param[in] ci #CONF_ITEM to print file/lineno for.
1984  * @param[in] f_rules Additional optional formatting controls.
1985  * @param[in] fmt of the message.
1986  * @param[in] ap Message args.
1987  */
1988 void _cf_vlog_perr(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line,
1989  fr_log_perror_format_t const *f_rules, char const *fmt, va_list ap)
1990 {
1991  va_list aq;
1992 
1993  if ((type == L_DBG) && !DEBUG_ENABLED) return;
1994 
1995  if (!ci || !ci->filename) {
1996  va_copy(aq, ap);
1997  fr_vlog_perror(LOG_DST, type, file, line, f_rules, fmt, aq);
1998  va_end(aq);
1999  return;
2000  }
2001 
2002  {
2003  char const *e, *p;
2004  int len;
2005  char *prefix;
2006  TALLOC_CTX *thread_log_pool;
2007  TALLOC_CTX *pool;
2008  fr_log_perror_format_t our_f_rules;
2009 
2010  if (f_rules) {
2011  our_f_rules = *f_rules;
2012  } else {
2013  our_f_rules = (fr_log_perror_format_t){};
2014  }
2015 
2016  /*
2017  * Get some scratch space from the logging code
2018  */
2019  thread_log_pool = fr_log_pool_init();
2020  pool = talloc_new(thread_log_pool);
2021 
2022  truncate_filename(&e, &p, &len, ci->filename);
2023 
2024  /*
2025  * Create the file location string
2026  */
2027  prefix = fr_asprintf(pool, "%s%.*s[%d]: ", e, len, p, ci->lineno);
2028 
2029  /*
2030  * Prepend it to an existing first prefix
2031  */
2032  if (f_rules && f_rules->first_prefix) {
2033  char *first;
2034 
2035  first = talloc_bstrdup(pool, prefix);
2036  talloc_buffer_append_buffer(pool, first, f_rules->first_prefix);
2037 
2038  our_f_rules.first_prefix = first;
2039  } else {
2040  our_f_rules.first_prefix = prefix;
2041  }
2042 
2043  /*
2044  * Prepend it to an existing subsq prefix
2045  */
2046  if (f_rules && f_rules->subsq_prefix) {
2047  char *subsq;
2048 
2049  subsq = talloc_bstrdup(pool, prefix);
2050  talloc_buffer_append_buffer(pool, subsq, f_rules->subsq_prefix);
2051 
2052  our_f_rules.subsq_prefix = subsq;
2053  } else {
2054  our_f_rules.subsq_prefix = prefix;
2055  }
2056 
2057  va_copy(aq, ap);
2058  fr_vlog_perror(LOG_DST, type, file, line, &our_f_rules, fmt, aq);
2059  va_end(aq);
2060 
2061  talloc_free(pool);
2062  }
2063 }
2064 
2065 /** Log an error message relating to a #CONF_ITEM
2066  *
2067  * Drains the fr_strerror() stack emitting one or more error messages.
2068  *
2069  * @param[in] type of log message.
2070  * @param[in] file src file the log message was generated in.
2071  * @param[in] line number the log message was generated on.
2072  * @param[in] ci #CONF_ITEM to print file/lineno for.
2073  * @param[in] f_rules Additional optional formatting controls.
2074  * @param[in] fmt of the message.
2075  * @param[in] ... Message args.
2076  */
2077 void _cf_log_perr(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line,
2078  fr_log_perror_format_t const *f_rules, char const *fmt, ...)
2079 {
2080  va_list ap;
2081 
2082  if ((type == L_DBG) && !DEBUG_ENABLED) return;
2083 
2084  va_start(ap, fmt);
2085  _cf_vlog_perr(type, ci, file, line, f_rules, fmt, ap);
2086  va_end(ap);
2087 }
2088 
2089 /** Log a debug message relating to a #CONF_ITEM
2090  *
2091  * Always emits a filename/lineno prefix if available
2092  *
2093  * @param[in] type of log message.
2094  * @param[in] file src file the log message was generated in.
2095  * @param[in] line number the log message was generated on.
2096  * @param[in] ci #CONF_ITEM to print file/lineno for.
2097  * @param[in] fmt of the message.
2098  * @param[in] ... Message args.
2099  */
2100 void _cf_log_with_filename(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, char const *fmt, ...)
2101 {
2102  va_list ap;
2103 
2104  if ((type == L_DBG) && !DEBUG_ENABLED) return;
2105 
2106  if (!ci || !ci->filename) {
2107  va_start(ap, fmt);
2108  fr_vlog(LOG_DST, type, file, line, fmt, ap);
2109  va_end(ap);
2110  return;
2111  }
2112 
2113  {
2114  char const *e, *p;
2115  int len;
2116  char *msg;
2117 
2118  truncate_filename(&e, &p, &len, ci->filename);
2119 
2120  va_start(ap, fmt);
2121  msg = fr_vasprintf(NULL, fmt, ap);
2122  va_end(ap);
2123 
2124  fr_log(LOG_DST, type, file, line, "%s%.*s[%d]: %s", e, len, p, ci->lineno, msg);
2125  talloc_free(msg);
2126  }
2127 }
2128 
2129 /** Log an error message in the context of a child pair of the specified parent
2130  *
2131  * @param[in] parent containing the pair.
2132  * @param[in] child name to use as a logging context.
2133  * @param[in] type of log message.
2134  * @param[in] file src file the log message was generated in.
2135  * @param[in] line number the log message was generated on.
2136  * @param[in] fmt of the message.
2137  * @param[in] ... Message args.
2138  */
2139 void _cf_log_by_child(fr_log_type_t type, CONF_SECTION const *parent, char const *child,
2140  char const *file, int line, char const *fmt, ...)
2141 {
2142  va_list ap;
2143  CONF_PAIR const *cp;
2144 
2145  cp = cf_pair_find(parent, child);
2146  if (cp) {
2147  va_start(ap, fmt);
2148  _cf_vlog(type, CF_TO_ITEM(cp), file, line, fmt, ap);
2149  va_end(ap);
2150  return;
2151  }
2152 
2153  va_start(ap, fmt);
2155  va_end(ap);
2156 }
2157 
2158 
2159 /** Log an error message in the context of a child pair of the specified parent
2160  *
2161  * @param[in] parent containing the pair.
2162  * @param[in] child name to use as a logging context.
2163  * @param[in] type of log message.
2164  * @param[in] file src file the log message was generated in.
2165  * @param[in] line number the log message was generated on.
2166  * @param[in] f_rules Line prefixes.
2167  * @param[in] fmt of the message.
2168  * @param[in] ... Message args.
2169  */
2171  char const *file, int line, fr_log_perror_format_t const *f_rules,
2172  char const *fmt, ...)
2173 {
2174  va_list ap;
2175  CONF_PAIR const *cp;
2176 
2177  cp = cf_pair_find(parent, child);
2178  if (cp) {
2179  va_start(ap, fmt);
2180  _cf_vlog_perr(type, CF_TO_ITEM(cp), file, line, f_rules, fmt, ap);
2181  va_end(ap);
2182  return;
2183  }
2184 
2185  va_start(ap, fmt);
2186  _cf_vlog_perr(type, CF_TO_ITEM(parent), file, line, f_rules, fmt, ap);
2187  va_end(ap);
2188 }
2189 
2190 /** Print out debugging information about a CONFIG_ITEM
2191  *
2192  * @param[in] ci being debugged.
2193  */
2194 void _cf_debug(CONF_ITEM const *ci)
2195 {
2196  /*
2197  * Print summary of the item
2198  */
2199  switch (ci->type) {
2200  case CONF_ITEM_SECTION:
2201  {
2202  CONF_SECTION const *cs = cf_item_to_section(ci);
2203  int i;
2204 
2205  DEBUG("SECTION - %p", cs);
2206  DEBUG(" name1 : %s", cs->name1);
2207  DEBUG(" name2 : %s", cs->name2 ? cs->name2 : "<none>");
2208  DEBUG(" name2_quote : %s", fr_table_str_by_value(fr_token_quotes_table, cs->name2_quote, "<INVALID>"));
2209  DEBUG(" argc : %u", cs->argc);
2210 
2211  for (i = 0; i < cs->argc; i++) {
2212  char const *quote = fr_table_str_by_value(fr_token_quotes_table, cs->argv_quote[i], "<INVALID>");
2213  DEBUG(" argv[%i] : %s%s%s", i, quote, cs->argv[i], quote);
2214  }
2215  }
2216  break;
2217 
2218  case CONF_ITEM_PAIR:
2219  {
2220  CONF_PAIR const *cp = cf_item_to_pair(ci);
2221 
2222  DEBUG("PAIR - %p", cp);
2223  DEBUG(" attr : %s", cp->attr);
2224  DEBUG(" value : %s", cp->value);
2225  DEBUG(" operator : %s", fr_table_str_by_value(fr_tokens_table, cp->op, "<INVALID>"));
2226  DEBUG(" lhs_quote : %s", fr_table_str_by_value(fr_token_quotes_table, cp->lhs_quote, "<INVALID>"));
2227  DEBUG(" rhs_quote : %s", fr_table_str_by_value(fr_token_quotes_table, cp->rhs_quote, "<INVALID>"));
2228  DEBUG(" pass2 : %s", cp->pass2 ? "yes" : "no");
2229  DEBUG(" parsed : %s", cp->parsed ? "yes" : "no");
2230  }
2231  break;
2232 
2233  case CONF_ITEM_DATA:
2234  {
2235  CONF_DATA const *cd = cf_item_to_data(ci);
2236 
2237  DEBUG("DATA - %p", cd);
2238  DEBUG(" type : %s", cd->type);
2239  DEBUG(" name : %s", cd->name);
2240  DEBUG(" data : %p", cd->data);
2241  DEBUG(" free wth prnt : %s", cd->free ? "yes" : "no");
2242  }
2243  break;
2244 
2245  default:
2246  DEBUG("INVALID - %p", ci);
2247  return;
2248  }
2249 
2250  DEBUG(" filename : %s", ci->filename);
2251  DEBUG(" line : %i", ci->lineno);
2252  DEBUG(" next : %p", fr_dlist_next(&ci->parent->children, ci));
2253  DEBUG(" parent : %p", ci->parent);
2254  DEBUG(" children : %s", cf_item_has_no_children(ci) ? "no" : "yes");
2255  DEBUG(" ident1 tree : %p (%u entries)", ci->ident1, ci->ident1 ? fr_rb_num_elements(ci->ident1) : 0);
2256  DEBUG(" ident2 tree : %p (%u entries)", ci->ident2, ci->ident2 ? fr_rb_num_elements(ci->ident2) : 0);
2257 
2258  if (cf_item_has_no_children(ci)) return;
2259 
2260  /*
2261  * Print summary of the item's children
2262  */
2263  DEBUG("CHILDREN");
2264 
2265  cf_item_foreach(ci, child) {
2266  char const *in_ident1, *in_ident2;
2267 
2268  in_ident1 = fr_rb_find(ci->ident1, child) == child? "in ident1 " : "";
2269 
2270  if (ci->type != CONF_ITEM_SECTION) {
2271  in_ident2 = false;
2272  } else {
2273  in_ident2 = fr_rb_find(ci->ident2, child) == child? "in ident2 " : "";
2274  }
2275 
2276  switch (child->type) {
2277  case CONF_ITEM_SECTION:
2278  {
2279  CONF_SECTION const *cs = cf_item_to_section(child);
2280 
2281  DEBUG(" SECTION %p (%s %s) %s%s", child, cs->name1, cs->name2 ? cs->name2 : "<none>",
2282  in_ident1, in_ident2);
2283  }
2284  break;
2285 
2286  case CONF_ITEM_PAIR:
2287  {
2288  CONF_PAIR const *cp = cf_item_to_pair(child);
2289  char const *lhs_quote = fr_table_str_by_value(fr_token_quotes_table, cp->lhs_quote, "<INVALID>");
2290  char const *rhs_quote = fr_table_str_by_value(fr_token_quotes_table, cp->rhs_quote, "<INVALID>");
2291 
2292  DEBUG(" PAIR %p (%s%s%s %s %s%s%s) %s%s", child,
2293  lhs_quote, cp->attr, lhs_quote,
2294  fr_table_str_by_value(fr_tokens_table, cp->op, "<INVALID>"),
2295  rhs_quote, cp->value, rhs_quote,
2296  in_ident1, in_ident2);
2297  }
2298  break;
2299 
2300  case CONF_ITEM_DATA:
2301  {
2302  CONF_DATA const *cd = cf_item_to_data(child);
2303 
2304  DEBUG(" DATA %p (%s *)%s = %p %s%s", child,
2305  cd->type, cd->name ? cd->name : "", cd->data,
2306  in_ident1, in_ident2);
2307  break;
2308  }
2309 
2310  default:
2311  DEBUG(" INVALID - %p", child);
2312  break;
2313  }
2314  }
2315 }
2316 
2317 /*
2318  * Used when we don't need the children any more, as with
2319  *
2320  * if (0) { ... }
2321  */
2323 {
2324  CONF_ITEM *child = NULL;
2325 
2326  while ((child = fr_dlist_next(&ci->children, child)) != NULL) {
2327  if (child->type == CONF_ITEM_DATA) {
2328  continue;
2329  }
2330 
2331  child = fr_dlist_talloc_free_item(&ci->children, child);
2332  }
2333 }
2334 
2335 void _cf_canonicalize_error(CONF_ITEM *ci, ssize_t slen, char const *msg, char const *str)
2336 {
2337  char *spaces, *text;
2338 
2339  fr_canonicalize_error(ci, &spaces, &text, slen, str);
2340 
2341  cf_log_err(ci, "%s", msg);
2342  cf_log_err(ci, "%s", text);
2343  cf_log_perr(ci, "%s^", spaces);
2344 
2346  talloc_free(text);
2347 }
static int const char char buffer[256]
Definition: acutest.h:574
int const char * file
Definition: acutest.h:702
va_end(args)
log_entry msg
Definition: acutest.h:794
static int const char * fmt
Definition: acutest.h:573
int const char int line
Definition: acutest.h:702
va_start(args, fmt)
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition: build.h:165
#define RCSID(id)
Definition: build.h:444
#define CMP_RETURN(_a, _b, _field)
Return if the comparison is not 0 (is unequal)
Definition: build.h:119
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition: build.h:110
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:174
int _cf_section_rule_push(CONF_SECTION *cs, conf_parser_t const *rule, char const *filename, int lineno)
Add a single rule to a CONF_SECTION.
Definition: cf_parse.c:1351
conf_parser_flags_t flags
Flags which control parsing behaviour.
Definition: cf_parse.h:569
#define cf_section_rules_push(_cs, _rule)
Definition: cf_parse.h:658
char const * name1
Name of the CONF_ITEM to parse.
Definition: cf_parse.h:564
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:583
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition: cf_parse.h:400
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:563
fr_rb_node_t ident2_node
Entry in the ident2 tree.
Definition: cf_priv.h:51
CONF_ITEM item
Common set of fields.
Definition: cf_priv.h:90
CONF_ITEM * parent
Parent.
Definition: cf_priv.h:56
fr_token_t name2_quote
The type of quoting around name2.
Definition: cf_priv.h:95
void * base
Definition: cf_priv.h:101
char const * name2
Second name token. Given foo bar {} would be bar.
Definition: cf_priv.h:93
int argc
number of additional arguments
Definition: cf_priv.h:97
char const * attr
Attribute name.
Definition: cf_priv.h:73
char const * name
Additional qualification of type.
Definition: cf_priv.h:117
#define cf_item_foreach_prev(_ci, _iter, _prev)
Iterate over the contents of a list.
Definition: cf_priv.h:148
fr_rb_tree_t * ident2
Tree to store the second identifier (name2 || name).
Definition: cf_priv.h:59
fr_token_t rhs_quote
Value Quoting style T_(DOUBLE|SINGLE|BACK)_QUOTE_STRING or T_BARE_WORD.
Definition: cf_priv.h:78
int depth
Definition: cf_priv.h:102
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:138
char const * name1
First name token. Given foo bar {} would be foo.
Definition: cf_priv.h:92
void const * data
User data.
Definition: cf_priv.h:119
static bool cf_item_has_no_children(CONF_ITEM const *ci)
Check if the CONF_ITEM has no children.
Definition: cf_priv.h:158
fr_dlist_head_t children
The head of the ordered list of children.
Definition: cf_priv.h:54
fr_token_t * argv_quote
Definition: cf_priv.h:99
fr_token_t op
Operator e.g. =, :=.
Definition: cf_priv.h:76
CONF_ITEM item
Common set of fields.
Definition: cf_priv.h:71
bool pass2
do expansion in pass2.
Definition: cf_priv.h:80
char const * filename
The file the config item was parsed from.
Definition: cf_priv.h:64
fr_rb_tree_t * ident1
Tree to store the first identifier (name1 || type || attr).
Definition: cf_priv.h:58
bool is_talloced
If true we can do extra checks.
Definition: cf_priv.h:120
CONF_SECTION * template
Definition: cf_priv.h:107
fr_rb_node_t ident1_node
Entry in the ident1 tree.
Definition: cf_priv.h:50
bool attr
is this thing an attribute definition?
Definition: cf_priv.h:104
@ CONF_ITEM_INVALID
Definition: cf_priv.h:40
@ CONF_ITEM_PAIR
Definition: cf_priv.h:41
@ CONF_ITEM_DATA
Definition: cf_priv.h:43
@ CONF_ITEM_SECTION
Definition: cf_priv.h:42
enum conf_type CONF_ITEM_TYPE
char const ** argv
additional arguments
Definition: cf_priv.h:98
char const * type
C type of data being stored.
Definition: cf_priv.h:116
CONF_ITEM item
Common set of fields.
Definition: cf_priv.h:114
bool parsed
Was this item used during parsing?
Definition: cf_priv.h:81
fr_token_t lhs_quote
Name quoting style T_(DOUBLE|SINGLE|BACK)_QUOTE_STRING or T_BARE_WORD.
Definition: cf_priv.h:77
bool free
If true, free data with talloc if parent node is freed.
Definition: cf_priv.h:121
int lineno
The line number the config item began on.
Definition: cf_priv.h:63
CONF_ITEM_TYPE type
Whether the config item is a config_pair, conf_section or cf_data.
Definition: cf_priv.h:61
Internal data that is associated with a configuration section.
Definition: cf_priv.h:113
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:89
CONF_ITEM * _cf_item_remove(CONF_ITEM *parent, CONF_ITEM *child)
Remove item from parent and fixup trees.
Definition: cf_util.c:428
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
Definition: cf_util.c:597
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition: cf_util.c:629
CONF_SECTION * cf_section_find_parent(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a parent CONF_SECTION with name1 and optionally name2.
Definition: cf_util.c:1039
static void cf_item_init(CONF_ITEM *ci, CONF_ITEM_TYPE type, CONF_ITEM *parent, char const *filename, int lineno)
Initialize a CONF_ITEM, so we don't have repeated code.
Definition: cf_util.c:505
CONF_ITEM * cf_section_to_item(CONF_SECTION const *cs)
Cast a CONF_SECTION to a CONF_ITEM.
Definition: cf_util.c:703
fr_token_t cf_pair_attr_quote(CONF_PAIR const *pair)
Return the value (lhs) quoting of a pair.
Definition: cf_util.c:1540
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
Definition: cf_util.c:1495
int _cf_data_walk(CONF_ITEM *ci, char const *type, cf_walker_t cb, void *ctx)
Walk over a specific type of CONF_DATA.
Definition: cf_util.c:1817
unsigned int cf_pair_count_descendents(CONF_SECTION const *cs)
Count the number of conf pairs beneath a section.
Definition: cf_util.c:1422
static CONF_ITEM * cf_find_next(CONF_ITEM const *parent, CONF_ITEM const *prev, CONF_ITEM_TYPE type, char const *ident1, char const *ident2)
Return the next child that's of the specified type with the specified identifiers.
Definition: cf_util.c:157
CONF_DATA const * _cf_data_add(CONF_ITEM *ci, void const *data, char const *name, bool do_free, char const *filename, int lineno)
Add talloced user data to a config section.
Definition: cf_util.c:1703
static CONF_ITEM * cf_next(CONF_ITEM const *parent, CONF_ITEM const *prev, CONF_ITEM_TYPE type)
Return the next child that's of the specified type.
Definition: cf_util.c:48
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:970
CONF_SECTION * cf_section_find_in_parent(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a section in the lineage of a CONF_SECTION which matches a specific name1 and optionally name2.
Definition: cf_util.c:1012
fr_token_t cf_section_argv_quote(CONF_SECTION const *cs, int argc)
Return the quoting for one of the variadic arguments.
Definition: cf_util.c:1201
CONF_PAIR * cf_pair_find_in_parent(CONF_SECTION const *cs, char const *attr)
Find a pair with a name matching attr in the specified section or one of its parents.
Definition: cf_util.c:1384
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:1437
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:1886
void _cf_item_insert_after(CONF_ITEM *parent, CONF_ITEM *prev, CONF_ITEM *child)
Insert a child after a given one.
Definition: cf_util.c:390
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:1356
static int8_t _cf_ident1_cmp(void const *a, void const *b)
Compare the first identifier of a child.
Definition: cf_util.c:241
#define FILENAME_TRUNCATE
fr_slen_t cf_pair_values_concat(fr_sbuff_t *out, CONF_SECTION const *cs, char const *attr, char const *sep)
Concatenate the values of any pairs with name attr.
Definition: cf_util.c:1457
void cf_item_free_children(CONF_ITEM *ci)
Definition: cf_util.c:2322
CONF_PAIR * cf_pair_next(CONF_SECTION const *cs, CONF_PAIR const *prev)
Return the next child that's a CONF_PAIR.
Definition: cf_util.c:1343
CONF_SECTION * _cf_section_alloc(TALLOC_CTX *ctx, CONF_SECTION *parent, char const *name1, char const *name2, char const *filename, int lineno)
Allocate a CONF_SECTION.
Definition: cf_util.c:752
CONF_DATA * _cf_data_find_in_parent(CONF_ITEM const *ci, char const *type, char const *name)
Find matching data in the specified section or one of its parents.
Definition: cf_util.c:1661
int8_t cf_section_name_cmp(CONF_SECTION const *cs, char const *name1, char const *name2)
Check if a given section matches the specified name1/name2 identifiers.
Definition: cf_util.c:1080
void _cf_log(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, char const *fmt,...)
Log an error message relating to a CONF_ITEM.
Definition: cf_util.c:1965
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition: cf_util.c:1126
static int8_t _cf_ident2_cmp(void const *a, void const *b)
Compare the first and second identifiers of a child.
Definition: cf_util.c:348
static int8_t cf_ident2_cmp(void const *a, void const *b)
Compare only the second identifier of a child.
Definition: cf_util.c:298
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition: cf_util.c:1511
void _cf_vlog_perr(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, fr_log_perror_format_t const *f_rules, char const *fmt, va_list ap)
Log an error message relating to a CONF_ITEM.
Definition: cf_util.c:1988
void cf_pair_mark_parsed(CONF_PAIR *cp)
Mark a pair as parsed.
Definition: cf_util.c:1318
static void _pair_count(int *count, CONF_SECTION const *cs)
Callback to determine the number of pairs in a section.
Definition: cf_util.c:1403
void _cf_filename_set(CONF_ITEM *ci, char const *filename)
Set the filename of a CONF_ITEM.
Definition: cf_util.c:861
CONF_DATA const * _cf_data_find_next(CONF_ITEM const *ci, CONF_ITEM const *prev, char const *type, char const *name)
Return the next item of user data.
Definition: cf_util.c:1645
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
Definition: cf_util.c:1680
void _cf_lineno_set(CONF_ITEM *ci, int lineno)
Set the line number of a CONF_ITEM.
Definition: cf_util.c:873
void _cf_log_by_child(fr_log_type_t type, CONF_SECTION const *parent, char const *child, char const *file, int line, char const *fmt,...)
Log an error message in the context of a child pair of the specified parent.
Definition: cf_util.c:2139
void _cf_log_perr(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, fr_log_perror_format_t const *f_rules, char const *fmt,...)
Log an error message relating to a CONF_ITEM.
Definition: cf_util.c:2077
static int _cd_free(CONF_DATA *cd)
Free user data associated with CONF_DATA.
Definition: cf_util.c:1565
void _cf_vlog(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, char const *fmt, va_list ap)
Log an error message relating to a CONF_ITEM.
Definition: cf_util.c:1926
void _cf_log_perr_by_child(fr_log_type_t type, CONF_SECTION const *parent, char const *child, char const *file, int line, fr_log_perror_format_t const *f_rules, char const *fmt,...)
Log an error message in the context of a child pair of the specified parent.
Definition: cf_util.c:2170
CONF_SECTION * _cf_root(CONF_ITEM const *ci)
Return the top level CONF_SECTION holding all other CONF_ITEM.
Definition: cf_util.c:523
void cf_section_add_name2_quote(CONF_SECTION *cs, fr_token_t token)
Set the quoting of the name2 identifier.
Definition: cf_util.c:1183
bool cf_item_is_data(CONF_ITEM const *ci)
Determine if CONF_ITEM is CONF_DATA.
Definition: cf_util.c:611
fr_token_t cf_pair_operator(CONF_PAIR const *pair)
Return the operator of a pair.
Definition: cf_util.c:1525
CONF_ITEM * cf_pair_to_item(CONF_PAIR const *cp)
Cast a CONF_PAIR to a CONF_ITEM.
Definition: cf_util.c:687
bool cf_pair_is_parsed(CONF_PAIR *cp)
Return whether a pair has already been parsed.
Definition: cf_util.c:1330
char const * _cf_filename(CONF_ITEM const *ci)
Return the filename the CONF_ITEM was parsed in.
Definition: cf_util.c:569
CONF_SECTION * cf_section_next(CONF_SECTION const *cs, CONF_SECTION const *prev)
Return the next child that's a CONF_SECTION.
Definition: cf_util.c:952
#define IS_WILDCARD(_ident)
Definition: cf_util.c:57
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition: cf_util.c:649
fr_token_t cf_pair_value_quote(CONF_PAIR const *pair)
Return the value (rhs) quoting of a pair.
Definition: cf_util.c:1555
void _cf_log_with_filename(fr_log_type_t type, CONF_ITEM const *ci, char const *file, int line, char const *fmt,...)
Log a debug message relating to a CONF_ITEM.
Definition: cf_util.c:2100
static void truncate_filename(char const **e, char const **p, int *len, char const *filename)
Definition: cf_util.c:1845
void * _cf_data_remove(CONF_ITEM *parent, CONF_DATA const *cd)
Remove data from a configuration section.
Definition: cf_util.c:1789
static CONF_ITEM * cf_find(CONF_ITEM const *parent, CONF_ITEM_TYPE type, char const *ident1, char const *ident2)
Return the next child that's of the specified type with the specified identifiers.
Definition: cf_util.c:70
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:991
void _cf_canonicalize_error(CONF_ITEM *ci, ssize_t slen, char const *msg, char const *str)
Definition: cf_util.c:2335
CONF_ITEM * cf_data_to_item(CONF_DATA const *cd)
Cast CONF_DATA to a CONF_ITEM.
Definition: cf_util.c:719
CONF_ITEM * _cf_item_next(CONF_ITEM const *ci, CONF_ITEM const *prev)
Return the next child of cs.
Definition: cf_util.c:490
CONF_DATA const * _cf_data_find(CONF_ITEM const *ci, char const *type, char const *name)
Find user data in a config section.
Definition: cf_util.c:1627
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
Definition: cf_util.c:583
CONF_DATA * cf_item_to_data(CONF_ITEM const *ci)
Cast CONF_ITEM to CONF_DATA performing a type check.
Definition: cf_util.c:669
CONF_SECTION * cf_section_dup(TALLOC_CTX *ctx, CONF_SECTION *parent, CONF_SECTION const *cs, char const *name1, char const *name2, bool copy_meta)
Duplicate a configuration section.
Definition: cf_util.c:894
static CONF_DATA * cf_data_alloc(CONF_ITEM *parent, void const *data, char const *type, char const *name, bool do_free)
Allocate a new user data container.
Definition: cf_util.c:1587
int _cf_lineno(CONF_ITEM const *ci)
Return the lineno the CONF_ITEM was parsed at.
Definition: cf_util.c:555
static int _cf_section_free(CONF_SECTION *cs)
Free a section and associated trees.
Definition: cf_util.c:731
fr_token_t cf_section_name2_quote(CONF_SECTION const *cs)
Return the quoting of the name2 identifier.
Definition: cf_util.c:1171
CONF_ITEM * _cf_parent(CONF_ITEM const *ci)
Return the parent of a CONF_ITEM.
Definition: cf_util.c:541
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:1370
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition: cf_util.c:1112
void _cf_debug(CONF_ITEM const *ci)
Print out debugging information about a CONFIG_ITEM.
Definition: cf_util.c:2194
int cf_pair_replace(CONF_SECTION *cs, CONF_PAIR *cp, char const *value)
Replace pair in a given section with a new pair, of the given value.
Definition: cf_util.c:1290
void _cf_item_add(CONF_ITEM *parent, CONF_ITEM *child)
Add a child.
Definition: cf_util.c:363
char const * cf_section_name(CONF_SECTION const *cs)
Return name2 if set, else name1.
Definition: cf_util.c:1138
char const * cf_section_value_find(CONF_SECTION const *cs, char const *attr)
Find a pair in a CONF_SECTION.
Definition: cf_util.c:1061
CONF_PAIR * cf_pair_dup(CONF_SECTION *parent, CONF_PAIR *cp)
Duplicate a CONF_PAIR.
Definition: cf_util.c:1261
char const * cf_section_argv(CONF_SECTION const *cs, int argc)
Return variadic argument at the specified index.
Definition: cf_util.c:1154
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:1220
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:1745
#define cf_item_add(_parent, _child)
Definition: cf_util.h:83
#define cf_log_err(_cf, _fmt,...)
Definition: cf_util.h:265
#define cf_data_find(_cf, _type, _name)
Definition: cf_util.h:220
#define cf_lineno_set(_ci, _lineno)
Definition: cf_util.h:128
#define cf_parent(_cf)
Definition: cf_util.h:98
#define cf_item_next(_ci, _prev)
Definition: cf_util.h:92
#define cf_item_remove(_parent, _child)
Definition: cf_util.h:89
#define cf_log_perr(_cf, _fmt,...)
Definition: cf_util.h:272
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition: cf_util.h:137
#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_filename_set(_ci, _filename)
Definition: cf_util.h:125
int(* cf_walker_t)(void *data, void *ctx)
Definition: cf_util.h:76
#define CF_IDENT_ANY
Definition: cf_util.h:78
static fr_atomic_queue_t * aq
Definition: control_test.c:47
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition: debug.h:137
#define fr_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error.
Definition: debug.h:214
static char const * spaces
Definition: dependency.c:364
#define ERROR(fmt,...)
Definition: dhcpclient.c:41
#define DEBUG(fmt,...)
Definition: dhcpclient.c:39
Test enumeration values.
Definition: dict_test.h:92
#define fr_dlist_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
Definition: dlist.h:260
static void * fr_dlist_talloc_free_item(fr_dlist_head_t *list_head, void *ptr)
Free the item specified.
Definition: dlist.h:876
static void * fr_dlist_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
Definition: dlist.h:555
static int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
Definition: dlist.h:378
static void * fr_dlist_remove(fr_dlist_head_t *list_head, void *ptr)
Remove an item from the list.
Definition: dlist.h:638
static int fr_dlist_insert_after(fr_dlist_head_t *list_head, void *pos, void *ptr)
Insert an item after an item already in the list.
Definition: dlist.h:414
#define LOG_DST
Definition: network.c:29
#define DEBUG_ENABLED4
True if global debug level 1-3 messages are enabled.
Definition: log.h:260
#define DEBUG_ENABLED
True if global debug level 1 messages are enabled.
Definition: log.h:257
talloc_free(reap)
TALLOC_CTX * fr_log_pool_init(void)
talloc ctx to use when composing log messages
Definition: log.c:315
void fr_vlog_perror(fr_log_t const *log, fr_log_type_t type, char const *file, int line, fr_log_perror_format_t const *f_rules, char const *fmt, va_list ap)
Drain any outstanding messages from the fr_strerror buffers.
Definition: log.c:630
void fr_vlog(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *fmt, va_list ap)
Send a server log message to its destination.
Definition: log.c:343
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:89
void fr_log(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *fmt,...)
Send a server log message to its destination.
Definition: log.c:599
char const * first_prefix
Prefix for the first line printed.
Definition: log.h:125
char const * subsq_prefix
Prefix for subsequent lines.
Definition: log.h:126
fr_log_type_t
Definition: log.h:54
@ L_INFO
Informational message.
Definition: log.h:55
@ L_DBG
Only displayed when debugging is enabled.
Definition: log.h:59
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
ssize_t fr_slen_t
Definition: merged_model.c:35
char * fr_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
Definition: print.c:853
char * fr_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Special version of asprintf which implements custom format specifiers.
Definition: print.c:876
static bool done
Definition: radclient.c:80
uint32_t fr_rb_num_elements(fr_rb_tree_t *tree)
Return how many nodes there are in a tree.
Definition: rb.c:775
void * fr_rb_iter_next_inorder(fr_rb_iter_inorder_t *iter)
Return the next node.
Definition: rb.c:844
void * fr_rb_remove_by_inline_node(fr_rb_tree_t *tree, fr_rb_node_t *node)
Remove an entry from the tree, using the node structure, without freeing the data.
Definition: rb.c:718
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
Definition: rb.c:624
void * fr_rb_iter_init_inorder(fr_rb_iter_inorder_t *iter, fr_rb_tree_t *tree)
Initialise an in-order iterator.
Definition: rb.c:818
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
Find an element in the tree, returning the data, not the node.
Definition: rb.c:576
#define fr_rb_inline_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black tree.
Definition: rb.h:271
Iterator structure for in-order traversal of an rbtree.
Definition: rb.h:321
static char const * name
ssize_t fr_sbuff_in_strcpy(fr_sbuff_t *sbuff, char const *str)
Copy bytes into the sbuff up to the first \0.
Definition: sbuff.c:1419
ssize_t fr_sbuff_in_escape(fr_sbuff_t *sbuff, char const *in, size_t inlen, fr_sbuff_escape_rules_t const *e_rules)
Print an escaped string to an sbuff.
Definition: sbuff.c:1579
#define FR_SBUFF(_sbuff_or_marker)
return count
Definition: module.c:175
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
fr_aka_sim_id_type_t type
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
Definition: table.h:134
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition: table.h:253
An element in a lexicographically sorted array of name to num mappings.
Definition: table.h:45
char * talloc_bstrdup(TALLOC_CTX *ctx, char const *in)
Binary safe strdup function.
Definition: talloc.c:424
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition: talloc.c:333
char * talloc_buffer_append_buffer(TALLOC_CTX *ctx, char *to, char const *from)
Concatenate to + from.
Definition: talloc.c:548
char * talloc_bstr_realloc(TALLOC_CTX *ctx, char *in, size_t inlen)
Trim a bstr (char) buffer.
Definition: talloc.c:516
int talloc_decrease_ref_count(void const *ptr)
Decrease the reference count on a ptr.
Definition: talloc.c:708
static int talloc_const_free(void const *ptr)
Free const'd memory.
Definition: talloc.h:212
const bool fr_assignment_op[T_TOKEN_LAST]
Definition: token.c:168
fr_table_num_ordered_t const fr_tokens_table[]
Definition: token.c:33
fr_table_num_sorted_t const fr_token_quotes_table[]
Definition: token.c:66
const bool fr_comparison_op[T_TOKEN_LAST]
Definition: token.c:198
const bool fr_binary_op[T_TOKEN_LAST]
Definition: token.c:216
enum fr_token fr_token_t
@ T_INVALID
Definition: token.h:39
@ T_BARE_WORD
Definition: token.h:120
#define FR_TABLE_NOT_FOUND
Macro to use as dflt.
Definition: token.h:137
static fr_slen_t parent
Definition: pair.h:844
FR_SBUFF_SET_RETURN(sbuff, &our_sbuff)
static fr_slen_t data
Definition: value.h:1259
int nonnull(2, 5))
static size_t char ** out
Definition: value.h:984