The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
users_file.c
Go to the documentation of this file.
1/*
2 * files.c Read config files into memory.
3 *
4 * Version: $Id: 8464bd60ea30cd61f2f103fe9fb0c1904817fde6 $
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 *
20 * @copyright 2000,2006 The FreeRADIUS server project
21 * @copyright 2000 Miquel van Smoorenburg (miquels@cistron.nl)
22 * @copyright 2000 Alan DeKok (aland@freeradius.org)
23 */
24
25RCSID("$Id: 8464bd60ea30cd61f2f103fe9fb0c1904817fde6 $")
26
27#include <freeradius-devel/server/log.h>
28#include <freeradius-devel/util/debug.h>
29#include <freeradius-devel/server/users_file.h>
30
31#include <freeradius-devel/util/misc.h>
32#include <freeradius-devel/util/pair_legacy.h>
33#include <freeradius-devel/util/syserror.h>
34
35#include <sys/stat.h>
36
37#include <fcntl.h>
38
39static int pairlist_read_internal(TALLOC_CTX *ctx, fr_dict_t const *dict, char const *file, PAIR_LIST_LIST *list,
40 bool complain, bool v3_compat, int *order);
41
42static inline void line_error_marker(char const *src_file, int src_line,
43 char const *user_file, int user_line,
44 fr_sbuff_t *sbuff, char const *error)
45{
46 char *end;
48
49 fr_sbuff_marker(&start, sbuff);
50 end = fr_sbuff_adv_to_chr(sbuff, SIZE_MAX, '\n');
51 if (!end) end = fr_sbuff_end(sbuff);
52 fr_sbuff_set(sbuff, &start);
53 fr_sbuff_marker_release(&start);
54
55 fr_log_marker(LOG_DST, L_ERR, src_file, src_line,
56 fr_sbuff_start(sbuff), end - fr_sbuff_start(sbuff),
57 fr_sbuff_used(sbuff), error, "%s[%d]: ", user_file, user_line);
58}
59/** Print out a line oriented error marker at the current position of the sbuff
60 *
61 * @param[in] _sbuff to print error for.
62 * @param[in] _error message.
63 */
64#define ERROR_MARKER(_sbuff, _error) line_error_marker(__FILE__, __LINE__, file, lineno, _sbuff, _error)
65
66static inline void line_error_marker_adj(char const *src_file, int src_line,
67 char const *user_file, int user_line,
68 fr_sbuff_t *sbuff, ssize_t marker_idx, char const *error)
69{
70 char *end;
72
73 fr_sbuff_marker(&start, sbuff);
74 end = fr_sbuff_adv_to_chr(sbuff, SIZE_MAX, '\n');
75 if (!end) end = fr_sbuff_end(sbuff);
76 fr_sbuff_set(sbuff, &start);
77 fr_sbuff_marker_release(&start);
78
79 fr_log_marker(LOG_DST, L_ERR, src_file, src_line,
80 fr_sbuff_current(sbuff), end - fr_sbuff_current(sbuff),
81 marker_idx, error, "%s[%d]: ", user_file, user_line);
82}
83/** Print out a line oriented error marker relative to the current position of the sbuff
84 *
85 * @param[in] _sbuff to print error for.
86 * @param[in] _idx Where the error occurred.
87 * @param[in] _error message.
88 */
89#define ERROR_MARKER_ADJ(_sbuff, _idx, _error) line_error_marker_adj(__FILE__, __LINE__, file, lineno, _sbuff, _idx, _error)
90
92 { L("!*"), T_OP_CMP_FALSE },
93 { L("!="), T_OP_NE },
94 { L("!~"), T_OP_REG_NE },
95 { L("+="), T_OP_ADD_EQ },
96 { L(":="), T_OP_SET },
97 { L("<"), T_OP_LT },
98 { L("<="), T_OP_LE },
99 { L("="), T_OP_EQ },
100 { L("=*"), T_OP_CMP_TRUE },
101 { L("=="), T_OP_CMP_EQ },
102 { L("=~"), T_OP_REG_EQ },
103 { L(">"), T_OP_GT },
104 { L(">="), T_OP_GE }
105};
107
109 L("\t"),
110 L("\n"),
111 L(" "),
112 L("#"),
113);
114
115static fr_sbuff_parse_rules_t const rhs_term = {
116 .escapes = &(fr_sbuff_unescape_rules_t){
117 .chr = '\\',
118 /*
119 * Allow barewords to contain whitespace
120 * if they're escaped.
121 */
122 .subs = {
123 ['\t'] = '\t',
124 ['\n'] = '\n',
125 [' '] = ' '
126 },
127 .do_hex = true,
128 .do_oct = false
129 },
130 .terminals = &FR_SBUFF_TERMS(
131 L(""),
132 L("\t"),
133 L("\n"),
134 L("#"),
135 L(","),
136 )
137};
138
139/*
140 * Caller saw a $INCLUDE at the start of a line.
141 */
142static int users_include(TALLOC_CTX *ctx, fr_dict_t const *dict, fr_sbuff_t *sbuff, PAIR_LIST_LIST *list,
143 char const *file, int lineno, bool v3_compat, int *order)
144{
145 size_t len;
146 char *newfile, c;
147 char const *p;
149
150 fr_sbuff_advance(sbuff, 8);
151
152 /*
153 * Skip spaces after the $INCLUDE.
154 */
155 if (fr_sbuff_adv_past_blank(sbuff, SIZE_MAX, NULL) == 0) {
156 ERROR_MARKER(sbuff, "Unexpected text after $INCLUDE");
157 return -1;
158 }
159
160 /*
161 * Remember when the name started, and skip over the name
162 * until spaces, comments, or LF
163 */
164 fr_sbuff_marker(&name, sbuff);
165 len = fr_sbuff_adv_until(sbuff, SIZE_MAX, &name_terms, 0);
166 if (len == 0) {
167 ERROR_MARKER(sbuff, "No filename after $INCLUDE");
168 fr_sbuff_marker_release(&name);
169 return -1;
170 }
171
172 /*
173 * If the input file is a relative path, try to copy the
174 * leading directory from it. If there's no leading
175 * directory, just use the $INCLUDE name as-is.
176 *
177 * If there is a leading directory in the input name,
178 * paste that as the directory to the $INCLUDE name.
179 *
180 * Otherwise the $INCLUDE name is an absolute path, use
181 * it as -is.
182 */
183 c = fr_sbuff_char(&name, '\0');
184 if (c != '/') {
185 p = strrchr(file, '/');
186
187 if (!p) goto copy_name;
188
189 newfile = talloc_asprintf(NULL, "%.*s/%.*s",
190 (int) (p - file), file,
191 (int) len, fr_sbuff_current(&name));
192 } else {
193 copy_name:
194 newfile = talloc_asprintf(NULL, "%.*s", (int) len, fr_sbuff_current(&name));
195 }
196 fr_sbuff_marker_release(&name);
197
198 /*
199 * Skip spaces and comments after the name.
200 */
201 fr_sbuff_adv_past_blank(sbuff, SIZE_MAX, NULL);
202 if (fr_sbuff_next_if_char(sbuff, '#')) {
203 (void) fr_sbuff_adv_to_chr(sbuff, SIZE_MAX, '\n');
204 }
205
206 /*
207 * There's no LF, but if we skip non-spaces and
208 * non-comments to find the LF, then there must be extra
209 * text after the filename. That's an error.
210 *
211 * Unless the line has EOF after the filename. in which
212 * case this error will get hit, too.
213 */
214 if (!fr_sbuff_is_char(sbuff, '\n') &&
215 (fr_sbuff_adv_to_chr(sbuff, SIZE_MAX, '\n') != NULL)) {
216 ERROR_MARKER(sbuff, "Unexpected text after filename");
217 talloc_free(newfile);
218 return -1;
219 }
220
221 /*
222 * Read the $INCLUDEd file recursively.
223 */
224 if (pairlist_read_internal(ctx, dict, newfile, list, false, v3_compat, order) != 0) {
225 ERROR("%s[%d]: Could not read included file %s: %s",
226 file, lineno, newfile, fr_syserror(errno));
227 talloc_free(newfile);
228 return -1;
229 }
230 talloc_free(newfile);
231
232 return 0;
233}
234
235int pairlist_read(TALLOC_CTX *ctx, fr_dict_t const *dict, char const *file, PAIR_LIST_LIST *list, bool v3_compat)
236{
237 int order = 0;
238
239 return pairlist_read_internal(ctx, dict, file, list, true, v3_compat, &order);
240}
241
242/*
243 * Read the users file. Return a PAIR_LIST.
244 */
245static int pairlist_read_internal(TALLOC_CTX *ctx, fr_dict_t const *dict, char const *file, PAIR_LIST_LIST *list, bool complain, bool v3_compat, int *order)
246{
247 char *q;
248 int lineno = 1;
249 map_t *new_map, *relative_map;
250 FILE *fp;
251 fr_sbuff_t sbuff;
253 tmpl_rules_t lhs_rules, rhs_rules;
254 char *filename = talloc_strdup(ctx, file);
255 char buffer[8192];
256
257 DEBUG2("Reading file %s", file);
258
259 /*
260 * Open the file. The error message should be a little
261 * more useful...
262 */
263 if ((fp = fopen(file, "r")) == NULL) {
264 if (complain) ERROR("Couldn't open %s for reading: %s", file, fr_syserror(errno));
265 return -1;
266 }
267
268 fr_sbuff_init_file(&sbuff, &fctx, buffer, sizeof(buffer), fp, SIZE_MAX);
269
270 lhs_rules = (tmpl_rules_t) {
271 .attr = {
272 .dict_def = dict,
273 .list_def = request_attr_request,
274 .list_presence = TMPL_ATTR_LIST_ALLOW,
275 },
276 .literals_safe_for = FR_VALUE_BOX_SAFE_FOR_ANY,
277
278 };
279 rhs_rules = (tmpl_rules_t) {
280 .attr = {
281 .dict_def = dict,
282 .list_def = request_attr_request,
283 .list_presence = TMPL_ATTR_LIST_ALLOW,
284 .bare_word_enum = v3_compat,
285 },
286 .literals_safe_for = FR_VALUE_BOX_SAFE_FOR_ANY,
287 };
288
289 while (true) {
290 size_t len;
291 ssize_t slen;
292 bool comma;
293 bool leading_spaces;
294 PAIR_LIST *t;
295
296 /*
297 * If the line is empty or has only comments,
298 * then we don't care about leading spaces.
299 */
300 leading_spaces = (fr_sbuff_adv_past_blank(&sbuff, SIZE_MAX, NULL) > 0);
301 if (fr_sbuff_next_if_char(&sbuff, '#')) {
302 (void) fr_sbuff_adv_to_chr(&sbuff, SIZE_MAX, '\n');
303 }
304 if (fr_sbuff_next_if_char(&sbuff, '\n')) {
305 lineno++;
306 continue;
307 }
308
309 /*
310 * We're trying to read a key value. It MUST have
311 * been at the start of the line. So whatever
312 * this is, it's wrong.
313 */
314 if (leading_spaces) {
315 ERROR_MARKER(&sbuff, "Entry does not begin with a key value");
316 fail:
317 fclose(fp);
318 return -1;
319 }
320
321 /*
322 * $INCLUDE filename. This will do some sanity checks, and then add the new entries to
323 * the tail of the current list.
324 */
325 if (fr_sbuff_is_str(&sbuff, "$INCLUDE", 8)) {
326 if (users_include(ctx, dict, &sbuff, list, file, lineno, v3_compat, order) < 0) goto fail;
327
328 if (fr_sbuff_next_if_char(&sbuff, '\n')) {
329 lineno++;
330 continue;
331 }
332
333 /*
334 * The next character is not LF, but the
335 * function skipped to LF. So, by
336 * process of elimination, we must be at
337 * EOF.
338 */
339 break;
340 } /* else it wasn't $INCLUDE */
341
342 /*
343 * We MUST be either at a valid entry, OR at EOF.
344 */
345 MEM(t = talloc_zero(ctx, PAIR_LIST));
346 map_list_init(&t->check);
347 map_list_init(&t->reply);
348 t->filename = filename;
349 t->lineno = lineno;
350 t->order = (*order)++;
351
352 /*
353 * Copy the name from the entry.
354 */
355 if (fr_sbuff_out_abstrncpy_until(t, &q, &len, &sbuff, SIZE_MAX, &name_terms, NULL) < 0) {
356 ERROR_MARKER(&sbuff, "Failed reading entry name");
357 talloc_free(t);
358 goto fail;
359 }
360 if (len == 0) {
361 talloc_free(t);
362 break;
363 }
364 t->name = q;
365
367 comma = false;
368
369check_item:
370 /*
371 * Skip spaces before the item, and allow the
372 * check list to end on comment or LF.
373 *
374 * Note that we _don't_ call map_afrom_substr() to
375 * skip spaces, as it will skip LF, too!
376 */
377 (void) fr_sbuff_adv_past_blank(&sbuff, SIZE_MAX, NULL);
378 if (fr_sbuff_is_char(&sbuff, '#')) goto check_item_comment;
379 if (fr_sbuff_is_char(&sbuff, '\n')) goto check_item_end;
380
381 /*
382 * Try to parse the check item.
383 */
384 slen = map_afrom_substr(t, &new_map, NULL, &sbuff, check_cmp_op_table, check_cmp_op_table_len,
385 &lhs_rules, &rhs_rules, &rhs_term);
386 if (!new_map) {
387 ERROR_MARKER_ADJ(&sbuff, slen, fr_strerror());
388 fail_entry:
389 talloc_free(t);
390 goto fail;
391 }
392
393 fr_assert(new_map->lhs != NULL);
394 fr_assert(new_map->rhs != NULL);
395
396 /*
397 * The default rule says that the check
398 * items look at the control list, but
399 * protocol attributes should be compared in the request.
400 */
401 if (!tmpl_attr_tail_da(new_map->lhs)->flags.internal) {
403 }
404
405 if (tmpl_contains_regex(new_map->rhs)) {
406 if (tmpl_is_regex_uncompiled(new_map->rhs) &&
407 (tmpl_regex_compile(new_map->rhs, false) < 0)) {
408 ERROR("%s[%d]: Failed compiling regular expression /%s/ - %s",
409 file, lineno, new_map->rhs->name, fr_strerror());
410 goto fail_entry;
411 }
412
413 goto do_insert;
414 }
415
416 do_insert:
417 fr_assert(!new_map->parent);
418 map_list_insert_tail(&t->check, new_map);
419
420 /*
421 * There can be spaces before any comma.
422 */
423 (void) fr_sbuff_adv_past_blank(&sbuff, SIZE_MAX, NULL);
424
425 /*
426 * Allow a comma after this item. But remember
427 * if we had a comma.
428 */
429 if (fr_sbuff_next_if_char(&sbuff, ',')) {
430 comma = true;
431 goto check_item;
432 }
433 comma = false;
434
435 check_item_comment:
436 /*
437 * There wasn't a comma after the item, so the
438 * next thing MUST be a comment, LF, EOF.
439 *
440 * If there IS stuff before the LF, then it's
441 * unknown text.
442 */
443 if (fr_sbuff_next_if_char(&sbuff, '#')) {
444 (void) fr_sbuff_adv_to_chr(&sbuff, SIZE_MAX, '\n');
445 }
446 check_item_end:
447 if (fr_sbuff_next_if_char(&sbuff, '\n')) {
448 /*
449 * The check item list ended with a comma.
450 * That's bad.
451 */
452 if (comma) {
453 ERROR_MARKER(&sbuff, "Invalid comma ending the check item list");
454 goto fail_entry;
455 }
456
457 lineno++;
458 goto setup_reply;
459 }
460
461 /*
462 * We didn't see SPACE LF or SPACE COMMENT LF.
463 * There's something else going on.
464 */
465 if (fr_sbuff_adv_to_chr(&sbuff, SIZE_MAX, '\n') != NULL) {
466 ERROR_MARKER(&sbuff, "Unexpected text after check item");
467 goto fail_entry;
468 }
469
470 /*
471 * The next character is not LF, but we
472 * skipped to LF above. So, by process
473 * of elimination, we must be at EOF.
474 */
475 if (!fr_sbuff_is_char(&sbuff, '\n')) {
476 add_entry:
477 fr_dlist_insert_tail(&list->head, t);
478 break;
479 }
480
481setup_reply:
482 /*
483 * Setup the reply items.
484 */
485 lhs_rules.attr.list_def = request_attr_reply;
486
487 comma = false;
488
490
491 relative_map = NULL;
492
493reply_item:
494 /*
495 * Reply items start with spaces. If there's no
496 * spaces, then the current entry is done. Add
497 * it to the list, and go back to reading the
498 * user name or $INCLUDE.
499 */
500 if (fr_sbuff_adv_past_blank(&sbuff, SIZE_MAX, NULL) == 0) {
501 if (comma) {
502 ERROR("%s[%d]: Unexpected trailing comma in previous line", file, lineno);
503 goto fail_entry;
504 }
505
506 /*
507 * The line doesn't begin with spaces.
508 * The list of reply items MUST be
509 * finished. Go look for an entry name.
510 *
511 * Note that we don't allow comments in
512 * the middle of the reply item list. Oh
513 * well.
514 */
515 fr_dlist_insert_tail(&list->head, t);
516 continue;
517
518 } else if (lineno == (t->lineno + 1)) {
519 fr_assert(comma == false);
520
521 } else if (!comma) {
522 ERROR("%s[%d]: Missing comma in previous line", file, lineno);
523 goto fail_entry;
524 }
525
526 /*
527 * SPACES COMMENT or SPACES LF means "end of
528 * reply item list"
529 */
530 if (fr_sbuff_is_char(&sbuff, '#')) {
531 (void) fr_sbuff_adv_to_chr(&sbuff, SIZE_MAX, '\n');
532 }
533 if (fr_sbuff_next_if_char(&sbuff, '\n')) {
534 lineno++;
535 goto add_entry;
536 }
537
538next_reply_item:
539 /*
540 * Unlike check items, we don't skip spaces or
541 * comments here. All of the code paths which
542 * lead to here have already checked for those
543 * cases.
544 */
545 slen = map_afrom_substr(t, &new_map, &relative_map, &sbuff, map_assignment_op_table, map_assignment_op_table_len,
546 &lhs_rules, &rhs_rules, &rhs_term);
547 if (!new_map) {
548 ERROR_MARKER_ADJ(&sbuff, slen, fr_strerror());
549 goto fail_entry;
550 }
551
552 fr_assert(new_map->lhs != NULL);
553
554 if (!tmpl_is_attr(new_map->lhs)) {
555 ERROR("%s[%d]: Unknown attribute '%s'",
556 file, lineno, new_map->lhs->name);
557 goto fail_entry;
558 }
559
560 /*
561 * We no longer really care what the RHS is, or what the list is on the LHS. The caller
562 * takes care of checking that for us.
563 */
564
565 if (!new_map->parent) map_list_insert_tail(&t->reply, new_map);
566
567 (void) fr_sbuff_adv_past_blank(&sbuff, SIZE_MAX, NULL);
568
569 /*
570 * Commas separate entries on the same line. And
571 * we allow spaces after commas, too.
572 */
573 if (fr_sbuff_next_if_char(&sbuff, ',')) {
574 comma = true;
575 (void) fr_sbuff_adv_past_blank(&sbuff, SIZE_MAX, NULL);
576 } else {
577 comma = false;
578 }
579
580 /*
581 * Comments or LF will end this particular line.
582 *
583 * Reading the next line will cause a complaint
584 * if this line ended with a comma.
585 */
586 if (fr_sbuff_next_if_char(&sbuff, '#')) {
587 (void) fr_sbuff_adv_to_chr(&sbuff, SIZE_MAX, '\n');
588 }
589
590 if (fr_sbuff_next_if_char(&sbuff, '\n')) {
591 lineno++;
592 goto reply_item;
593 }
594
595 /*
596 * Not comment or LF, the content MUST be another
597 * pair.
598 */
599 if (comma) goto next_reply_item;
600
601 ERROR_MARKER(&sbuff, "Unexpected text after reply");
602 goto fail_entry;
603 }
604
605 /*
606 * Else we were looking for an entry. We didn't get one
607 * because we were at EOF, so that's OK.
608 */
609
610 fclose(fp);
611
612 return 0;
613}
static int const char char buffer[256]
Definition acutest.h:641
int const char * file
Definition acutest.h:855
#define RCSID(id)
Definition build.h:603
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:245
#define NUM_ELEMENTS(_t)
Definition build.h:437
fr_dict_t * dict
Definition common.c:31
#define MEM(x)
Definition debug.h:38
#define ERROR(fmt,...)
Definition dhcpclient.c:40
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:360
talloc_free(hp)
#define LOG_DST
Definition network.c:29
fr_table_num_sorted_t const map_assignment_op_table[]
Definition map.c:394
ssize_t map_afrom_substr(TALLOC_CTX *ctx, map_t **out, map_t **parent_p, fr_sbuff_t *in, fr_table_num_sorted_t const *op_table, size_t op_table_len, tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules, fr_sbuff_parse_rules_t const *p_rules)
Parse sbuff into (which may contain refs) to map_t.
Definition map.c:492
size_t map_assignment_op_table_len
Definition map.c:410
void fr_log_marker(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *str, size_t str_len, ssize_t marker_idx, char const *marker, char const *line_prefix_fmt,...)
Print out an error marker.
Definition log.c:827
@ L_ERR
Error message.
Definition log.h:53
long int ssize_t
#define fr_assert(_expr)
Definition rad_assert.h:37
#define DEBUG2(fmt,...)
fr_dict_attr_t const * request_attr_request
Definition request.c:43
fr_dict_attr_t const * request_attr_control
Definition request.c:45
fr_dict_attr_t const * request_attr_reply
Definition request.c:44
static char const * name
char * fr_sbuff_adv_to_chr(fr_sbuff_t *sbuff, size_t len, char c)
Wind position to first instance of specified char.
Definition sbuff.c:2115
size_t fr_sbuff_adv_until(fr_sbuff_t *sbuff, size_t len, fr_sbuff_term_t const *tt, char escape_chr)
Wind position until we hit a character in the terminal set.
Definition sbuff.c:2011
bool fr_sbuff_next_if_char(fr_sbuff_t *sbuff, char c)
Return true if the current char matches, and if it does, advance.
Definition sbuff.c:2247
#define fr_sbuff_start(_sbuff_or_marker)
#define fr_sbuff_set(_dst, _src)
#define fr_sbuff_current(_sbuff_or_marker)
#define fr_sbuff_char(_sbuff_or_marker, _eob)
#define FR_SBUFF_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
Definition sbuff.h:191
#define fr_sbuff_is_char(_sbuff_or_marker, _c)
#define fr_sbuff_end(_sbuff_or_marker)
#define fr_sbuff_adv_past_blank(_sbuff, _len, _tt)
#define fr_sbuff_advance(_sbuff_or_marker, _len)
#define fr_sbuff_used(_sbuff_or_marker)
Set of terminal elements.
File sbuff extension structure.
Definition sbuff.h:149
Set of parsing rules for *unescape_until functions.
void tmpl_attr_set_list(tmpl_t *vpt, fr_dict_attr_t const *list)
#define tmpl_contains_regex(vpt)
Definition tmpl.h:233
#define tmpl_is_attr(vpt)
Definition tmpl.h:215
@ TMPL_ATTR_LIST_ALLOW
Attribute refs are allowed to have a list.
Definition tmpl.h:269
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition tmpl.h:346
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
Definition tmpl.h:824
struct tmpl_rules_s tmpl_rules_t
Definition tmpl.h:240
#define tmpl_is_regex_uncompiled(vpt)
Definition tmpl.h:221
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:343
Value pair map.
Definition map.h:77
tmpl_t * lhs
Typically describes the attribute to add, modify or compare.
Definition map.h:78
map_t * parent
Definition map.h:88
tmpl_t * rhs
Typically describes a literal value or a src attribute to copy or compare.
Definition map.h:79
fr_dict_attr_t const * list_def
Default list to use with unqualified attribute reference.
Definition tmpl.h:302
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Definition tmpl.h:280
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
An element in a lexicographically sorted array of name to num mappings.
Definition table.h:49
#define talloc_asprintf
Definition talloc.h:151
#define talloc_strdup(_ctx, _str)
Definition talloc.h:149
@ T_OP_CMP_TRUE
Definition token.h:102
@ T_OP_EQ
Definition token.h:81
@ T_OP_SET
Definition token.h:82
@ T_OP_NE
Definition token.h:95
@ T_OP_ADD_EQ
Definition token.h:67
@ T_OP_CMP_FALSE
Definition token.h:103
@ T_OP_REG_EQ
Definition token.h:100
@ T_OP_CMP_EQ
Definition token.h:104
@ T_OP_LE
Definition token.h:98
@ T_OP_GE
Definition token.h:96
@ T_OP_GT
Definition token.h:97
@ T_OP_LT
Definition token.h:99
@ T_OP_REG_NE
Definition token.h:101
static size_t check_cmp_op_table_len
Definition users_file.c:106
#define ERROR_MARKER_ADJ(_sbuff, _idx, _error)
Print out a line oriented error marker relative to the current position of the sbuff.
Definition users_file.c:89
static void line_error_marker_adj(char const *src_file, int src_line, char const *user_file, int user_line, fr_sbuff_t *sbuff, ssize_t marker_idx, char const *error)
Definition users_file.c:66
#define ERROR_MARKER(_sbuff, _error)
Print out a line oriented error marker at the current position of the sbuff.
Definition users_file.c:64
static int pairlist_read_internal(TALLOC_CTX *ctx, fr_dict_t const *dict, char const *file, PAIR_LIST_LIST *list, bool complain, bool v3_compat, int *order)
Definition users_file.c:245
static fr_table_num_sorted_t const check_cmp_op_table[]
Definition users_file.c:91
static int users_include(TALLOC_CTX *ctx, fr_dict_t const *dict, fr_sbuff_t *sbuff, PAIR_LIST_LIST *list, char const *file, int lineno, bool v3_compat, int *order)
Definition users_file.c:142
static fr_sbuff_parse_rules_t const rhs_term
Definition users_file.c:115
static const fr_sbuff_term_t name_terms
Definition users_file.c:108
static void line_error_marker(char const *src_file, int src_line, char const *user_file, int user_line, fr_sbuff_t *sbuff, char const *error)
Definition users_file.c:42
int pairlist_read(TALLOC_CTX *ctx, fr_dict_t const *dict, char const *file, PAIR_LIST_LIST *list, bool v3_compat)
Definition users_file.c:235
char const * name
Key for matching entry.
Definition users_file.h:39
fr_dlist_head_t head
Head of the list of PAIR_LISTs.
Definition users_file.h:51
char const * filename
Filename entry read from.
Definition users_file.h:45
int lineno
Line number entry read from.
Definition users_file.h:46
int order
Sequence of entry in source file.
Definition users_file.h:42
map_list_t check
List of maps for comparison / modifying control list.
Definition users_file.h:40
map_list_t reply
List of maps for modifying reply list.
Definition users_file.h:41
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:558
static fr_sbuff_err_t char size_t * len
Definition value.h:1061
#define FR_VALUE_BOX_SAFE_FOR_ANY
Definition value.h:178