26RCSID(
"$Id: 702b3f48a7164347fd2be0d2fcd0843123174413 $")
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/rand.h>
52#include <freeradius-devel/util/sha1.h>
53#include <freeradius-devel/util/syserror.h>
55#include <freeradius-devel/util/dict_priv.h>
68#define EXIT_WITH_FAILURE \
74#define COMMAND_OUTPUT_MAX 8192
76#define RETURN_OK(_len) \
78 result->rcode = RESULT_OK; \
79 result->file = __FILE__; \
80 result->line = __LINE__; \
84#define RETURN_OK_WITH_ERROR() \
86 result->rcode = RESULT_OK; \
87 result->file = __FILE__; \
88 result->line = __LINE__; \
89 result->error_to_data = true; \
93#define RETURN_NOOP(_len) \
95 result->rcode = RESULT_NOOP; \
96 result->file = __FILE__; \
97 result->line = __LINE__; \
101#define RETURN_SKIP_FILE() \
103 result->rcode = RESULT_SKIP_FILE; \
104 result->file = __FILE__; \
105 result->line = __LINE__; \
109#define RETURN_PARSE_ERROR(_offset) \
111 result->rcode = RESULT_PARSE_ERROR; \
112 result->offset = _offset; \
113 result->file = __FILE__; \
114 result->line = __LINE__; \
118#define RETURN_COMMAND_ERROR() \
120 result->rcode = RESULT_COMMAND_ERROR; \
121 result->file = __FILE__; \
122 result->line = __LINE__; \
126#define RETURN_MISMATCH(_len) \
128 result->rcode = RESULT_MISMATCH; \
129 result->file = __FILE__; \
130 result->line = __LINE__; \
134#define RETURN_EXIT(_ret) \
136 result->rcode = RESULT_EXIT; \
137 result->ret = _ret; \
138 result->file = __FILE__; \
139 result->line = __LINE__; \
143#define SBUFF_RETURN_OK_WITH_ERROR(_function, ...) \
145 slen = _function(__VA_ARGS__); \
146 if (slen <= 0) RETURN_OK_WITH_ERROR(); \
152#define DEFAULT_BUFFER_SIZE 1024
243 size_t data_used,
char *
in,
size_t inlen);
287#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
288# define BUFF_POISON_START 1024
289# define BUFF_POISON_END 1024
304# define BUFF_POISON_START 0
305# define BUFF_POISON_END 0
331 if (!our_buff)
return -1;
333#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
334 talloc_set_destructor(our_buff, _free_buffer);
347#define POISONED_BUFFER_START(_p) ((_p) + BUFF_POISON_START)
348#define POISONED_BUFFER_END(_p) ((_p) + BUFF_POISON_START + (talloc_array_length(_p) - (BUFF_POISON_START + BUFF_POISON_END)))
351 char *expected,
size_t expected_len,
char *got,
size_t got_len,
359 ERROR(
" got : %.*s", (
int) got_len, got);
360 ERROR(
" expected : %.*s", (
int) expected_len, expected);
365 while (*g && *e && (*g == *e)) {
370 if (expected_len < 100) {
373 ERROR(
" EXPECTED : %.*s", (
int) expected_len, expected);
374 ERROR(
" GOT : %.*s", (
int) got_len, got);
375 ERROR(
" %.*s^ differs here (%td)", (
int) (e - expected),
spaces, e - expected);
377 ERROR(
" EXPECTED : %.*s", (
int) expected_len, expected);
378 ERROR(
" GOT : %.*s", (
int) got_len, got);
379 ERROR(
"Differs at : %td", e - expected);
385 if (elen > 70) elen = 70;
387 if (glen > 70) glen = 70;
389 ERROR(
"(%td) ... %.*s ... ", e - expected, (
int) elen, e);
390 ERROR(
"(%td) ... %.*s ... ", e - expected, (
int) glen, g);
401 char *end = p + outlen;
409 for (i = 0; i < inlen; i++) {
444 file_fd = openat(fd_dir, digest_str, O_RDWR | O_CREAT | O_TRUNC,
445 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
452 if (flock(file_fd, LOCK_EX) < 0) {
462 ret = write(file_fd,
data, data_len);
466 (void)flock(file_fd, LOCK_UN);
467 unlinkat(fd_dir, digest_str, 0);
474 (void)flock(file_fd, LOCK_UN);
487static char const hextab[] =
"0123456789abcdef";
496 while (*p && (outlen > 0)) {
502 *(output++) = *(p++);
531 ERROR(
"String is not terminated");
541 for (p =
buffer; *p !=
'\0'; p++) {
542 if (*p ==
'{')
depth++;
545 if (
depth == 0)
break;
550 ERROR(
"No trailing '}' in string starting with \"%s\"",
buffer);
561 if (slen <= 0)
return 0;
569 char *end =
in + inlen;
570 uint8_t *out_p =
out, *out_end = out_p + outlen;
575 if (out_p >= out_end) {
593 if (!c2)
goto bad_input;
608 ERROR(
"Invalid character following attribute definition");
632 if (sublen <= 0)
return 0;
648 slen =
hex_to_bin(output, outlen, p, strlen(p));
661 attr = strtol(
buffer, endptr, 10);
663 ERROR(
"No valid number found in string starting with \"%s\"",
buffer);
668 ERROR(
"Nothing follows attribute number");
672 if ((attr <= 0) || (attr > 256)) {
673 ERROR(
"Attribute number is out of valid range");
685 ERROR(
"Invalid separator before vendor id");
689 vendor = strtol(
buffer + 1, endptr, 10);
690 if (*endptr == (
buffer + 1)) {
691 ERROR(
"No valid vendor number found");
696 ERROR(
"Nothing follows vendor number");
700 if ((vendor <= 0) || (vendor > (1 << 24))) {
701 ERROR(
"Vendor number is out of valid range");
705 if (**endptr !=
'.') {
706 ERROR(
"Invalid data following vendor number");
721 if (attr == 0)
return 0;
734 if (slen <= 0)
return slen;
735 if (slen > (255 - 2)) {
736 ERROR(
"TLV data is too long");
752 if (vendor == 0)
return 0;
755 output[1] = (vendor >> 16) & 0xff;
756 output[2] = (vendor >> 8) & 0xff;
757 output[3] = vendor & 0xff;
760 if (slen <= 0)
return slen;
761 if (slen > (255 - 6)) {
762 ERROR(
"VSA data is too long");
777 if (vendor == 0)
return 0;
780 if (attr == 0)
return 0;
783 output[1] = (vendor >> 16) & 0xff;
784 output[2] = (vendor >> 8) & 0xff;
785 output[3] = vendor & 0xff;
789 if (slen <= 0)
return slen;
801 if (attr == 0)
return 0;
810 if (slen <= 0)
return slen;
811 if (slen > (255 - 3)) {
812 ERROR(
"Extended Attr data is too long");
826 if (attr == 0)
return 0;
835 if (slen <= 0)
return slen;
842 if (slen <= 0)
return slen;
846 int sublen = 255 - output[1];
848 if (slen <= sublen) {
856 memmove(output + 255 + 4, output + 255, slen);
857 memcpy(output + 255, output, 4);
877 if (attr == 0)
return 0;
884 sublen =
encode_vsa(p, output + 2, outlen - 2);
886 }
else if ((attr < 241) || (attr > 246)) {
891 ERROR(
"Invalid data following attribute number");
904 if (sublen <= 0)
return sublen;
905 if (sublen > (255 -2)) {
906 ERROR(
"RFC Data is too long");
911 return slen + sublen;
931 snprintf(dl_name,
sizeof(dl_name),
"libfreeradius-%s", proto_name);
932 if (
dl) TALLOC_FREE(
dl);
936 fr_perror(
"Failed to link to library \"%s\"", dl_name);
945 return strlen(proto_name);
955 fr_strerror_printf(
"No protocol library loaded. Specify library with \"load <proto name>\"");
964 if ((*p ==
'.') && (q = strchr(p,
' ')) && (q != (p + 1)) && ((
size_t)(q - p) <
sizeof(
buffer))) {
1006 if (
in[0] ==
'\0') {
1018 q = strchr(
in,
' ');
1025 dir = default_subdir;
1141 printf(
"%s ", info->
parents[i]);
1144 printf(
":%s ", info->
name);
1153 void *walk_ctx = NULL;
1155 printf(
"Command hierarchy --------");
1158 printf(
"Command list --------");
1164#define CLEAR_TEST_POINT(_cc) \
1166 talloc_free_children((_cc)->tmp_ctx); \
1186 bool exit_now =
false;
1190 fprintf(stderr,
"Can't do $INCLUDE with -w %s\n",
write_filename);
1194 q = strrchr(cc->
path,
'/');
1227#define ATTR_COMMON \
1228 fr_sbuff_t our_in = FR_SBUFF_IN(in, inlen); \
1229 fr_dict_attr_err_t err; \
1231 fr_dict_attr_t const *root; \
1232 fr_dict_attr_t const *da; \
1233 root = cc->tmpl_rules.attr.dict_def ? \
1234 fr_dict_root(cc->tmpl_rules.attr.dict_def) : \
1235 fr_dict_root(fr_dict_internal()); \
1236 slen = fr_dict_attr_by_oid_substr(&err, \
1240 if (err != FR_DICT_ATTR_OK) FR_SBUFF_ERROR_RETURN(&our_in)
1247 char *
data,
UNUSED size_t data_used,
char *
in,
size_t inlen)
1255 namespace = dict_attr_namespace(da);
1261 if (da->flags.is_alias) {
1287 char *
data,
UNUSED size_t data_used,
char *
in,
size_t inlen)
1301 char *
data,
UNUSED size_t data_used,
char *
in,
size_t inlen)
1315 char *
data,
UNUSED size_t data_used,
char *
in,
size_t inlen)
1329 char *
data,
UNUSED size_t data_used,
char *
in,
size_t inlen)
1354 char *
data,
UNUSED size_t data_used,
char *
in,
size_t inlen)
1360 char const *p, *
value, *end;
1371 if (match_len == 0)
return 0;
1394 if (match_len == 0)
return 0;
1439 char *
data,
UNUSED size_t data_used,
char *
in,
size_t inlen)
1445 char const *p, *
value, *end;
1470 if (match_len == 0)
return 0;
1472 fr_value_box_list_insert_tail(&group->vb_group, a);
1476 if (strncmp(p,
"->", 2) == 0)
break;
1504 char *
data,
UNUSED size_t data_used,
char *
in,
size_t inlen)
1509 char const *p, *
value, *end;
1519 if (match_len == 0)
return 0;
1554 char *
data,
UNUSED size_t data_used,
char *
in,
size_t inlen)
1556 TALLOC_FREE(cc->
path);
1653 memcpy(&argv, &info.
argv,
sizeof(argv));
1655 if (info.
argc <= 0) {
1662 len =
snprintf(p, end - p,
"%d - ", num_expansions);
1670 for (i = 0; i < num_expansions; i++) {
1671 len =
snprintf(p, end - p,
"'%s', ", expansions[i]);
1679 if (num_expansions > 0) {
1691 char *
data,
UNUSED size_t data_used,
char *
in,
size_t inlen)
1721 if ((
size_t) slen < inlen) {
1741 fr_strerror_const(
"Command count would overflow data buffer (shouldn't happen)");
1770 void *decode_ctx = NULL;
1772 uint8_t *to_dec, *to_dec_start;
1775#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
1814 inlen = strlen(
data);
1827 to_dec_end = to_dec + slen;
1829#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
1838 while (to_dec < to_dec_end) {
1840 (
uint8_t *)to_dec, (to_dec_end - to_dec), decode_ctx);
1848 if ((
size_t)slen > (
size_t)(to_dec_end - to_dec)) {
1849 fr_perror(
"%s: Internal sanity check failed at %d", __FUNCTION__, __LINE__);
1868 if (hex_p) *hex_p = p;
1871 return to_dec - to_dec_start;
1875 char *
data,
UNUSED size_t data_used,
char *
in,
size_t inlen)
1894 talloc_free_children(cc->
tmp_ctx);
1900 char *
data,
UNUSED size_t data_used,
char *
in,
size_t inlen)
1903 void *decode_ctx = NULL;
1905 uint8_t *to_dec, *to_dec_start;
1908#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
1946 inlen = strlen(
data);
1959 to_dec_end = to_dec + slen;
1961#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
1967 (
uint8_t *)to_dec, (to_dec_end - to_dec), decode_ctx);
2022 char *filename, *dir = NULL;
2028 if (
in[0] ==
'\0') {
2033 p = strchr(
in,
' ');
2037 if (*filename !=
'/') {
2080 next = strchr(p,
',');
2081 if (next) *next = 0;
2083 enc_p = cc->buffer_start;
2098 cc->buffer_start, cc->buffer_end - cc->buffer_start, enc_p,
true, box, NULL);
2113 next = strchr(p,
',');
2114 if (next) *next = 0;
2117 if ((cc->fuzzer_fd >= 0) &&
2118 (
dump_fuzzer_data(cc->fuzzer_fd,
in, cc->buffer_start, enc_p - cc->buffer_start) < 0)) {
2126 char *
data,
UNUSED size_t data_used,
char *
in,
size_t inlen)
2128 ssize_t slen, total, i, outlen;
2141 for (i = 0; i < total; i += slen) {
2152 if (i > 0) *(
out++) =
',';
2158 if (outlen <= 0)
goto error;
2193 size_t iterations = 0;
2203#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
2210 DEBUG(
"%s[%" PRIu32
"]: Iteration %zu - Safe region %p-%p (%td bytes), "
2211 "poisoned region %p-%p (%td bytes)", cc->
filename, cc->
lineno, iterations - 1,
2214 DEBUG(
"%s[%" PRIu32
"]: Iteration %zu - Allowed region %p-%p (%td bytes)",
2215 cc->
filename, cc->
lineno, iterations - 1, enc_p, enc_end, enc_end - enc_p);
2227 if (truncate)
DEBUG(
"%s[%" PRIu32
"]: Iteration %zu - Result %zd%s%s",
2231 if (slen < 0)
break;
2236 if (slen > (enc_end - enc_p)) {
2238 (enc_end - enc_p), (
size_t)slen);
2239#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
2249 if (slen == 0)
break;
2253#ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
2265 }
while (truncate && (enc_end < cc->buffer_end));
2285 if (fuzzer_text && (cc->
fuzzer_fd >= 0) &&
2294 char *
data,
UNUSED size_t data_used,
char *
in,
size_t inlen)
2304 bool truncate =
false;
2330 if (strncmp(p,
"truncate",
sizeof(
"truncate") - 1) == 0) {
2332 p +=
sizeof(
"truncate") - 1;
2353 if (parse_len <= 0) {
2369 char *
data,
UNUSED size_t data_used,
char *
in,
size_t inlen)
2438 fp = fopen(filename,
"r");
2480 char *
data,
UNUSED size_t data_used,
char *
in,
size_t inlen)
2520 if (parse_len <= 0) {
2566 char *fuzzer_dir = NULL;
2567 bool retry_dir =
true;
2580 fd = open(fuzzer_dir, O_RDONLY);
2582 if (mkdir(fuzzer_dir, 0777) == 0) {
2583 fd = open(fuzzer_dir, O_RDONLY);
2584 if (fd >= 0)
goto stat;
2589 }
else if ((errno == EEXIST) && retry_dir) {
2599 if (fstat(fd, &sdir) < 0) {
2605 if (!(sdir.st_mode & S_IFDIR)) {
2632 if (
in[0] ==
'\0') {
2661 char *
name, *tmp = NULL;
2668 if (
in[0] ==
'\0') {
2673 q = strchr(
in,
' ');
2703 char *
data,
size_t data_used,
char *
in,
size_t inlen)
2705 if (strcmp(
in,
data) != 0) {
2727 char *
data,
size_t data_used,
char *
in,
size_t inlen)
2733 slen = regex_compile(cc->
tmp_ctx, ®ex,
in, inlen, NULL,
false,
true);
2736 ret = regex_exec(regex,
data, data_used, NULL);
2765 size = strtoul(
in, &end, 10);
2766 if ((size == ULONG_MAX) || *end || (size >= 65536)) {
2793 if (strncmp(p,
"xlat_new_functions",
sizeof(
"xlat_new_functions") - 1) == 0) {
2794 p +=
sizeof(
"xlat_new_functions") - 1;
2810 if ((strcmp(p,
"yes") == 0) || (strcmp(p,
"true") == 0) || (strcmp(p,
"1") == 0)) {
2813 }
else if ((strcmp(p,
"no") == 0) || (strcmp(p,
"false") == 0) || (strcmp(p,
"0") == 0)) {
2832 if (
in[0] ==
'\0') {
2834 "Use -f to print features");
2840 DEBUG(
"Skipping, missing feature \"%s\"",
in);
2851 char *
data,
size_t data_used,
char *
in,
size_t inlen)
2854 switch (result->
rcode) {
2859 ERROR(
"%s[%" PRIu32
"]: %.*s: returned 'ok', where we expected 'result-mismatch'",
2883 char *
data,
UNUSED size_t data_used,
char *
in,
size_t inlen,
2900 .allow_compare = allow_compare,
2928 char *
data,
size_t data_used,
char *
in,
size_t inlen)
2934 char *
data,
size_t data_used,
char *
in,
size_t inlen)
2974 char *fuzzer_dir = NULL;
2991 for (p =
buffer, q = new_root->name; *q !=
'\0'; p++, q++) {
3020 seed = strtoull(
in, &end, 10);
3021 if ((*
in ==
'-') || errno || *end) {
3040 size_t input_len = strlen(
in), escaped_len;
3064 if (((
size_t) slen != input_len)) {
3126 &rules->
attr.namespace,
3153 &rules->
attr.request_def,
3179 static size_t tmpl_rule_func_table_len =
NUM_ELEMENTS(tmpl_rule_func_table);
3219 if (match_len == 0) {
3270 char fuzzer_buffer[1024];
3271 char *fuzzer_p = fuzzer_buffer, *fuzzer_end = fuzzer_p +
sizeof(fuzzer_buffer);
3275 strlcpy(fuzzer_p,
data, slen > fuzzer_end - fuzzer_p ? fuzzer_end - fuzzer_p : slen);
3278 (
uint8_t *)fuzzer_buffer, strlen(fuzzer_buffer)) < 0) {
3289 char *
data,
size_t data_used,
char *
in,
size_t inlen)
3293 bool locked =
false;
3297 fd = open(path, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
3303 if (locked) (void)flock(fd, LOCK_UN);
3309 if (flock(fd, LOCK_EX) < 0) {
3317 ret = write(fd,
data, data_used);
3325 (void)flock(fd, LOCK_UN);
3340 size_t input_len = strlen(
in), escaped_len;
3369 if (((
size_t) slen != input_len)) {
3386 size_t input_len = strlen(
in), escaped_len;
3404 if (((
size_t) dec_len != input_len)) {
3421 size_t input_len = strlen(
in), escaped_len;
3450 if (((
size_t) slen != input_len)) {
3456 DEBUG(
"Before purify --------------------------------------------------");
3466 DEBUG(
"After purify --------------------------------------------------");
3483 size_t input_len = strlen(
in), escaped_len;
3512 if (((
size_t) slen != input_len)) {
3518 DEBUG(
"Before purify --------------------------------------------------");
3528 DEBUG(
"After purify --------------------------------------------------");
3549 size_t input_len = strlen(
in);
3577 for (i = 0, p =
data; i < argc; i++) {
3593 .usage =
"#<string>",
3594 .description =
"A comment - not processed"
3598 .usage =
"$INCLUDE <relative_path>",
3599 .description =
"Execute a test file"
3603 .usage =
"allow-unresolved yes|no",
3604 .description =
"Allow or disallow unresolved attributes in xlats and references"
3608 .usage =
"attr.children",
3609 .description =
"Return the children of the named attribute",
3613 .usage =
"attr.flags",
3614 .description =
"Return the flags of the named attribute",
3618 .usage =
"attr.name",
3619 .description =
"Return the number of the named attribute",
3623 .func = command_attr_number,
3624 .usage =
"attr.number",
3625 .description =
"Return the number of the named attribute",
3630 .usage =
"attr.oid",
3631 .description =
"Return the OID of the named attribute",
3635 .func = command_attr_ref,
3636 .usage =
"attr.ref",
3637 .description =
"Return the reference (if any) of the named attribute",
3642 .usage =
"attr.type",
3643 .description =
"Return the data type of the named attribute",
3647 .usage =
"calc <type1> <value1> <operator> <type2> <value2> -> <output-type>",
3648 .description =
"Perform calculations on value boxes",
3652 .usage =
"calc_nary op <type1> <value1> <type2> <value2> ... -> <output-type>",
3653 .description =
"Perform calculations on value boxes",
3657 .usage =
"cast (type) <value> -> <output-type>",
3658 .description =
"Perform calculations on value boxes",
3662 .usage =
"cd <path>",
3663 .description =
"Change the directory for loading dictionaries and $INCLUDEs, writing the full path into the data buffer on success"
3668 .description =
"Explicitly zero out the contents of the data buffer"
3672 .usage =
"command add <string>",
3673 .description =
"Add a command to a radmin command tree"
3677 .usage =
"command tab <string>",
3678 .description =
"Test a tab completion against a radmin command tree"
3682 .usage =
"condition <string>",
3683 .description =
"Parse and reprint a condition, writing the normalised condition to the data buffer on success"
3688 .description =
"Write the number of executed tests to the data buffer. A test is any command that should return 'ok'"
3692 .usage =
"de-encode-pair[.<testpoint_symbol>] (-|<hex_string>)",
3693 .description =
"Decode a binary value into attribute value pairs, encode the pairs again, and write the result to the data buffer as hex. Protocol must be loaded with \"load <protocol>\" first",
3697 .usage =
"decode-dns-label (-|<hex_string>)",
3698 .description =
"Decode one or more DNS labels, writing the decoded strings to the data buffer.",
3702 .usage =
"decode-pair[.<testpoint_symbol>] (-|<hex_string>)",
3703 .description =
"Produce an attribute value pair from a binary value using a specified protocol decoder. Protocol must be loaded with \"load <protocol>\" first",
3707 .usage =
"decode-proto[.<testpoint_symbol>] (-|<hex string>)",
3708 .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",
3712 .usage =
"dictionary <string>",
3713 .description =
"Parse dictionary attribute definition, writing \"ok\" to the data buffer if successful",
3717 .usage =
"dictionary-dump",
3718 .description =
"Print the contents of the currently active dictionary to stdout",
3722 .usage =
"dictionary-read <filename>",
3723 .description =
"Load the named dictionary file, writing \"ok\" to the data buffer if successful",
3727 .usage =
"encode-dns-label (-|string[,string])",
3728 .description =
"Encode one or more DNS labels, writing a hex string to the data buffer.",
3732 .usage =
"encode-pair[.<testpoint_symbol>] [truncate] (-|<attribute> = <value>[,<attribute = <value>])",
3733 .description =
"Encode one or more attribute value pairs, writing a hex string to the data buffer. Protocol must be loaded with \"load <protocol>\" first",
3737 .usage =
"encode-proto[.<testpoint_symbol>] (-|<attribute> = <value>[,<attribute = <value>])",
3738 .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"
3743 .description =
"Mark the end of a 'virtual' file. Used to prevent 'need-feature' skipping all the content of a command stream or file",
3747 .usage =
"exit[ <num>]",
3748 .description =
"Exit with the specified error number. If no <num> is provided, process will exit with 0"
3752 .usage =
"fuzzer-out <dir>",
3753 .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",
3757 .usage =
"load-dictionary <name> [<dir>]",
3758 .description =
"Load an additional dictionary from the same directory as the input file. "
3759 "Optionally you can specify a full path via <dir>. ",
3763 .usage =
"match <string>",
3764 .description =
"Compare the contents of the data buffer with an expected value"
3768 .usage =
"match-regex <regex>",
3769 .description =
"Compare the contents of the data buffer with a regular expression"
3773 .usage =
"max-buffer-size[ <integer>]",
3774 .description =
"Limit the maximum temporary buffer space available for any command which uses it"
3778 .usage =
"migrate <flag>=<value>",
3779 .description =
"Set migration flag"
3783 .usage =
"need-feature <feature>",
3784 .description =
"Skip the contents of the current file, or up to the next \"eof\" command if a particular feature is not available"
3789 .description =
"Negate the result of a command returning 'ok'"
3793 .usage =
"pair ... data ...",
3794 .description =
"Parse a list of pairs",
3798 .usage =
"pair-compare ... data ...",
3799 .description =
"Parse a list of pairs, allowing comparison operators",
3803 .usage =
"proto <protocol>",
3804 .description =
"Switch the active protocol to the one specified, unloading the previous protocol",
3808 .usage =
"proto-dictionary <proto_name> [<proto_dir>]",
3809 .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.",
3815 .usage =
"proto-dictionary-root[ <root_attribute>]",
3816 .description =
"Set the root attribute for the current protocol dictionary. "
3817 "If no attribute name is provided, the root will be reset to the root of the current dictionary",
3821 .usage =
"rand-seed[ <integer>]",
3822 .description =
"Seed the random number generator, so random values such as "
3823 "identifiers and salts are the same on every run. The seed defaults to 0"
3827 .usage =
"raw <string>",
3828 .description =
"Create nested attributes from OID strings and values"
3832 .usage =
"read_file <filename>",
3833 .description =
"Read a list of pairs from a file",
3837 .usage =
"returned",
3838 .description =
"Print the returned value to the data buffer"
3843 .usage =
"parse <string>",
3844 .description =
"Parse then print a tmpl expansion, writing the normalised tmpl expansion to the data buffer"
3849 .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]",
3850 .description =
"Alter the tmpl parsing rules for subsequent tmpl parsing commands in the same command context"
3854 .usage =
"touch <file>",
3855 .description =
"Touch a file, updating its created timestamp. Useful for marking the completion of a series of tests"
3859 .usage =
"value <type> <string>",
3860 .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"
3864 .usage =
"write <file>",
3865 .description =
"Write the contents of the data buffer (as a raw binary string) to the specified file"
3869 .usage =
"xlat <string>",
3870 .description =
"Parse then print an xlat expansion, writing the normalised xlat expansion to the data buffer"
3875 .usage =
"xlat_argv <string>",
3876 .description =
"Parse then print an xlat expansion argv, writing the normalised xlat expansion arguments to the data buffer"
3881 .usage =
"xlat_expr <string>",
3882 .description =
"Parse then print an xlat expression, writing the normalised xlat expansion to the data buffer"
3887 .usage =
"xlat_purify <string>",
3888 .description =
"Parse, purify, then print an xlat expression, writing the normalised xlat expansion to the data buffer"
3893 .usage =
"xlat_purify_cond <string>",
3894 .description =
"Parse, purify, then print an xlat condition, writing the normalised xlat expansion to the data buffer"
3915 if (!*p || (*p ==
'#')) {
3944 if ((p[0] ==
'-') && ((p[1] ==
' ') || (p[1] ==
'\0'))) {
3945 data_used = command->
func(result, cc,
data, data_used,
data, data_used);
3948 data_used = command->
func(result, cc,
data, data_used, p, strlen(p));
3964 data[data_used] =
'\0';
3984 talloc_free_children(cc->
tmp_ctx);
4014 cc->
tmp_ctx = talloc_named_const(ctx, 0,
"tmp_ctx");
4039 fr_perror(
"Failed allocating test dict_gctx");
4045 fr_perror(
"Failed loading test dict_gctx internal dictionary");
4064 cc->
tmp_ctx = talloc_named_const(ctx, 0,
"tmp_ctx");
4075 fr_perror(
"Failed loading test dict_gctx internal dictionary");
4092 static char path[PATH_MAX] =
"";
4094 bool opened_fp =
false;
4103 if (strcmp(filename,
"-") == 0) {
4105 filename =
"<stdin>";
4109 if (root_dir && *root_dir) {
4110 snprintf(path,
sizeof(path),
"%s/%s", root_dir, filename);
4112 strlcpy(path, filename,
sizeof(path));
4115 fp = fopen(path,
"r");
4133 char *p = strchr(
buffer,
'\n');
4141 if (!lr)
goto finish;
4158 switch (result.
rcode) {
4178 if (fp != stdin)
goto finish;
4191 ERROR(
"%s[%" PRIu32
"]: Unknown command: %s", cc->
path, cc->
lineno, p);
4238 if (opened_fp) fclose(fp);
4249 ERROR(
"Empty input file is invalid");
4262 INFO(
"usage: %s [options] (-|<filename>[:<lines>] [ <filename>[:<lines>]])",
name);
4264 INFO(
" -d <confdir> Set user dictionary path (defaults to " CONFDIR
").");
4265 INFO(
" -D <dictdir> Set main dictionary path (defaults to " DICTDIR
").");
4266 INFO(
" -x Debugging mode.");
4267 INFO(
" -f Print features.");
4268 INFO(
" -c Print commands.");
4269 INFO(
" -h Print help text.");
4270 INFO(
" -M Show talloc memory report.");
4271 INFO(
" -p Allow xlat_purify");
4272 INFO(
" -o <receipt_file> Create the <receipt_file> as a 'success' exit.");
4273 INFO(
" -m <message> On failure, print <message> followed by the failed file.");
4274 INFO(
" -w <output_file> Write 'corrected' output to <output_file>.");
4275 INFO(
"Where <filename> is a file containing one or more commands and '-' indicates commands should be read from stdin.");
4276 INFO(
"Ranges of <lines> may be specified in the format <start>[-[<end>]][,]");
4316 ERROR(
"Invalid line start number");
4322 ERROR(
"Out of order line numbers (%u > %u) not allowed",
max, lr->
start);
4332 if (!fr_sbuff_is_in_charset(
in, tokens)) {
4333 ERROR(
"Unexpected text \"%pV\"",
4360 lr->
end = UINT32_MAX;
4365 ERROR(
"Invalid line end number");
4369 ERROR(
"Line end must be >= line start (%u < %u)", lr->
end, lr->
start);
4373 ERROR(
"Out of order line numbers (%u > %u) not allowed",
max, lr->
end);
4389 char *p, *dir = NULL, *
file;
4390 int ret = EXIT_SUCCESS;
4399 fr_sbuff_marker(&file_start, &
in);
4400 fr_sbuff_marker(&file_end, &
in);
4401 fr_sbuff_marker(&dir_end, &
in);
4420 return EXIT_FAILURE;
4440 (strncmp(path,
"src/tests/unit/", 15) == 0)) {
4441 p =
UNCONST(
char *, strchr(path + 15,
'/'));
4443 printf(
"UNIT-TEST %s\n", path + 15);
4445 char *q =
UNCONST(
char *, strchr(p + 1,
'/'));
4450 printf(
"UNIT-TEST %s - %s\n", path + 15, p + 1);
4454 printf(
"UNIT-TEST %s - %s\n", p + 1, q + 1);
4469 return EXIT_FAILURE;
4475 if ((ret == EXIT_SUCCESS) &&
receipt_dir && dir) {
4476 char *touch_file, *subdir;
4478 if (strncmp(dir,
"src/", 4) == 0) {
4487 p = strchr(touch_file,
'/');
4490 if (
fr_mkdir(NULL, touch_file, (
size_t) (p - touch_file), S_IRWXU, NULL, NULL) < 0) {
4491 fr_perror(
"unit_test_attribute - failed to make directory %.*s - ",
4492 (
int) (p - touch_file), touch_file);
4495 return EXIT_FAILURE;
4498 if (
fr_touch(NULL, touch_file, 0644,
true, 0755) <= 0) {
4499 fr_perror(
"unit_test_attribute - failed to create receipt file %s - ",
4511 if (ret != EXIT_SUCCESS) {
4523 return EXIT_FAILURE;
4543 for (p = str; *p !=
'\0'; p++) {
4561 int ret = EXIT_SUCCESS;
4563 TALLOC_CTX *thread_ctx;
4564 bool exit_now =
false;
4572 bool do_features =
false;
4573 bool do_commands =
false;
4574 bool do_usage =
false;
4577 char const *error_str = NULL, *fail_str = NULL;
4619 while ((c = getopt(argc, argv,
"cd:D:F:fxm:Mhpo:S:w:")) != -1)
switch (c) {
4629 config.dict_dir = optarg;
4633 config.fuzzer_base_dir = optarg;
4646 talloc_enable_leak_report();
4650 p = strrchr(optarg,
'/');
4673 fprintf(stderr,
"Invalid option to -S\n");
4685 argc -= (optind - 1);
4686 argv += (optind - 1);
4691 if (do_usage || do_features || do_commands) {
4710 if (fr_openssl_init() < 0) {
4779 ERROR(
"Failed registering xlat");
4789 ERROR(
"Failed registering xlat");
4806 ERROR(
"Can only use '-w' with input files");
4812 }
else if ((argc == 2) && (strcmp(argv[1],
"-") == 0)) {
4818 while (fgets(
buffer,
sizeof(
buffer) - 1, stdin) != NULL) {
4822 while (isspace((
unsigned int) *p)) p++;
4824 if (!*p || (*p ==
'#'))
continue;
4844 if ((ret != EXIT_SUCCESS) || exit_now)
break;
4847 }
else if (argc > 1) {
4852 ERROR(
"Receipt file cannot be one of the input files");
4860 for (i = 1; i < argc; i++) {
4862 if ((ret != EXIT_SUCCESS) || exit_now)
break;
4871#undef EXIT_WITH_FAILURE
4872#define EXIT_WITH_FAILURE \
4874 ret = EXIT_FAILURE; \
4875 error_str = fr_strerror(); \
4876 if (error_str) error_str = talloc_strdup(NULL, error_str); \
4897 fail_str =
"cleaning up dynamically loaded libraries";
4902 fail_str =
"cleaning up dictionaries";
4907 fail_str =
"creating receipt file";
4916 fail_str =
"cleaning up all memory";
4920 if (ret != EXIT_SUCCESS) {
4922 if (!fail_str) fail_str =
"in an input file";
4923 if (!error_str) error_str =
"";
4925 fprintf(stderr,
"unit_test_attribute failed %s - %s\n", fail_str, error_str);
4936 fputc(
'\n', stdout);
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 uint8_t request[4]
#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, unsigned long fault_signals)
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...
#define PANIC_ACTION_SIGNALS
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.
void fr_dict_debug(FILE *fp, fr_dict_t const *dict)
fr_dict_attr_err_t
Errors returned by attribute lookup functions.
@ FR_DICT_ATTR_OK
No error.
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.
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.
int fr_dict_internal_afrom_file(fr_dict_t **out, char const *dict_subdir, char const *dependent)
(Re-)Initialize the special internal dictionary
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)
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
void fr_rand_seed(uint64_t seed)
Seed the random number generator with a fixed value.
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.
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.
fr_sbuff_err_t fr_sbuff_out_bool(bool *out, fr_sbuff_t *in)
See if the string contains a truth value.
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(_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)
static size_t encode_pair(command_result_t *result, command_file_ctx_t *cc, char *data, fr_test_point_pair_encode_t *tp, void *encode_ctx, fr_pair_list_t *head, bool truncate, char const *fuzzer_text)
Encode a list of pairs, writing the result to the data buffer as hex.
#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 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)
@ 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 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.
#define SBUFF_RETURN_OK_WITH_ERROR(_function,...)
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_rand_seed(command_result_t *result, UNUSED command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Seed the random number generator, so fr_rand() returns a fixed sequence.
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 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_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 size_t command_attr_name(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, size_t inlen)
Print attribute information.
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 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 void shell_word_print(FILE *fp, char const *str)
Print a string as a single shell word.
static size_t command_decode_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_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 size_t command_attr_oid(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, size_t inlen)
Print attribute information.
static char const * receipt_file
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.
static size_t decode_pair(command_result_t *result, command_file_ctx_t *cc, char *data, char *in, size_t inlen, fr_pair_t **head_p, char **hex_p)
Decode hex data into a list of pairs.
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_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_decode_pair(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, size_t inlen)
#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)
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)
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 char const * fail_message
static size_t command_attr_type(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, size_t inlen)
Print attribute information.
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_attr_flags(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, size_t inlen)
Print attribute information.
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)
static size_t command_attr_children(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, size_t inlen)
Print attribute information.
fr_dict_t * test_internal_dict
Internal dictionary of test_gctx.
static size_t command_de_encode_pair(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, size_t inlen)
Decode hex data into pairs, and then encode the pairs again.
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.
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
ssize_t 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.
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.
unsigned int required
Argument must be present, and non-empty.
#define XLAT_ARG_PARSER_TERMINATOR
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_concat(char const *prefix, char const *line_sep)
Print the stack of string buffers to a thread local buffer.
#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_cmp_ret_t fr_value_box_cmp(fr_value_box_t const *a, fr_value_box_t const *b)
Compare two values.
fr_slen_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(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.
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.
fr_slen_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.
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.
static fr_sbuff_err_t char size_t fr_sbuff_t * in
#define fr_value_box_mark_safe_for(_box, _safe_for)
static fr_sbuff_err_t char size_t fr_sbuff_t size_t max
#define fr_box_strvalue_len(_val, _len)
static fr_sbuff_err_t char ** out
static fr_sbuff_err_t char size_t * len
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
#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.