21RCSID(
"$Id: 7402681c512874c8b9045f43cc94396fb09a8820 $")
23#include <freeradius-devel/server/base.h>
24#include <freeradius-devel/server/cf_parse.h>
25#include <freeradius-devel/server/dl_module.h>
26#include <freeradius-devel/server/module.h>
27#include <freeradius-devel/server/module_rlm.h>
28#include <freeradius-devel/server/section.h>
29#include <freeradius-devel/unlang/call_env.h>
30#include <freeradius-devel/unlang/base.h>
31#include <freeradius-devel/util/atexit.h>
32#include <freeradius-devel/util/dl.h>
33#include <freeradius-devel/util/types.h>
35#include <freeradius-devel/json/base.h>
57#define quote_name(_t) fr_token_to_enum_str(_t)
70 if (dladdr(fn, &info) == 0)
return NULL;
71 if (!info.dli_sname)
return NULL;
73 name = info.dli_sname;
75 return json_object_new_string(
name);
80 struct json_object *o;
82 if (!
value)
return NULL;
83 o = json_object_new_object();
84 json_object_object_add(o,
"value", json_object_new_string(
value));
85 json_object_object_add(o,
"quote", json_object_new_string(
quote_name(quote)));
96 struct json_object *a = json_object_new_array();
98 for (
size_t bit = 0; bit < 32; bit++) {
99 uint64_t
mask = UINT64_C(1) << bit;
102 if (!(flags &
mask))
continue;
105 json_object_array_add(a, json_object_new_string(
name));
114 struct json_object *o = json_object_new_object();
119 json_object_object_add(o,
"name1", name1 ? json_object_new_string(name1) : NULL);
120 json_object_object_add(o,
"name2", name2 ? json_object_new_string(name2) : NULL);
127 json_object_object_add(o,
"subcs",
138 struct json_object *a = json_object_new_array();
156 size_t n = json_object_array_length(ref);
158 for (
size_t i = 0; i <
n; i++) {
159 json_object_array_add(a, json_object_get(json_object_array_get_idx(ref, i)));
161 json_object_put(ref);
173 struct json_object *a = json_object_new_array();
175 for (
size_t bit = 0; bit < 32; bit++) {
176 uint64_t
mask = UINT64_C(1) << bit;
179 if (!(flags &
mask))
continue;
182 json_object_array_add(a, json_object_new_string(
name));
189 if (!
name)
return NULL;
191 return json_object_new_string(
name);
198 struct json_object *o = json_object_new_object();
205 struct json_object *s = json_object_new_object();
207 json_object_object_add(s,
"func",
func_symbol((
void const *)r->section.func));
208 json_object_object_add(s,
"subcs",
210 json_object_new_array());
211 json_object_object_add(o,
"section", s);
213 struct json_object *p = json_object_new_object();
214 struct json_object *parsed = json_object_new_object();
222 json_object_object_add(p,
"cast_type",
226 json_object_object_add(p,
"type",
228 json_object_object_add(p,
"dflt",
build_dflt(r->pair.dflt, r->pair.dflt_quote));
229 json_object_object_add(p,
"func",
func_symbol((
void const *)r->pair.func));
231 json_object_object_add(parsed,
"type",
233 json_object_object_add(p,
"parsed", parsed);
235 json_object_object_add(o,
"pair", p);
243 struct json_object *a = json_object_new_array();
255 struct json_object *a = json_object_new_array();
259 struct json_object *entry = json_object_new_object();
260 struct json_object *section = json_object_new_object();
264 json_object_object_add(entry,
"section", section);
265 json_object_object_add(entry,
"method",
func_symbol((
void const *)b->method));
266 json_object_object_add(entry,
"env",
267 (b->method_env && b->method_env->env) ?
269 json_object_new_array());
271 json_object_array_add(a, entry);
287 struct json_object *entry;
298 entry = json_object_new_object();
299 json_object_object_add(entry,
"module", json_object_new_string(m->
common.name ? m->
common.name : bare_name));
305static int dump_module(
struct json_object *modules,
char const *bare_name)
312 fprintf(stderr,
"rlm_%s: pipe failed: %s\n", bare_name,
fr_syserror(errno));
320 fprintf(stderr,
"rlm_%s: fork failed: %s\n", bare_name,
fr_syserror(errno));
325 struct json_object *entry;
330 fprintf(stderr,
"rlm_%s: build_module failed\n", bare_name);
335 char const *s = json_object_to_json_string_ext(entry, JSON_C_TO_STRING_PLAIN |
336 JSON_C_TO_STRING_NOSLASHESCAPE);
337 size_t remaining = strlen(s);
340 while (remaining > 0) {
341 n = write(fds[1], s, remaining);
343 fprintf(stderr,
"rlm_%s: write to pipe failed: %s\n",
351 json_object_put(entry);
361 while ((
n = read(fds[0], buf +
used,
sizeof(buf) - 1 -
used)) > 0) {
363 if (
used >=
sizeof(buf) - 1)
break;
368 waitpid(pid, &status, 0);
371 fprintf(stderr,
"rlm_%s: child %s (status=0x%x), skipping\n", bare_name,
372 WIFEXITED(status) ?
"exited non-zero" :
"crashed", status);
377 struct json_object *entry = json_tokener_parse(buf);
379 json_object_array_add(modules, entry);
382 fprintf(stderr,
"rlm_%s: failed to parse child JSON\n", bare_name);
395static int discover_modules(TALLOC_CTX *ctx,
char const *dir,
char ***out_names,
size_t *out_count)
400 size_t n = 0, alloc = 0;
405 fprintf(stderr,
"Failed opening module dir %s: %s\n", dir,
fr_syserror(errno));
409 while ((e = readdir(d)) != NULL) {
410 size_t nlen = strlen(e->d_name);
412 if (nlen <= extlen)
continue;
413 if (strcmp(e->d_name + nlen - extlen,
DL_EXTENSION) != 0)
continue;
414 if (strncmp(e->d_name,
"rlm_", 4) != 0)
continue;
417 alloc = alloc ? alloc * 2 : 16;
434 return strcmp(*(
char *
const *)a, *(
char *
const *)b);
439 FILE *fp = (rcode == 0) ? stdout : stderr;
442 "Usage: radmod2json [options]\n"
443 " -m <list> Comma-separated list of module names without rlm_ prefix\n"
444 " (default: every rlm_*" DL_EXTENSION " under the module directory).\n"
445 " -M <dir> Module directory to load from (default: " LIBDIR
").\n"
446 " -D <dict> Dictionary directory (default: " DICTDIR
").\n"
447 " -o <file> Write JSON to <file> (default stdout).\n"
448 " -x Enable debug output (repeatable).\n"
453int main(
int argc,
char *argv[])
456 int rcode = EXIT_SUCCESS;
457 char const *modules_arg = NULL;
458 char const *output_file = NULL;
459 char const *module_dir = LIBDIR;
460 char const *dict_dir = DICTDIR;
472 while ((c = getopt(argc, argv,
"D:hm:M:o:x")) != -1) {
480 modules_arg = optarg;
486 output_file = optarg;
535 for (p = list; (tok =
strsep(&p,
",")) != NULL;) {
536 char const *bare = tok;
538 if (!*bare)
continue;
539 if (strncmp(bare,
"rlm_", 4) == 0) bare += 4;
540 if (n_names == alloc) {
541 alloc = alloc ? alloc * 2 : 16;
554 struct json_object *root = json_object_new_object();
555 struct json_object *modules = json_object_new_array();
556 char const *json_str;
558 json_object_object_add(root,
"modules", modules);
560 for (
size_t i = 0; i < n_names; i++) {
564 json_str = json_object_to_json_string_ext(root, JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_NOSLASHESCAPE);
566 FILE *
out = fopen(output_file,
"w");
568 fprintf(stderr,
"Failed opening %s: %s\n", output_file,
fr_syserror(errno));
571 fputs(json_str,
out);
575 fputs(json_str, stdout);
579 json_object_put(root);
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define NEVER_RETURNS
Should be placed before the function return type.
char const * call_env_flag_to_enum_str(call_env_flags_t mask)
Return the source-identifier name for a single CALL_ENV_FLAG_* bit.
char const * call_env_result_type_to_enum_str(call_env_result_type_t t)
Return the source-identifier name for a call_env_result_type_t value.
char const * call_env_parse_type_to_enum_str(call_env_parse_type_t t)
Return the source-identifier name for a call_env_parse_type_t value.
call_env_flags_t flags
Flags controlling parser behaviour.
char const * name
Of conf pair to pass to tmpl_tokenizer.
@ CALL_ENV_FLAG_SUBSECTION
This is a subsection.
char const * cf_parser_flag_to_enum_str(conf_parser_flags_t mask)
Return the source-identifier name for a single CONF_FLAG_* bit.
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
conf_parser_flags_t flags
Flags which control parsing behaviour.
fr_type_t type
An fr_type_t value, controls the output type.
char const * name2
Second identifier for CONF_SECTION.
fr_token_t quote
Quoting around the default value. Only used for templates.
char const * name1
Name of the CONF_ITEM to parse.
cf_parse_t on_read
Function to call as the item is being read, just after it has been allocated and initialized.
@ CONF_FLAG_REF
reference another conf_parser_t inline in this one
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Defines a CONF_PAIR to C data type mapping.
static NEVER_RETURNS void usage(void)
int fr_dict_internal_afrom_file(fr_dict_t **out, char const *dict_subdir, char const *dependent))
(Re-)Initialize the special internal dictionary
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_module_t * dl_module_alloc(dl_module_t const *parent, char const *name, dl_module_type_t type)
Load a module library using dlopen() or return a previously loaded module from the cache.
dl_module_common_t * exported
Symbol exported by the module, containing its public functions, name and behaviour control flags.
@ DL_MODULE_TYPE_MODULE
Standard loadable module.
int unlang_global_init(void)
@ L_DST_STDERR
Log to stderr.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
char * strsep(char **stringp, char const *delim)
module_method_group_t method_group
named methods
module_t common
Common fields presented by all modules.
#define WIFEXITED(stat_val)
#define WEXITSTATUS(stat_val)
int main(int argc, char *argv[])
static int discover_modules(TALLOC_CTX *ctx, char const *dir, char ***out_names, size_t *out_count)
static struct json_object * build_conf_parser_rules(conf_parser_t const *rules)
static struct json_object * build_dflt(char const *value, fr_token_t quote)
static struct json_object * build_module(char const *bare_name)
static int compare_str(void const *a, void const *b)
static int dump_module(struct json_object *modules, char const *bare_name)
static struct json_object * build_conf_parser_rule(conf_parser_t const *r)
static struct json_object * build_call_env_rule(call_env_parser_t const *r)
static struct json_object * build_method_bindings(module_method_binding_t const *bindings)
char const * radiusd_version
static struct json_object * func_symbol(void const *fn)
static struct json_object * build_call_env_flags(call_env_flags_t flags)
static struct json_object * build_call_env_rules(call_env_parser_t const *rules)
static struct json_object * json_section_ident(char const *name)
static struct json_object * build_conf_parser_flags(conf_parser_flags_t flags)
int request_global_init(void)
module_method_binding_t * bindings
named methods
conf_parser_t const * config
How to convert a CONF_SECTION to a module instance.
section_name_t const * section
Identifier for a section.
Named methods exported by a module.
void modules_init(char const *lib_dir)
Perform global initialisation for modules.
fr_log_dst_t dst
Log destination.
int fd
File descriptor to write messages to.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
#define talloc_strndup(_ctx, _str, _len)
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
#define talloc_strdup(_ctx, _str)
static const char * names[8]
#define FR_DICTIONARY_INTERNAL_DIR
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
char const * fr_type_to_enum_str(fr_type_t t)
Return the source-identifier name for a type (e.g.
int fr_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
#define RADIUSD_VERSION_BUILD(_x)
Create a version string for a utility in the suite of FreeRADIUS utilities.
#define RADIUSD_MAGIC_NUMBER
static size_t char ** out