26 RCSID(
"$Id: fc277cff965464d4907475169694f931c5683d08 $")
30 #include <freeradius-devel/io/test_point.h>
31 #include <freeradius-devel/server/cf_parse.h>
32 #include <freeradius-devel/server/cf_util.h>
33 #include <freeradius-devel/server/command.h>
34 #include <freeradius-devel/server/dependency.h>
35 #include <freeradius-devel/server/dl_module.h>
36 #include <freeradius-devel/server/log.h>
37 #include <freeradius-devel/server/map.h>
38 #include <freeradius-devel/server/tmpl.h>
40 # include <freeradius-devel/tls/base.h>
42 #include <freeradius-devel/unlang/base.h>
43 #include <freeradius-devel/unlang/xlat.h>
44 #include <freeradius-devel/unlang/xlat_func.h>
45 #include <freeradius-devel/util/atexit.h>
46 #include <freeradius-devel/util/base64.h>
47 #include <freeradius-devel/util/calc.h>
48 #include <freeradius-devel/util/conf.h>
49 #include <freeradius-devel/util/dict.h>
50 #include <freeradius-devel/util/dns.h>
51 #include <freeradius-devel/util/file.h>
52 #include <freeradius-devel/util/log.h>
53 #include <freeradius-devel/util/misc.h>
54 #include <freeradius-devel/util/pair_legacy.h>
55 #include <freeradius-devel/util/sha1.h>
56 #include <freeradius-devel/util/syserror.h>
61 # undef HAVE_SANITIZER_LSAN_INTERFACE_H
63 #ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
64 # include <sanitizer/asan_interface.h>
79 #ifndef HAVE_SANITIZER_LSAN_INTERFACE_H
80 # define ASAN_POISON_MEMORY_REGION(_start, _end)
81 # define ASAN_UNPOISON_MEMORY_REGION(_start, _end)
84 #define EXIT_WITH_FAILURE \
90 #define COMMAND_OUTPUT_MAX 8192
92 #define RETURN_OK(_len) \
94 result->rcode = RESULT_OK; \
95 result->file = __FILE__; \
96 result->line = __LINE__; \
100 #define RETURN_OK_WITH_ERROR() \
102 result->rcode = RESULT_OK; \
103 result->file = __FILE__; \
104 result->line = __LINE__; \
105 result->error_to_data = true; \
109 #define RETURN_NOOP(_len) \
111 result->rcode = RESULT_NOOP; \
112 result->file = __FILE__; \
113 result->line = __LINE__; \
117 #define RETURN_SKIP_FILE() \
119 result->rcode = RESULT_SKIP_FILE; \
120 result->file = __FILE__; \
121 result->line = __LINE__; \
125 #define RETURN_PARSE_ERROR(_offset) \
127 result->rcode = RESULT_PARSE_ERROR; \
128 result->offset = _offset; \
129 result->file = __FILE__; \
130 result->line = __LINE__; \
134 #define RETURN_COMMAND_ERROR() \
136 result->rcode = RESULT_COMMAND_ERROR; \
137 result->file = __FILE__; \
138 result->line = __LINE__; \
142 #define RETURN_MISMATCH(_len) \
144 result->rcode = RESULT_MISMATCH; \
145 result->file = __FILE__; \
146 result->line = __LINE__; \
150 #define RETURN_EXIT(_ret) \
152 result->rcode = RESULT_EXIT; \
153 result->ret = _ret; \
154 result->file = __FILE__; \
155 result->line = __LINE__; \
162 #define DEFAULT_BUFFER_SIZE 1024
251 size_t data_used,
char *
in,
size_t inlen);
276 static int process_file(
bool *exit_now, TALLOC_CTX *ctx,
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,
350 ERROR(
" got : %.*s", (
int) got_len, got);
351 ERROR(
" expected : %.*s", (
int) expected_len, expected);
357 while (*g && *e && (*g == *e)) {
362 spaces = talloc_zero_array(NULL,
char, (e - expected) + 1);
364 if (((e - expected) < 80) && (expected_len < 80)) {
367 ERROR(
" %s^ differs here (%zu) ... %.*s ...",
spaces, e - expected,
380 char *end = p + outlen;
388 for (i = 0; i <
inlen; i++) {
406 char *end =
out + outlen;
440 file_fd = openat(fd_dir, digest_str, O_RDWR | O_CREAT | O_TRUNC,
441 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
448 if (flock(file_fd, LOCK_EX) < 0) {
457 ret = write(file_fd,
data, data_len);
461 (void)flock(file_fd, LOCK_UN);
462 unlinkat(fd_dir, digest_str, 0);
468 (void)flock(file_fd, LOCK_UN);
480 static char const hextab[] =
"0123456789abcdef";
489 while (*p && (outlen > 0)) {
495 *(output++) = *(p++);
523 ERROR(
"String is not terminated");
533 for (p =
buffer; *p !=
'\0'; p++) {
534 if (*p ==
'{')
depth++;
537 if (
depth == 0)
break;
542 ERROR(
"No trailing '}' in string starting with \"%s\"",
buffer);
553 if (slen <= 0)
return 0;
562 uint8_t *out_p =
out, *out_end = out_p + outlen;
567 if (out_p >= out_end) {
584 if (!c2)
goto bad_input;
598 ERROR(
"Invalid character following attribute definition");
622 if (sublen <= 0)
return 0;
638 slen =
hex_to_bin(output, outlen, p, strlen(p));
651 attr = strtol(
buffer, endptr, 10);
653 ERROR(
"No valid number found in string starting with \"%s\"",
buffer);
658 ERROR(
"Nothing follows attribute number");
662 if ((attr <= 0) || (attr > 256)) {
663 ERROR(
"Attribute number is out of valid range");
675 ERROR(
"Invalid separator before vendor id");
679 vendor = strtol(
buffer + 1, endptr, 10);
680 if (*endptr == (
buffer + 1)) {
681 ERROR(
"No valid vendor number found");
686 ERROR(
"Nothing follows vendor number");
690 if ((vendor <= 0) || (vendor > (1 << 24))) {
691 ERROR(
"Vendor number is out of valid range");
695 if (**endptr !=
'.') {
696 ERROR(
"Invalid data following vendor number");
711 if (attr == 0)
return 0;
724 if (slen <= 0)
return slen;
725 if (slen > (255 - 2)) {
726 ERROR(
"TLV data is too long");
742 if (vendor == 0)
return 0;
745 output[1] = (vendor >> 16) & 0xff;
746 output[2] = (vendor >> 8) & 0xff;
747 output[3] = vendor & 0xff;
750 if (slen <= 0)
return slen;
751 if (slen > (255 - 6)) {
752 ERROR(
"VSA data is too long");
767 if (vendor == 0)
return 0;
770 if (attr == 0)
return 0;
773 output[1] = (vendor >> 16) & 0xff;
774 output[2] = (vendor >> 8) & 0xff;
775 output[3] = vendor & 0xff;
779 if (slen <= 0)
return slen;
791 if (attr == 0)
return 0;
800 if (slen <= 0)
return slen;
801 if (slen > (255 - 3)) {
802 ERROR(
"Extended Attr data is too long");
816 if (attr == 0)
return 0;
825 if (slen <= 0)
return slen;
832 if (slen <= 0)
return slen;
836 int sublen = 255 - output[1];
838 if (slen <= sublen) {
846 memmove(output + 255 + 4, output + 255, slen);
847 memcpy(output + 255, output, 4);
867 if (attr == 0)
return 0;
874 sublen =
encode_vsa(p, output + 2, outlen - 2);
876 }
else if ((attr < 241) || (attr > 246)) {
881 ERROR(
"Invalid data following attribute number");
894 if (sublen <= 0)
return sublen;
895 if (sublen > (255 -2)) {
896 ERROR(
"RFC Data is too long");
901 return slen + sublen;
920 snprintf(dl_name,
sizeof(dl_name),
"libfreeradius-%s", proto_name);
921 if (
dl) TALLOC_FREE(
dl);
925 fr_perror(
"Failed to link to library \"%s\"", dl_name);
933 return strlen(proto_name);
943 fr_strerror_printf(
"No protocol library loaded. Specify library with \"load <proto name>\"");
952 if ((*p ==
'.') && (q = strchr(p,
' ')) && (q != (p + 1)) && ((
size_t)(q - p) <
sizeof(
buffer))) {
1006 q = strchr(
in,
' ');
1013 dir = default_subdir;
1109 printf(
"%s ", info->
parents[i]);
1112 printf(
":%s ", info->
name);
1121 void *walk_ctx = NULL;
1123 printf(
"Command hierarchy --------");
1126 printf(
"Command list --------");
1132 #define CLEAR_TEST_POINT(_cc) \
1134 talloc_free_children((_cc)->tmp_ctx); \
1154 bool exit_now =
false;
1158 fprintf(stderr,
"Can't do $INCLUDE with -w %s\n",
write_filename);
1162 q = strrchr(cc->
path,
'/');
1217 char const *p, *
value, *end;
1228 if (match_len == 0)
return 0;
1251 if (match_len == 0)
return 0;
1302 char const *p, *
value, *end;
1327 if (match_len == 0)
return 0;
1329 fr_value_box_list_insert_tail(&group->vb_group, a);
1333 if (strncmp(p,
"->", 2) == 0)
break;
1362 TALLOC_FREE(cc->
path);
1422 table->
syntax = talloc_strdup(table, p);
1459 memcpy(&argv, &info.
argv,
sizeof(argv));
1461 if (info.
argc <= 0) {
1468 len =
snprintf(p, end - p,
"%d - ", num_expansions);
1476 for (i = 0; i < num_expansions; i++) {
1477 len =
snprintf(p, end - p,
"'%s', ", expansions[i]);
1485 if (num_expansions > 0) {
1535 fr_strerror_const(
"Command count would overflow data buffer (shouldn't happen)");
1543 char *
data,
size_t data_used,
char *
in,
size_t inlen)
1546 void *decode_ctx = NULL;
1598 to_dec_end = to_dec + slen;
1606 while (to_dec < to_dec_end) {
1608 (
uint8_t *)to_dec, (to_dec_end - to_dec), decode_ctx);
1615 if ((
size_t)slen > (
size_t)(to_dec_end - to_dec)) {
1616 fr_perror(
"%s: Internal sanity check failed at %d", __FUNCTION__, __LINE__);
1644 char *
data,
size_t data_used,
char *
in,
size_t inlen)
1647 void *decode_ctx = NULL;
1699 to_dec_end = to_dec + slen;
1704 (
uint8_t *)to_dec, (to_dec_end - to_dec), decode_ctx);
1774 next = strchr(p,
',');
1777 enc_p = cc->buffer_start;
1793 cc->buffer_start, cc->buffer_end - cc->buffer_start, enc_p,
true, box, NULL);
1808 next = strchr(p,
',');
1812 if ((cc->fuzzer_dir >= 0) &&
1813 (
dump_fuzzer_data(cc->fuzzer_dir,
in, cc->buffer_start, enc_p - cc->buffer_start) < 0)) {
1823 ssize_t slen, total, i, outlen;
1836 for (i = 0; i < total; i += slen) {
1847 if (i > 0) *(
out++) =
',';
1853 if (outlen <= 0)
goto error;
1876 bool truncate =
false;
1878 size_t iterations = 0;
1903 if (strncmp(p,
"truncate",
sizeof(
"truncate") - 1) == 0) {
1905 p +=
sizeof(
"truncate") - 1;
1938 #ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
1945 DEBUG(
"%s[%d]: Iteration %zu - Safe region %p-%p (%zu bytes), "
1946 "poisoned region %p-%p (%zu bytes)", cc->
filename, cc->
lineno, iterations - 1,
1949 DEBUG(
"%s[%d]: Iteration %zu - Allowed region %p-%p (%zu bytes)",
1950 cc->
filename, cc->
lineno, iterations - 1, enc_p, enc_end, enc_end - enc_p);
1962 if (truncate)
DEBUG(
"%s[%d]: Iteration %zu - Result %zd%s%s",
1966 if (slen < 0)
break;
1971 if (slen > (enc_end - enc_p)) {
1973 (enc_end - enc_p), (
size_t)slen);
1974 #ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
1984 if (slen == 0)
break;
1988 #ifdef HAVE_SANITIZER_LSAN_INTERFACE_H
2000 }
while (truncate && (enc_end < cc->buffer_end));
2062 filename = talloc_asprintf(cc->
tmp_ctx,
"%s/%s", cc->
path,
in);
2064 fp = fopen(filename,
"r");
2193 bool retry_dir =
true;
2203 if (
in[0] ==
'\0') {
2208 fuzzer_dir = talloc_asprintf(cc->
tmp_ctx,
"%s/%s",
2212 fd = open(fuzzer_dir, O_RDONLY);
2214 if (mkdir(fuzzer_dir, 0777) == 0) {
2215 fd = open(fuzzer_dir, O_RDONLY);
2216 if (fd >= 0)
goto stat;
2221 }
else if ((errno == EEXIST) && retry_dir) {
2231 if (fstat(fd, &sdir) < 0) {
2237 if (!(sdir.st_mode & S_IFDIR)) {
2262 char *
name, *tmp = NULL;
2269 if (
in[0] ==
'\0') {
2274 q = strchr(
in,
' ');
2296 char *
data,
size_t data_used,
char *
in,
size_t inlen)
2298 if (strcmp(
in,
data) != 0) {
2320 char *
data,
size_t data_used,
char *
in,
size_t inlen)
2326 slen = regex_compile(cc->
tmp_ctx, ®ex,
in,
inlen, NULL,
false,
true);
2329 ret = regex_exec(regex,
data, data_used, NULL);
2358 size = strtoul(
in, &end, 10);
2359 if ((size == ULONG_MAX) || *end || (size >= 65536)) {
2388 if (strncmp(p,
"xlat_new_functions",
sizeof(
"xlat_new_functions") - 1) == 0) {
2389 p +=
sizeof(
"xlat_new_functions") - 1;
2392 }
else if (strncmp(p,
"tmpl_require_enum_prefix",
sizeof(
"tmpl_require_enum_prefix") - 1) == 0) {
2393 p +=
sizeof(
"tmpl_require_enum_prefix") - 1;
2409 if ((strcmp(p,
"yes") == 0) || (strcmp(p,
"true") == 0) || (strcmp(p,
"1") == 0)) {
2412 }
else if ((strcmp(p,
"no") == 0) || (strcmp(p,
"false") == 0) || (strcmp(p,
"0") == 0)) {
2431 if (
in[0] ==
'\0') {
2433 "Use -f to print features");
2439 DEBUG(
"Skipping, missing feature \"%s\"",
in);
2450 char *
data,
size_t data_used,
char *
in,
size_t inlen)
2453 switch (result->
rcode) {
2458 ERROR(
"%s[%d]: %.*s: returned 'ok', where we expected 'result-mismatch'",
2622 &rules->
attr.namespace,
2649 &rules->
attr.request_def,
2675 static size_t tmpl_rule_func_table_len =
NUM_ELEMENTS(tmpl_rule_func_table);
2715 if (match_len == 0) {
2766 char fuzzer_buffer[1024];
2767 char *fuzzer_p = fuzzer_buffer, *fuzzer_end = fuzzer_p +
sizeof(fuzzer_buffer);
2771 strlcpy(fuzzer_p,
data, slen > fuzzer_end - fuzzer_p ? fuzzer_end - fuzzer_p : slen);
2774 (
uint8_t *)fuzzer_buffer, strlen(fuzzer_buffer)) < 0) {
2785 char *
data,
size_t data_used,
char *
in,
size_t inlen)
2789 bool locked =
false;
2793 fd = open(path, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
2799 if (locked) (void)flock(fd, LOCK_UN);
2805 if (flock(fd, LOCK_EX) < 0) {
2813 ret = write(fd,
data, data_used);
2821 (void)flock(fd, LOCK_UN);
2836 size_t input_len = strlen(
in), escaped_len;
2856 if (((
size_t) dec_len != input_len)) {
2873 size_t input_len = strlen(
in), escaped_len;
2891 if (((
size_t) dec_len != input_len)) {
2908 size_t input_len = strlen(
in), escaped_len;
2933 if (((
size_t) dec_len != input_len)) {
2939 DEBUG(
"Before purify --------------------------------------------------");
2946 DEBUG(
"After purify --------------------------------------------------");
2967 size_t input_len = strlen(
in);
2990 for (i = 0, p =
data; i < argc; i++) {
3006 .usage =
"#<string>",
3007 .description =
"A comment - not processed"
3011 .usage =
"$INCLUDE <relative_path>",
3012 .description =
"Execute a test file"
3016 .usage =
"allow-unresolved yes|no",
3017 .description =
"Allow or disallow unresolved attributes in xlats and references"
3021 .usage =
"calc <type1> <value1> <operator> <type2> <value2> -> <output-type>",
3022 .description =
"Perform calculations on value boxes",
3026 .usage =
"calc_nary op <type1> <value1> <type2> <value2> ... -> <output-type>",
3027 .description =
"Perform calculations on value boxes",
3031 .usage =
"cd <path>",
3032 .description =
"Change the directory for loading dictionaries and $INCLUDEs, writing the full path into the data buffer on success"
3037 .description =
"Explicitly zero out the contents of the data buffer"
3041 .usage =
"command add <string>",
3042 .description =
"Add a command to a radmin command tree"
3046 .usage =
"command tab <string>",
3047 .description =
"Test a tab completion against a radmin command tree"
3051 .usage =
"condition <string>",
3052 .description =
"Parse and reprint a condition, writing the normalised condition to the data buffer on success"
3057 .description =
"Write the number of executed tests to the data buffer. A test is any command that should return 'ok'"
3061 .usage =
"decode-dns-label (-|<hex_string>)",
3062 .description =
"Decode one or more DNS labels, writing the decoded strings to the data buffer.",
3066 .usage =
"decode-pair[.<testpoint_symbol>] (-|<hex_string>)",
3067 .description =
"Produce an attribute value pair from a binary value using a specified protocol decoder. Protocol must be loaded with \"load <protocol>\" first",
3071 .usage =
"decode-proto[.<testpoint_symbol>] (-|<hex string>)",
3072 .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",
3076 .usage =
"dictionary <string>",
3077 .description =
"Parse dictionary attribute definition, writing \"ok\" to the data buffer if successful",
3081 .usage =
"dictionary-dump",
3082 .description =
"Print the contents of the currently active dictionary to stdout",
3086 .usage =
"encode-dns-label (-|string[,string])",
3087 .description =
"Encode one or more DNS labels, writing a hex string to the data buffer.",
3091 .usage =
"encode-pair[.<testpoint_symbol>] [truncate] (-|<attribute> = <value>[,<attribute = <value>])",
3092 .description =
"Encode one or more attribute value pairs, writing a hex string to the data buffer. Protocol must be loaded with \"load <protocol>\" first",
3096 .usage =
"encode-proto[.<testpoint_symbol>] (-|<attribute> = <value>[,<attribute = <value>])",
3097 .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"
3102 .description =
"Mark the end of a 'virtual' file. Used to prevent 'need-feature' skipping all the content of a command stream or file",
3106 .usage =
"exit[ <num>]",
3107 .description =
"Exit with the specified error number. If no <num> is provided, process will exit with 0"
3111 .usage =
"fuzzer-out <dir>",
3112 .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",
3116 .usage =
"load-dictionary <name> [<dir>]",
3117 .description =
"Load an additional dictionary from the same directory as the input file. "
3118 "Optionally you can specify a full path via <dir>. ",
3122 .usage =
"match <string>",
3123 .description =
"Compare the contents of the data buffer with an expected value"
3127 .usage =
"match-regex <regex>",
3128 .description =
"Compare the contents of the data buffer with a regular expression"
3132 .usage =
"max-buffer-size[ <integer>]",
3133 .description =
"Limit the maximum temporary buffer space available for any command which uses it"
3137 .usage =
"migrate <flag>=<value>",
3138 .description =
"Set migration flag"
3142 .usage =
"need-feature <feature>",
3143 .description =
"Skip the contents of the current file, or up to the next \"eof\" command if a particular feature is not available"
3148 .description =
"Negate the result of a command returning 'ok'"
3152 .usage =
"pair ... data ...",
3153 .description =
"Parse a list of pairs",
3157 .usage =
"proto <protocol>",
3158 .description =
"Switch the active protocol to the one specified, unloading the previous protocol",
3162 .usage =
"proto-dictionary <proto_name> [<proto_dir>]",
3163 .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.",
3169 .usage =
"proto-dictionary-root[ <root_attribute>]",
3170 .description =
"Set the root attribute for the current protocol dictionary. "
3171 "If no attribute name is provided, the root will be reset to the root of the current dictionary",
3175 .usage =
"raw <string>",
3176 .description =
"Create nested attributes from OID strings and values"
3180 .usage =
"read_file <filename>",
3181 .description =
"Read a list of pairs from a file",
3185 .usage =
"returned",
3186 .description =
"Print the returned value to the data buffer"
3191 .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]",
3192 .description =
"Alter the tmpl parsing rules for subsequent tmpl parsing commands in the same command context"
3196 .usage =
"touch <file>",
3197 .description =
"Touch a file, updating its created timestamp. Useful for marking the completion of a series of tests"
3201 .usage =
"value <type> <string>",
3202 .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"
3206 .usage =
"write <file>",
3207 .description =
"Write the contents of the data buffer (as a raw binary string) to the specified file"
3211 .usage =
"xlat <string>",
3212 .description =
"Parse then print an xlat expansion, writing the normalised xlat expansion to the data buffer"
3217 .usage =
"xlat_argv <string>",
3218 .description =
"Parse then print an xlat expansion argv, writing the normalised xlat expansion arguments to the data buffer"
3223 .usage =
"xlat_expr <string>",
3224 .description =
"Parse then print an xlat expression, writing the normalised xlat expansion to the data buffer"
3229 .usage =
"xlat_purify <string>",
3230 .description =
"Parse, purify, then print an xlat expression, writing the normalised xlat expansion to the data buffer"
3250 if (!*p || (*p ==
'#')) {
3279 if ((p[0] ==
'-') && ((p[1] ==
' ') || (p[1] ==
'\0'))) {
3280 data_used = command->
func(result, cc,
data, data_used,
data, data_used);
3283 data_used = command->
func(result, cc,
data, data_used, p, strlen(p));
3296 data[data_used] =
'\0';
3314 talloc_free_children(cc->
tmp_ctx);
3344 cc->
tmp_ctx = talloc_named_const(ctx, 0,
"tmp_ctx");
3345 cc->
path = talloc_strdup(cc, path);
3369 fr_perror(
"Failed allocating test dict_gctx");
3375 fr_perror(
"Failed loading test dict_gctx internal dictionary");
3393 cc->
tmp_ctx = talloc_named_const(ctx, 0,
"tmp_ctx");
3404 fr_perror(
"Failed loading test dict_gctx internal dictionary");
3421 static char path[PATH_MAX] =
"";
3431 if (strcmp(filename,
"-") == 0) {
3433 filename =
"<stdin>";
3435 if (root_dir && *root_dir) {
3436 snprintf(path,
sizeof(path),
"%s/%s", root_dir, filename);
3438 strlcpy(path, filename,
sizeof(path));
3441 fp = fopen(path,
"r");
3458 char *p = strchr(
buffer,
'\n');
3466 if (!lr)
goto finish;
3483 switch (result.
rcode) {
3503 if (fp != stdin)
goto finish;
3562 if (fp && (fp != stdin)) fclose(fp);
3581 INFO(
"usage: %s [options] (-|<filename>[:<lines>] [ <filename>[:<lines>]])",
name);
3583 INFO(
" -d <raddb> Set user dictionary path (defaults to " RADDBDIR
").");
3584 INFO(
" -D <dictdir> Set main dictionary path (defaults to " DICTDIR
").");
3585 INFO(
" -x Debugging mode.");
3586 INFO(
" -f Print features.");
3587 INFO(
" -c Print commands.");
3588 INFO(
" -h Print help text.");
3589 INFO(
" -M Show talloc memory report.");
3590 INFO(
" -p Allow xlat_purify");
3591 INFO(
" -r <receipt_file> Create the <receipt_file> as a 'success' exit.");
3592 INFO(
" -w <output_file> Write 'corrected' output to <output_file>.");
3593 INFO(
"Where <filename> is a file containing one or more commands and '-' indicates commands should be read from stdin.");
3594 INFO(
"Ranges of <lines> may be specified in the format <start>[-[<end>]][,]");
3623 static bool tokens[
UINT8_MAX + 1] = { [
','] =
true , [
'-'] =
true };
3636 ERROR(
"Invalid line start number");
3641 if (max > lr->
start) {
3642 ERROR(
"Out of order line numbers (%u > %u) not allowed", max, lr->
start);
3652 if (!fr_sbuff_is_in_charset(
in, tokens)) {
3653 ERROR(
"Unexpected text \"%pV\"",
3680 lr->
end = UINT32_MAX;
3686 ERROR(
"Invalid line end number");
3690 ERROR(
"Line end must be >= line start (%u < %u)", lr->
end, lr->
start);
3693 if (max > lr->
end) {
3694 ERROR(
"Out of order line numbers (%u > %u) not allowed", max, lr->
end);
3715 char const *receipt_file = NULL;
3717 int ret = EXIT_SUCCESS;
3719 TALLOC_CTX *thread_ctx;
3720 bool exit_now =
false;
3723 .raddb_dir = RADDBDIR,
3728 bool do_features =
false;
3729 bool do_commands =
false;
3730 bool do_usage =
false;
3731 bool allow_purify =
false;
3774 while ((c = getopt(argc, argv,
"cd:D:F:fxMhpr:w:")) != -1)
switch (c) {
3780 config.raddb_dir = optarg;
3784 config.dict_dir = optarg;
3788 config.fuzzer_dir = optarg;
3801 talloc_enable_leak_report();
3805 receipt_file = optarg;
3809 allow_purify =
true;
3821 argc -= (optind - 1);
3822 argv += (optind - 1);
3827 if (do_usage || do_features || do_commands) {
3832 if (receipt_file && (
fr_unlink(receipt_file) < 0)) {
3851 if (fr_openssl_init() < 0) {
3911 ERROR(
"Failed registering xlat");
3927 ERROR(
"Can't use '-w' with stdin");
3941 ERROR(
"Can't use '-w' with multiple filenames");
3955 for (i = 1; i < argc; i++) {
3956 char *dir = NULL, *
file;
3965 fr_sbuff_marker(&file_start, &
in);
3966 fr_sbuff_marker(&file_end, &
in);
3967 fr_sbuff_marker(&dir_end, &
in);
4005 if ((ret != 0) || exit_now)
break;
4039 fr_perror(
"unit_test_attribute - dl_loader - ");
4047 if (receipt_file && (ret == EXIT_SUCCESS) && (
fr_touch(NULL, receipt_file, 0644,
true, 0755) <= 0)) {
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(...)
ssize_t fr_base64_encode_nstd(fr_sbuff_t *out, fr_dbuff_t *in, bool add_padding, char const alphabet[static UINT8_MAX])
Base 64 encode binary data.
char const fr_base64_url_alphabet_encode[UINT8_MAX]
#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.
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_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.
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.
#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_command_debug(FILE *fp, fr_cmd_t *head)
int fr_command_add(TALLOC_CTX *talloc_ctx, fr_cmd_t **head, char const *name, void *ctx, fr_cmd_table_t const *table)
Add one command to the global command tree.
int fr_command_tab_expand(TALLOC_CTX *ctx, fr_cmd_t *head, fr_cmd_info_t *info, int max_expansions, char const **expansions)
Get the commands && help at a particular level.
char const * help
help text
int argc
current argument count
fr_cmd_func_t func
function to process this command
char const * syntax
e.g. "STRING"
fr_value_box_t ** box
value_box version of commands.
char const * parent
e.g. "show module"
fr_cmd_tab_t tab_expand
tab expand things in the syntax string
int max_argc
maximum number of arguments
char const * name
e.g. "stats"
char const ** argv
text version of commands
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
static void * fr_dcursor_current(fr_dcursor_t *cursor)
Return the item the cursor current points to.
void fr_disable_null_tracking_on_free(TALLOC_CTX *ctx)
Disable the null tracking context when a talloc chunk is freed.
int fr_fault_setup(TALLOC_CTX *ctx, char const *cmd, char const *program)
Registers signal handlers to execute panic_action on fatal signal.
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
void dependency_features_init(CONF_SECTION *cs)
Initialise core feature flags.
static char const * spaces
int fr_dict_internal_afrom_file(fr_dict_t **out, char const *internal_name, char const *dependent)
(Re-)Initialize the special internal dictionary
int fr_dict_global_ctx_dir_set(char const *dict_dir)
Allow the default dict dir to be changed after initialisation.
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *attr))
Locate a fr_dict_attr_t by its name.
fr_slen_t fr_dict_attr_by_oid_substr(fr_dict_attr_err_t *err, fr_dict_attr_t const **out, fr_dict_attr_t const *parent, fr_sbuff_t *in, fr_sbuff_term_t const *tt))
Resolve an attribute using an OID string.
int fr_dict_protocol_afrom_file(fr_dict_t **out, char const *proto_name, char const *proto_dir, char const *dependent)
(Re)-initialize a protocol dictionary
int fr_dict_str_to_argv(char *str, char **argv, int max_argc)
void fr_dict_debug(fr_dict_t const *dict)
void fr_dict_global_ctx_set(fr_dict_gctx_t const *gctx)
Set a new, active, global dictionary context.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a 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_global_ctx_free(fr_dict_gctx_t const *gctx)
Explicitly free all data associated with a global dictionary context.
int fr_dict_parse_str(fr_dict_t *dict, char *buf, fr_dict_attr_t const *parent)
int fr_dict_read(fr_dict_t *dict, char const *dict_dir, char const *filename)
Read supplementary attribute definitions into an existing dictionary.
fr_dict_attr_err_t
Errors returned by attribute lookup functions.
@ FR_DICT_ATTR_OK
No error.
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.
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_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
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 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 int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of 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.
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.
bool fr_hostname_lookups
hostname -> IP lookups?
bool fr_reverse_lookups
IP -> hostname lookups?
int unlang_global_init(void)
fr_event_list_t * fr_event_list_alloc(TALLOC_CTX *ctx, fr_event_status_cb_t status, void *status_uctx)
Initialise a new event list.
Stores all information relating to an event list.
@ L_DST_STDOUT
Log to stdout.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_MAX
Number of defined data types.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_GROUP
A grouping of other attributes.
@ 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.
#define fr_skip_whitespace(_p)
Skip whitespace ('\t', '\n', '\v', '\f', '\r', ' ')
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)
Read valuepairs from the fp up to End-Of-File.
struct fr_pair_parse_s fr_pair_parse_t
#define is_truncated(_ret, _max)
static const conf_parser_t config[]
void * fr_proto_next_encodable(fr_dlist_head_t *list, 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 TALLOC_CTX * autofree
fr_dict_attr_t const * request_attr_request
int request_global_init(void)
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.
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.
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]
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
void modules_init(char const *lib_dir)
Perform global initialisation for modules.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
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
fr_dict_attr_t const * list_def
Default list to use with unqualified attribute reference.
uint8_t allow_unresolved
Allow attributes that look valid but were not found in the dictionaries.
uint8_t allow_foreign
Allow arguments not found in dict_def.
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
uint8_t allow_unknown
Allow unknown attributes i.e.
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_str_by_value(_table, _number, _def)
Convert an integer to a string.
An element in a lexicographically sorted array of name to num mappings.
An element in a lexicographically sorted array of name to ptr mappings.
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
fr_tp_proto_decode_t func
Decoder for proto layer.
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
fr_dcursor_iter_t next_encodable
Iterator to use to select attributes to encode.
fr_tp_proto_encode_t func
Encoder for proto layer.
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
fr_pair_decode_t func
Decoder for pairs.
fr_pair_encode_t func
Encoder for pairs.
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
Entry point for pair decoders.
Entry point for pair encoders.
Entry point for protocol decoders.
Entry point for protocol encoders.
int fr_time_start(void)
Initialize the local time.
const bool fr_assignment_op[T_TOKEN_LAST]
fr_table_num_ordered_t const fr_tokens_table[]
static int command_func(UNUSED FILE *fp, UNUSED FILE *fp_err, UNUSED void *ctx, UNUSED fr_cmd_info_t const *info)
int fuzzer_dir
File descriptor pointing to a a directory to write fuzzer output.
#define POISONED_BUFFER_START(_p)
static size_t commands_len
static int dump_fuzzer_data(int fd_dir, char const *text, uint8_t const *data, size_t data_len)
static size_t command_touch(command_result_t *result, UNUSED command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Touch a file to indicate a test completed.
uint32_t start
Start of line range.
static ssize_t encode_data_string(char *buffer, uint8_t *output, size_t outlen)
static dl_loader_t * dl_loader
#define BUFF_POISON_START
static ssize_t encode_extended(char *buffer, uint8_t *output, size_t outlen)
int main(int argc, char *argv[])
static fr_dict_t * dictionary_current(command_file_ctx_t *cc)
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.
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_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 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_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.
bool tmpl_require_enum_prefix
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.
static void usage(char const *name)
ssize_t last_ret
Last return value.
#define ASAN_POISON_MEMORY_REGION(_start, _end)
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 int decode_attr(char *buffer, char **endptr)
static size_t command_encode_pair(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, size_t inlen)
fr_dlist_t entry
Entry in the dlist.
uint8_t * buffer_end
Where the non-poisoned region of the buffer ends.
static fr_table_ptr_sorted_t commands[]
#define RETURN_NOOP(_len)
TALLOC_CTX * tmp_ctx
Talloc context for test points.
static size_t command_radmin_tab(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
static size_t command_calc_nary(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, size_t inlen)
Perform calculations on multi-valued ops.
static size_t command_dictionary_dump(command_result_t *result, command_file_ctx_t *cc, UNUSED char *data, size_t data_used, UNUSED char *in, UNUSED size_t inlen)
Print the currently loaded dictionary.
fr_dict_gctx_t const * test_gctx
Dictionary context for test dictionaries.
static size_t command_proto(command_result_t *result, command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Dynamically load a protocol library.
static fr_cmd_t * command_head
static size_t command_write(command_result_t *result, command_file_ctx_t *cc, char *data, size_t data_used, char *in, size_t inlen)
char * path
Current path we're operating in.
static int poisoned_buffer_allocate(TALLOC_CTX *ctx, uint8_t **buff, size_t size)
Allocate a special buffer with poisoned memory regions at the start and end.
#define DEFAULT_BUFFER_SIZE
Default buffer size for a command_file_ctx_t.
static size_t strerror_concat(char *out, size_t outlen)
Concatenate error stack.
static size_t command_match_regex(command_result_t *result, command_file_ctx_t *cc, char *data, size_t data_used, char *in, size_t inlen)
Compare the data buffer against an expected expression.
static size_t command_encode_raw(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Encode a RADIUS attribute writing the result to the data buffer as space separated hexits.
#define RETURN_PARSE_ERROR(_offset)
static ssize_t command_tmpl_rule_allow_unknown(UNUSED TALLOC_CTX *ctx, tmpl_rules_t *rules, fr_sbuff_t *value)
command_config_t const * config
static int _command_ctx_free(command_file_ctx_t *cc)
static command_file_ctx_t * command_ctx_alloc(TALLOC_CTX *ctx, command_config_t const *config, char const *path, char const *filename)
#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 ssize_t encode_tlv(char *buffer, uint8_t *output, size_t outlen)
static int command_walk(UNUSED void *ctx, fr_cmd_walk_info_t *info)
static size_t command_condition_normalise(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, size_t inlen)
Parse and reprint a condition.
static size_t command_count(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, UNUSED char *in, UNUSED size_t inlen)
static fr_table_num_sorted_t command_rcode_table[]
static size_t command_max_buffer_size(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Artificially limit the maximum packet size.
static const fr_token_t token2op[UINT8_MAX+1]
tmpl_rules_t tmpl_rules
To pass to parsing functions.
size_t(* command_func_t)(command_result_t *result, command_file_ctx_t *cc, char *data, size_t data_used, char *in, size_t inlen)
Command to execute.
#define RETURN_MISMATCH(_len)
uint32_t end
End of line range.
static char const hextab[]
static 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)
#define RETURN_EXIT(_ret)
static fr_event_list_t * el
static size_t command_decode_pair(command_result_t *result, command_file_ctx_t *cc, char *data, size_t data_used, char *in, size_t inlen)
static size_t command_xlat_expr(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Parse and reprint an xlat expression expansion.
char const * fuzzer_dir
Where to write fuzzer files.
#define EXIT_WITH_FAILURE
static size_t command_pair(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, size_t inlen)
Parse an print an attribute pair or pair list.
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 ssize_t encode_data(char *p, uint8_t *output, size_t outlen)
#define RETURN_COMMAND_ERROR()
static size_t command_eof(UNUSED command_result_t *result, UNUSED command_file_ctx_t *cc, UNUSED char *data, UNUSED size_t data_used, UNUSED char *in, UNUSED size_t inlen)
Command eof.
static size_t command_match(command_result_t *result, command_file_ctx_t *cc, char *data, size_t data_used, char *in, size_t inlen)
Compare the data buffer to an expected value.
#define ASAN_UNPOISON_MEMORY_REGION(_start, _end)
#define RETURN_SKIP_FILE()
static ssize_t command_tmpl_rule_attr_parent(UNUSED TALLOC_CTX *ctx, tmpl_rules_t *rules, fr_sbuff_t *value)
fr_dict_gctx_t const * dict_gctx
Dictionary gctx to "reset" to.
static ssize_t command_tmpl_rule_list_def(UNUSED TALLOC_CTX *ctx, tmpl_rules_t *rules, fr_sbuff_t *value)
static ssize_t command_tmpl_rule_allow_foreign(UNUSED TALLOC_CTX *ctx, tmpl_rules_t *rules, fr_sbuff_t *value)
static size_t parse_typed_value(command_result_t *result, fr_value_box_t *box, char const **out, char const *in, size_t inlen)
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_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
uint8_t * buffer
Temporary resizable buffer we use for holding non-string data.
static size_t command_no(command_result_t *result, command_file_ctx_t *cc, char *data, size_t data_used, char *in, size_t inlen)
Negate the result of a match command or any command which returns "OK".
static size_t command_rcode_table_len
static size_t command_encode_dns_label(command_result_t *result, command_file_ctx_t *cc, char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
Configuration parameters passed to command functions.
int unlang_thread_instantiate(TALLOC_CTX *ctx)
Create thread-specific data structures for unlang.
fr_slen_t xlat_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_argv(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in, xlat_t const *xlat, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, bool comma, bool allow_attr)
Tokenize an xlat expansion into a series of XLAT_TYPE_CHILD arguments.
int xlat_instantiate(void)
Call instantiation functions for all registered, "permanent" xlats.
int xlat_flatten_compiled_argv(TALLOC_CTX *ctx, xlat_exp_head_t ***argv, xlat_exp_head_t *head)
Turn xlat_tokenize_argv() into an argv[] array, and nuke the input list.
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.
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, fr_value_box_safe_for_t literals_safe_for)
Tokenize an xlat expansion.
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
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_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)
return fr_table_value_by_longest_prefix(NULL, schemes, fr_sbuff_start(&sbuff), fr_sbuff_used(&sbuff), def)
#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(_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.
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
char const * fr_strerror_peek(void)
Get the last library error.
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.
#define fr_type_is_null(_x)
int fr_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
#define RADIUSD_MAGIC_NUMBER
fr_sbuff_escape_rules_t fr_value_escape_double
ssize_t fr_value_box_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, bool tainted)
Convert string value to a fr_value_box_t type.
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, bool tainted)
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.
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_print_quoted(fr_sbuff_t *out, fr_value_box_t const *data, fr_token_t quote)
Print one boxed value to a string with quotes (where needed)
fr_sbuff_parse_rules_t const value_parse_rules_double_quoted
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
fr_sbuff_unescape_rules_t fr_value_unescape_double
#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
xlat_t * xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function.