The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
radmod2json.c
Go to the documentation of this file.
1/*
2 * radmod2json.c Dump FreeRADIUS v4 module conf_parser_t and call_env_parser_t
3 * definitions as JSON.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 *
19 * Copyright (C) 2026 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
20 */
21RCSID("$Id: f5daddbef7cacf88728d0dc802323a7ce3d1d5d3 $")
22
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>
33
34#include <json-c/json.h>
35
36#include <dirent.h>
37#include <dlfcn.h>
38#include <sys/wait.h>
39
40#ifdef HAVE_GETOPT_H
41# include <getopt.h>
42#endif
43
44char const *radiusd_version = RADIUSD_VERSION_BUILD("radmod2json");
45
46/*
47 * Symbolic names for the five quote tokens, keyed by `fr_token_t`.
48 * fr_table_str_by_value() routes us through fr_table_indexed_str_by_num
49 * via the _Generic dispatch on the table type.
50 */
51/*
52 * `fr_token_to_enum_str()` (src/lib/util/token.c) returns the
53 * source-identifier form of the token ("T_BARE_WORD" etc.) which
54 * is what the converter's rule layer greps for.
55 */
56#define quote_name(_t) fr_token_to_enum_str(_t)
57
58/*
59 * Resolve a function pointer back to its source symbol name via dladdr().
60 * macOS C symbols get a leading '_' from the linker - strip that before
61 * emitting.
62 */
63static struct json_object *func_symbol(void const *fn)
64{
65 Dl_info info;
66 char const *name;
67
68 if (!fn) return NULL;
69 if (dladdr(fn, &info) == 0) return NULL;
70 if (!info.dli_sname) return NULL;
71
72 name = info.dli_sname;
73 if (name[0] == '_') name++;
74 return json_object_new_string(name);
75}
76
77static struct json_object *build_dflt(char const *value, fr_token_t quote)
78{
79 struct json_object *o;
80
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)));
85 return o;
86}
87
88/*
89 * Walk every set bit of `flags`; resolve each single-bit mask
90 * through the library's `*_flag_to_enum_str()` lookup. Bits with
91 * no symbolic name are skipped. The result preserves bit-order.
92 */
93static struct json_object *build_conf_parser_flags(conf_parser_flags_t flags)
94{
95 struct json_object *a = json_object_new_array();
96
97 for (size_t bit = 0; bit < 32; bit++) {
98 uint64_t mask = UINT64_C(1) << bit;
99 char const *name;
100
101 if (!(flags & mask)) continue;
103 if (!name) continue;
104 json_object_array_add(a, json_object_new_string(name));
105 }
106 return a;
107}
108
109static struct json_object *build_conf_parser_rules(conf_parser_t const *rules);
110
111static struct json_object *build_conf_parser_rule(conf_parser_t const *r)
112{
113 struct json_object *o = json_object_new_object();
114 bool is_sub = (r->flags & CONF_FLAG_SUBSECTION) != 0;
115
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);
118 json_object_object_add(o, "type", json_object_new_string(fr_type_to_enum_str(r->type)));
119 json_object_object_add(o, "flags", build_conf_parser_flags(r->flags));
120 json_object_object_add(o, "func", func_symbol((void const *)r->func));
121 json_object_object_add(o, "on_read", func_symbol((void const *)r->on_read));
122
123 if (is_sub) {
124 json_object_object_add(o, "subcs",
125 r->subcs ? build_conf_parser_rules(r->subcs) : json_object_new_array());
126 } else {
127 json_object_object_add(o, "dflt", build_dflt(r->dflt, r->quote));
128 }
129
130 return o;
131}
132
133static struct json_object *build_conf_parser_rules(conf_parser_t const *rules)
134{
135 struct json_object *a = json_object_new_array();
136
137 if (rules) {
138 for (conf_parser_t const *r = rules; r->name1; r++) {
139 json_object_array_add(a, build_conf_parser_rule(r));
140 }
141 }
142 return a;
143}
144
145static struct json_object *build_call_env_flags(call_env_flags_t flags)
146{
147 struct json_object *a = json_object_new_array();
148
149 for (size_t bit = 0; bit < 32; bit++) {
150 uint64_t mask = UINT64_C(1) << bit;
151 char const *name;
152
153 if (!(flags & mask)) continue;
155 if (!name) continue;
156 json_object_array_add(a, json_object_new_string(name));
157 }
158 return a;
159}
160
161static struct json_object *json_section_ident(char const *name)
162{
163 if (!name) return NULL;
164 if (name == CF_IDENT_ANY) return json_object_new_string("*");
165 return json_object_new_string(name);
166}
167
168static struct json_object *build_call_env_rules(call_env_parser_t const *rules);
169
170static struct json_object *build_call_env_rule(call_env_parser_t const *r)
171{
172 struct json_object *o = json_object_new_object();
173 bool is_sub = (r->flags & CALL_ENV_FLAG_SUBSECTION) != 0;
174
175 json_object_object_add(o, "name", json_section_ident(r->name));
176 json_object_object_add(o, "flags", build_call_env_flags(r->flags));
177
178 if (is_sub) {
179 struct json_object *s = json_object_new_object();
180 json_object_object_add(s, "name2", json_section_ident(r->section.name2));
181 json_object_object_add(s, "func", func_symbol((void const *)r->section.func));
182 json_object_object_add(s, "subcs",
183 r->section.subcs ? build_call_env_rules(r->section.subcs) :
184 json_object_new_array());
185 json_object_object_add(o, "section", s);
186 } else {
187 struct json_object *p = json_object_new_object();
188 struct json_object *parsed = json_object_new_object();
189
190 /*
191 * FR_TYPE_NULL / FR_TYPE_VOID both mean "no cast" - the
192 * framework hands the parsed value through without
193 * coercion. Collapse to a JSON null so the converter
194 * only has to check one sentinel.
195 */
196 json_object_object_add(p, "cast_type",
197 ((r->pair.cast_type == FR_TYPE_NULL) || (r->pair.cast_type == FR_TYPE_VOID)) ?
198 NULL :
199 json_object_new_string(fr_type_to_enum_str(r->pair.cast_type)));
200 json_object_object_add(p, "type",
201 json_object_new_string(call_env_result_type_to_enum_str(r->pair.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));
204
205 json_object_object_add(parsed, "type",
206 json_object_new_string(call_env_parse_type_to_enum_str(r->pair.parsed.type)));
207 json_object_object_add(p, "parsed", parsed);
208
209 json_object_object_add(o, "pair", p);
210 }
211
212 return o;
213}
214
215static struct json_object *build_call_env_rules(call_env_parser_t const *rules)
216{
217 struct json_object *a = json_object_new_array();
218
219 if (rules) {
220 for (call_env_parser_t const *r = rules; r->name; r++) {
221 json_object_array_add(a, build_call_env_rule(r));
222 }
223 }
224 return a;
225}
226
227static struct json_object *build_method_bindings(module_method_binding_t const *bindings)
228{
229 struct json_object *a = json_object_new_array();
230
231 if (bindings) {
232 for (module_method_binding_t const *b = bindings; b->section; b++) {
233 struct json_object *entry = json_object_new_object();
234 struct json_object *section = json_object_new_object();
235
236 json_object_object_add(section, "name1", json_section_ident(b->section->name1));
237 json_object_object_add(section, "name2", json_section_ident(b->section->name2));
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) ?
242 build_call_env_rules(b->method_env->env) :
243 json_object_new_array());
244
245 json_object_array_add(a, entry);
246 }
247 }
248
249 return a;
250}
251
252/*
253 * Build the JSON for one module using the server's normal dl loader.
254 * `bare_name` is the module name without the "rlm_" prefix (so "files"
255 * for rlm_files). Returns the json object or NULL on error.
256 */
257static struct json_object *build_module(char const *bare_name)
258{
259 dl_module_t *dl_module;
260 module_rlm_t *m;
261 struct json_object *entry;
262
263 dl_module = dl_module_alloc(NULL, bare_name, DL_MODULE_TYPE_MODULE);
264 if (!dl_module) {
265 fr_perror("rlm_%s", bare_name);
266 return NULL;
267 }
268
269 m = (module_rlm_t *)dl_module->exported;
270 if (!m) return NULL;
271
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));
274 json_object_object_add(entry, "config", build_conf_parser_rules(m->common.config));
275 json_object_object_add(entry, "call_env", build_method_bindings(m->method_group.bindings));
276 return entry;
277}
278
279static int dump_module(struct json_object *modules, char const *bare_name)
280{
281 int fds[2];
282 pid_t pid;
283 int status;
284
285 if (pipe(fds) < 0) {
286 fprintf(stderr, "rlm_%s: pipe failed: %s\n", bare_name, fr_syserror(errno));
287 return -1;
288 }
289
290 pid = fork();
291 if (pid < 0) {
292 close(fds[0]);
293 close(fds[1]);
294 fprintf(stderr, "rlm_%s: fork failed: %s\n", bare_name, fr_syserror(errno));
295 return -1;
296 }
297
298 if (pid == 0) {
299 struct json_object *entry;
300
301 close(fds[0]);
302 entry = build_module(bare_name);
303 if (!entry) {
304 fprintf(stderr, "rlm_%s: build_module failed\n", bare_name);
305 _exit(1);
306 }
307
308 {
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);
312 ssize_t n;
313
314 while (remaining > 0) {
315 n = write(fds[1], s, remaining);
316 if (n < 0) {
317 fprintf(stderr, "rlm_%s: write to pipe failed: %s\n",
318 bare_name, fr_syserror(errno));
319 _exit(1);
320 }
321 s += n;
322 remaining -= n;
323 }
324 }
325 json_object_put(entry);
326 close(fds[1]);
327 _exit(0);
328 }
329
330 close(fds[1]);
331 {
332 char buf[262144];
333 size_t used = 0;
334 ssize_t n;
335 while ((n = read(fds[0], buf + used, sizeof(buf) - 1 - used)) > 0) {
336 used += n;
337 if (used >= sizeof(buf) - 1) break;
338 }
339 close(fds[0]);
340 buf[used] = '\0';
341
342 waitpid(pid, &status, 0);
343
344 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
345 fprintf(stderr, "rlm_%s: child %s (status=0x%x), skipping\n", bare_name,
346 WIFEXITED(status) ? "exited non-zero" : "crashed", status);
347 return -1;
348 }
349
350 if (used > 0) {
351 struct json_object *entry = json_tokener_parse(buf);
352 if (entry) {
353 json_object_array_add(modules, entry);
354 return 0;
355 }
356 fprintf(stderr, "rlm_%s: failed to parse child JSON\n", bare_name);
357 return -1;
358 }
359 }
360
361 return -1;
362}
363
364/*
365 * Discover top-level rlm_*.dylib (or .so) files in a directory, returning
366 * the bare module names (no "rlm_" prefix, no extension). The dl loader
367 * will re-prefix and resolve the full path itself.
368 */
369static int discover_modules(TALLOC_CTX *ctx, char const *dir, char ***out_names, size_t *out_count)
370{
371 DIR *d;
372 struct dirent *e;
373 char **names = NULL;
374 size_t n = 0, alloc = 0;
375 size_t extlen = strlen(DL_EXTENSION);
376
377 d = opendir(dir);
378 if (!d) {
379 fprintf(stderr, "Failed opening module dir %s: %s\n", dir, fr_syserror(errno));
380 return -1;
381 }
382
383 while ((e = readdir(d)) != NULL) {
384 size_t nlen = strlen(e->d_name);
385
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;
389
390 if (n == alloc) {
391 alloc = alloc ? alloc * 2 : 16;
392 MEM(names = talloc_realloc(ctx, names, char *, alloc));
393 }
394
395 /* Strip "rlm_" prefix and DL_EXTENSION suffix */
396 MEM(names[n++] = talloc_strndup(names, e->d_name + 4, nlen - 4 - extlen));
397 }
398
399 closedir(d);
400
401 *out_names = names;
402 *out_count = n;
403 return 0;
404}
405
406static int compare_str(void const *a, void const *b)
407{
408 return strcmp(*(char *const *)a, *(char *const *)b);
409}
410
411static NEVER_RETURNS void usage(int rcode)
412{
413 FILE *fp = (rcode == 0) ? stdout : stderr;
414
415 fprintf(fp,
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"
423 " -h This help.\n");
424 exit(rcode);
425}
426
427int main(int argc, char *argv[])
428{
429 int c;
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;
435 char **names = NULL;
436 size_t n_names = 0;
437 fr_dict_t *internal = NULL;
438 TALLOC_CTX *autofree;
439
441
442 fr_debug_lvl = 0;
444 default_log.fd = STDERR_FILENO;
445
446 while ((c = getopt(argc, argv, "D:hm:M:o:x")) != -1) {
447 switch (c) {
448 case 'D':
449 dict_dir = optarg;
450 break;
451 case 'h':
452 usage(EXIT_SUCCESS);
453 case 'm':
454 modules_arg = optarg;
455 break;
456 case 'M':
457 module_dir = optarg;
458 break;
459 case 'o':
460 output_file = optarg;
461 break;
462 case 'x':
463 fr_debug_lvl++;
464 break;
465 default:
466 usage(EXIT_FAILURE);
467 }
468 }
469
471 fr_perror("radmod2json");
472 exit(EXIT_FAILURE);
473 }
474
475 /* Init the dl loader against the requested module dir. */
476 modules_init(module_dir);
477
478 /*
479 * dl_module_alloc triggers fr_dict_autoload on the loaded
480 * module, which needs a global dict ctx to exist. Some
481 * modules also autoload internal-protocol attributes that
482 * are in the dictionary tree, so load it up front.
483 */
484 if (!fr_dict_global_ctx_init(NULL, true, dict_dir)) {
485 fr_perror("radmod2json");
486 exit(EXIT_FAILURE);
487 }
488
489 if (fr_dict_internal_afrom_file(&internal, FR_DICTIONARY_INTERNAL_DIR, __FILE__) < 0) {
490 fr_perror("radmod2json");
491 exit(EXIT_FAILURE);
492 }
493
494 if (modules_arg) {
495 char *list = talloc_strdup(autofree, modules_arg);
496 char *p, *tok;
497 size_t alloc = 0;
498
499 for (p = list; (tok = strsep(&p, ",")) != NULL;) {
500 char const *bare = tok;
501
502 if (!*bare) continue;
503 if (strncmp(bare, "rlm_", 4) == 0) bare += 4;
504 if (n_names == alloc) {
505 alloc = alloc ? alloc * 2 : 16;
506 MEM(names = talloc_realloc(autofree, names, char *, alloc));
507 }
508 names[n_names++] = UNCONST(char *, bare);
509 }
510 } else {
511 if (discover_modules(autofree, module_dir, &names, &n_names) < 0) {
512 exit(EXIT_FAILURE);
513 }
514 if (n_names > 0) qsort(names, n_names, sizeof(names[0]), compare_str);
515 }
516
517 {
518 struct json_object *root = json_object_new_object();
519 struct json_object *modules = json_object_new_array();
520 char const *json_str;
521
522 json_object_object_add(root, "modules", modules);
523
524 for (size_t i = 0; i < n_names; i++) {
525 if (dump_module(modules, names[i]) < 0) rcode = EXIT_FAILURE;
526 }
527
528 json_str = json_object_to_json_string_ext(root, JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_NOSLASHESCAPE);
529 if (output_file) {
530 FILE *out = fopen(output_file, "w");
531 if (!out) {
532 fprintf(stderr, "Failed opening %s: %s\n", output_file, fr_syserror(errno));
533 exit(EXIT_FAILURE);
534 }
535 fputs(json_str, out);
536 fputc('\n', out);
537 fclose(out);
538 } else {
539 fputs(json_str, stdout);
540 fputc('\n', stdout);
541 }
542
543 json_object_put(root);
544 }
545
546 return rcode;
547}
int n
Definition acutest.h:577
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:186
#define RCSID(id)
Definition build.h:512
#define NEVER_RETURNS
Should be placed before the function return type.
Definition build.h:334
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.
Definition call_env.c:851
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.
Definition call_env.c:874
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.
Definition call_env.c:863
call_env_flags_t flags
Flags controlling parser behaviour.
Definition call_env.h:182
char const * name
Of conf pair to pass to tmpl_tokenizer.
Definition call_env.h:181
call_env_flags_t
Definition call_env.h:73
@ CALL_ENV_FLAG_SUBSECTION
This is a subsection.
Definition call_env.h:87
Per method call config.
Definition call_env.h:180
char const * cf_parser_flag_to_enum_str(conf_parser_flags_t mask)
Return the source-identifier name for a single CONF_FLAG_* bit.
Definition cf_parse.c:1857
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition cf_parse.h:623
conf_parser_flags_t flags
Flags which control parsing behaviour.
Definition cf_parse.h:612
fr_type_t type
An fr_type_t value, controls the output type.
Definition cf_parse.h:610
char const * name2
Second identifier for CONF_SECTION.
Definition cf_parse.h:608
fr_token_t quote
Quoting around the default value. Only used for templates.
Definition cf_parse.h:661
char const * name1
Name of the CONF_ITEM to parse.
Definition cf_parse.h:607
cf_parse_t on_read
Function to call as the item is being read, just after it has been allocated and initialized.
Definition cf_parse.h:626
conf_parser_flags_t
Definition cf_parse.h:421
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:423
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:606
#define CF_IDENT_ANY
Definition cf_util.h:80
#define MEM(x)
Definition debug.h:36
static NEVER_RETURNS void usage(void)
Definition dhcpclient.c:113
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.
Definition dict_util.c:4707
Test enumeration values.
Definition dict_test.h:92
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.
Definition dl_module.c:312
dl_module_common_t * exported
Symbol exported by the module, containing its public functions, name and behaviour control flags.
Definition dl_module.h:128
@ DL_MODULE_TYPE_MODULE
Standard loadable module.
Definition dl_module.h:66
#define DL_EXTENSION
Definition dl_module.h:57
static TALLOC_CTX * autofree
Definition fuzzer.c:44
int fr_debug_lvl
Definition log.c:41
fr_log_t default_log
Definition log.c:306
@ L_DST_STDERR
Log to stderr.
Definition log.h:78
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_VOID
User data.
long int ssize_t
static size_t used
char * strsep(char **stringp, char const *delim)
Definition missing.c:122
module_method_group_t method_group
named methods
Definition module_rlm.h:40
module_t common
Common fields presented by all modules.
Definition module_rlm.h:39
#define WIFEXITED(stat_val)
Definition radiusd.c:66
#define WEXITSTATUS(stat_val)
Definition radiusd.c:63
int main(int argc, char *argv[])
#define quote_name(_t)
Definition radmod2json.c:56
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)
Definition radmod2json.c:77
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
Definition radmod2json.c:44
static struct json_object * func_symbol(void const *fn)
Definition radmod2json.c:63
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)
Definition radmod2json.c:93
static uint32_t mask
Definition rbmonkey.c:39
static char const * name
module_method_binding_t * bindings
named methods
Definition module.h:165
conf_parser_t const * config
How to convert a CONF_SECTION to a module instance.
Definition module.h:206
section_name_t const * section
Identifier for a section.
Definition module.h:175
Named methods exported by a module.
Definition module.h:174
void modules_init(char const *lib_dir)
Perform global initialisation for modules.
Definition module.c:1951
fr_log_dst_t dst
Log destination.
Definition log.h:94
int fd
File descriptor to write messages to.
Definition log.h:109
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
#define talloc_strndup(_ctx, _str, _len)
Definition talloc.h:150
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
Definition talloc.h:55
#define talloc_strdup(_ctx, _str)
Definition talloc.h:149
static const char * names[8]
Definition time.c:600
enum fr_token fr_token_t
#define FR_DICTIONARY_INTERNAL_DIR
Definition conf.h:8
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
Definition strerror.c:737
char const * fr_type_to_enum_str(fr_type_t t)
Return the source-identifier name for a type (e.g.
Definition types.c:142
int fr_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
Definition version.c:40
#define RADIUSD_VERSION_BUILD(_x)
Create a version string for a utility in the suite of FreeRADIUS utilities.
Definition version.h:58
#define RADIUSD_MAGIC_NUMBER
Definition version.h:81
static size_t char ** out
Definition value.h:1030