26RCSID(
"$Id: cb5d5b60c2bf0982f20cc38b6d51319614dee310 $")
30#include <freeradius-devel/io/test_point.h>
31#include <freeradius-devel/server/cf_parse.h>
32#include <freeradius-devel/server/command.h>
33#include <freeradius-devel/server/dependency.h>
34#include <freeradius-devel/server/dl_module.h>
35#include <freeradius-devel/server/log.h>
36#include <freeradius-devel/server/map.h>
38# include <freeradius-devel/tls/base.h>
40#include <freeradius-devel/unlang/base.h>
41#include <freeradius-devel/unlang/xlat_func.h>
42#include <freeradius-devel/util/lsan.h>
43#include <freeradius-devel/util/atexit.h>
44#include <freeradius-devel/util/base64.h>
45#include <freeradius-devel/util/calc.h>
46#include <freeradius-devel/util/conf.h>
47#include <freeradius-devel/util/dns.h>
48#include <freeradius-devel/util/file.h>
49#include <freeradius-devel/util/skip.h>
50#include <freeradius-devel/util/pair_legacy.h>
51#include <freeradius-devel/util/sha1.h>
52#include <freeradius-devel/util/syserror.h>
54#include <freeradius-devel/util/dict_priv.h>
67#define EXIT_WITH_FAILURE \
73#define COMMAND_OUTPUT_MAX 8192
75#define RETURN_OK(_len) \
77 result->rcode = RESULT_OK; \
78 result->file = __FILE__; \
79 result->line = __LINE__; \
83#define RETURN_OK_WITH_ERROR() \
85 result->rcode = RESULT_OK; \
86 result->file = __FILE__; \
87 result->line = __LINE__; \
88 result->error_to_data = true; \
92#define RETURN_NOOP(_len) \
94 result->rcode = RESULT_NOOP; \
95 result->file = __FILE__; \
96 result->line = __LINE__; \
100#define RETURN_SKIP_FILE() \
102 result->rcode = RESULT_SKIP_FILE; \
103 result->file = __FILE__; \
104 result->line = __LINE__; \
108#define RETURN_PARSE_ERROR(_offset) \
110 result->rcode = RESULT_PARSE_ERROR; \
111 result->offset = _offset; \
112 result->file = __FILE__; \
113 result->line = __LINE__; \
117#define RETURN_COMMAND_ERROR() \
119 result->rcode = RESULT_COMMAND_ERROR; \
120 result->file = __FILE__; \
121 result->line = __LINE__; \
125#define RETURN_MISMATCH(_len) \
127 result->rcode = RESULT_MISMATCH; \
128 result->file = __FILE__; \
129 result->line = __LINE__; \
133#define RETURN_EXIT(_ret) \
135 result->rcode = RESULT_EXIT; \
136 result->ret = _ret; \
137 result->file = __FILE__; \
138 result->line = __LINE__; \
145#define DEFAULT_BUFFER_SIZE 1024
236 size_t data_used,
char *
in,
size_t inlen);
279#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
280# define BUFF_POISON_START 1024
281# define BUFF_POISON_END 1024
296# define BUFF_POISON_START 0
297# define BUFF_POISON_END 0
323 if (!our_buff)
return -1;
325#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
326 talloc_set_destructor(our_buff, _free_buffer);
339#define POISONED_BUFFER_START(_p) ((_p) + BUFF_POISON_START)
340#define POISONED_BUFFER_END(_p) ((_p) + BUFF_POISON_START + (talloc_array_length(_p) - (BUFF_POISON_START + BUFF_POISON_END)))
343 char *expected,
size_t expected_len,
char *got,
size_t got_len,
351 ERROR(
" got : %.*s", (
int) got_len, got);
352 ERROR(
" expected : %.*s", (
int) expected_len, expected);
357 while (*g && *e && (*g == *e)) {
362 if (expected_len < 100) {
365 ERROR(
" EXPECTED : %.*s", (
int) expected_len, expected);
366 ERROR(
" GOT : %.*s", (
int) got_len, got);
367 ERROR(
" %.*s^ differs here (%zu)", (
int) (e - expected),
spaces, e - expected);
369 ERROR(
" EXPECTED : %.*s", (
int) expected_len, expected);
370 ERROR(
" GOT : %.*s", (
int) got_len, got);
371 ERROR(
"Differs at : %zu", e - expected);
377 if (elen > 70) elen = 70;
379 if (glen > 70) glen = 70;
381 ERROR(
"(%zu) ... %.*s ... ", e - expected, (
int) elen, e);
382 ERROR(
"(%zu) ... %.*s ... ", e - expected, (
int) glen, g);
393 char *end = p + outlen;
401 for (i = 0; i <
inlen; i++) {
419 char *end =
out + outlen;
458 file_fd = openat(fd_dir, digest_str, O_RDWR | O_CREAT | O_TRUNC,
459 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
466 if (flock(file_fd, LOCK_EX) < 0) {
476 ret = write(file_fd,
data, data_len);
480 (void)flock(file_fd, LOCK_UN);
481 unlinkat(fd_dir, digest_str, 0);
488 (void)flock(file_fd, LOCK_UN);
501static char const hextab[] =
"0123456789abcdef";
510 while (*p && (outlen > 0)) {
516 *(output++) = *(p++);
545 ERROR(
"String is not terminated");
555 for (p =
buffer; *p !=
'\0'; p++) {
556 if (*p ==
'{')
depth++;
559 if (
depth == 0)
break;
564 ERROR(
"No trailing '}' in string starting with \"%s\"",
buffer);
575 if (slen <= 0)
return 0;
584 uint8_t *out_p =
out, *out_end = out_p + outlen;
589 if (out_p >= out_end) {
607 if (!c2)
goto bad_input;
622 ERROR(
"Invalid character following attribute definition");
646 if (sublen <= 0)
return 0;
662 slen =
hex_to_bin(output, outlen, p, strlen(p));
675 attr = strtol(
buffer, endptr, 10);
677 ERROR(
"No valid number found in string starting with \"%s\"",
buffer);
682 ERROR(
"Nothing follows attribute number");
686 if ((attr <= 0) || (attr > 256)) {
687 ERROR(
"Attribute number is out of valid range");
699 ERROR(
"Invalid separator before vendor id");
703 vendor = strtol(
buffer + 1, endptr, 10);
704 if (*endptr == (
buffer + 1)) {
705 ERROR(
"No valid vendor number found");
710 ERROR(
"Nothing follows vendor number");
714 if ((vendor <= 0) || (vendor > (1 << 24))) {
715 ERROR(
"Vendor number is out of valid range");
719 if (**endptr !=
'.') {
720 ERROR(
"Invalid data following vendor number");
735 if (attr == 0)
return 0;
748 if (slen <= 0)
return slen;
749 if (slen > (255 - 2)) {
750 ERROR(
"TLV data is too long");
766 if (vendor == 0)
return 0;
769 output[1] = (vendor >> 16) & 0xff;
770 output[2] = (vendor >> 8) & 0xff;
771 output[3] = vendor & 0xff;
774 if (slen <= 0)
return slen;
775 if (slen > (255 - 6)) {
776 ERROR(
"VSA data is too long");
791 if (vendor == 0)
return 0;
794 if (attr == 0)
return 0;
797 output[1] = (vendor >> 16) & 0xff;
798 output[2] = (vendor >> 8) & 0xff;
799 output[3] = vendor & 0xff;
803 if (slen <= 0)
return slen;
815 if (attr == 0)
return 0;
824 if (slen <= 0)
return slen;
825 if (slen > (255 - 3)) {
826 ERROR(
"Extended Attr data is too long");
840 if (attr == 0)
return 0;
849 if (slen <= 0)
return slen;
856 if (slen <= 0)
return slen;
860 int sublen = 255 - output[1];
862 if (slen <= sublen) {
870 memmove(output + 255 + 4, output + 255, slen);
871 memcpy(output + 255, output, 4);
891 if (attr == 0)
return 0;
898 sublen =
encode_vsa(p, output + 2, outlen - 2);
900 }
else if ((attr < 241) || (attr > 246)) {
905 ERROR(
"Invalid data following attribute number");
918 if (sublen <= 0)
return sublen;
919 if (sublen > (255 -2)) {
920 ERROR(
"RFC Data is too long");
925 return slen + sublen;
945 snprintf(dl_name,
sizeof(dl_name),
"libfreeradius-%s", proto_name);
946 if (
dl) TALLOC_FREE(
dl);
950 fr_perror(
"Failed to link to library \"%s\"", dl_name);
959 return strlen(proto_name);
969 fr_strerror_printf(
"No protocol library loaded. Specify library with \"load <proto name>\"");
978 if ((*p ==
'.') && (q = strchr(p,
' ')) && (q != (p + 1)) && ((
size_t)(q - p) <
sizeof(
buffer))) {
1020 if (
in[0] ==
'\0') {
1032 q = strchr(
in,
' ');
1039 dir = default_subdir;
1155 printf(
"%s ", info->
parents[i]);
1158 printf(
":%s ", info->
name);
1167 void *walk_ctx = NULL;
1169 printf(
"Command hierarchy --------");
1172 printf(
"Command list --------");
1178#define CLEAR_TEST_POINT(_cc) \
1180 talloc_free_children((_cc)->tmp_ctx); \
1200 bool exit_now =
false;
1204 fprintf(stderr,
"Can't do $INCLUDE with -w %s\n",
write_filename);
1208 q = strrchr(cc->
path,
'/');
1241#define ATTR_COMMON \
1242 fr_sbuff_t our_in = FR_SBUFF_IN(in, inlen); \
1243 fr_dict_attr_err_t err; \
1245 fr_dict_attr_t const *root; \
1246 fr_dict_attr_t const *da; \
1247 root = cc->tmpl_rules.attr.dict_def ? \
1248 fr_dict_root(cc->tmpl_rules.attr.dict_def) : \
1249 fr_dict_root(fr_dict_internal()); \
1250 slen = fr_dict_attr_by_oid_substr(&err, \
1254 if (err != FR_DICT_ATTR_OK) FR_SBUFF_ERROR_RETURN(&our_in)
1269 namespace = dict_attr_namespace(da);
1275 if (da->flags.is_alias) {
1378 char const *p, *
value, *end;
1389 if (match_len == 0)
return 0;
1412 if (match_len == 0)
return 0;
1463 char const *p, *
value, *end;
1488 if (match_len == 0)
return 0;
1490 fr_value_box_list_insert_tail(&group->vb_group, a);
1494 if (strncmp(p,
"->", 2) == 0)
break;
1527 char const *p, *
value, *end;
1537 if (match_len == 0)
return 0;
1574 TALLOC_FREE(cc->
path);
1671 memcpy(&argv, &info.
argv,
sizeof(argv));
1673 if (info.
argc <= 0) {
1680 len =
snprintf(p, end - p,
"%d - ", num_expansions);
1688 for (i = 0; i < num_expansions; i++) {
1689 len =
snprintf(p, end - p,
"'%s', ", expansions[i]);
1697 if (num_expansions > 0) {
1739 if ((
size_t) slen <
inlen) {
1759 fr_strerror_const(
"Command count would overflow data buffer (shouldn't happen)");
1767 char *
data,
size_t data_used,
char *
in,
size_t inlen)
1770 void *decode_ctx = NULL;
1772 uint8_t *to_dec, *to_dec_start;
1775#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
1825 to_dec_end = to_dec + slen;
1827#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
1836 while (to_dec < to_dec_end) {
1838 (
uint8_t *)to_dec, (to_dec_end - to_dec), decode_ctx);
1846 if ((
size_t)slen > (
size_t)(to_dec_end - to_dec)) {
1847 fr_perror(
"%s: Internal sanity check failed at %d", __FUNCTION__, __LINE__);
1880 char *
data,
size_t data_used,
char *
in,
size_t inlen)
1883 void *decode_ctx = NULL;
1885 uint8_t *to_dec, *to_dec_start;
1888#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
1937 to_dec_end = to_dec + slen;
1939#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
1945 (
uint8_t *)to_dec, (to_dec_end - to_dec), decode_ctx);
2000 char *filename, *dir = NULL;
2006 if (
in[0] ==
'\0') {
2011 p = strchr(
in,
' ');
2015 if (*filename !=
'/') {
2058 next = strchr(p,
',');
2059 if (next) *next = 0;
2061 enc_p = cc->buffer_start;
2076 cc->buffer_start, cc->buffer_end - cc->buffer_start, enc_p,
true, box, NULL);
2091 next = strchr(p,
',');
2092 if (next) *next = 0;
2095 if ((cc->fuzzer_fd >= 0) &&
2096 (
dump_fuzzer_data(cc->fuzzer_fd,
in, cc->buffer_start, enc_p - cc->buffer_start) < 0)) {
2106 ssize_t slen, total, i, outlen;
2119 for (i = 0; i < total; i += slen) {
2130 if (i > 0) *(
out++) =
',';
2136 if (outlen <= 0)
goto error;
2159 bool truncate =
false;
2161 size_t iterations = 0;
2186 if (strncmp(p,
"truncate",
sizeof(
"truncate") - 1) == 0) {
2188 p +=
sizeof(
"truncate") - 1;
2224#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
2231 DEBUG(
"%s[%d]: Iteration %zu - Safe region %p-%p (%zu bytes), "
2232 "poisoned region %p-%p (%zu bytes)", cc->
filename, cc->
lineno, iterations - 1,
2235 DEBUG(
"%s[%d]: Iteration %zu - Allowed region %p-%p (%zu bytes)",
2236 cc->
filename, cc->
lineno, iterations - 1, enc_p, enc_end, enc_end - enc_p);
2248 if (truncate)
DEBUG(
"%s[%d]: Iteration %zu - Result %zd%s%s",
2252 if (slen < 0)
break;
2257 if (slen > (enc_end - enc_p)) {
2259 (enc_end - enc_p), (
size_t)slen);
2260#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
2270 if (slen == 0)
break;
2274#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
2286 }
while (truncate && (enc_end < cc->buffer_end));
2350 fp = fopen(filename,
"r");
2477 char *fuzzer_dir = NULL;
2478 bool retry_dir =
true;
2491 fd = open(fuzzer_dir, O_RDONLY);
2493 if (mkdir(fuzzer_dir, 0777) == 0) {
2494 fd = open(fuzzer_dir, O_RDONLY);
2495 if (fd >= 0)
goto stat;
2500 }
else if ((errno == EEXIST) && retry_dir) {
2510 if (fstat(fd, &sdir) < 0) {
2516 if (!(sdir.st_mode & S_IFDIR)) {
2543 if (
in[0] ==
'\0') {
2572 char *
name, *tmp = NULL;
2579 if (
in[0] ==
'\0') {
2584 q = strchr(
in,
' ');
2614 char *
data,
size_t data_used,
char *
in,
size_t inlen)
2616 if (strcmp(
in,
data) != 0) {
2638 char *
data,
size_t data_used,
char *
in,
size_t inlen)
2644 slen = regex_compile(cc->
tmp_ctx, ®ex,
in,
inlen, NULL,
false,
true);
2647 ret = regex_exec(regex,
data, data_used, NULL);
2676 size = strtoul(
in, &end, 10);
2677 if ((size == ULONG_MAX) || *end || (size >= 65536)) {
2704 if (strncmp(p,
"xlat_new_functions",
sizeof(
"xlat_new_functions") - 1) == 0) {
2705 p +=
sizeof(
"xlat_new_functions") - 1;
2721 if ((strcmp(p,
"yes") == 0) || (strcmp(p,
"true") == 0) || (strcmp(p,
"1") == 0)) {
2724 }
else if ((strcmp(p,
"no") == 0) || (strcmp(p,
"false") == 0) || (strcmp(p,
"0") == 0)) {
2743 if (
in[0] ==
'\0') {
2745 "Use -f to print features");
2751 DEBUG(
"Skipping, missing feature \"%s\"",
in);
2762 char *
data,
size_t data_used,
char *
in,
size_t inlen)
2765 switch (result->
rcode) {
2770 ERROR(
"%s[%d]: %.*s: returned 'ok', where we expected 'result-mismatch'",
2810 .allow_compare = allow_compare,
2838 char *
data,
size_t data_used,
char *
in,
size_t inlen)
2844 char *
data,
size_t data_used,
char *
in,
size_t inlen)
2884 char *fuzzer_dir = NULL;
2901 for (p =
buffer, q = new_root->name; *q !=
'\0'; p++, q++) {
2925 size_t input_len = strlen(
in), escaped_len;
2949 if (((
size_t) slen != input_len)) {
3011 &rules->
attr.namespace,
3038 &rules->
attr.request_def,
3064 static size_t tmpl_rule_func_table_len =
NUM_ELEMENTS(tmpl_rule_func_table);
3104 if (match_len == 0) {
3155 char fuzzer_buffer[1024];
3156 char *fuzzer_p = fuzzer_buffer, *fuzzer_end = fuzzer_p +
sizeof(fuzzer_buffer);
3160 strlcpy(fuzzer_p,
data, slen > fuzzer_end - fuzzer_p ? fuzzer_end - fuzzer_p : slen);
3163 (
uint8_t *)fuzzer_buffer, strlen(fuzzer_buffer)) < 0) {
3174 char *
data,
size_t data_used,
char *
in,
size_t inlen)
3178 bool locked =
false;
3182 fd = open(path, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
3188 if (locked) (void)flock(fd, LOCK_UN);
3194 if (flock(fd, LOCK_EX) < 0) {
3202 ret = write(fd,
data, data_used);
3210 (void)flock(fd, LOCK_UN);
3225 size_t input_len = strlen(
in), escaped_len;
3254 if (((
size_t) slen != input_len)) {
3271 size_t input_len = strlen(
in), escaped_len;
3289 if (((
size_t) dec_len != input_len)) {
3306 size_t input_len = strlen(
in), escaped_len;
3335 if (((
size_t) slen != input_len)) {
3341 DEBUG(
"Before purify --------------------------------------------------");
3351 DEBUG(
"After purify --------------------------------------------------");
3368 size_t input_len = strlen(
in), escaped_len;
3397 if (((
size_t) slen != input_len)) {
3403 DEBUG(
"Before purify --------------------------------------------------");
3413 DEBUG(
"After purify --------------------------------------------------");
3434 size_t input_len = strlen(
in);
3462 for (i = 0, p =
data; i < argc; i++) {
3478 .usage =
"#<string>",
3479 .description =
"A comment - not processed"
3483 .usage =
"$INCLUDE <relative_path>",
3484 .description =
"Execute a test file"
3488 .usage =
"allow-unresolved yes|no",
3489 .description =
"Allow or disallow unresolved attributes in xlats and references"
3493 .usage =
"attr.children",
3494 .description =
"Return the children of the named attribute",
3498 .usage =
"attr.flags",
3499 .description =
"Return the flags of the named attribute",
3503 .usage =
"attr.name",
3504 .description =
"Return the number of the named attribute",
3508 .func = command_attr_number,
3509 .usage =
"attr.number",
3510 .description =
"Return the number of the named attribute",
3515 .usage =
"attr.oid",
3516 .description =
"Return the OID of the named attribute",
3520 .func = command_attr_ref,
3521 .usage =
"attr.ref",
3522 .description =
"Return the reference (if any) of the named attribute",
3527 .usage =
"attr.type",
3528 .description =
"Return the data type of the named attribute",
3532 .usage =
"calc <type1> <value1> <operator> <type2> <value2> -> <output-type>",
3533 .description =
"Perform calculations on value boxes",
3537 .usage =
"calc_nary op <type1> <value1> <type2> <value2> ... -> <output-type>",
3538 .description =
"Perform calculations on value boxes",
3542 .usage =
"cast (type) <value> -> <output-type>",
3543 .description =
"Perform calculations on value boxes",
3547 .usage =
"cd <path>",
3548 .description =
"Change the directory for loading dictionaries and $INCLUDEs, writing the full path into the data buffer on success"
3553 .description =
"Explicitly zero out the contents of the data buffer"
3557 .usage =
"command add <string>",
3558 .description =
"Add a command to a radmin command tree"
3562 .usage =
"command tab <string>",
3563 .description =
"Test a tab completion against a radmin command tree"
3567 .usage =
"condition <string>",
3568 .description =
"Parse and reprint a condition, writing the normalised condition to the data buffer on success"
3573 .description =
"Write the number of executed tests to the data buffer. A test is any command that should return 'ok'"
3577 .usage =
"decode-dns-label (-|<hex_string>)",
3578 .description =
"Decode one or more DNS labels, writing the decoded strings to the data buffer.",
3582 .usage =
"decode-pair[.<testpoint_symbol>] (-|<hex_string>)",
3583 .description =
"Produce an attribute value pair from a binary value using a specified protocol decoder. Protocol must be loaded with \"load <protocol>\" first",
3587 .usage =
"decode-proto[.<testpoint_symbol>] (-|<hex string>)",
3588 .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",
3592 .usage =
"dictionary <string>",
3593 .description =
"Parse dictionary attribute definition, writing \"ok\" to the data buffer if successful",
3597 .usage =
"dictionary-dump",
3598 .description =
"Print the contents of the currently active dictionary to stdout",
3602 .usage =
"dictionary-read <filename>",
3603 .description =
"Load the named dictionary file, writing \"ok\" to the data buffer if successful",
3607 .usage =
"encode-dns-label (-|string[,string])",
3608 .description =
"Encode one or more DNS labels, writing a hex string to the data buffer.",
3612 .usage =
"encode-pair[.<testpoint_symbol>] [truncate] (-|<attribute> = <value>[,<attribute = <value>])",
3613 .description =
"Encode one or more attribute value pairs, writing a hex string to the data buffer. Protocol must be loaded with \"load <protocol>\" first",
3617 .usage =
"encode-proto[.<testpoint_symbol>] (-|<attribute> = <value>[,<attribute = <value>])",
3618 .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"
3623 .description =
"Mark the end of a 'virtual' file. Used to prevent 'need-feature' skipping all the content of a command stream or file",
3627 .usage =
"exit[ <num>]",
3628 .description =
"Exit with the specified error number. If no <num> is provided, process will exit with 0"
3632 .usage =
"fuzzer-out <dir>",
3633 .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",
3637 .usage =
"load-dictionary <name> [<dir>]",
3638 .description =
"Load an additional dictionary from the same directory as the input file. "
3639 "Optionally you can specify a full path via <dir>. ",
3643 .usage =
"match <string>",
3644 .description =
"Compare the contents of the data buffer with an expected value"
3648 .usage =
"match-regex <regex>",
3649 .description =
"Compare the contents of the data buffer with a regular expression"
3653 .usage =
"max-buffer-size[ <integer>]",
3654 .description =
"Limit the maximum temporary buffer space available for any command which uses it"
3658 .usage =
"migrate <flag>=<value>",
3659 .description =
"Set migration flag"
3663 .usage =
"need-feature <feature>",
3664 .description =
"Skip the contents of the current file, or up to the next \"eof\" command if a particular feature is not available"
3669 .description =
"Negate the result of a command returning 'ok'"
3673 .usage =
"pair ... data ...",
3674 .description =
"Parse a list of pairs",
3678 .usage =
"pair-compare ... data ...",
3679 .description =
"Parse a list of pairs, allowing comparison operators",
3683 .usage =
"proto <protocol>",
3684 .description =
"Switch the active protocol to the one specified, unloading the previous protocol",
3688 .usage =
"proto-dictionary <proto_name> [<proto_dir>]",
3689 .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.",
3695 .usage =
"proto-dictionary-root[ <root_attribute>]",
3696 .description =
"Set the root attribute for the current protocol dictionary. "
3697 "If no attribute name is provided, the root will be reset to the root of the current dictionary",
3701 .usage =
"raw <string>",
3702 .description =
"Create nested attributes from OID strings and values"
3706 .usage =
"read_file <filename>",
3707 .description =
"Read a list of pairs from a file",
3711 .usage =
"returned",
3712 .description =
"Print the returned value to the data buffer"
3717 .usage =
"parse <string>",
3718 .description =
"Parse then print a tmpl expansion, writing the normalised tmpl expansion to the data buffer"
3723 .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]",
3724 .description =
"Alter the tmpl parsing rules for subsequent tmpl parsing commands in the same command context"
3728 .usage =
"touch <file>",
3729 .description =
"Touch a file, updating its created timestamp. Useful for marking the completion of a series of tests"
3733 .usage =
"value <type> <string>",
3734 .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"
3738 .usage =
"write <file>",
3739 .description =
"Write the contents of the data buffer (as a raw binary string) to the specified file"
3743 .usage =
"xlat <string>",
3744 .description =
"Parse then print an xlat expansion, writing the normalised xlat expansion to the data buffer"
3749 .usage =
"xlat_argv <string>",
3750 .description =
"Parse then print an xlat expansion argv, writing the normalised xlat expansion arguments to the data buffer"
3755 .usage =
"xlat_expr <string>",
3756 .description =
"Parse then print an xlat expression, writing the normalised xlat expansion to the data buffer"
3761 .usage =
"xlat_purify <string>",
3762 .description =
"Parse, purify, then print an xlat expression, writing the normalised xlat expansion to the data buffer"
3767 .usage =
"xlat_purify_cond <string>",
3768 .description =
"Parse, purify, then print an xlat condition, writing the normalised xlat expansion to the data buffer"
3788 if (!*p || (*p ==
'#')) {
3817 if ((p[0] ==
'-') && ((p[1] ==
' ') || (p[1] ==
'\0'))) {
3818 data_used = command->
func(result, cc,
data, data_used,
data, data_used);
3821 data_used = command->
func(result, cc,
data, data_used, p, strlen(p));
3834 data[data_used] =
'\0';
3852 talloc_free_children(cc->
tmp_ctx);
3882 cc->
tmp_ctx = talloc_named_const(ctx, 0,
"tmp_ctx");
3907 fr_perror(
"Failed allocating test dict_gctx");
3913 fr_perror(
"Failed loading test dict_gctx internal dictionary");
3932 cc->
tmp_ctx = talloc_named_const(ctx, 0,
"tmp_ctx");
3943 fr_perror(
"Failed loading test dict_gctx internal dictionary");
3960 static char path[PATH_MAX] =
"";
3962 bool opened_fp =
false;
3971 if (strcmp(filename,
"-") == 0) {
3973 filename =
"<stdin>";
3977 if (root_dir && *root_dir) {
3978 snprintf(path,
sizeof(path),
"%s/%s", root_dir, filename);
3980 strlcpy(path, filename,
sizeof(path));
3983 fp = fopen(path,
"r");
4001 char *p = strchr(
buffer,
'\n');
4009 if (!lr)
goto finish;
4026 switch (result.
rcode) {
4046 if (fp != stdin)
goto finish;
4106 if (opened_fp) fclose(fp);
4117 ERROR(
"Empty input file is invalid");
4130 INFO(
"usage: %s [options] (-|<filename>[:<lines>] [ <filename>[:<lines>]])",
name);
4132 INFO(
" -d <confdir> Set user dictionary path (defaults to " CONFDIR
").");
4133 INFO(
" -D <dictdir> Set main dictionary path (defaults to " DICTDIR
").");
4134 INFO(
" -x Debugging mode.");
4135 INFO(
" -f Print features.");
4136 INFO(
" -c Print commands.");
4137 INFO(
" -h Print help text.");
4138 INFO(
" -M Show talloc memory report.");
4139 INFO(
" -p Allow xlat_purify");
4140 INFO(
" -o <receipt_file> Create the <receipt_file> as a 'success' exit.");
4141 INFO(
" -w <output_file> Write 'corrected' output to <output_file>.");
4142 INFO(
"Where <filename> is a file containing one or more commands and '-' indicates commands should be read from stdin.");
4143 INFO(
"Ranges of <lines> may be specified in the format <start>[-[<end>]][,]");
4185 ERROR(
"Invalid line start number");
4190 if (max > lr->
start) {
4191 ERROR(
"Out of order line numbers (%u > %u) not allowed", max, lr->
start);
4201 if (!fr_sbuff_is_in_charset(
in, tokens)) {
4202 ERROR(
"Unexpected text \"%pV\"",
4229 lr->
end = UINT32_MAX;
4235 ERROR(
"Invalid line end number");
4239 ERROR(
"Line end must be >= line start (%u < %u)", lr->
end, lr->
start);
4242 if (max > lr->
end) {
4243 ERROR(
"Out of order line numbers (%u > %u) not allowed", max, lr->
end);
4259 char *p, *dir = NULL, *
file;
4260 int ret = EXIT_SUCCESS;
4269 fr_sbuff_marker(&file_start, &
in);
4270 fr_sbuff_marker(&file_end, &
in);
4271 fr_sbuff_marker(&dir_end, &
in);
4290 return EXIT_FAILURE;
4310 (strncmp(path,
"src/tests/unit/", 15) == 0)) {
4311 p =
UNCONST(
char *, strchr(path + 15,
'/'));
4313 printf(
"UNIT-TEST %s\n", path + 15);
4315 char *q =
UNCONST(
char *, strchr(p + 1,
'/'));
4320 printf(
"UNIT-TEST %s - %s\n", path + 15, p + 1);
4324 printf(
"UNIT-TEST %s - %s\n", p + 1, q + 1);
4339 return EXIT_FAILURE;
4345 if ((ret == EXIT_SUCCESS) &&
receipt_dir && dir) {
4346 char *touch_file, *subdir;
4348 if (strncmp(dir,
"src/", 4) == 0) {
4357 p = strchr(touch_file,
'/');
4360 if (
fr_mkdir(NULL, touch_file, (
size_t) (p - touch_file), S_IRWXU, NULL, NULL) < 0) {
4361 fr_perror(
"unit_test_attribute - failed to make directory %.*s - ",
4362 (
int) (p - touch_file), touch_file);
4365 return EXIT_FAILURE;
4368 if (
fr_touch(NULL, touch_file, 0644,
true, 0755) <= 0) {
4369 fr_perror(
"unit_test_attribute - failed to create receipt file %s - ",
4381 if (ret != EXIT_SUCCESS) {
4393 return EXIT_FAILURE;
4408 int ret = EXIT_SUCCESS;
4410 TALLOC_CTX *thread_ctx;
4411 bool exit_now =
false;
4419 bool do_features =
false;
4420 bool do_commands =
false;
4421 bool do_usage =
false;
4424 char const *error_str = NULL, *fail_str = NULL;
4467 while ((c = getopt(argc, argv,
"cd:D:F:fxMhpo:S:w:")) != -1)
switch (c) {
4477 config.dict_dir = optarg;
4481 config.fuzzer_base_dir = optarg;
4494 talloc_enable_leak_report();
4498 p = strrchr(optarg,
'/');
4517 fprintf(stderr,
"Invalid option to -S\n");
4529 argc -= (optind - 1);
4530 argv += (optind - 1);
4535 if (do_usage || do_features || do_commands) {
4554 if (fr_openssl_init() < 0) {
4623 ERROR(
"Failed registering xlat");
4633 ERROR(
"Failed registering xlat");
4650 ERROR(
"Can only use '-w' with input files");
4656 }
else if ((argc == 2) && (strcmp(argv[1],
"-") == 0)) {
4662 while (fgets(
buffer,
sizeof(
buffer) - 1, stdin) != NULL) {
4666 while (isspace((
unsigned int) *p)) p++;
4668 if (!*p || (*p ==
'#'))
continue;
4688 if ((ret != EXIT_SUCCESS) || exit_now)
break;
4691 }
else if (argc > 1) {
4696 ERROR(
"Receipt file cannot be one of the input files");
4704 for (i = 1; i < argc; i++) {
4706 if ((ret != EXIT_SUCCESS) || exit_now)
break;
4715#undef EXIT_WITH_FAILURE
4716#define EXIT_WITH_FAILURE \
4718 ret = EXIT_FAILURE; \
4719 error_str = fr_strerror(); \
4720 if (error_str) error_str = talloc_strdup(NULL, error_str); \
4741 fail_str =
"cleaning up dynamically loaded libraries";
4746 fail_str =
"cleaning up dictionaries";
4751 fail_str =
"creating receipt file";
4760 fail_str =
"cleaning up all memory";
4764 if (ret != EXIT_SUCCESS) {
4766 if (!fail_str) fail_str =
"in an input file";
4767 if (!error_str) error_str =
"";
4769 fprintf(stderr,
"unit_test_attribute failed %s - %s\n", fail_str, error_str);
4774 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.
#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
fr_dict_attr_t const * root_da
#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)
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.
int fr_dict_internal_afrom_file(fr_dict_t **out, char const *dict_subdir, char const *dependent))
(Re-)Initialize the special internal dictionary
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_str_to_argv(char *str, char **argv, int max_argc)
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_read(fr_dict_t *dict, char const *dict_dir, char const *filename))
Read supplementary attribute definitions into an existing dictionary.
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_protocol_afrom_file(fr_dict_t **out, char const *proto_name, char const *proto_dir, char const *dependent))
(Re)-initialize a protocol dictionary
bool fr_dict_filename_loaded(fr_dict_t const *dict, char const *dict_dir, char const *filename))
int fr_dict_global_ctx_free(fr_dict_gctx_t const *gctx)
Explicitly free all data associated with a global dictionary context.
fr_dict_attr_err_t
Errors returned by attribute lookup functions.
@ FR_DICT_ATTR_OK
No error.
int fr_dict_parse_str(fr_dict_t *dict, char const *str, fr_dict_attr_t const *parent))
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.
#define FR_DICT_ATTR_MAX_NAME_LEN
Maximum length of a attribute name.
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.
int fr_dict_afrom_file(fr_dict_t **out, char const *dir, char const *filename))
Load one dictionary file.
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.
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.
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.
@ L_DST_STDOUT
Log to stdout.
#define ASAN_POISON_MEMORY_REGION(_start, _size)
#define ASAN_UNPOISON_MEMORY_REGION(_start, _size)
@ 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.
int tmpl_global_init(void)
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.
#define talloc_strdup(_ctx, _str)
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
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)
#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.
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)
int fuzzer_fd
File descriptor pointing to a a directory to write fuzzer output.
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.
char * fuzzer_proto_dir
Subdirectory of where to write fuzzer files, from 'fuzzer-out dir'.
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 int fuzzer_open_fd(command_file_ctx_t *cc, char **out, char const *base, char const *dir)
Helper function to open a fuzzer path, and update the name / FD.
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.
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.
#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)
static size_t command_dictionary_read(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Read a dictionary from a file, and then free it.
#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 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.
char const * fuzzer_base_dir
Base directory of where to write fuzzer files, from '-F'.
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 const fr_token_t token2op[SBUFF_CHAR_CLASS]
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 consumed 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
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.
fr_sbuff_escape_rules_t const fr_value_escape_double
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)
fr_sbuff_unescape_rules_t const fr_value_unescape_double
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.
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.