21RCSID(
"$Id: f5daddbef7cacf88728d0dc802323a7ce3d1d5d3 $")
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/util/atexit.h>
31#include <freeradius-devel/util/dl.h>
32#include <freeradius-devel/util/types.h>
34#include <json-c/json.h>
56#define quote_name(_t) fr_token_to_enum_str(_t)
69 if (dladdr(fn, &info) == 0)
return NULL;
70 if (!info.dli_sname)
return NULL;
72 name = info.dli_sname;
74 return json_object_new_string(
name);
79 struct json_object *o;
81 if (!
value)
return NULL;
82 o = json_object_new_object();
83 json_object_object_add(o,
"value", json_object_new_string(
value));
84 json_object_object_add(o,
"quote", json_object_new_string(
quote_name(quote)));
95 struct json_object *a = json_object_new_array();
97 for (
size_t bit = 0; bit < 32; bit++) {
98 uint64_t
mask = UINT64_C(1) << bit;
101 if (!(flags &
mask))
continue;
104 json_object_array_add(a, json_object_new_string(
name));
113 struct json_object *o = json_object_new_object();
116 json_object_object_add(o,
"name1", r->
name1 ? json_object_new_string(r->
name1) : NULL);
117 json_object_object_add(o,
"name2", r->
name2 ? json_object_new_string(r->
name2) : NULL);
124 json_object_object_add(o,
"subcs",
135 struct json_object *a = json_object_new_array();
147 struct json_object *a = json_object_new_array();
149 for (
size_t bit = 0; bit < 32; bit++) {
150 uint64_t
mask = UINT64_C(1) << bit;
153 if (!(flags &
mask))
continue;
156 json_object_array_add(a, json_object_new_string(
name));
163 if (!
name)
return NULL;
165 return json_object_new_string(
name);
172 struct json_object *o = json_object_new_object();
179 struct json_object *s = json_object_new_object();
181 json_object_object_add(s,
"func",
func_symbol((
void const *)r->section.func));
182 json_object_object_add(s,
"subcs",
184 json_object_new_array());
185 json_object_object_add(o,
"section", s);
187 struct json_object *p = json_object_new_object();
188 struct json_object *parsed = json_object_new_object();
196 json_object_object_add(p,
"cast_type",
200 json_object_object_add(p,
"type",
202 json_object_object_add(p,
"dflt",
build_dflt(r->pair.dflt, r->pair.dflt_quote));
203 json_object_object_add(p,
"func",
func_symbol((
void const *)r->pair.func));
205 json_object_object_add(parsed,
"type",
207 json_object_object_add(p,
"parsed", parsed);
209 json_object_object_add(o,
"pair", p);
217 struct json_object *a = json_object_new_array();
229 struct json_object *a = json_object_new_array();
233 struct json_object *entry = json_object_new_object();
234 struct json_object *section = json_object_new_object();
238 json_object_object_add(entry,
"section", section);
239 json_object_object_add(entry,
"method",
func_symbol((
void const *)b->method));
240 json_object_object_add(entry,
"env",
241 (b->method_env && b->method_env->env) ?
243 json_object_new_array());
245 json_object_array_add(a, entry);
261 struct json_object *entry;
272 entry = json_object_new_object();
273 json_object_object_add(entry,
"module", json_object_new_string(m->
common.name ? m->
common.name : bare_name));
279static int dump_module(
struct json_object *modules,
char const *bare_name)
286 fprintf(stderr,
"rlm_%s: pipe failed: %s\n", bare_name,
fr_syserror(errno));
294 fprintf(stderr,
"rlm_%s: fork failed: %s\n", bare_name,
fr_syserror(errno));
299 struct json_object *entry;
304 fprintf(stderr,
"rlm_%s: build_module failed\n", bare_name);
309 char const *s = json_object_to_json_string_ext(entry, JSON_C_TO_STRING_PLAIN |
310 JSON_C_TO_STRING_NOSLASHESCAPE);
311 size_t remaining = strlen(s);
314 while (remaining > 0) {
315 n = write(fds[1], s, remaining);
317 fprintf(stderr,
"rlm_%s: write to pipe failed: %s\n",
325 json_object_put(entry);
335 while ((
n = read(fds[0], buf +
used,
sizeof(buf) - 1 -
used)) > 0) {
337 if (
used >=
sizeof(buf) - 1)
break;
342 waitpid(pid, &status, 0);
345 fprintf(stderr,
"rlm_%s: child %s (status=0x%x), skipping\n", bare_name,
346 WIFEXITED(status) ?
"exited non-zero" :
"crashed", status);
351 struct json_object *entry = json_tokener_parse(buf);
353 json_object_array_add(modules, entry);
356 fprintf(stderr,
"rlm_%s: failed to parse child JSON\n", bare_name);
369static int discover_modules(TALLOC_CTX *ctx,
char const *dir,
char ***out_names,
size_t *out_count)
374 size_t n = 0, alloc = 0;
379 fprintf(stderr,
"Failed opening module dir %s: %s\n", dir,
fr_syserror(errno));
383 while ((e = readdir(d)) != NULL) {
384 size_t nlen = strlen(e->d_name);
386 if (nlen <= extlen)
continue;
387 if (strcmp(e->d_name + nlen - extlen,
DL_EXTENSION) != 0)
continue;
388 if (strncmp(e->d_name,
"rlm_", 4) != 0)
continue;
391 alloc = alloc ? alloc * 2 : 16;
408 return strcmp(*(
char *
const *)a, *(
char *
const *)b);
413 FILE *fp = (rcode == 0) ? stdout : stderr;
416 "Usage: radmod2json [options]\n"
417 " -m <list> Comma-separated list of module names without rlm_ prefix\n"
418 " (default: every rlm_*" DL_EXTENSION " under the module directory).\n"
419 " -M <dir> Module directory to load from (default: " LIBDIR
").\n"
420 " -D <dict> Dictionary directory (default: " DICTDIR
").\n"
421 " -o <file> Write JSON to <file> (default stdout).\n"
422 " -x Enable debug output (repeatable).\n"
427int main(
int argc,
char *argv[])
430 int rcode = EXIT_SUCCESS;
431 char const *modules_arg = NULL;
432 char const *output_file = NULL;
433 char const *module_dir = LIBDIR;
434 char const *dict_dir = DICTDIR;
446 while ((c = getopt(argc, argv,
"D:hm:M:o:x")) != -1) {
454 modules_arg = optarg;
460 output_file = optarg;
499 for (p = list; (tok =
strsep(&p,
",")) != NULL;) {
500 char const *bare = tok;
502 if (!*bare)
continue;
503 if (strncmp(bare,
"rlm_", 4) == 0) bare += 4;
504 if (n_names == alloc) {
505 alloc = alloc ? alloc * 2 : 16;
518 struct json_object *root = json_object_new_object();
519 struct json_object *modules = json_object_new_array();
520 char const *json_str;
522 json_object_object_add(root,
"modules", modules);
524 for (
size_t i = 0; i < n_names; i++) {
528 json_str = json_object_to_json_string_ext(root, JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_NOSLASHESCAPE);
530 FILE *
out = fopen(output_file,
"w");
532 fprintf(stderr,
"Failed opening %s: %s\n", output_file,
fr_syserror(errno));
535 fputs(json_str,
out);
539 fputs(json_str, stdout);
543 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_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.
static TALLOC_CTX * autofree
@ 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)
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