26RCSID(
"$Id: d35155c4045b3312790d0b8a3b8d8b75cb026b91 $")
30#include <freeradius-devel/io/test_point.h>
31#include <freeradius-devel/server/cf_parse.h>
32#include <freeradius-devel/server/cf_util.h>
33#include <freeradius-devel/server/command.h>
34#include <freeradius-devel/server/dependency.h>
35#include <freeradius-devel/server/dl_module.h>
36#include <freeradius-devel/server/log.h>
37#include <freeradius-devel/server/map.h>
38#include <freeradius-devel/server/tmpl.h>
40# include <freeradius-devel/tls/base.h>
42#include <freeradius-devel/unlang/base.h>
43#include <freeradius-devel/unlang/xlat.h>
44#include <freeradius-devel/unlang/xlat_func.h>
45#include <freeradius-devel/util/atexit.h>
46#include <freeradius-devel/util/base64.h>
47#include <freeradius-devel/util/calc.h>
48#include <freeradius-devel/util/conf.h>
49#include <freeradius-devel/util/dict.h>
50#include <freeradius-devel/util/dns.h>
51#include <freeradius-devel/util/file.h>
52#include <freeradius-devel/util/log.h>
53#include <freeradius-devel/util/skip.h>
54#include <freeradius-devel/util/pair_legacy.h>
55#include <freeradius-devel/util/sha1.h>
56#include <freeradius-devel/util/syserror.h>
58#include <freeradius-devel/util/dict_priv.h>
63# undef HAVE_SANITIZER_LSAN_INTERFACE_H
65#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
66# include <sanitizer/asan_interface.h>
81#ifndef HAVE_SANITIZER_LSAN_INTERFACE_H
82# define ASAN_POISON_MEMORY_REGION(_start, _end)
83# define ASAN_UNPOISON_MEMORY_REGION(_start, _end)
86#define EXIT_WITH_FAILURE \
92#define COMMAND_OUTPUT_MAX 8192
94#define RETURN_OK(_len) \
96 result->rcode = RESULT_OK; \
97 result->file = __FILE__; \
98 result->line = __LINE__; \
102#define RETURN_OK_WITH_ERROR() \
104 result->rcode = RESULT_OK; \
105 result->file = __FILE__; \
106 result->line = __LINE__; \
107 result->error_to_data = true; \
111#define RETURN_NOOP(_len) \
113 result->rcode = RESULT_NOOP; \
114 result->file = __FILE__; \
115 result->line = __LINE__; \
119#define RETURN_SKIP_FILE() \
121 result->rcode = RESULT_SKIP_FILE; \
122 result->file = __FILE__; \
123 result->line = __LINE__; \
127#define RETURN_PARSE_ERROR(_offset) \
129 result->rcode = RESULT_PARSE_ERROR; \
130 result->offset = _offset; \
131 result->file = __FILE__; \
132 result->line = __LINE__; \
136#define RETURN_COMMAND_ERROR() \
138 result->rcode = RESULT_COMMAND_ERROR; \
139 result->file = __FILE__; \
140 result->line = __LINE__; \
144#define RETURN_MISMATCH(_len) \
146 result->rcode = RESULT_MISMATCH; \
147 result->file = __FILE__; \
148 result->line = __LINE__; \
152#define RETURN_EXIT(_ret) \
154 result->rcode = RESULT_EXIT; \
155 result->ret = _ret; \
156 result->file = __FILE__; \
157 result->line = __LINE__; \
164#define DEFAULT_BUFFER_SIZE 1024
253 size_t data_used,
char *
in,
size_t inlen);
296#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
297# define BUFF_POISON_START 1024
298# define BUFF_POISON_END 1024
313# define BUFF_POISON_START 0
314# define BUFF_POISON_END 0
340 if (!our_buff)
return -1;
342#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
343 talloc_set_destructor(our_buff, _free_buffer);
356#define POISONED_BUFFER_START(_p) ((_p) + BUFF_POISON_START)
357#define POISONED_BUFFER_END(_p) ((_p) + BUFF_POISON_START + (talloc_array_length(_p) - (BUFF_POISON_START + BUFF_POISON_END)))
360 char *expected,
size_t expected_len,
char *got,
size_t got_len,
368 ERROR(
" got : %.*s", (
int) got_len, got);
369 ERROR(
" expected : %.*s", (
int) expected_len, expected);
374 while (*g && *e && (*g == *e)) {
379 if (expected_len < 100) {
382 ERROR(
" EXPECTED : %.*s", (
int) expected_len, expected);
383 ERROR(
" GOT : %.*s", (
int) got_len, got);
384 ERROR(
" %.*s^ differs here (%zu)", (
int) (e - expected),
spaces, e - expected);
386 ERROR(
" EXPECTED : %.*s", (
int) expected_len, expected);
387 ERROR(
" GOT : %.*s", (
int) got_len, got);
388 ERROR(
"Differs at : %zu", e - expected);
394 if (elen > 70) elen = 70;
396 if (glen > 70) glen = 70;
398 ERROR(
"(%zu) ... %.*s ... ", e - expected, (
int) elen, e);
399 ERROR(
"(%zu) ... %.*s ... ", e - expected, (
int) glen, g);
410 char *end = p + outlen;
418 for (i = 0; i <
inlen; i++) {
436 char *end =
out + outlen;
472 file_fd = openat(fd_dir, digest_str, O_RDWR | O_CREAT | O_TRUNC,
473 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
480 if (flock(file_fd, LOCK_EX) < 0) {
490 ret = write(file_fd,
data, data_len);
494 (void)flock(file_fd, LOCK_UN);
495 unlinkat(fd_dir, digest_str, 0);
502 (void)flock(file_fd, LOCK_UN);
515static char const hextab[] =
"0123456789abcdef";
524 while (*p && (outlen > 0)) {
530 *(output++) = *(p++);
558 ERROR(
"String is not terminated");
568 for (p =
buffer; *p !=
'\0'; p++) {
569 if (*p ==
'{')
depth++;
572 if (
depth == 0)
break;
577 ERROR(
"No trailing '}' in string starting with \"%s\"",
buffer);
588 if (slen <= 0)
return 0;
597 uint8_t *out_p =
out, *out_end = out_p + outlen;
602 if (out_p >= out_end) {
619 if (!c2)
goto bad_input;
633 ERROR(
"Invalid character following attribute definition");
657 if (sublen <= 0)
return 0;
673 slen =
hex_to_bin(output, outlen, p, strlen(p));
686 attr = strtol(
buffer, endptr, 10);
688 ERROR(
"No valid number found in string starting with \"%s\"",
buffer);
693 ERROR(
"Nothing follows attribute number");
697 if ((attr <= 0) || (attr > 256)) {
698 ERROR(
"Attribute number is out of valid range");
710 ERROR(
"Invalid separator before vendor id");
714 vendor = strtol(
buffer + 1, endptr, 10);
715 if (*endptr == (
buffer + 1)) {
716 ERROR(
"No valid vendor number found");
721 ERROR(
"Nothing follows vendor number");
725 if ((vendor <= 0) || (vendor > (1 << 24))) {
726 ERROR(
"Vendor number is out of valid range");
730 if (**endptr !=
'.') {
731 ERROR(
"Invalid data following vendor number");
746 if (attr == 0)
return 0;
759 if (slen <= 0)
return slen;
760 if (slen > (255 - 2)) {
761 ERROR(
"TLV data is too long");
777 if (vendor == 0)
return 0;
780 output[1] = (vendor >> 16) & 0xff;
781 output[2] = (vendor >> 8) & 0xff;
782 output[3] = vendor & 0xff;
785 if (slen <= 0)
return slen;
786 if (slen > (255 - 6)) {
787 ERROR(
"VSA data is too long");
802 if (vendor == 0)
return 0;
805 if (attr == 0)
return 0;
808 output[1] = (vendor >> 16) & 0xff;
809 output[2] = (vendor >> 8) & 0xff;
810 output[3] = vendor & 0xff;
814 if (slen <= 0)
return slen;
826 if (attr == 0)
return 0;
835 if (slen <= 0)
return slen;
836 if (slen > (255 - 3)) {
837 ERROR(
"Extended Attr data is too long");
851 if (attr == 0)
return 0;
860 if (slen <= 0)
return slen;
867 if (slen <= 0)
return slen;
871 int sublen = 255 - output[1];
873 if (slen <= sublen) {
881 memmove(output + 255 + 4, output + 255, slen);
882 memcpy(output + 255, output, 4);
902 if (attr == 0)
return 0;
909 sublen =
encode_vsa(p, output + 2, outlen - 2);
911 }
else if ((attr < 241) || (attr > 246)) {
916 ERROR(
"Invalid data following attribute number");
929 if (sublen <= 0)
return sublen;
930 if (sublen > (255 -2)) {
931 ERROR(
"RFC Data is too long");
936 return slen + sublen;
956 snprintf(dl_name,
sizeof(dl_name),
"libfreeradius-%s", proto_name);
957 if (
dl) TALLOC_FREE(
dl);
961 fr_perror(
"Failed to link to library \"%s\"", dl_name);
970 return strlen(proto_name);
980 fr_strerror_printf(
"No protocol library loaded. Specify library with \"load <proto name>\"");
989 if ((*p ==
'.') && (q = strchr(p,
' ')) && (q != (p + 1)) && ((
size_t)(q - p) <
sizeof(
buffer))) {
1003 *symbol = dl_symbol;
1031 if (
in[0] ==
'\0') {
1043 q = strchr(
in,
' ');
1050 dir = default_subdir;
1166 printf(
"%s ", info->
parents[i]);
1169 printf(
":%s ", info->
name);
1178 void *walk_ctx = NULL;
1180 printf(
"Command hierarchy --------");
1183 printf(
"Command list --------");
1189#define CLEAR_TEST_POINT(_cc) \
1191 talloc_free_children((_cc)->tmp_ctx); \
1211 bool exit_now =
false;
1215 fprintf(stderr,
"Can't do $INCLUDE with -w %s\n",
write_filename);
1219 q = strrchr(cc->
path,
'/');
1252#define ATTR_COMMON \
1253 fr_sbuff_t our_in = FR_SBUFF_IN(in, inlen); \
1254 fr_dict_attr_err_t err; \
1256 fr_dict_attr_t const *root; \
1257 fr_dict_attr_t const *da; \
1258 root = cc->tmpl_rules.attr.dict_def ? \
1259 fr_dict_root(cc->tmpl_rules.attr.dict_def) : \
1260 fr_dict_root(fr_dict_internal()); \
1261 slen = fr_dict_attr_by_oid_substr(&err, \
1265 if (err != FR_DICT_ATTR_OK) FR_SBUFF_ERROR_RETURN(&our_in)
1280 namespace = dict_attr_namespace(da);
1286 if (da->flags.is_alias) {
1389 char const *p, *
value, *end;
1400 if (match_len == 0)
return 0;
1423 if (match_len == 0)
return 0;
1474 char const *p, *
value, *end;
1499 if (match_len == 0)
return 0;
1501 fr_value_box_list_insert_tail(&group->vb_group, a);
1505 if (strncmp(p,
"->", 2) == 0)
break;
1538 char const *p, *
value, *end;
1548 if (match_len == 0)
return 0;
1585 TALLOC_FREE(cc->
path);
1645 table->
syntax = talloc_strdup(table, p);
1682 memcpy(&argv, &info.
argv,
sizeof(argv));
1684 if (info.
argc <= 0) {
1691 len =
snprintf(p, end - p,
"%d - ", num_expansions);
1699 for (i = 0; i < num_expansions; i++) {
1700 len =
snprintf(p, end - p,
"'%s', ", expansions[i]);
1708 if (num_expansions > 0) {
1750 if ((
size_t) slen <
inlen) {
1770 fr_strerror_const(
"Command count would overflow data buffer (shouldn't happen)");
1778 char *
data,
size_t data_used,
char *
in,
size_t inlen)
1781 void *decode_ctx = NULL;
1833 to_dec_end = to_dec + slen;
1841 while (to_dec < to_dec_end) {
1843 (
uint8_t *)to_dec, (to_dec_end - to_dec), decode_ctx);
1850 if ((
size_t)slen > (
size_t)(to_dec_end - to_dec)) {
1851 fr_perror(
"%s: Internal sanity check failed at %d", __FUNCTION__, __LINE__);
1879 char *
data,
size_t data_used,
char *
in,
size_t inlen)
1882 void *decode_ctx = NULL;
1934 to_dec_end = to_dec + slen;
1939 (
uint8_t *)to_dec, (to_dec_end - to_dec), decode_ctx);
2009 next = strchr(p,
',');
2010 if (next) *next = 0;
2012 enc_p = cc->buffer_start;
2027 cc->buffer_start, cc->buffer_end - cc->buffer_start, enc_p,
true, box, NULL);
2042 next = strchr(p,
',');
2043 if (next) *next = 0;
2046 if ((cc->fuzzer_dir >= 0) &&
2047 (
dump_fuzzer_data(cc->fuzzer_dir,
in, cc->buffer_start, enc_p - cc->buffer_start) < 0)) {
2057 ssize_t slen, total, i, outlen;
2070 for (i = 0; i < total; i += slen) {
2081 if (i > 0) *(
out++) =
',';
2087 if (outlen <= 0)
goto error;
2110 bool truncate =
false;
2112 size_t iterations = 0;
2137 if (strncmp(p,
"truncate",
sizeof(
"truncate") - 1) == 0) {
2139 p +=
sizeof(
"truncate") - 1;
2175#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
2182 DEBUG(
"%s[%d]: Iteration %zu - Safe region %p-%p (%zu bytes), "
2183 "poisoned region %p-%p (%zu bytes)", cc->
filename, cc->
lineno, iterations - 1,
2186 DEBUG(
"%s[%d]: Iteration %zu - Allowed region %p-%p (%zu bytes)",
2187 cc->
filename, cc->
lineno, iterations - 1, enc_p, enc_end, enc_end - enc_p);
2199 if (truncate)
DEBUG(
"%s[%d]: Iteration %zu - Result %zd%s%s",
2203 if (slen < 0)
break;
2208 if (slen > (enc_end - enc_p)) {
2210 (enc_end - enc_p), (
size_t)slen);
2211#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
2221 if (slen == 0)
break;
2225#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
2237 }
while (truncate && (enc_end < cc->buffer_end));
2299 filename = talloc_asprintf(cc->
tmp_ctx,
"%s/%s", cc->
path,
in);
2301 fp = fopen(filename,
"r");
2433 bool retry_dir =
true;
2443 if (
in[0] ==
'\0') {
2448 fuzzer_dir = talloc_asprintf(cc->
tmp_ctx,
"%s/%s",
2452 fd = open(fuzzer_dir, O_RDONLY);
2454 if (mkdir(fuzzer_dir, 0777) == 0) {
2455 fd = open(fuzzer_dir, O_RDONLY);
2456 if (fd >= 0)
goto stat;
2461 }
else if ((errno == EEXIST) && retry_dir) {
2471 if (fstat(fd, &sdir) < 0) {
2477 if (!(sdir.st_mode & S_IFDIR)) {
2502 char *
name, *tmp = NULL;
2509 if (
in[0] ==
'\0') {
2514 q = strchr(
in,
' ');
2544 char *
data,
size_t data_used,
char *
in,
size_t inlen)
2546 if (strcmp(
in,
data) != 0) {
2568 char *
data,
size_t data_used,
char *
in,
size_t inlen)
2574 slen = regex_compile(cc->
tmp_ctx, ®ex,
in,
inlen, NULL,
false,
true);
2577 ret = regex_exec(regex,
data, data_used, NULL);
2606 size = strtoul(
in, &end, 10);
2607 if ((size == ULONG_MAX) || *end || (size >= 65536)) {
2634 if (strncmp(p,
"xlat_new_functions",
sizeof(
"xlat_new_functions") - 1) == 0) {
2635 p +=
sizeof(
"xlat_new_functions") - 1;
2651 if ((strcmp(p,
"yes") == 0) || (strcmp(p,
"true") == 0) || (strcmp(p,
"1") == 0)) {
2654 }
else if ((strcmp(p,
"no") == 0) || (strcmp(p,
"false") == 0) || (strcmp(p,
"0") == 0)) {
2673 if (
in[0] ==
'\0') {
2675 "Use -f to print features");
2681 DEBUG(
"Skipping, missing feature \"%s\"",
in);
2692 char *
data,
size_t data_used,
char *
in,
size_t inlen)
2695 switch (result->
rcode) {
2700 ERROR(
"%s[%d]: %.*s: returned 'ok', where we expected 'result-mismatch'",
2740 .allow_compare = allow_compare,
2768 char *
data,
size_t data_used,
char *
in,
size_t inlen)
2774 char *
data,
size_t data_used,
char *
in,
size_t inlen)
2837 size_t input_len = strlen(
in), escaped_len;
2861 if (((
size_t) slen != input_len)) {
2923 &rules->
attr.namespace,
2950 &rules->
attr.request_def,
2976 static size_t tmpl_rule_func_table_len =
NUM_ELEMENTS(tmpl_rule_func_table);
3016 if (match_len == 0) {
3067 char fuzzer_buffer[1024];
3068 char *fuzzer_p = fuzzer_buffer, *fuzzer_end = fuzzer_p +
sizeof(fuzzer_buffer);
3072 strlcpy(fuzzer_p,
data, slen > fuzzer_end - fuzzer_p ? fuzzer_end - fuzzer_p : slen);
3075 (
uint8_t *)fuzzer_buffer, strlen(fuzzer_buffer)) < 0) {
3086 char *
data,
size_t data_used,
char *
in,
size_t inlen)
3090 bool locked =
false;
3094 fd = open(path, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
3100 if (locked) (void)flock(fd, LOCK_UN);
3106 if (flock(fd, LOCK_EX) < 0) {
3114 ret = write(fd,
data, data_used);
3122 (void)flock(fd, LOCK_UN);
3137 size_t input_len = strlen(
in), escaped_len;
3166 if (((
size_t) slen != input_len)) {
3183 size_t input_len = strlen(
in), escaped_len;
3201 if (((
size_t) dec_len != input_len)) {
3218 size_t input_len = strlen(
in), escaped_len;
3247 if (((
size_t) slen != input_len)) {
3253 DEBUG(
"Before purify --------------------------------------------------");
3263 DEBUG(
"After purify --------------------------------------------------");
3280 size_t input_len = strlen(
in), escaped_len;
3309 if (((
size_t) slen != input_len)) {
3315 DEBUG(
"Before purify --------------------------------------------------");
3325 DEBUG(
"After purify --------------------------------------------------");
3346 size_t input_len = strlen(
in);
3374 for (i = 0, p =
data; i < argc; i++) {
3390 .usage =
"#<string>",
3391 .description =
"A comment - not processed"
3395 .usage =
"$INCLUDE <relative_path>",
3396 .description =
"Execute a test file"
3400 .usage =
"allow-unresolved yes|no",
3401 .description =
"Allow or disallow unresolved attributes in xlats and references"
3405 .usage =
"attr.children",
3406 .description =
"Return the children of the named attribute",
3410 .usage =
"attr.flags",
3411 .description =
"Return the flags of the named attribute",
3415 .usage =
"attr.name",
3416 .description =
"Return the number of the named attribute",
3420 .func = command_attr_number,
3421 .usage =
"attr.number",
3422 .description =
"Return the number of the named attribute",
3427 .usage =
"attr.oid",
3428 .description =
"Return the OID of the named attribute",
3432 .func = command_attr_ref,
3433 .usage =
"attr.ref",
3434 .description =
"Return the reference (if any) of the named attribute",
3439 .usage =
"attr.type",
3440 .description =
"Return the data type of the named attribute",
3444 .usage =
"calc <type1> <value1> <operator> <type2> <value2> -> <output-type>",
3445 .description =
"Perform calculations on value boxes",
3449 .usage =
"calc_nary op <type1> <value1> <type2> <value2> ... -> <output-type>",
3450 .description =
"Perform calculations on value boxes",
3454 .usage =
"cast (type) <value> -> <output-type>",
3455 .description =
"Perform calculations on value boxes",
3459 .usage =
"cd <path>",
3460 .description =
"Change the directory for loading dictionaries and $INCLUDEs, writing the full path into the data buffer on success"
3465 .description =
"Explicitly zero out the contents of the data buffer"
3469 .usage =
"command add <string>",
3470 .description =
"Add a command to a radmin command tree"
3474 .usage =
"command tab <string>",
3475 .description =
"Test a tab completion against a radmin command tree"
3479 .usage =
"condition <string>",
3480 .description =
"Parse and reprint a condition, writing the normalised condition to the data buffer on success"
3485 .description =
"Write the number of executed tests to the data buffer. A test is any command that should return 'ok'"
3489 .usage =
"decode-dns-label (-|<hex_string>)",
3490 .description =
"Decode one or more DNS labels, writing the decoded strings to the data buffer.",
3494 .usage =
"decode-pair[.<testpoint_symbol>] (-|<hex_string>)",
3495 .description =
"Produce an attribute value pair from a binary value using a specified protocol decoder. Protocol must be loaded with \"load <protocol>\" first",
3499 .usage =
"decode-proto[.<testpoint_symbol>] (-|<hex string>)",
3500 .description =
"Decode a packet as attribute value pairs from a binary value using a specified protocol decoder. Protocol must be loaded with \"load <protocol>\" first",
3504 .usage =
"dictionary <string>",
3505 .description =
"Parse dictionary attribute definition, writing \"ok\" to the data buffer if successful",
3509 .usage =
"dictionary-dump",
3510 .description =
"Print the contents of the currently active dictionary to stdout",
3514 .usage =
"encode-dns-label (-|string[,string])",
3515 .description =
"Encode one or more DNS labels, writing a hex string to the data buffer.",
3519 .usage =
"encode-pair[.<testpoint_symbol>] [truncate] (-|<attribute> = <value>[,<attribute = <value>])",
3520 .description =
"Encode one or more attribute value pairs, writing a hex string to the data buffer. Protocol must be loaded with \"load <protocol>\" first",
3524 .usage =
"encode-proto[.<testpoint_symbol>] (-|<attribute> = <value>[,<attribute = <value>])",
3525 .description =
"Encode one or more attributes as a packet, writing a hex string to the data buffer. Protocol must be loaded with \"proto <protocol>\" first"
3530 .description =
"Mark the end of a 'virtual' file. Used to prevent 'need-feature' skipping all the content of a command stream or file",
3534 .usage =
"exit[ <num>]",
3535 .description =
"Exit with the specified error number. If no <num> is provided, process will exit with 0"
3539 .usage =
"fuzzer-out <dir>",
3540 .description =
"Write encode-pair, encode-proto, and encode-dns-label output, and value input as separate files in the specified directory. Text input will be sha1 hashed and base64 encoded to create the filename",
3544 .usage =
"load-dictionary <name> [<dir>]",
3545 .description =
"Load an additional dictionary from the same directory as the input file. "
3546 "Optionally you can specify a full path via <dir>. ",
3550 .usage =
"match <string>",
3551 .description =
"Compare the contents of the data buffer with an expected value"
3555 .usage =
"match-regex <regex>",
3556 .description =
"Compare the contents of the data buffer with a regular expression"
3560 .usage =
"max-buffer-size[ <integer>]",
3561 .description =
"Limit the maximum temporary buffer space available for any command which uses it"
3565 .usage =
"migrate <flag>=<value>",
3566 .description =
"Set migration flag"
3570 .usage =
"need-feature <feature>",
3571 .description =
"Skip the contents of the current file, or up to the next \"eof\" command if a particular feature is not available"
3576 .description =
"Negate the result of a command returning 'ok'"
3580 .usage =
"pair ... data ...",
3581 .description =
"Parse a list of pairs",
3585 .usage =
"pair-compare ... data ...",
3586 .description =
"Parse a list of pairs, allowing comparison operators",
3590 .usage =
"proto <protocol>",
3591 .description =
"Switch the active protocol to the one specified, unloading the previous protocol",
3595 .usage =
"proto-dictionary <proto_name> [<proto_dir>]",
3596 .description =
"Switch the active dictionary. Root is set to the default dictionary path, or the one specified with -d. <proto_dir> is relative to the root.",
3602 .usage =
"proto-dictionary-root[ <root_attribute>]",
3603 .description =
"Set the root attribute for the current protocol dictionary. "
3604 "If no attribute name is provided, the root will be reset to the root of the current dictionary",
3608 .usage =
"raw <string>",
3609 .description =
"Create nested attributes from OID strings and values"
3613 .usage =
"read_file <filename>",
3614 .description =
"Read a list of pairs from a file",
3618 .usage =
"returned",
3619 .description =
"Print the returned value to the data buffer"
3624 .usage =
"parse <string>",
3625 .description =
"Parse then print a tmpl expansion, writing the normalised tmpl expansion to the data buffer"
3630 .usage =
"tmpl-rule [allow_foreign=yes] [allow_unknown=yes|no] [allow_unresolved=yes|no] [attr_parent=<oid>] [list_def=request|reply|control|session-state] [request_def=current|outer|parent]",
3631 .description =
"Alter the tmpl parsing rules for subsequent tmpl parsing commands in the same command context"
3635 .usage =
"touch <file>",
3636 .description =
"Touch a file, updating its created timestamp. Useful for marking the completion of a series of tests"
3640 .usage =
"value <type> <string>",
3641 .description =
"Parse a value of a given type from its presentation form, print it, then parse it again (checking printed/parsed versions match), writing printed form to the data buffer"
3645 .usage =
"write <file>",
3646 .description =
"Write the contents of the data buffer (as a raw binary string) to the specified file"
3650 .usage =
"xlat <string>",
3651 .description =
"Parse then print an xlat expansion, writing the normalised xlat expansion to the data buffer"
3656 .usage =
"xlat_argv <string>",
3657 .description =
"Parse then print an xlat expansion argv, writing the normalised xlat expansion arguments to the data buffer"
3662 .usage =
"xlat_expr <string>",
3663 .description =
"Parse then print an xlat expression, writing the normalised xlat expansion to the data buffer"
3668 .usage =
"xlat_purify <string>",
3669 .description =
"Parse, purify, then print an xlat expression, writing the normalised xlat expansion to the data buffer"
3674 .usage =
"xlat_purify_cond <string>",
3675 .description =
"Parse, purify, then print an xlat condition, writing the normalised xlat expansion to the data buffer"
3695 if (!*p || (*p ==
'#')) {
3724 if ((p[0] ==
'-') && ((p[1] ==
' ') || (p[1] ==
'\0'))) {
3725 data_used = command->
func(result, cc,
data, data_used,
data, data_used);
3728 data_used = command->
func(result, cc,
data, data_used, p, strlen(p));
3741 data[data_used] =
'\0';
3759 talloc_free_children(cc->
tmp_ctx);
3789 cc->
tmp_ctx = talloc_named_const(ctx, 0,
"tmp_ctx");
3790 cc->
path = talloc_strdup(cc, path);
3814 fr_perror(
"Failed allocating test dict_gctx");
3820 fr_perror(
"Failed loading test dict_gctx internal dictionary");
3839 cc->
tmp_ctx = talloc_named_const(ctx, 0,
"tmp_ctx");
3850 fr_perror(
"Failed loading test dict_gctx internal dictionary");
3867 static char path[PATH_MAX] =
"";
3869 bool opened_fp =
false;
3878 if (strcmp(filename,
"-") == 0) {
3880 filename =
"<stdin>";
3884 if (root_dir && *root_dir) {
3885 snprintf(path,
sizeof(path),
"%s/%s", root_dir, filename);
3887 strlcpy(path, filename,
sizeof(path));
3890 fp = fopen(path,
"r");
3908 char *p = strchr(
buffer,
'\n');
3916 if (!lr)
goto finish;
3933 switch (result.
rcode) {
3953 if (fp != stdin)
goto finish;
4013 if (opened_fp) fclose(fp);
4032 INFO(
"usage: %s [options] (-|<filename>[:<lines>] [ <filename>[:<lines>]])",
name);
4034 INFO(
" -d <confdir> Set user dictionary path (defaults to " CONFDIR
").");
4035 INFO(
" -D <dictdir> Set main dictionary path (defaults to " DICTDIR
").");
4036 INFO(
" -x Debugging mode.");
4037 INFO(
" -f Print features.");
4038 INFO(
" -c Print commands.");
4039 INFO(
" -h Print help text.");
4040 INFO(
" -M Show talloc memory report.");
4041 INFO(
" -p Allow xlat_purify");
4042 INFO(
" -r <receipt_file> Create the <receipt_file> as a 'success' exit.");
4043 INFO(
" -w <output_file> Write 'corrected' output to <output_file>.");
4044 INFO(
"Where <filename> is a file containing one or more commands and '-' indicates commands should be read from stdin.");
4045 INFO(
"Ranges of <lines> may be specified in the format <start>[-[<end>]][,]");
4074 static bool tokens[
UINT8_MAX + 1] = { [
','] = true , [
'-'] =
true };
4087 ERROR(
"Invalid line start number");
4092 if (max > lr->
start) {
4093 ERROR(
"Out of order line numbers (%u > %u) not allowed", max, lr->
start);
4103 if (!fr_sbuff_is_in_charset(
in, tokens)) {
4104 ERROR(
"Unexpected text \"%pV\"",
4131 lr->
end = UINT32_MAX;
4137 ERROR(
"Invalid line end number");
4141 ERROR(
"Line end must be >= line start (%u < %u)", lr->
end, lr->
start);
4144 if (max > lr->
end) {
4145 ERROR(
"Out of order line numbers (%u > %u) not allowed", max, lr->
end);
4161 char *p, *dir = NULL, *
file;
4162 int ret = EXIT_SUCCESS;
4171 fr_sbuff_marker(&file_start, &
in);
4172 fr_sbuff_marker(&file_end, &
in);
4173 fr_sbuff_marker(&dir_end, &
in);
4192 return EXIT_FAILURE;
4212 (strncmp(path,
"src/tests/unit/", 15) == 0)) {
4213 p = strchr(path + 15,
'/');
4215 printf(
"UNIT-TEST %s\n", path + 15);
4217 char *q = strchr(p + 1,
'/');
4222 printf(
"UNIT-TEST %s - %s\n", path + 15, p + 1);
4226 printf(
"UNIT-TEST %s - %s\n", p + 1, q + 1);
4241 return EXIT_FAILURE;
4247 if ((ret == EXIT_SUCCESS) &&
receipt_dir && dir) {
4248 char *touch_file, *subdir;
4250 if (strncmp(dir,
"src/", 4) == 0) {
4256 touch_file = talloc_asprintf(ctx,
"build/%s/%s", subdir,
file);
4259 p = strchr(touch_file,
'/');
4262 if (
fr_mkdir(NULL, touch_file, (
size_t) (p - touch_file), S_IRWXU, NULL, NULL) < 0) {
4263 fr_perror(
"unit_test_attribute - failed to make directory %.*s - ",
4264 (
int) (p - touch_file), touch_file);
4267 return EXIT_FAILURE;
4270 if (
fr_touch(NULL, touch_file, 0644,
true, 0755) <= 0) {
4271 fr_perror(
"unit_test_attribute - failed to create receipt file %s - ",
4283 if (ret != EXIT_SUCCESS) {
4295 return EXIT_FAILURE;
4310 int ret = EXIT_SUCCESS;
4312 TALLOC_CTX *thread_ctx;
4313 bool exit_now =
false;
4321 bool do_features =
false;
4322 bool do_commands =
false;
4323 bool do_usage =
false;
4326 char const *error_str = NULL, *fail_str = NULL;
4369 while ((c = getopt(argc, argv,
"cd:D:F:fxMhpr:S:w:")) != -1)
switch (c) {
4379 config.dict_dir = optarg;
4383 config.fuzzer_dir = optarg;
4396 talloc_enable_leak_report();
4400 p = strrchr(optarg,
'/');
4419 fprintf(stderr,
"Invalid option to -S\n");
4431 argc -= (optind - 1);
4432 argv += (optind - 1);
4437 if (do_usage || do_features || do_commands) {
4456 if (fr_openssl_init() < 0) {
4517 ERROR(
"Failed registering xlat");
4527 ERROR(
"Failed registering xlat");
4544 ERROR(
"Can only use '-w' with input files");
4550 }
else if ((argc == 2) && (strcmp(argv[1],
"-") == 0)) {
4556 while (fgets(
buffer,
sizeof(
buffer) - 1, stdin) != NULL) {
4560 while (isspace((
unsigned int) *p)) p++;
4562 if (!*p || (*p ==
'#'))
continue;
4582 if ((ret != EXIT_SUCCESS) || exit_now)
break;
4585 }
else if (argc > 1) {
4591 for (i = 1; i < argc; i++) {
4593 if ((ret != EXIT_SUCCESS) || exit_now)
break;
4602#undef EXIT_WITH_FAILURE
4603#define EXIT_WITH_FAILURE \
4605 ret = EXIT_FAILURE; \
4606 error_str = fr_strerror(); \
4607 if (error_str) error_str = talloc_strdup(NULL, error_str); \
4628 fail_str =
"cleaning up dynamically loaded libraries";
4633 fail_str =
"cleaning up dictionaries";
4638 fail_str =
"creating receipt file";
4647 fail_str =
"cleaning up all memory";
4651 if (ret != EXIT_SUCCESS) {
4653 if (!fail_str) fail_str =
"in an input file";
4654 if (!error_str) error_str =
"";
4656 fprintf(stderr,
"unit_test_attribute failed %s - %s\n", fail_str, error_str);
4661 p = getenv(
"UNIT_TEST_ATTRIBUTE");
static int const char char buffer[256]
strcpy(log_entry->msg, buffer)
int fr_atexit_global_setup(void)
Setup the atexit handler, should be called at the start of a program's execution.
int fr_atexit_global_trigger_all(void)
Cause all global free triggers to fire.
#define fr_atexit_thread_trigger_all(...)
char const fr_base64_url_alphabet_encode[SBUFF_CHAR_CLASS]
ssize_t fr_base64_encode_nstd(fr_sbuff_t *out, fr_dbuff_t *in, bool add_padding, char const alphabet[static SBUFF_CHAR_CLASS])
Base 64 encode binary data.
static TALLOC_CTX * autofree
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define L(_str)
Helper for initialising arrays of string literals.
int fr_value_calc_nary_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t type, fr_token_t op, fr_value_box_t const *group)
Calculate DST = OP { A, B, C, ... }.
int fr_value_calc_assignment_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_token_t op, fr_value_box_t const *src)
Calculate DST OP SRC.
int fr_value_calc_binary_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t hint, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b)
Calculate DST = A OP B.
Configuration AVP similar to a fr_pair_t.
A section grouping multiple CONF_PAIR.
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.
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
#define cf_lineno_set(_ci, _lineno)
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
#define cf_filename_set(_ci, _filename)
int fr_command_walk(fr_cmd_t *head, void **walk_ctx, void *ctx, fr_cmd_walk_t callback)
Walk over a command hierarchy.
void fr_cmd_debug(FILE *fp, fr_cmd_t *head)
int fr_command_add(TALLOC_CTX *talloc_ctx, fr_cmd_t **head, char const *name, void *ctx, fr_cmd_table_t const *table)
Add one command to the global command tree.
int fr_command_tab_expand(TALLOC_CTX *ctx, fr_cmd_t *head, fr_cmd_info_t *info, int max_expansions, char const **expansions)
Get the commands && help at a particular level.
char const * help
help text
int argc
current argument count
fr_cmd_func_t func
function to process this command
char const * syntax
e.g. "STRING"
fr_value_box_t ** box
value_box version of commands.
char const * parent
e.g. "show module"
fr_cmd_tab_t tab_expand
tab expand things in the syntax string
int max_argc
maximum number of arguments
char const * name
e.g. "stats"
char const ** argv
text version of commands
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
static void * fr_dcursor_current(fr_dcursor_t *cursor)
Return the item the cursor current points to.
void fr_disable_null_tracking_on_free(TALLOC_CTX *ctx)
Disable the null tracking context when a talloc chunk is freed.
int fr_fault_setup(TALLOC_CTX *ctx, char const *cmd, char const *program)
Registers signal handlers to execute panic_action on fatal signal.
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
void dependency_features_init(CONF_SECTION *cs)
Initialise core feature flags.
static NEVER_RETURNS void usage(void)
fr_dict_gctx_t * fr_dict_global_ctx_init(TALLOC_CTX *ctx, bool free_at_exit, char const *dict_dir)
Initialise the global protocol hashes.
int fr_dict_internal_afrom_file(fr_dict_t **out, char const *internal_name, char const *dependent)
(Re-)Initialize the special internal dictionary
int fr_dict_global_ctx_dir_set(char const *dict_dir)
Allow the default dict dir to be changed after initialisation.
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *attr))
Locate a fr_dict_attr_t by its name.
void fr_dict_debug(FILE *fp, fr_dict_t const *dict)
fr_slen_t fr_dict_attr_by_oid_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out, fr_dict_attr_t const *parent, fr_sbuff_t *in, fr_sbuff_term_t const *tt))
Resolve an attribute using an OID string.
int fr_dict_protocol_afrom_file(fr_dict_t **out, char const *proto_name, char const *proto_dir, char const *dependent)
(Re)-initialize a protocol dictionary
int fr_dict_str_to_argv(char *str, char **argv, int max_argc)
bool fr_dict_filename_loaded(fr_dict_t const *dict, char const *dict_dir, char const *filename)
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
void fr_dict_global_ctx_set(fr_dict_gctx_t const *gctx)
Set a new, active, global dictionary context.
int fr_dict_free(fr_dict_t **dict, char const *dependent)
Decrement the reference count on a previously loaded dictionary.
int fr_dict_const_free(fr_dict_t const **dict, char const *dependent)
Decrement the reference count on a previously loaded dictionary.
fr_dict_t const * fr_dict_internal(void)
int fr_dict_global_ctx_free(fr_dict_gctx_t const *gctx)
Explicitly free all data associated with a global dictionary context.
int fr_dict_parse_str(fr_dict_t *dict, char *buf, fr_dict_attr_t const *parent)
int fr_dict_read(fr_dict_t *dict, char const *dict_dir, char const *filename)
Read supplementary attribute definitions into an existing dictionary.
fr_dict_attr_err_t
Errors returned by attribute lookup functions.
@ FR_DICT_ATTR_OK
No error.
static fr_dict_attr_t const * fr_dict_attr_ref(fr_dict_attr_t const *da)
Return the reference associated with a group type attribute.
dl_loader_t * dl_loader_init(TALLOC_CTX *ctx, void *uctx, bool uctx_free, bool defer_symbol_init)
Initialise structures needed by the dynamic linker.
dl_t * dl_by_name(dl_loader_t *dl_loader, char const *name, void *uctx, bool uctx_free)
Search for a dl's shared object in various locations.
void * handle
Handle returned by dlopen.
#define fr_dlist_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
static void * fr_dlist_head(fr_dlist_head_t const *list_head)
Return the HEAD item of a list or NULL if the list is empty.
static void fr_dlist_talloc_free(fr_dlist_head_t *head)
Free all items in a doubly linked list (with talloc)
static bool fr_dlist_empty(fr_dlist_head_t const *list_head)
Check whether a list has any items.
static int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
static void * fr_dlist_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
Head of a doubly linked list.
Entry in a doubly linked list.
ssize_t fr_dns_label_from_value_box(size_t *need, uint8_t *buf, size_t buf_len, uint8_t *where, bool compression, fr_value_box_t const *value, fr_dns_labels_t *lb)
Encode a single value box of type string, serializing its contents to a dns label.
ssize_t fr_dns_label_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *dst, uint8_t const *src, size_t len, uint8_t const *label, bool tainted, fr_dns_labels_t *lb)
Decode a fr_value_box_t from one DNS label.
ssize_t fr_mkdir(int *fd_out, char const *path, ssize_t len, mode_t mode, fr_mkdir_func_t func, void *uctx)
Create directories that are missing in the specified path.
int fr_unlink(char const *filename)
Remove a regular file from the filesystem.
ssize_t fr_touch(int *fd_out, char const *filename, mode_t mode, bool mkdir, mode_t dir_mode)
Create an empty file.
char * fr_realpath(TALLOC_CTX *ctx, char const *path, ssize_t len)
Convenience wrapper around realpath.
void * fr_hash_table_iter_next(fr_hash_table_t *ht, fr_hash_iter_t *iter)
Iterate over entries in a hash table.
void * fr_hash_table_iter_init(fr_hash_table_t *ht, fr_hash_iter_t *iter)
Initialise an iterator.
Stores the state of the current iteration operation.
bool fr_hostname_lookups
hostname -> IP lookups?
bool fr_reverse_lookups
IP -> hostname lookups?
int unlang_global_init(void)
fr_event_list_t * fr_event_list_alloc(TALLOC_CTX *ctx, fr_event_status_cb_t status, void *status_uctx)
Initialise a new event list.
Stores all information relating to an event list.
@ L_DST_STDOUT
Log to stdout.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_MAX
Number of defined data types.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_GROUP
A grouping of other attributes.
ssize_t fr_dict_attr_flags_print(fr_sbuff_t *out, fr_dict_t const *dict, fr_type_t type, fr_dict_attr_flags_t const *flags)
ssize_t fr_dict_attr_oid_print(fr_sbuff_t *out, fr_dict_attr_t const *ancestor, fr_dict_attr_t const *da, bool numeric)
fr_slen_t tmpl_print(fr_sbuff_t *out, tmpl_t const *vpt, fr_sbuff_escape_rules_t const *e_rules)
@ FR_SBUFF_PARSE_OK
No error.
static uint8_t depth(fr_minmax_heap_index_t i)
static bool is_whitespace(char const *value)
Check whether the string is all whitespace.
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
fr_slen_t fr_pair_list_afrom_substr(fr_pair_parse_t const *root, fr_pair_parse_t *relative, fr_sbuff_t *in)
Parse a fr_pair_list_t from a substring.
int fr_pair_list_afrom_file(TALLOC_CTX *ctx, fr_dict_t const *dict, fr_pair_list_t *out, FILE *fp, bool *pfiledone, bool allow_exec)
Read valuepairs from the fp up to End-Of-File.
#define is_truncated(_ret, _max)
static const conf_parser_t config[]
void * fr_proto_next_encodable(fr_dcursor_t *cursor, void *current, void *uctx)
Implements the default iterator to encode pairs belonging to a specific dictionary that are not inter...
static fr_internal_encode_ctx_t encode_ctx
static const char * spaces
fr_dict_attr_t const * request_attr_request
int request_global_init(void)
ssize_t fr_sbuff_in_strcpy(fr_sbuff_t *sbuff, char const *str)
Copy bytes into the sbuff up to the first \0.
size_t fr_sbuff_trim(fr_sbuff_t *sbuff, bool const to_trim[static SBUFF_CHAR_CLASS])
Trim trailing characters from a string we're composing.
fr_slen_t fr_sbuff_out_bool(bool *out, fr_sbuff_t *in)
See if the string contains a truth value.
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.
ssize_t fr_sbuff_in_sprintf(fr_sbuff_t *sbuff, char const *fmt,...)
Print using a fmt string to an sbuff.
bool fr_sbuff_next_if_char(fr_sbuff_t *sbuff, char c)
Return true if the current char matches, and if it does, advance.
#define fr_sbuff_start(_sbuff_or_marker)
#define fr_sbuff_out_by_longest_prefix(_match_len, _out, _table, _sbuff, _def)
#define fr_sbuff_set(_dst, _src)
#define fr_sbuff_diff(_a, _b)
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_adv_past_whitespace(_sbuff, _len, _tt)
#define fr_sbuff_current(_sbuff_or_marker)
#define FR_SBUFF_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
#define fr_sbuff_extend(_sbuff_or_marker)
#define FR_SBUFF_ERROR_RETURN(_sbuff_or_marker)
#define fr_sbuff_end(_sbuff_or_marker)
#define fr_sbuff_advance(_sbuff_or_marker, _len)
#define fr_sbuff_out(_err, _out, _in)
#define fr_sbuff_switch(_sbuff_or_marker, _eob)
#define fr_sbuff_remaining(_sbuff_or_marker)
#define FR_SBUFF_OUT(_start, _len_or_end)
#define fr_sbuff_used(_sbuff_or_marker)
Set of terminal elements.
ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_token_t quote, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Convert an arbitrary string into a tmpl_t.
tmpl_xlat_rules_t xlat
Rules/data for parsing xlats.
bool new_functions
new function syntax
fr_slen_t tmpl_request_ref_list_afrom_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err, FR_DLIST_HEAD(tmpl_request_list) _CONST **out, fr_sbuff_t *in)
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
struct tmpl_rules_s tmpl_rules_t
fr_slen_t tmpl_attr_list_from_substr(fr_dict_attr_t const **da_p, fr_sbuff_t *in)
Parse one a single list reference.
fr_event_list_t * runtime_el
The eventlist to use for runtime instantiation of xlats.
Optional arguments passed to vp_tmpl functions.
void fr_sha1_init(fr_sha1_ctx *context)
void fr_sha1_final(uint8_t digest[static SHA1_DIGEST_LENGTH], fr_sha1_ctx *context)
void fr_sha1_update(fr_sha1_ctx *context, uint8_t const *in, size_t len)
#define SHA1_DIGEST_LENGTH
static char buff[sizeof("18446744073709551615")+3]
#define fr_skip_whitespace(_p)
Skip whitespace ('\t', '\n', '\v', '\f', '\r', ' ')
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
void modules_init(char const *lib_dir)
Perform global initialisation for modules.
fr_aka_sim_id_type_t type
size_t strlcpy(char *dst, char const *src, size_t siz)
fr_log_dst_t dst
Log destination.
int fd
File descriptor to write messages to.
bool print_level
sometimes we don't want log levels printed
unsigned int allow_unknown
Allow unknown attributes i.e.
fr_dict_attr_t const * list_def
Default list to use with unqualified attribute reference.
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
unsigned int allow_foreign
Allow arguments not found in dict_def.
unsigned int allow_unresolved
Allow attributes that look valid but were not found in the dictionaries.
Stores an attribute, a value and various bits of other data.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
#define fr_table_value_by_longest_prefix(_match_len, _table, _name, _name_len, _def)
Find the longest string match using a sorted or ordered table.
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
An element in a lexicographically sorted array of name to num mappings.
An element in a lexicographically sorted array of name to ptr mappings.
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
fr_tp_proto_decode_t func
Decoder for proto layer.
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
fr_dcursor_iter_t next_encodable
Iterator to use to select attributes to encode.
fr_tp_proto_encode_t func
Encoder for proto layer.
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
fr_pair_decode_t func
Decoder for pairs.
fr_pair_encode_t func
Encoder for pairs.
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
Entry point for pair decoders.
Entry point for pair encoders.
Entry point for protocol decoders.
Entry point for protocol encoders.
int fr_time_start(void)
Initialize the local time.
const bool fr_assignment_op[T_TOKEN_LAST]
fr_table_num_ordered_t const fr_tokens_table[]
static int command_func(UNUSED FILE *fp, UNUSED FILE *fp_err, UNUSED void *ctx, UNUSED fr_cmd_info_t const *info)
int fuzzer_dir
File descriptor pointing to a a directory to write fuzzer output.
#define POISONED_BUFFER_START(_p)
static size_t commands_len
static int dump_fuzzer_data(int fd_dir, char const *text, uint8_t const *data, size_t data_len)
static size_t command_touch(command_result_t *result, UNUSED command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Touch a file to indicate a test completed.
uint32_t start
Start of line range.
static ssize_t encode_data_string(char *buffer, uint8_t *output, size_t outlen)
static dl_loader_t * dl_loader
#define BUFF_POISON_START
static ssize_t encode_extended(char *buffer, uint8_t *output, size_t outlen)
int main(int argc, char *argv[])
static size_t command_decode_dns_label(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, size_t inlen)
static size_t command_decode_proto(command_result_t *result, command_file_ctx_t *cc, char *data, size_t data_used, char *in, size_t inlen)
static void unload_proto_library(void)
static size_t command_xlat_normalise(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Parse an reprint and xlat expansion.
static size_t parse_typed_value(command_result_t *result, command_file_ctx_t *cc, fr_value_box_t *box, char const **out, char const *in, size_t inlen)
uint32_t test_count
How many tests we've executed in this file.
static int decode_vendor(char *buffer, char **endptr)
static size_t command_xlat_purify_condition(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Parse, purify, and reprint an xlat expression expansion.
static size_t command_proto_dictionary(command_result_t *result, command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
static char const * fail_file
static void commands_print(void)
#define POISONED_BUFFER_END(_p)
static char proto_name_prev[128]
TALLOC_CTX * tmp_ctx
Temporary context to hold buffers in this.
static size_t hex_print(char *out, size_t outlen, uint8_t const *in, size_t inlen)
Print hex string to buffer.
static size_t command_exit(command_result_t *result, UNUSED command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Exit gracefully with the specified code.
static ssize_t hex_to_bin(uint8_t *out, size_t outlen, char *in, size_t inlen)
#define RETURN_OK_WITH_ERROR()
static size_t command_xlat_purify(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Parse, purify, and reprint an xlat expression expansion.
char const * filename
Current file we're operating on.
static void mismatch_print(command_file_ctx_t *cc, char const *command, char *expected, size_t expected_len, char *got, size_t got_len, bool print_diff)
static size_t command_tmpl(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Parse an reprint a tmpl expansion.
static size_t command_tmpl_rules(command_result_t *result, command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, char *in, size_t inlen)
static size_t command_fuzzer_out(command_result_t *result, command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Enable fuzzer output.
static ssize_t encode_rfc(char *buffer, uint8_t *output, size_t outlen)
static size_t command_attr_name(command_result_t *result, command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, char *in, size_t inlen)
Print attribute information.
static void command_ctx_reset(command_file_ctx_t *cc, TALLOC_CTX *ctx)
static int dictionary_load_common(command_result_t *result, command_file_ctx_t *cc, char const *in, char const *default_subdir)
Common dictionary load function.
static size_t command_include(command_result_t *result, command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Execute another test file.
static size_t command_proto_dictionary_root(command_result_t *result, command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
static ssize_t command_tmpl_rule_request_def(TALLOC_CTX *ctx, tmpl_rules_t *rules, fr_sbuff_t *value)
static ssize_t command_tmpl_rule_allow_unresolved(UNUSED TALLOC_CTX *ctx, tmpl_rules_t *rules, fr_sbuff_t *value)
uint32_t lineno
Current line number.
ssize_t last_ret
Last return value.
static size_t command_attr_children(command_result_t *result, command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, char *in, size_t inlen)
Print attribute information.
#define ASAN_POISON_MEMORY_REGION(_start, _end)
static size_t command_pair_compare(command_result_t *result, command_file_ctx_t *cc, char *data, size_t data_used, char *in, size_t inlen)
static void features_print(CONF_SECTION *features)
static size_t command_returned(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, UNUSED char *in, UNUSED size_t inlen)
static xlat_arg_parser_t const xlat_test_args[]
static int decode_attr(char *buffer, char **endptr)
static fr_dict_t * dictionary_current(command_file_ctx_t *cc)
static size_t command_encode_pair(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, size_t inlen)
fr_dlist_t entry
Entry in the dlist.
uint8_t * buffer_end
Where the non-poisoned region of the buffer ends.
static size_t command_attr_oid(command_result_t *result, command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, char *in, size_t inlen)
Print attribute information.
static fr_table_ptr_sorted_t commands[]
#define RETURN_NOOP(_len)
TALLOC_CTX * tmp_ctx
Talloc context for test points.
static size_t command_radmin_tab(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
static size_t command_calc_nary(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, size_t inlen)
Perform calculations on multi-valued ops.
static size_t command_dictionary_dump(command_result_t *result, command_file_ctx_t *cc, UNUSED char *data, size_t data_used, UNUSED char *in, UNUSED size_t inlen)
Print the currently loaded dictionary.
fr_dict_gctx_t const * test_gctx
Dictionary context for test dictionaries.
static size_t command_proto(command_result_t *result, command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Dynamically load a protocol library.
static fr_cmd_t * command_head
static size_t command_write(command_result_t *result, command_file_ctx_t *cc, char *data, size_t data_used, char *in, size_t inlen)
char * path
Current path we're operating in.
static int poisoned_buffer_allocate(TALLOC_CTX *ctx, uint8_t **buff, size_t size)
Allocate a special buffer with poisoned memory regions at the start and end.
#define DEFAULT_BUFFER_SIZE
Default buffer size for a command_file_ctx_t.
static char const * receipt_file
static size_t strerror_concat(char *out, size_t outlen)
Concatenate error stack.
static size_t command_match_regex(command_result_t *result, command_file_ctx_t *cc, char *data, size_t data_used, char *in, size_t inlen)
Compare the data buffer against an expected expression.
static size_t command_encode_raw(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Encode a RADIUS attribute writing the result to the data buffer as space separated hexits.
#define RETURN_PARSE_ERROR(_offset)
static ssize_t command_tmpl_rule_allow_unknown(UNUSED TALLOC_CTX *ctx, tmpl_rules_t *rules, fr_sbuff_t *value)
command_config_t const * config
static int _command_ctx_free(command_file_ctx_t *cc)
#define COMMAND_OUTPUT_MAX
static size_t command_allow_unresolved(command_result_t *result, command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, char *in, size_t inlen)
Determine if unresolved attributes are allowed.
static size_t command_read_file(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Parse a list of pairs.
static int process_file(bool *exit_now, TALLOC_CTX *ctx, command_config_t const *config, const char *root_dir, char const *filename, fr_dlist_head_t *lines)
static size_t command_cast(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, size_t inlen)
Perform casting.
static ssize_t encode_tlv(char *buffer, uint8_t *output, size_t outlen)
static int command_walk(UNUSED void *ctx, fr_cmd_walk_info_t *info)
static size_t command_condition_normalise(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, size_t inlen)
Parse and reprint a condition.
static size_t command_count(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, UNUSED char *in, UNUSED size_t inlen)
static fr_table_num_sorted_t command_rcode_table[]
static size_t command_max_buffer_size(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Artificially limit the maximum packet size.
static const fr_token_t token2op[UINT8_MAX+1]
tmpl_rules_t tmpl_rules
To pass to parsing functions.
size_t(* command_func_t)(command_result_t *result, command_file_ctx_t *cc, char *data, size_t data_used, char *in, size_t inlen)
Command to execute.
#define RETURN_MISMATCH(_len)
uint32_t end
End of line range.
static char const hextab[]
static command_file_ctx_t * command_ctx_alloc(TALLOC_CTX *ctx, command_config_t const *config, char const *path, char const *filename)
static size_t command_encode_proto(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, size_t inlen)
static size_t command_load_dictionary(command_result_t *result, command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
static ssize_t load_test_point_by_command(void **symbol, char *command, char const *dflt_symbol)
static void command_print(void)
static size_t command_pair_common(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, size_t inlen, bool allow_compare)
Parse an print an attribute pair or pair list.
#define RETURN_EXIT(_ret)
static fr_event_list_t * el
static char const * receipt_dir
static size_t command_decode_pair(command_result_t *result, command_file_ctx_t *cc, char *data, size_t data_used, char *in, size_t inlen)
static size_t command_xlat_expr(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Parse and reprint an xlat expression expansion.
char const * fuzzer_dir
Where to write fuzzer files.
#define EXIT_WITH_FAILURE
CONF_SECTION * features
Enabled features.
static size_t command_calc(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, size_t inlen)
Perform calculations.
static size_t command_migrate(command_result_t *result, command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Set or clear migration flags.
static size_t command_dictionary_attribute_parse(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Parse a dictionary attribute, writing "ok" to the data buffer is everything was ok.
static size_t command_xlat_argv(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Parse an reprint and xlat argv expansion.
#define CLEAR_TEST_POINT(_cc)
static int process_path(bool *exit_now, TALLOC_CTX *ctx, command_config_t const *config, const char *path)
static ssize_t encode_data(char *p, uint8_t *output, size_t outlen)
#define RETURN_COMMAND_ERROR()
static size_t command_eof(UNUSED command_result_t *result, UNUSED command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, UNUSED char *in, UNUSED size_t inlen)
Command eof.
static size_t command_match(command_result_t *result, command_file_ctx_t *cc, char *data, size_t data_used, char *in, size_t inlen)
Compare the data buffer to an expected value.
static size_t command_attr_type(command_result_t *result, command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, char *in, size_t inlen)
Print attribute information.
#define ASAN_UNPOISON_MEMORY_REGION(_start, _end)
#define RETURN_SKIP_FILE()
static ssize_t command_tmpl_rule_attr_parent(UNUSED TALLOC_CTX *ctx, tmpl_rules_t *rules, fr_sbuff_t *value)
fr_dict_gctx_t const * dict_gctx
Dictionary gctx to "reset" to.
static ssize_t command_tmpl_rule_list_def(UNUSED TALLOC_CTX *ctx, tmpl_rules_t *rules, fr_sbuff_t *value)
static ssize_t command_tmpl_rule_allow_foreign(UNUSED TALLOC_CTX *ctx, tmpl_rules_t *rules, fr_sbuff_t *value)
static size_t command_attr_flags(command_result_t *result, command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, char *in, size_t inlen)
Print attribute information.
static ssize_t encode_vsa(char *buffer, uint8_t *output, size_t outlen)
size_t process_line(command_result_t *result, command_file_ctx_t *cc, char *data, size_t data_used, char *in, size_t inlen)
static ssize_t load_proto_library(char const *proto_name)
@ RESULT_MISMATCH
Fatal error - Result didn't match what we expected.
@ RESULT_COMMAND_ERROR
Fatal error - Command operation error.
@ RESULT_NOOP
Not an error - Did nothing...
@ RESULT_OK
Not an error - Result as expected.
@ RESULT_EXIT
Stop processing files and exit.
@ RESULT_SKIP_FILE
Not an error - Skip the rest of this file, or until we reach an "eof" command.
@ RESULT_PARSE_ERROR
Fatal error - Command syntax error.
static int line_ranges_parse(TALLOC_CTX *ctx, fr_dlist_head_t *out, fr_sbuff_t *in)
static size_t command_cd(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, size_t inlen)
Change the working directory.
static size_t command_pair(command_result_t *result, command_file_ctx_t *cc, char *data, size_t data_used, char *in, size_t inlen)
static size_t command_comment(UNUSED command_result_t *result, UNUSED command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, UNUSED char *in, UNUSED size_t inlen)
Placeholder function for comments.
uint8_t * buffer_start
Where the non-poisoned region of the buffer starts.
static ssize_t encode_data_tlv(char *buffer, char **endptr, uint8_t *output, size_t outlen)
static size_t command_radmin_add(command_result_t *result, command_file_ctx_t *cc, char *data, size_t UNUSED data_used, char *in, UNUSED size_t inlen)
static size_t command_need_feature(command_result_t *result, command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Skip the test file if we're missing a particular feature.
static ssize_t encode_long_extended(char *buffer, uint8_t *output, size_t outlen)
ssize_t(* command_tmpl_rule_func)(TALLOC_CTX *ctx, tmpl_rules_t *rules, fr_sbuff_t *value)
Callback for a tmpl rule parser.
static size_t command_clear(command_result_t *result, UNUSED command_file_ctx_t *cc, char *data, size_t UNUSED data_used, UNUSED char *in, UNUSED size_t inlen)
fr_dict_t * test_internal_dict
Internal dictionary of test_gctx.
static ssize_t encode_evs(char *buffer, uint8_t *output, size_t outlen)
static size_t command_value_box_normalise(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
static xlat_action_t xlat_test(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, UNUSED fr_value_box_list_t *in)
fr_dict_t * dict
Dictionary to "reset" to.
static char const * write_filename
static xlat_arg_parser_t const xlat_test_no_args[]
uint8_t * buffer
Temporary resizable buffer we use for holding non-string data.
static size_t command_no(command_result_t *result, command_file_ctx_t *cc, char *data, size_t data_used, char *in, size_t inlen)
Negate the result of a match command or any command which returns "OK".
static size_t command_rcode_table_len
static size_t command_encode_dns_label(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Configuration parameters passed to command functions.
int unlang_thread_instantiate(TALLOC_CTX *ctx)
Create thread-specific data structures for unlang.
fr_slen_t xlat_tokenize_condition(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
fr_slen_t xlat_print(fr_sbuff_t *in, xlat_exp_head_t const *node, fr_sbuff_escape_rules_t const *e_rules)
Reconstitute an xlat expression from its constituent nodes.
void xlat_debug_head(xlat_exp_head_t const *head)
fr_slen_t xlat_tokenize(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
Tokenize an xlat expansion.
int xlat_instantiate(void)
Call instantiation functions for all registered, "permanent" xlats.
int xlat_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Create thread specific instance tree and create thread instances.
int xlat_purify(xlat_exp_head_t *head, unlang_interpret_t *intp)
Purify an xlat.
int xlat_flatten_to_argv(TALLOC_CTX *ctx, xlat_exp_head_t ***argv, xlat_exp_head_t *head)
Turn am xlat list into an argv[] array, and nuke the input list.
unsigned int required
Argument must be present, and non-empty.
#define XLAT_ARG_PARSER_TERMINATOR
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
fr_slen_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in, xlat_arg_parser_t const *xlat_args, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, bool spaces))
Tokenize an xlat expansion into a series of XLAT_TYPE_CHILD arguments.
fr_slen_t xlat_tokenize_expression(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Definition for a single argument consumend by an xlat function.
#define FR_DICTIONARY_INTERNAL_DIR
#define fr_pair_dcursor_iter_init(_cursor, _list, _iter, _uctx)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
#define PAIR_LIST_VERIFY_WITH_CTX(_c, _x)
ssize_t fr_pair_list_print(fr_sbuff_t *out, fr_dict_attr_t const *parent, fr_pair_list_t const *list)
Print a pair list.
char const * fr_strerror(void)
Get the last library error.
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
char const * fr_strerror_peek(void)
Get the last library error.
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
char const * fr_strerror_pop(void)
Pop the last library error.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
#define fr_strerror_const_push(_msg)
#define fr_strerror_printf_push_head(_fmt,...)
Add a message to an existing stack of messages at the head.
#define fr_strerror_const(_msg)
fr_table_num_ordered_t const fr_type_table[]
Map data types to names representing those types.
@ FR_TYPE_ATTR
A contains an attribute reference.
#define fr_type_is_null(_x)
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
int fr_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
#define RADIUSD_MAGIC_NUMBER
fr_sbuff_escape_rules_t fr_value_escape_double
ssize_t fr_value_box_print(fr_sbuff_t *out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules)
Print one boxed value to a string.
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
int8_t fr_value_box_cmp(fr_value_box_t const *a, fr_value_box_t const *b)
Compare two values.
fr_sbuff_parse_rules_t const value_parse_rules_bareword_unquoted
Default formatting rules.
int fr_value_box_cast_in_place(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv)
Convert one type of fr_value_box_t to another in place.
ssize_t fr_value_box_from_str(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, char const *in, size_t inlen, fr_sbuff_unescape_rules_t const *erules)
ssize_t fr_value_box_print_quoted(fr_sbuff_t *out, fr_value_box_t const *data, fr_token_t quote)
Print one boxed value to a string with quotes (where needed)
fr_sbuff_parse_rules_t const value_parse_rules_double_quoted
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
fr_sbuff_unescape_rules_t fr_value_unescape_double
ssize_t fr_value_box_from_substr(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *rules)
Convert string value to a fr_value_box_t type.
#define fr_value_box_mark_safe_for(_box, _safe_for)
#define fr_box_strvalue_len(_val, _len)
static size_t char fr_sbuff_t size_t inlen
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
static size_t char ** out
#define FR_VALUE_BOX_SAFE_FOR_ANY
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
xlat_t * xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function.