The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
virtual_servers.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: f3853465980c9e4f05fc00c7a6c8bc7f7f138a55 $
19 *
20 * @file virtual_servers.c
21 * @brief Defines functions for virtual_server initialisation.
22 *
23 * @copyright 2003,2006 The FreeRADIUS server project
24 * @copyright 2000 Alan DeKok (aland@freeradius.org)
25 * @copyright 2000 Alan Curry (pacman@world.std.com)
26 */
27RCSID("$Id: f3853465980c9e4f05fc00c7a6c8bc7f7f138a55 $")
28
29#include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
30#include <freeradius-devel/server/base.h>
31#include <freeradius-devel/server/process.h>
32
33#include <freeradius-devel/unlang/compile.h>
34#include <freeradius-devel/unlang/function.h>
35#include <freeradius-devel/unlang/timeout.h>
36
37#include <freeradius-devel/io/application.h>
38#include <freeradius-devel/io/master.h>
39#include <freeradius-devel/io/listen.h>
40
41typedef struct {
42 module_instance_t *proto_mi; //!< The proto_* module for a listen section.
43 fr_app_t const *proto_module; //!< Public interface to the proto_mi.
44 ///< cached for convenience.
46
48 CONF_SECTION *server_cs; //!< The server section.
49 fr_virtual_listen_t **listeners; //!< Listeners in this virtual server.
50
51 module_instance_t *process_mi; //!< The process_* module for a virtual server.
52 ///< Contains the dictionary used by the virtual
53 ///< server and the entry point for the state machine.
54 fr_process_module_t const *process_module; //!< Public interface to the process_mi.
55 ///< cached for convenience.
56
57 fr_rb_tree_t *sections; //!< List of sections that need to be compiled.
58
59 fr_log_t *log; //!< log destination
60 char const *log_name; //!< name of log destination
61
62 fr_time_delta_t timeout_delay; //!< for timeout sections
63 void *timeout_instruction; //!< the timeout instruction
65};
66
68
70
73 { .out = &dict_freeradius, .proto = "freeradius" },
74 { NULL }
75};
76
79 { .out = &attr_auth_type, .name = "Auth-Type", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
80
81 { NULL }
82};
83
84/** List of process modules we've loaded
85 *
86 * This is global for all virtual servers. Must be initialised
87 * _before_ the configuration is loaded.
88 */
90
91/** List of proto modules we've loaded
92 *
93 * This is global for all virtual servers. Must be initialised
94 * _before_ the configuration is loaded.
95 */
97
98/** Top level structure holding all virtual servers
99 *
100 */
102
103/** CONF_SECTION holding all the virtual servers
104 *
105 * Set during the call to virtual_server_bootstrap and used by
106 * other virtual server functions.
107 */
109
111
112static int namespace_on_read(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
113
114static int namespace_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
115static int listen_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
116static int server_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule);
117
124
126 /*
127 * Not really ok if it's missing but we want to
128 * let logic elsewhere handle the issue.
129 */
131 .subcs_size = sizeof(virtual_server_t), .subcs_type = "virtual_server_t",
132 .subcs = (void const *) server_on_read_config, .name2 = CF_IDENT_ANY,
133 .on_read = cf_null_on_read },
134
136};
137
138static const conf_parser_t server_config[] = {
141
143 virtual_server_t, listeners),
144 .name2 = CF_IDENT_ANY,
145 .subcs_size = sizeof(fr_virtual_listen_t), .subcs_type = "fr_virtual_listen_t",
146 .func = listen_parse },
147
148 { FR_CONF_OFFSET("log", virtual_server_t, log_name), },
149
151};
152
154 /*
155 * Not really ok if it's missing but we want to
156 * let logic elsewhere handle the issue.
157 */
159 .subcs_size = sizeof(virtual_server_t), .subcs_type = "virtual_server_t",
160 .subcs = (void const *) server_config, .name2 = CF_IDENT_ANY,
161 .func = server_parse },
162
164};
165
166/** Print all the loaded listener instances
167 *
168 */
173
174/** Print all the loaded process module instances
175 *
176 */
181
182/** Resolve proto data to a module instance
183 *
184 * @param[in] data Pointer to the proto data.
185 * @return
186 * - The module instance for the proto data.
187 * - NULL if no data matches.
188 */
193
194/** Generic conf_parser_t func for loading drivers
195 *
196 */
197int virtual_server_listen_transport_parse(TALLOC_CTX *ctx, void *out, void *parent,
198 CONF_ITEM *ci, conf_parser_t const *rule)
199{
200 conf_parser_t our_rule = *rule;
201
202 our_rule.uctx = &proto_modules;
203
204 return module_submodule_parse(ctx, out, parent, ci, &our_rule);
205}
206
207/** Parse a "namespace" parameter
208 *
209 * We need to load the process module before continuing to parse the virtual server contents
210 * as we need to know the namespace so that we can resolve attribute names.
211 *
212 * We also need the compilation list from the proto module to figure out which sections we
213 * need to compile.
214 *
215 * @param[in] ctx to allocate data in.
216 * @param[out] out always NULL
217 * @param[in] parent Base structure address.
218 * @param[in] ci #CONF_SECTION containing the listen section.
219 * @param[in] rule unused.
220 * @return
221 * - 0 on success.
222 * - -1 on failure.
223 */
224static int namespace_on_read(TALLOC_CTX *ctx, UNUSED void *out, UNUSED void *parent,
225 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
226{
227 CONF_PAIR *cp = cf_item_to_pair(ci);
228 CONF_SECTION *server_cs = cf_item_to_section(cf_parent(ci));
230 char const *namespace;
231 char *module_name, *p, *end;
232 char const *inst_name;
233 fr_process_module_t const *process;
234
236 "virtual_servers_init MUST be called before reading virtual server config");
237
238 namespace = cf_pair_value(cp);
239 module_name = talloc_strdup(ctx, namespace);
240
241 /*
242 * Smush all hyphens to underscores for module names
243 */
244 for (p = module_name, end = module_name + talloc_array_length(module_name) - 1;
245 p < end;
246 p++) if (*p == '-') *p = '_';
247
248 if (module_instance_name_from_conf(&inst_name, server_cs) < 0) return -1;
249
250 /*
251 * The module being loaded is the namespace with all '-'
252 * transformed to '_'.
253 *
254 * The instance name is the virtual server name.
255 */
257 module_name, inst_name,
258 0);
259 talloc_free(module_name);
260 if (mi == NULL) {
261 error:
262 cf_log_perr(ci, "Failed loading process module");
263 return -1;
264 }
265 if (unlikely(module_instance_conf_parse(mi, mi->conf) < 0)) goto error;
266
267 process = (fr_process_module_t const *)mi->module->exported;
268 if (!*(process->dict)) {
269 cf_log_err(ci, "Process module is invalid - missing namespace dictionary");
270 talloc_free(mi);
271 return -1;
272 }
273 cf_data_add(server_cs, mi, "process_module", false);
274 cf_data_add(server_cs, *(process->dict), "dict", false);
275
276 return 0;
277}
278
279static inline CC_HINT(always_inline)
281{
282 int i;
284
285 if (!compile_list) return 0;
286
287 for (i = 0; list[i].section; i++) {
288#ifndef NDEBUG
289 /*
290 * We can't have a wildcard for name1. It MUST be a real name.
291 *
292 * The wildcard was allowed previously for ideas which later didn't turn out.
293 */
294 if (list[i].section->name1 == CF_IDENT_ANY) {
295 fr_assert(0);
296 continue;
297 }
298
299#endif
300 if (virtual_server_section_register(vs, &list[i]) < 0) {
301 cf_log_err(cs, "Failed registering processing section name %s for %s",
302 list[i].section->name1, name);
303 return -1;
304 }
305 }
306
307 return 0;
308}
309
310/** dl_open a process_* module
311 *
312 * @param[in] ctx to allocate data in.
313 * @param[out] out Where to our listen configuration. Is a #fr_virtual_listen_t structure.
314 * @param[in] parent Base structure address.
315 * @param[in] ci #CONF_SECTION containing the listen section.
316 * @param[in] rule unused.
317 * @return
318 * - 0 on success.
319 * - -1 on failure.
320 */
321static int namespace_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
322{
323 CONF_PAIR *cp = cf_item_to_pair(ci);
324 CONF_SECTION *server_cs = cf_item_to_section(cf_parent(ci));
325 CONF_SECTION *process_cs;
326 virtual_server_t *server = talloc_get_type_abort(((uint8_t *) out) - offsetof(virtual_server_t, process_mi), virtual_server_t);
327 char const *namespace = cf_pair_value(cp);
328 module_instance_t *mi = cf_data_value(cf_data_find(server_cs, module_instance_t, "process_module"));
329
330 /*
331 * We don't have access to virtual_server_t
332 * in the onread callback, so we need to do the
333 * fixups here.
334 */
335 server->process_mi = mi;
336 server->process_module = (fr_process_module_t const *)mi->module->exported;
337
338 *(module_instance_t const **)out = mi;
339
340 /*
341 * Enforce that the protocol process configuration is in
342 * a subsection named for the protocol.
343 */
344 process_cs = cf_section_find(server_cs, namespace, NULL);
345 if (!process_cs) {
346 process_cs = cf_section_alloc(server_cs, server_cs, namespace, NULL);
347 }
348
349 if (module_instance_conf_parse(mi, process_cs) < 0) {
350 cf_log_perr(ci, "Failed bootstrapping process module");
351 cf_data_remove(server_cs, module_instance_t, "process_module");
352 cf_data_remove(server_cs, fr_dict_t, "dict");
353 TALLOC_FREE(server->process_mi);
354 return -1;
355 }
356
357 /*
358 * Pull the list of sections we need to compile out of
359 * the process module's public struct.
360 */
361 add_compile_list(server, server->process_mi->conf, server->process_module->compile_list, namespace);
362
363 return 0;
364}
365
366/** dl_open a proto_* module
367 *
368 * @param[in] ctx to allocate data in.
369 * @param[out] out Where to our listen configuration. Is a #fr_virtual_listen_t structure.
370 * @param[in] parent Base structure address.
371 * @param[in] ci #CONF_SECTION containing the listen section.
372 * @param[in] rule unused.
373 * @return
374 * - 0 on success.
375 * - -1 on failure.
376 */
377static int listen_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
378{
379 fr_virtual_listen_t *listener = talloc_get_type_abort(out, fr_virtual_listen_t); /* Pre-allocated for us */
380 CONF_SECTION *listener_cs = cf_item_to_section(ci);
381 CONF_SECTION *server_cs = cf_item_to_section(cf_parent(ci));
382 CONF_PAIR *namespace = cf_pair_find(server_cs, "namespace");
383
384 CONF_PAIR *cp;
385 char const *protocol, *transport, *name2;
386 char *inst_name;
387
389
391 "virtual_servers_init MUST be called before reading virtual server config");
392
393 if (!namespace) {
394 cf_log_err(server_cs, "No 'namespace' set for virtual server");
395 cf_log_err(server_cs, "Please add 'namespace = <protocol>' inside of the 'server %s { ... }' section",
396 cf_section_name2(server_cs));
397 return -1;
398 }
399
400 /*
401 * Module name comes from the 'proto' pair if the
402 * listen section has one else it comes from the
403 * namespace of the virtual server.
404 *
405 * The following results in proto_radius being loaded:
406 *
407 * server foo {
408 * namespace = radius
409 * listen {
410 *
411 * }
412 * }
413 *
414 * The following results in proto_load being loaded:
415 *
416 * server foo {
417 * namespace = radius
418 * listen {
419 * proto = load
420 *
421 * }
422 * }
423 *
424 * In this way the server behaves reasonably out
425 * of the box, but allows foreign or generic listeners
426 * to be included in the server.
427 *
428 */
429 cp = cf_pair_find(listener_cs, "proto");
430 if (cp) {
431 protocol = cf_pair_value(cp);
432 if (!protocol) {
433 cf_log_err(cp, "Missing value");
434 return -1;
435 }
436 } else {
437 protocol = cf_pair_value(namespace);
438 }
439
440 name2 = cf_section_name2(listener_cs);
441
442 /*
443 * As with almost everything else, the listeners are
444 * modules. Create a unique name for them.
445 */
446 cp = cf_pair_find(listener_cs, "transport");
447 if (cp && cf_pair_value(cp)) {
448 transport = cf_pair_value(cp);
449 } else {
450 transport = "generic";
451 }
452
453 /*
454 * Instance names are default.radius.udp.foo, or default.radius.udp
455 */
456 if (name2) {
457 MEM(inst_name = talloc_asprintf(ctx, "%s.%s.%s.%s", cf_section_name2(server_cs),
458 protocol, transport, name2));
459 } else {
460 MEM(inst_name = talloc_asprintf(ctx, "%s.%s.%s", cf_section_name2(server_cs),
461 protocol, transport));
462 }
463
464 if (module_instance_name_valid(inst_name) < 0) {
465 error:
466 cf_log_err(listener_cs, "Failed loading listen section.");
467 return -1;
468 }
469 mi = module_instance_alloc(proto_modules, NULL, DL_MODULE_TYPE_PROTO, protocol, inst_name, 0);
470 talloc_free(inst_name);
471 if (!mi) goto error;
472
473 if (unlikely(module_instance_conf_parse(mi, listener_cs) < 0)) goto error;
474
475 listener->proto_mi = mi;
476 listener->proto_module = (fr_app_t const *)listener->proto_mi->module->exported;
477 cf_data_add(listener_cs, mi, "proto_module", false);
478
479 return 0;
480}
481
482static int8_t virtual_server_compile_name_cmp(void const *a, void const *b)
483{
484 virtual_server_compile_t const *sa = a;
485 virtual_server_compile_t const *sb = b;
486
487 return section_name_cmp(sa->section, sb->section);
488}
489
490/** Callback to validate the server section
491 *
492 * @param[in] ctx to allocate data in.
493 * @param[out] out Where to our listen configuration. Is a #virtual_server_t structure.
494 * @param[in] parent Base structure address.
495 * @param[in] ci #CONF_SECTION containing the listen section.
496 * @param[in] rule unused.
497 * @return
498 * - 0 on success.
499 * - -1 on failure.
500 */
501static int server_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
502 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
503{
504 virtual_server_t *server = talloc_get_type_abort(out, virtual_server_t);
505 CONF_SECTION *server_cs = cf_item_to_section(ci);
506 CONF_PAIR *namespace;
507
508 namespace = cf_pair_find(server_cs, "namespace");
509 if (!namespace) {
510 cf_log_err(server_cs, "virtual server %s MUST contain a 'namespace' option",
511 cf_section_name2(server_cs));
512 return -1;
513 }
514
516 server->server_cs = server_cs;
517
518 /*
519 * Now parse the listeners
520 */
521 if (cf_section_parse(out, server, server_cs) < 0) return -1;
522
523 /*
524 * And cache this struct for later referencing.
525 */
526 cf_data_add(server_cs, server, NULL, false);
527
528 return 0;
529}
530
531/** Return the namespace for the named virtual server
532 *
533 * @param[in] virtual_server to look for namespace in.
534 * @return
535 * - NULL on error.
536 * - Namespace on success.
537 */
538fr_dict_t const *virtual_server_dict_by_name(char const *virtual_server)
539{
540 virtual_server_t const *vs;
541
542 vs = virtual_server_find(virtual_server);
543 if (!vs) return NULL;
544
546}
547
548/** Return the namespace for the virtual server specified by a config section
549 *
550 * @param[in] server_cs to look for namespace in.
551 * @return
552 * - NULL on error.
553 * - Namespace on success.
554 */
556{
557 CONF_DATA const *cd;
558 fr_dict_t *dict;
559
560 cd = cf_data_find(server_cs, fr_dict_t, "dict");
561 if (!cd) return NULL;
562
563 dict = cf_data_value(cd);
564 (void) talloc_get_type_abort(dict, fr_dict_t);
565
566 return dict;
567}
568
569/** Return the namespace for a given virtual server specified by a CONF_ITEM within the virtual server
570 *
571 * @param[in] ci to look for namespace in.
572 * @return
573 * - NULL on error.
574 * - Namespace on success.
575 */
577{
578 CONF_DATA const *cd;
579 fr_dict_t *dict;
580
581 cd = cf_data_find_in_parent(ci, fr_dict_t, "dict");
582 if (!cd) return NULL;
583
584 dict = cf_data_value(cd);
585 (void) talloc_get_type_abort(dict, fr_dict_t);
586
587 return dict;
588}
589
590/** Verify that a given virtual_server exists and is of a particular namespace
591 *
592 * Mostly used by modules to check virtual servers specified by their configs.
593 *
594 * @param[out] out we found. May be NULL if just checking for existence.
595 * @param[in] virtual_server to check.
596 * @param[in] namespace the virtual server must belong to.
597 * @param[in] ci to log errors against. May be NULL if caller
598 * doesn't want errors logged.
599 * @return
600 * - 0 on success.
601 * - -1 if no virtual server could be found.
602 * - -2 if virtual server is not of the correct namespace.
603 */
605 char const *virtual_server, fr_dict_t const *namespace, CONF_ITEM *ci)
606{
607 virtual_server_t const *vs;
608 CONF_SECTION *server_cs;
609 fr_dict_t const *dict;
610
611 if (out) *out = NULL;
612
613 vs = virtual_server_find(virtual_server);
614 if (!vs) {
615 if (ci) cf_log_err(ci, "Can't find virtual server \"%s\"", virtual_server);
616 return -1;
617 }
618 server_cs = virtual_server_cs(vs);
619
620 dict = virtual_server_dict_by_name(virtual_server);
621 if (!dict) {
622 /*
623 * Not sure this is even a valid state?
624 */
625 if (ci) cf_log_err(ci, "No namespace found in virtual server \"%s\"", virtual_server);
626 return -2;
627 }
628
629 if (dict != namespace) {
630 if (ci) {
631 cf_log_err(ci,
632 "Expected virtual server \"%s\" to be of namespace \"%s\", got namespace \"%s\"",
633 virtual_server, fr_dict_root(namespace)->name, fr_dict_root(dict)->name);
634 }
635 return -2;
636 }
637
638 if (out) *out = server_cs;
639
640 return 0;
641}
642
643/*
644 * If we pushed a log destination, we need to pop it/
645 */
647 request_t *request, void *uctx)
648{
649 virtual_server_t *server = uctx;
650
651 request_log_prepend(request, server->log, L_DBG_LVL_DISABLE);
652
654}
655
656static void server_signal_remove_log_destination(request_t *request, UNUSED fr_signal_t action, void *uctx)
657{
658 virtual_server_t *server = uctx;
659
660 request_log_prepend(request, server->log, L_DBG_LVL_DISABLE);
661}
662
663/** Set the request processing function.
664 *
665 * Short-term hack
666 */
667unlang_action_t virtual_server_push(request_t *request, CONF_SECTION *server_cs, bool top_frame)
668{
669 virtual_server_t *server;
670
671 server = cf_data_value(cf_data_find(server_cs, virtual_server_t, NULL));
672 if (!server) {
673 cf_log_err(server_cs, "server_cs does not contain virtual server data");
674 return UNLANG_ACTION_FAIL;
675 }
676
677 /*
678 * Add a log destination specific to this virtual server.
679 *
680 * If we add a log destination, make sure to remove it when we walk back up the stack.
681 * But ONLY if we're not at the top of the stack.
682 *
683 * When a brand new request comes in, it has a "call" frame pushed, and then this function is
684 * called. So if we're at the top of the stack, we don't need to pop any logging function,
685 * because the request will die immediately after the top "call" frame is popped.
686 *
687 * However, if we're being reached from a "call" frame in the middle of the stack, then
688 * we do have to pop the log destination when we return.
689 */
690 if (server->log) {
691 request_log_prepend(request, server->log, fr_debug_lvl);
692
693 if (unlang_interpret_stack_depth(request) > 1) {
694 unlang_action_t action;
695
696 action = unlang_function_push(request, NULL, /* don't call it immediately */
697 server_remove_log_destination, /* but when we pop the frame */
699 top_frame, server);
700 if (action != UNLANG_ACTION_PUSHED_CHILD) return action;
701
702 /*
703 * The pushed function may be a top frame, but the virtual server
704 * we're about to push is now definitely a sub frame.
705 */
706 top_frame = UNLANG_SUB_FRAME;
707 }
708 }
709
710 /*
711 * Push a timeout after updating the log destination.
712 */
713 if (server->timeout_cs) {
714 if (unlang_timeout_section_push(request, server->timeout_cs, server->timeout_delay, top_frame) < 0) {
715 return UNLANG_ACTION_FAIL;
716 }
717
718 top_frame = UNLANG_SUB_FRAME;
719 }
720
721 /*
722 * Bootstrap the stack with a module instance.
723 */
724 if (unlang_module_push(&request->rcode, request, server->process_mi,
725 server->process_module->process, top_frame) < 0) return UNLANG_ACTION_FAIL;
726
728}
729
730static int cmd_show_server_list(FILE *fp, UNUSED FILE *fp_err, UNUSED void *ctx, UNUSED fr_cmd_info_t const *info)
731{
732 size_t i, server_cnt = virtual_servers ? talloc_array_length(virtual_servers) : 0;
733
734 if (!server_cnt) return 0;
735
736 for (i = 0; i < server_cnt; i++) {
737 fprintf(fp, "%-30snamespace = %s\n", cf_section_name2(virtual_servers[i]->server_cs),
738 fr_dict_root(*(virtual_servers[i]->process_module->dict))->name);
739 }
740
741 return 0;
742}
743
745 {
746 .parent = "show",
747 .name = "server",
748 .help = "Show virtual server settings.",
749 .read_only = true,
750 },
751
752 {
753 .parent = "show server",
754 .name = "list",
755 .func = cmd_show_server_list,
756 .help = "Show the list of virtual servers loaded in the server.",
757 .read_only = true,
758 },
759
761
762};
763
764/** Compare listeners by app_io_addr
765 *
766 * Only works for IP addresses, and will blow up on file names
767 */
768static int8_t listen_addr_cmp(void const *one, void const *two)
769{
770 fr_listen_t const *a = one;
771 fr_listen_t const *b = two;
772 fr_ipaddr_t aip, bip;
773 int ret;
774
775 /*
776 * The caller must ensure that the address field is set.
777 */
778 if (!a->app_io_addr && !b->app_io_addr) return 0;
779 if (!a->app_io_addr && b->app_io_addr) return -1;
780 if (a->app_io_addr && !b->app_io_addr) return +1;
781
782 /*
783 * Address family
784 */
785 CMP_RETURN(a, b, app_io_addr->af);
786
787 fr_assert((a->app_io_addr->af == AF_INET) || ((a->app_io_addr->af == AF_INET6)));
788
789 /*
790 * UDP vs TCP
791 */
792 CMP_RETURN(a, b, app_io_addr->type);
793
794 /*
795 * Check ports.
796 */
797 CMP_RETURN(a, b, app_io_addr->inet.src_port);
798
799 /*
800 * Don't call fr_ipaddr_cmp(), as we need to do our own
801 * checks here. We have various wildcard checks which
802 * aren't globally applicable.
803 */
804
805 /*
806 * Different address families.
807 */
808 CMP_RETURN(a, b, app_io_addr->inet.src_ipaddr.af);
809
810 /*
811 * If both are bound to interfaces, AND the interfaces
812 * are different, then there is no conflict.
813 */
814 if (a->app_io_addr->inet.src_ipaddr.scope_id && b->app_io_addr->inet.src_ipaddr.scope_id) {
815 CMP_RETURN(a, b, app_io_addr->inet.src_ipaddr.scope_id);
816 }
817
818 ret = a->app_io_addr->inet.src_ipaddr.prefix - b->app_io_addr->inet.src_ipaddr.prefix;
819 aip = a->app_io_addr->inet.src_ipaddr;
820 bip = b->app_io_addr->inet.src_ipaddr;
821
822 /*
823 * Mask out the longer prefix to match the shorter
824 * prefix.
825 */
826 if (ret < 0) {
827 fr_ipaddr_mask(&bip, a->app_io_addr->inet.src_ipaddr.prefix);
828
829 } else if (ret > 0) {
830 fr_ipaddr_mask(&aip, b->app_io_addr->inet.src_ipaddr.prefix);
831
832 }
833
834 return fr_ipaddr_cmp(&aip, &bip);
835}
836
837/** See if another global listener is using a particular IP / port
838 *
839 */
841{
842 if (!listen_addr_root) return false;
843
844 return fr_rb_find(listen_addr_root, li);
845}
846
847
848/** Record that we're listening on a particular IP / port
849 *
850 */
852{
853 if (!listen_addr_root) return false;
854
855 if (!li->app_io_addr) return true;
856
857 if (listen_find_any(li) != NULL) return false;
858
859 return fr_rb_insert(listen_addr_root, li);
860}
861
862/** Return the configuration section for a virtual server
863 *
864 * @param[in] vs to return conf section for
865 * @return
866 * - The CONF_SECTION of the virtual server.
867 */
869{
870 return vs->server_cs;
871}
872
873/** Return virtual server matching the specified name
874 *
875 * @note May be called in bootstrap or instantiate as all servers should be present.
876 *
877 * @param[in] name of virtual server.
878 * @return
879 * - NULL if no virtual server was found.
880 * - The CONF_SECTION of the named virtual server.
881 */
883{
884 CONF_SECTION *server_cs = cf_section_find(virtual_server_root, "server", name);
885 CONF_DATA const *cd;
886
887 if (unlikely(server_cs == NULL)) return NULL;
888
889 cd = cf_data_find(server_cs, virtual_server_t, NULL);
890 if (unlikely(cd == NULL)) return NULL;
891
892 return cf_data_value(cd);
893}
894
895/** Find a virtual server using one of its sections
896 *
897 * @param[in] ci to find parent virtual server for.
898 * @return
899 * - The virtual server section on success.
900 * - NULL if the child isn't associated with any virtual server section.
901 */
903{
904 CONF_SECTION *cs;
905 CONF_DATA const *cd;
906
907 cs = cf_section_find_parent(ci, "server", CF_IDENT_ANY);
908 if (unlikely(!cs)) {
909 cf_log_err(ci, "Child section is not associated with a virtual server");
910 return NULL;
911 }
912
913 cd = cf_data_find(cs, virtual_server_t, NULL);
914 if (unlikely(!cd)) {
915 cf_log_err(ci, "Virtual server section missing virtual_server_t data");
916 return NULL;
917 }
918
919 return cf_data_value(cd);
920}
921
922/** Wrapper for the config parser to allow pass1 resolution of virtual servers
923 *
924 */
925int virtual_server_cf_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
926 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
927{
928 virtual_server_t const *vs;
929
931 if (!vs) {
932 cf_log_err(ci, "virtual-server \"%s\" not found", cf_pair_value(cf_item_to_pair(ci)));
933 return -1;
934 }
935
936 *((CONF_SECTION **)out) = vs->server_cs;
937
938 return 0;
939}
940
942 .actions = {
943 [RLM_MODULE_REJECT] = 3,
944 [RLM_MODULE_FAIL] = 1,
945 [RLM_MODULE_OK] = 4,
947 [RLM_MODULE_INVALID] = 2,
950 [RLM_MODULE_NOOP] = 8,
952 },
953 .retry = RETRY_INIT,
954};
955
956/** Compile sections for a virtual server.
957 *
958 * When the "proto_foo" module calls fr_app_process_instantiate(), it
959 * loads the compile list from the #fr_app_worker_t, and calls this
960 * function.
961 *
962 * This function walks down the registration table, compiling each
963 * named section.
964 *
965 * @param[in] vs to to compile sections for.
966 * @param[in] rules to apply for pass1.
967 */
969{
971 void *instance = vs->process_mi->data;
972 CONF_SECTION *server = vs->server_cs;
973 int i, found;
974 CONF_SECTION *subcs = NULL;
975
976 found = 0;
977
978 /*
979 * Complain about v3 things being used in v4.
980 *
981 * Don't complain when running in normal mode, because the server will just ignore the new
982 * sections. But the check_config stuff is generally run before the service starts, and we
983 * definitely want to tell people when running in debug mode.
984 */
986 bool fail = false;
987
988 while ((subcs = cf_section_next(server, subcs)) != NULL) {
989 char const *name;
990
991 if (cf_section_name2(subcs) != NULL) continue;
992
993 name = cf_section_name1(subcs);
994 if ((strcmp(name, "authorize") == 0) ||
995 (strcmp(name, "authenticate") == 0) ||
996 (strcmp(name, "post-auth") == 0) ||
997 (strcmp(name, "preacct") == 0) ||
998 (strcmp(name, "accounting") == 0) ||
999 (strcmp(name, "pre-proxy") == 0) ||
1000 (strcmp(name, "post-proxy") == 0)) {
1001 cf_log_err(subcs, "Version 3 processing section '%s' is not valid in version 4.",
1002 name);
1003 fail = true;
1004 }
1005 }
1006
1007 /*
1008 * Complain about _all_ of the sections, and not just the first one.
1009 */
1010 if (fail) return -1;
1011 }
1012
1013 /*
1014 * The sections are in trees, so this isn't as bad as it
1015 * looks. It's not O(n^2), but O(n logn). But it could
1016 * still be improved.
1017 */
1018 for (i = 0; list[i].section; i++) {
1019 int rcode;
1020 CONF_SECTION *bad;
1021
1022 /*
1023 * We are looking for a specific subsection.
1024 * Warn if it isn't found, or compile it if
1025 * found.
1026 */
1027 if (list[i].section->name2 != CF_IDENT_ANY) {
1028 void *instruction = NULL;
1029
1030 subcs = cf_section_find(server, list[i].section->name1, list[i].section->name2);
1031 if (!subcs) {
1032 DEBUG3("Warning: Skipping %s %s { ... } as it was not found.",
1033 list[i].section->name1, list[i].section->name2);
1034 /*
1035 * Initialise CONF_SECTION pointer for missing section
1036 */
1037 if ((instance) && !list[i].dont_cache) {
1038 *(CONF_SECTION **) (((uint8_t *) instance) + list[i].offset) = NULL;
1039 }
1040 continue;
1041 }
1042
1043 /*
1044 * Duplicate sections are forbidden.
1045 */
1046 bad = cf_section_find_next(server, subcs, list[i].section->name1, list[i].section->name2);
1047 if (bad) {
1048 forbidden:
1049 cf_log_err(bad, "Duplicate sections are forbidden.");
1050 cf_log_err(subcs, "Previous definition occurs here.");
1051 return -1;
1052 }
1053
1054 rcode = unlang_compile(vs, subcs, list[i].actions, rules, &instruction);
1055 if (rcode < 0) return -1;
1056
1057 /*
1058 * Cache the CONF_SECTION which was found.
1059 */
1060 if (instance) {
1061 if (!list[i].dont_cache) {
1062 *(CONF_SECTION **) (((uint8_t *) instance) + list[i].offset) = subcs;
1063 }
1064 if (list[i].instruction > 0) {
1065 *(void **) (((uint8_t *) instance) + list[i].instruction) = instruction;
1066 }
1067 }
1068
1069 found++;
1070 continue;
1071 }
1072
1073 /*
1074 * Reset this so that we start from the beginning
1075 * again, instead of starting from the last "send
1076 * foo" block.
1077 */
1078 subcs = NULL;
1079
1080 /*
1081 * Find all subsections with the given first name
1082 * and compile them.
1083 */
1084 while ((subcs = cf_section_find_next(server, subcs, list[i].section->name1, CF_IDENT_ANY))) {
1085 char const *name2;
1086
1087 name2 = cf_section_name2(subcs);
1088 if (!name2) {
1089 cf_log_err(subcs, "Invalid '%s { ... }' section, it must have a name", list[i].section->name1);
1090 return -1;
1091 }
1092
1093 /*
1094 * Duplicate sections are forbidden.
1095 */
1096 bad = cf_section_find_next(server, subcs, list[i].section->name1, name2);
1097 if (bad) goto forbidden;
1098
1099 rcode = unlang_compile(vs, subcs, list[i].actions, rules, NULL);
1100 if (rcode < 0) return -1;
1101
1102 /*
1103 * Note that we don't store the
1104 * CONF_SECTION here, as it's a wildcard.
1105 *
1106 * @todo - count number of subsections
1107 * and store them in an array?
1108 */
1109 found++;
1110 }
1111 }
1112
1113 /*
1114 * A 'timeout' section applies to any request which is run through this virtual server.
1115 */
1116 subcs = cf_section_find(server, "timeout", CF_IDENT_ANY);
1117 if (subcs) {
1118 int rcode;
1119 void *instruction = NULL;
1120 char const *value;
1121 fr_value_box_t box;
1122
1123 value = cf_section_name2(subcs);
1124 if (!value) {
1125 cf_log_err(subcs, "Invalid 'timeout { ... }' section, it must define a timeout value");
1126 return -1;
1127 }
1128
1129 if (fr_value_box_from_str(subcs, &box, FR_TYPE_TIME_DELTA, NULL, value, strlen(value), NULL) < 0) {
1130 cf_log_perr(subcs, "Failed parsing timeout value");
1131 return -1;
1132 }
1133
1134 if (fr_time_delta_cmp(box.vb_time_delta, fr_time_delta_from_msec(10)) < 0) {
1135 cf_log_warn(subcs, "Timeout value %pV too small - it should be >= .01s", &box);
1136
1137 box.vb_time_delta = fr_time_delta_from_msec(10);
1138 }
1139
1140 if (fr_time_delta_cmp(box.vb_time_delta, main_config->worker.max_request_time) > 0) {
1141 cf_log_warn(subcs, "Timeout value %pV too large - limiting it to max_request_time of %pV",
1143
1144 box.vb_time_delta = main_config->worker.max_request_time;
1145 }
1146
1147 rcode = unlang_compile(vs, subcs, &mod_actions_timeout, rules, &instruction);
1148 if (rcode < 0) return -1;
1149
1150 vs->timeout_delay = box.vb_time_delta;
1151 vs->timeout_instruction = instruction;
1152 vs->timeout_cs = subcs;
1153
1154 found++;
1155 }
1156
1157 return found;
1158}
1159
1160/** Register name1 / name2 as allowed processing sections
1161 *
1162 * This function is called from the virtual server bootstrap routine,
1163 * which happens before module_bootstrap();
1164 */
1166{
1168
1169 old = fr_rb_find(vs->sections, entry);
1170 if (old) return 0;
1171
1172#ifndef NDEBUG
1173 /*
1174 * Catch stupid programmers.
1175 *
1176 * Processing sections can't allow "*" for module
1177 * methods, because otherwise you would be allowed to run
1178 * DHCP things in a RADIUS accounting section. And that
1179 * would be bad.
1180 */
1181 if (entry->methods) {
1182 int i;
1183
1184 for (i = 0; entry->methods[i]; i++) {
1185 if (entry->methods[i]->name1 == CF_IDENT_ANY) {
1186 ERROR("Processing sections cannot allow \"*\"");
1187 return -1;
1188 }
1189
1190 if (entry->methods[i]->name2 == CF_IDENT_ANY) {
1191 ERROR("Processing sections cannot allow \"%s *\"",
1192 entry->methods[i]->name1);
1193 return -1;
1194 }
1195 }
1196 }
1197#endif
1198
1199 if (!fr_rb_insert(vs->sections, entry)) {
1200 fr_strerror_const("Failed inserting entry into internal tree");
1201 return -1;
1202 }
1203
1204 return 0;
1205}
1206
1207/** Find the component for a section
1208 *
1209 */
1211{
1213
1214 /*
1215 * Look up the specific name first. That way we can
1216 * define both "accounting on", and "accounting *".
1217 */
1218 if (section->name2 != CF_IDENT_ANY) {
1219 entry = fr_rb_find(vs->sections,
1221 .section = section
1222 });
1223 if (entry) return entry->methods;
1224 }
1225
1226 /*
1227 * Then look up the wildcard, if we didn't find any matching name2.
1228 */
1229 entry = fr_rb_find(vs->sections,
1231 .section = SECTION_NAME(section->name1, CF_IDENT_ANY)
1232 });
1233 if (!entry) return NULL;
1234
1235 return entry->methods;
1236}
1237
1238/** Define a values for Auth-Type attributes by the sections present in a virtual-server
1239 *
1240 * The.name2 value of any sections found will be converted into values of the specified da.
1241 *
1242 * @param[in] server_cs The virtual server containing the sections.
1243 * @param[in] subcs_name of the subsection to search for.
1244 * @param[in] da to add enumeration values for.
1245 * @return
1246 * - 0 all values added successfully.
1247 * - -1 an error occurred.
1248 */
1249int virtual_server_section_attribute_define(CONF_SECTION *server_cs, char const *subcs_name, fr_dict_attr_t const *da)
1250{
1251 int rcode = 0;
1252 CONF_SECTION *subcs = NULL;
1253
1254 fr_assert(strcmp(cf_section_name1(server_cs), "server") == 0);
1255
1256 while ((subcs = cf_section_find_next(server_cs, subcs, subcs_name, CF_IDENT_ANY))) {
1257 char const *name2;
1259
1260 name2 = cf_section_name2(subcs);
1261 if (!name2) {
1262 cf_log_err(subcs, "Invalid '%s { ... }' section, it must have a name", subcs_name);
1263 return -1;
1264 }
1265
1266 /*
1267 * If the value already exists, don't
1268 * create it again.
1269 */
1270 dv = fr_dict_enum_by_name(da, name2, -1);
1271 if (dv) continue;
1272
1273 cf_log_debug(subcs, "Creating %s = %s", da->name, name2);
1274
1275 /*
1276 * Create a new unique value with a meaningless
1277 * number. You can't look at it from outside of
1278 * this code, so it doesn't matter. The only
1279 * requirement is that it's unique.
1280 */
1282 PERROR("Failed adding section value");
1283 return -1;
1284 }
1285
1286 rcode = 1;
1287 }
1288
1289 return rcode;
1290}
1291
1293{
1294 char const *ref;
1295 fr_dict_attr_t const *da;
1296 CONF_ITEM *ci = NULL;
1297
1298 ref = cf_section_name2(cs);
1299 if (!ref) {
1300 cf_log_err(cs, "Expected 'values <name> { ... }'");
1301 return -1;
1302 }
1303
1304 da = fr_dict_attr_by_name(NULL, parent, ref);
1305 if (!da) {
1306 cf_log_err(cs, "No such attribute \"%s\"", ref);
1307 return -1;
1308 }
1309
1310 if (fr_type_is_structural(da->type)) {
1311 cf_log_err(cs, "Cannot define value for structural attribute \"%s\"", ref);
1312 return -1;
1313 }
1314
1315 /*
1316 * This both does not make any sense, and does not get
1317 * parsed correctly if the string contains backslashes.
1318 */
1319 if (da->type == FR_TYPE_STRING) {
1320 cf_log_err(cs, "Cannot define value for 'string' attribute \"%s\"", ref);
1321 return -1;
1322 }
1323
1324 while ((ci = cf_item_next(cs, ci))) {
1325 ssize_t slen, len;
1326 char const *attr, *value;
1327 CONF_PAIR *cp;
1329 fr_value_box_t box;
1330
1331 if (cf_item_is_section(ci)) {
1332 cf_log_err(ci, "Unexpected subsection");
1333 return -1;
1334 }
1335
1336 if (!cf_item_is_pair(ci)) continue;
1337
1338 cp = cf_item_to_pair(ci);
1339 fr_assert(cp != NULL);
1340
1341 /*
1342 * =* is a hack by the cf parser to say "no operator"
1343 */
1344 if ((cf_pair_operator(cp) != T_OP_EQ) ||
1346 cf_log_err(ci, "Definition is not in 'name = value' format");
1347 return -1;
1348 }
1349
1350 attr = cf_pair_attr(cp);
1351 value = cf_pair_value(cp);
1352
1353 dv = fr_dict_enum_by_name(parent, attr, talloc_array_length(attr) - 1);
1354 if (dv) {
1355 cf_log_err(cp, "Duplicate value name");
1356 return -1;
1357 }
1358
1360
1361 len = talloc_array_length(value) - 1;
1362
1363 /*
1364 * @todo - unescape for double quoted strings. Whoops.
1365 */
1366 slen = fr_value_box_from_str(NULL, &box, da->type, da, value, len, NULL);
1367 if (slen < 0) {
1368 cf_log_err(cp, "Failed parsing value - %s", fr_strerror());
1369 return -1;
1370 }
1371
1372 if (slen != len) {
1373 cf_log_err(cp, "Unexpected text after value");
1374 return -1;
1375 }
1376
1377 if (fr_dict_enum_add_name(UNCONST(fr_dict_attr_t *, da), attr, &box, false, false) < 0) {
1378 cf_log_err(cp, "Failed adding value - %s", fr_strerror());
1379 return -1;
1380 }
1381
1382 fr_value_box_clear(&box);
1383 }
1384
1385 return 0;
1386}
1387
1388
1390{
1391 CONF_ITEM *ci = NULL;
1392
1393 fr_dict_attr_flags_t flags = {
1394 .internal = true,
1395 .name_only = true,
1396 .local = true,
1397 };
1398
1399 fr_assert(dict != NULL);
1400 fr_assert(parent != NULL);
1401
1402 while ((ci = cf_item_next(cs, ci))) {
1404 char const *attr, *value;
1405 CONF_PAIR *cp;
1406 CONF_SECTION *subcs = NULL;
1407
1408 if (cf_item_is_section(ci)) {
1409 subcs = cf_item_to_section(ci);
1410 fr_assert(subcs != NULL);
1411
1412 attr = cf_section_name1(subcs);
1413
1414 if (strcmp(attr, "values") == 0) {
1415 if (define_server_values(subcs, parent) < 0) return -1;
1416 continue;
1417 }
1418
1419 if (strcmp(attr, "tlv") != 0) goto invalid_type;
1420
1421 value = cf_section_name2(subcs);
1422 if (!value) {
1423 cf_log_err(ci, "Definition is not in 'tlv name { ... }' format");
1424 return -1;
1425 }
1426
1427 type = FR_TYPE_TLV;
1428 goto check_for_dup;
1429 }
1430
1431 if (!cf_item_is_pair(ci)) continue;
1432
1433 cp = cf_item_to_pair(ci);
1434 fr_assert(cp != NULL);
1435
1436 /*
1437 * =* is a hack by the cf parser to say "no operator"
1438 */
1439 if ((cf_pair_operator(cp) != T_OP_CMP_TRUE) ||
1442 cf_log_err(ci, "Definition is not in 'type name' format");
1443 return -1;
1444 }
1445
1446 attr = cf_pair_attr(cp);
1447 value = cf_pair_value(cp);
1448
1450 if (type == FR_TYPE_NULL) {
1452 cf_log_err(ci, "Invalid data type '%s'", attr);
1453 return -1;
1454 }
1455
1456 /*
1457 * Leaf and group are OK. TLV, Vendor, Struct, VSA, etc. are not as variable definitions.
1458 */
1459 if (!(fr_type_is_leaf(type) || (type == FR_TYPE_GROUP))) goto invalid_type;
1460
1461 /*
1462 * No duplicates are allowed.
1463 */
1464 check_for_dup:
1465 if (root && (fr_dict_attr_by_name(NULL, root, value) != NULL)) {
1466 cf_log_err(ci, "Local variable '%s' duplicates a dictionary attribute.", value);
1467 return -1;
1468 }
1469
1470 if (fr_dict_attr_by_name(NULL, parent, value) != NULL) {
1471 cf_log_err(ci, "Local variable '%s' duplicates a previous local attribute.", value);
1472 return -1;
1473 }
1474
1475 if (fr_dict_attr_add_name_only(dict, parent, value, type, &flags) < 0) {
1476 cf_log_err(ci, "Failed adding local variable '%s' - %s", value, fr_strerror());
1477 return -1;
1478 }
1479
1480 if (type == FR_TYPE_TLV) {
1481 fr_dict_attr_t const *da;
1482
1483 if (!subcs) return -1; /* shouldn't happen, but shut up compiler */
1484
1485 da = fr_dict_attr_by_name(NULL, parent, value);
1486 fr_assert(da != NULL);
1487
1488 if (define_server_attrs(subcs, dict, UNCONST(fr_dict_attr_t *, da), NULL) < 0) return -1;
1489 }
1490 }
1491
1492 return 0;
1493}
1494
1495static fr_dict_t const *virtual_server_local_dict(CONF_SECTION *server_cs, fr_dict_t const *dict_def)
1496{
1497 fr_dict_t *dict;
1498 CONF_SECTION *cs;
1499
1500 cs = cf_section_find(server_cs, "dictionary", NULL);
1501 if (!cs) return dict_def;
1502
1503 dict = fr_dict_protocol_alloc(dict_def);
1504 if (!dict) {
1505 cf_log_err(cs, "Failed allocating local dictionary");
1506 return NULL;
1507 }
1508
1509 if (define_server_attrs(cs, dict, UNCONST(fr_dict_attr_t *, fr_dict_root(dict)), fr_dict_root(dict_def)) < 0) return NULL;
1510
1511 /*
1512 * Replace the original dictionary with the new one.
1513 */
1514 cf_data_remove(server_cs, fr_dict_t, "dict");
1515 cf_data_add(server_cs, dict, "dict", false);
1516
1517 return dict;
1518}
1519
1520
1521/** Open all the listen sockets
1522 *
1523 * @param[in] sc Scheduler to add I/O paths to.
1524 * @return
1525 * - 0 on success.
1526 * - -1 on failure.
1527 */
1529{
1530 size_t i, server_cnt = virtual_servers ? talloc_array_length(virtual_servers) : 0;
1531
1533
1534 DEBUG2("#### Opening listener interfaces ####");
1536
1537 for (i = 0; i < server_cnt; i++) {
1538 fr_virtual_listen_t **listeners;
1539 size_t j, listener_cnt;
1540
1541 listeners = virtual_servers[i]->listeners;
1542 listener_cnt = talloc_array_length(listeners);
1543
1544 for (j = 0; j < listener_cnt; j++) {
1545 fr_virtual_listen_t *listener = listeners[j];
1546
1547 fr_assert(listener != NULL);
1548 fr_assert(listener->proto_mi != NULL);
1549 fr_assert(listener->proto_module != NULL);
1550
1551 /*
1552 * The socket is opened with app_instance,
1553 * but all subsequent calls (network.c, etc.) use app_io_instance.
1554 *
1555 * The reason is that we call (for example) proto_radius to
1556 * open the socket, and proto_radius is responsible for setting up
1557 * proto_radius_udp, and then calling proto_radius_udp->open.
1558 *
1559 * Even then, proto_radius usually calls fr_master_io_listen() in order
1560 * to create the fr_listen_t structure.
1561 */
1562 if (listener->proto_module->open) {
1563 int ret;
1564
1565 /*
1566 * Sometimes the open function needs to modify instance
1567 * data, so we need to temporarily remove the protection.
1568 */
1570 ret = listener->proto_module->open(listener->proto_mi->data, sc,
1571 listener->proto_mi->conf);
1573 if (unlikely(ret < 0)) {
1574 cf_log_err(listener->proto_mi->conf,
1575 "Opening %s I/O interface failed",
1576 listener->proto_module->common.name);
1577
1578 return -1;
1579 }
1580
1581 }
1582
1583 /*
1584 * Socket information is printed out by
1585 * the socket handlers. e.g. proto_radius_udp
1586 */
1587 DEBUG3("Opened listener for %s", listener->proto_module->common.name);
1588 }
1589 }
1590
1591 return 0;
1592}
1593
1594/** Free thread-specific data for all process modules and listeners
1595 *
1596 */
1602
1603/** Perform thread instantiation for all process modules and listeners
1604 *
1605 */
1607{
1608 if (modules_thread_instantiate(ctx, process_modules, el) < 0) return -1;
1611 return -1;
1612 }
1613 return 0;
1614}
1615
1616/** Instantiate all the virtual servers
1617 *
1618 * @return
1619 * - 0 on success.
1620 * - -1 on failure.
1621 */
1623{
1624 size_t i, server_cnt;
1625
1626 /*
1627 * User didn't specify any "server" sections
1628 */
1629 if (unlikely(!virtual_servers)) {
1630 ERROR("No virtual servers configured");
1631 return -1;
1632 }
1633
1634 server_cnt = talloc_array_length(virtual_servers);
1635
1636 DEBUG2("#### Instantiating listeners ####");
1637
1639 PERROR("Failed registering radmin commands for virtual servers");
1640 return -1;
1641 }
1642
1643 for (i = 0; i < server_cnt; i++) {
1644 CONF_ITEM *ci = NULL;
1645 CONF_SECTION *server_cs = virtual_servers[i]->server_cs;
1646 fr_dict_t const *dict;
1648 fr_process_module_t const *process = (fr_process_module_t const *)
1649 vs->process_mi->module->exported;
1650
1651 /*
1652 * Set up logging before doing anything else.
1653 */
1654 if (vs->log_name) {
1655 vs->log = log_dst_by_name(vs->log_name);
1656 if (!vs->log) {
1657 CONF_PAIR *cp = cf_pair_find(server_cs, "log");
1658
1659 if (cp) {
1660 cf_log_err(cp, "Unknown log destination '%s'", vs->log_name);
1661 } else {
1662 cf_log_err(server_cs, "Unknown log destination '%s'", vs->log_name);
1663 }
1664
1665 return -1;
1666 }
1667 }
1668
1669 dict = virtual_server_local_dict(server_cs, *(process)->dict);
1670 if (!dict) return -1;
1671
1672 DEBUG("Compiling policies in server %s { ... }", cf_section_name2(server_cs));
1673
1674 fr_assert(virtual_servers[i]->process_mi);
1675
1676 /*
1677 * Compile the processing sections indicated by
1678 * the process module. This must be done before
1679 * module_instantiate is called, as the instance
1680 * data is protected after this call.
1681 */
1682 if (process->compile_list) {
1683 tmpl_rules_t parse_rules = {
1684 .attr = {
1685 .dict_def = dict,
1686 .list_def = request_attr_request,
1687 },
1688
1689 .literals_safe_for = FR_VALUE_BOX_SAFE_FOR_ANY,
1690 };
1691
1692 fr_assert(parse_rules.attr.dict_def != NULL);
1693
1694 if (virtual_server_compile_sections(virtual_servers[i], &parse_rules) < 0) {
1695 return -1;
1696 }
1697 }
1698
1699 /*
1700 * Print out warnings for unused "recv" and
1701 * "send" sections.
1702 *
1703 * @todo - check against the "compile_list"
1704 * registered for this virtual server, instead of hard-coding stuff.
1705 */
1706 while ((ci = cf_item_next(server_cs, ci))) {
1707 char const *name;
1708 CONF_SECTION *subcs;
1709
1710 if (!cf_item_is_section(ci)) continue;
1711
1712 subcs = cf_item_to_section(ci);
1713 name = cf_section_name1(subcs);
1714
1715 /*
1716 * Skip known "other" sections
1717 */
1718 if ((strcmp(name, "listen") == 0) || (strcmp(name, "client") == 0)) continue;
1719
1720 /*
1721 * For every other section, warn if it hasn't
1722 * been compiled.
1723 */
1724 if (!cf_data_find(subcs, unlang_group_t, NULL)) {
1725 char const *name2;
1726
1727 name2 = cf_section_name2(subcs);
1728 if (!name2) name2 = "";
1729
1730 cf_log_warn(subcs, "%s %s { ... } section is unused", name, name2);
1731 }
1732 }
1733 }
1734
1736 PERROR("Failed instantiating process modules");
1737 return -1;
1738 }
1740 PERROR("Failed instantiating protocol modules");
1741 return -1;
1742 }
1743
1744 return 0;
1745}
1746
1747/** Load protocol modules and call their bootstrap methods
1748 *
1749 * @param[in] config section containing the virtual servers to bootstrap.
1750 * @return
1751 * - 0 on success.
1752 * - -1 on failure.
1753 */
1755{
1757
1758 /*
1759 * Ensure any libraries the modules depend on are instantiated
1760 */
1762
1764 PERROR("Failed instantiating process modules");
1765 return -1;
1766 }
1768 PERROR("Failed instantiating protocol modules");
1769 return -1;
1770 }
1771
1772 return 0;
1773}
1774
1776{
1777 if (talloc_free(listen_addr_root) < 0) return -1;
1778 listen_addr_root = NULL;
1779 if (talloc_free(process_modules) < 0) return -1;
1780 process_modules = NULL;
1781 if (talloc_free(proto_modules) < 0) return -1;
1782 proto_modules = NULL;
1784
1785 return 0;
1786}
1787
1788static int _virtual_servers_atexit(UNUSED void *uctx)
1789{
1790 return virtual_servers_free();
1791}
1792
1793/** Performs global initialisation for the virtual server code
1794 *
1795 * This has to be done separately and explicitly, because the above code makes
1796 * use of "onread" callbacks.
1797 *
1798 * Will automatically free module lists on exit, but all modules should have
1799 * been removed from this list by the point that happens.
1800 */
1802{
1804 PERROR("%s", __FUNCTION__);
1805 return -1;
1806 }
1808 PERROR("%s", __FUNCTION__);
1810 return -1;
1811 }
1812
1814
1815 /*
1816 * FIXME - We should be able to turn on write protection,
1817 * but there are too many proto modules that hang things
1818 * off of their instance data.
1819 */
1820 MEM(proto_modules = module_list_alloc(NULL, &module_list_type_global, "protocol", false));
1821 MEM(listen_addr_root = fr_rb_inline_alloc(NULL, fr_listen_t, virtual_server_node, listen_addr_cmp, NULL));
1822
1823 /*
1824 * Create a list to hold all the proto_* modules
1825 * that get loaded during startup.
1826 */
1828
1829 return 0;
1830}
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
@ UNLANG_ACTION_PUSHED_CHILD
unlang_t pushed a new child onto the stack, execute it instead of continuing.
Definition action.h:39
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
Definition action.h:36
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
Definition action.h:37
module_t common
Common fields provided by all modules.
Definition application.h:72
fr_app_open_t open
Callback to allow the fr_app_t to build an fr_listen_t and register it with the scheduler so we can r...
Definition application.h:76
Describes a new application (protocol)
Definition application.h:71
#define fr_atexit_global(_func, _uctx)
Add a free function to the global free list.
Definition atexit.h:59
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:167
#define RCSID(id)
Definition build.h:485
#define CMP_RETURN(_a, _b, _field)
Return if the comparison is not 0 (is unequal)
Definition build.h:121
#define unlikely(_x)
Definition build.h:383
#define UNUSED
Definition build.h:317
static int invalid_type(fr_type_t type)
Definition calc.c:698
bool check_config
Definition cf_file.c:62
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
Definition cf_parse.c:1154
int cf_null_on_read(UNUSED TALLOC_CTX *ctx, UNUSED void *out, UNUSED void *parent, UNUSED CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
NULL callback for sections.
Definition cf_parse.c:1706
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:658
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition cf_parse.h:612
void const * uctx
User data accessible by the cf_parse_t func.
Definition cf_parse.h:618
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:284
char const * name2
Second identifier for CONF_SECTION.
Definition cf_parse.h:597
#define FR_CONF_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
Definition cf_parse.h:339
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:615
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:434
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
Definition cf_parse.h:448
@ CONF_FLAG_OK_MISSING
OK if it's missing.
Definition cf_parse.h:456
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:428
#define FR_CONF_OFFSET_TYPE_FLAGS(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:241
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:595
Internal data that is associated with a configuration section.
Definition cf_priv.h:124
Common header for all CONF_* types.
Definition cf_priv.h:49
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:70
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
Definition cf_util.c:631
fr_token_t cf_pair_attr_quote(CONF_PAIR const *pair)
Return the value (lhs) quoting of a pair.
Definition cf_util.c:1622
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1184
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
Definition cf_util.c:1762
CONF_SECTION * cf_section_next(CONF_SECTION const *cs, CONF_SECTION const *curr)
Return the next child that's a CONF_SECTION.
Definition cf_util.c:996
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1170
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition cf_util.c:1027
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition cf_util.c:683
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
Definition cf_util.c:1438
fr_token_t cf_pair_operator(CONF_PAIR const *pair)
Return the operator of a pair.
Definition cf_util.c:1607
fr_token_t cf_pair_value_quote(CONF_PAIR const *pair)
Return the value (rhs) quoting of a pair.
Definition cf_util.c:1637
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
Definition cf_util.c:617
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:663
CONF_SECTION * cf_section_find_next(CONF_SECTION const *cs, CONF_SECTION const *prev, char const *name1, char const *name2)
Return the next matching section.
Definition cf_util.c:1048
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1593
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
Definition cf_util.c:1577
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:289
#define cf_data_add(_cf, _data, _name, _free)
Definition cf_util.h:255
#define cf_data_find(_cf, _type, _name)
Definition cf_util.h:244
#define cf_data_remove(_cf, _type, _name)
Remove an item from a parent by type and name.
Definition cf_util.h:267
#define cf_parent(_cf)
Definition cf_util.h:101
#define cf_item_next(_parent, _curr)
Definition cf_util.h:92
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:296
#define cf_section_find_parent(_cf, _name1, _name2)
Definition cf_util.h:175
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition cf_util.h:140
#define cf_data_find_in_parent(_cf, _type, _name)
Definition cf_util.h:250
#define cf_log_warn(_cf, _fmt,...)
Definition cf_util.h:290
#define cf_log_debug(_cf, _fmt,...)
Definition cf_util.h:292
#define CF_IDENT_ANY
Definition cf_util.h:78
fr_command_register_hook_t fr_command_register_hook
Definition command.c:42
char const * parent
e.g. "show module"
Definition command.h:52
#define CMD_TABLE_END
Definition command.h:62
int unlang_compile(virtual_server_t const *vs, CONF_SECTION *cs, unlang_mod_actions_t const *actions, tmpl_rules_t const *rules, void **instruction)
Compile an unlang section for a virtual server.
Definition compile.c:5064
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:156
#define MEM(x)
Definition debug.h:36
#define ERROR(fmt,...)
Definition dhcpclient.c:41
#define DEBUG(fmt,...)
Definition dhcpclient.c:39
int fr_dict_enum_add_name(fr_dict_attr_t *da, char const *name, fr_value_box_t const *value, bool coerce, bool replace)
Add a value name.
Definition dict_util.c:1943
int fr_dict_attr_add_name_only(fr_dict_t *dict, fr_dict_attr_t const *parent, char const *name, fr_type_t type, fr_dict_attr_flags_t const *flags))
Add an attribute to the dictionary.
Definition dict_util.c:1740
#define fr_dict_autofree(_to_free)
Definition dict.h:862
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.
Definition dict_util.c:3265
fr_dict_attr_t * fr_dict_attr_unconst(fr_dict_attr_t const *da)
Coerce to non-const.
Definition dict_util.c:4599
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2402
unsigned int internal
Internal attribute, should not be received in protocol packets, should not be encoded.
Definition dict.h:87
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:272
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:285
fr_dict_enum_value_t * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Definition dict_util.c:3397
int fr_dict_enum_add_name_next(fr_dict_attr_t *da, char const *name)
Add an name to an integer attribute hashing the name for the integer value.
Definition dict_util.c:1955
int fr_dict_attr_autoload(fr_dict_attr_autoload_t const *to_load)
Process a dict_attr_autoload element to load/verify a dictionary attribute.
Definition dict_util.c:4092
#define fr_dict_autoload(_to_load)
Definition dict.h:859
fr_dict_t * fr_dict_protocol_alloc(fr_dict_t const *parent)
Allocate a new local dictionary.
Definition dict_util.c:3963
Specifies an attribute which must be present for the module to function.
Definition dict.h:271
Values of the encryption flags.
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:284
Value of an enumerated attribute.
Definition dict.h:231
Test enumeration values.
Definition dict_test.h:92
@ DL_MODULE_TYPE_PROTO
Protocol module.
Definition dl_module.h:67
@ DL_MODULE_TYPE_PROCESS
protocol processor.
Definition dl_module.h:68
#define unlang_function_push(_request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack.
Definition function.h:111
int global_lib_instantiate(void)
Walk the tree of libraries and instantiate any which are pending.
Definition global_lib.c:218
int8_t fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
Compare two ip addresses.
Definition inet.c:1346
void fr_ipaddr_mask(fr_ipaddr_t *addr, uint8_t prefix)
Zeroes out the host portion of an fr_ipaddr_t.
Definition inet.c:217
IPv4/6 prefix.
int unlang_interpret_stack_depth(request_t *request)
Return the depth of the request's stack.
Definition interpret.c:1334
#define UNLANG_SUB_FRAME
Definition interpret.h:36
fr_socket_t * app_io_addr
for tracking duplicate sockets
Definition listen.h:36
fr_log_t * log_dst_by_name(char const *name)
Get a logging destination by name.
Definition log.c:1072
#define PERROR(_fmt,...)
Definition log.h:228
#define DEBUG3(_fmt,...)
Definition log.h:266
#define DEBUG_ENABLED
True if global debug level 1 messages are enabled.
Definition log.h:257
talloc_free(reap)
Stores all information relating to an event list.
Definition event.c:377
int fr_debug_lvl
Definition log.c:40
@ L_DBG_LVL_DISABLE
Don't print messages.
Definition log.h:68
main_config_t const * main_config
Main server configuration.
Definition main_config.c:58
fr_worker_config_t worker
Worker thread configuration.
Definition main_config.h:61
fr_type_t
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_VOID
User data.
@ FR_TYPE_GROUP
A grouping of other attributes.
long int ssize_t
unsigned char uint8_t
@ MOD_ACTION_RETURN
Definition mod_action.h:40
unlang_mod_action_t actions[RLM_MODULE_NUMCODES]
Definition mod_action.h:62
static const virtual_server_compile_t compile_list[]
Definition base.c:205
static const conf_parser_t config[]
Definition base.c:183
fr_dict_t const ** dict
pointer to local fr_dict_t *
Definition process.h:59
module_method_t process
Process packets.
Definition process.h:57
virtual_server_compile_t const * compile_list
list of processing sections
Definition process.h:58
Common public symbol definition for all process modules.
Definition process.h:54
#define fr_assert(_expr)
Definition rad_assert.h:38
#define DEBUG2(fmt,...)
Definition radclient.h:43
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
Find an element in the tree, returning the data, not the node.
Definition rb.c:577
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
Definition rb.c:626
#define fr_rb_alloc(_ctx, _data_cmp, _data_free)
Allocs a red black tree.
Definition rb.h:223
#define fr_rb_inline_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black tree.
Definition rb.h:271
The main red black tree structure.
Definition rb.h:73
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
@ RLM_MODULE_INVALID
The module considers the request invalid.
Definition rcode.h:45
@ RLM_MODULE_OK
The module is OK, continue.
Definition rcode.h:43
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition rcode.h:42
@ RLM_MODULE_DISALLOW
Reject the request (user is locked out).
Definition rcode.h:46
@ RLM_MODULE_REJECT
Immediately reject the request.
Definition rcode.h:41
@ RLM_MODULE_NOTFOUND
User not found.
Definition rcode.h:47
@ RLM_MODULE_UPDATED
OK (pairs modified).
Definition rcode.h:49
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition rcode.h:48
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
Definition rcode.h:44
fr_dict_attr_t const * request_attr_request
Definition request.c:43
void request_log_prepend(request_t *request, fr_log_t *log_dst, fr_log_lvl_t lvl)
Prepend another logging destination to the list.
Definition request.c:92
static char const * name
The scheduler.
Definition schedule.c:125
int8_t section_name_cmp(void const *one, void const *two)
Compare two sections.
Definition section.c:47
char const * name2
Second section name. Usually a packet type like 'access-request', 'access-accept',...
Definition section.h:46
char const * name1
First section name. Usually a verb like 'recv', 'send', etc...
Definition section.h:45
Section name identifier.
Definition section.h:44
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:330
void * data
Module's instance data.
Definition module.h:272
module_t * exported
Public module structure.
Definition module.h:277
Module instance data.
Definition module.h:266
A list of modules.
Definition module.h:386
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition tmpl.h:335
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:332
fr_signal_t
Signals that can be generated/processed by request signal handlers.
Definition signal.h:38
@ FR_SIGNAL_CANCEL
Request has been cancelled.
Definition signal.h:40
static const uchar sc[16]
Definition smbdes.c:115
int module_instance_data_protect(module_instance_t const *mi)
Mark module data as read only.
Definition module.c:693
void module_list_debug(module_list_t const *ml)
Print the contents of a module list.
Definition module.c:615
module_instance_t * module_instance_alloc(module_list_t *ml, module_instance_t const *parent, dl_module_type_t type, char const *mod_name, char const *inst_name, module_instance_state_t init_state)
Allocate a new module and add it to a module list for later bootstrap/instantiation.
Definition module.c:1645
fr_slen_t module_instance_name_from_conf(char const **name, CONF_SECTION *conf)
Avoid boilerplate when setting the module instance name.
Definition module.c:729
void modules_thread_detach(module_list_t *ml)
Remove thread-specific data for a given module list.
Definition module.c:1003
int modules_thread_instantiate(TALLOC_CTX *ctx, module_list_t const *ml, fr_event_list_t *el)
Creates per-thread instance data for modules which need it.
Definition module.c:1154
module_instance_t * module_instance_by_data(module_list_t const *ml, void const *data)
Find an existing module instance by its private instance data.
Definition module.c:951
int modules_instantiate(module_list_t const *ml)
Completes instantiation of modules.
Definition module.c:1275
module_list_t * module_list_alloc(TALLOC_CTX *ctx, module_list_type_t const *type, char const *name, bool write_protect)
Allocate a new module list.
Definition module.c:1851
fr_slen_t module_instance_name_valid(char const *inst_name)
Check to see if a module instance name is valid.
Definition module.c:1585
int module_instance_data_unprotect(module_instance_t const *mi)
Mark module data as read/write.
Definition module.c:705
module_list_type_t const module_list_type_global
Callbacks for a global module list.
Definition module.c:528
int modules_bootstrap(module_list_t const *ml)
Bootstrap any modules which have not been bootstrapped already.
Definition module.c:1366
int module_submodule_parse(UNUSED TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic callback for conf_parser_t to load a submodule.
Definition module.c:841
int module_instance_conf_parse(module_instance_t *mi, CONF_SECTION *conf)
Covert a CONF_SECTION into parsed module instance data.
Definition module.c:758
int unlang_module_push(rlm_rcode_t *p_result, request_t *request, module_instance_t *mi, module_method_t method, bool top_frame)
Push a module or submodule onto the stack for evaluation.
Definition module.c:51
fr_aka_sim_id_type_t type
Definition log.h:96
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Definition tmpl.h:273
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
Definition table.h:653
static fr_time_delta_t fr_time_delta_from_msec(int64_t msec)
Definition time.h:575
static int8_t fr_time_delta_cmp(fr_time_delta_t a, fr_time_delta_t b)
Compare two fr_time_delta_t values.
Definition time.h:930
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
int unlang_timeout_section_push(request_t *request, CONF_SECTION *cs, fr_time_delta_t timeout, bool top_frame)
When a timeout fires, run the given section.
Definition timeout.c:184
@ T_OP_CMP_TRUE
Definition token.h:104
@ T_BARE_WORD
Definition token.h:120
@ T_OP_EQ
Definition token.h:83
static fr_event_list_t * el
Generic representation of a grouping.
static fr_slen_t parent
Definition pair.h:845
#define RETRY_INIT
Definition retry.h:39
int af
AF_INET, AF_INET6, or AF_UNIX.
Definition socket.h:78
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:553
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
Definition strerror.c:576
#define fr_strerror_const(_msg)
Definition strerror.h:223
fr_table_num_ordered_t const fr_type_table[]
Map data types to names representing those types.
Definition types.c:31
#define fr_type_is_structural(_x)
Definition types.h:371
#define fr_type_is_leaf(_x)
Definition types.h:372
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)
Definition value.c:5450
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition value.c:3946
static fr_slen_t data
Definition value.h:1274
#define fr_value_box_init_null(_vb)
Initialise an empty/null box that will be filled later.
Definition value.h:604
#define fr_box_time_delta(_val)
Definition value.h:354
static size_t char ** out
Definition value.h:1012
#define FR_VALUE_BOX_SAFE_FOR_ANY
Definition value.h:166
fr_dict_autoload_t virtual_server_dict_autoload[]
static const conf_parser_t server_on_read_config[]
bool listen_record(fr_listen_t *li)
Record that we're listening on a particular IP / port.
int virtual_server_section_register(virtual_server_t *vs, virtual_server_compile_t const *entry)
Register name1 / name2 as allowed processing sections.
fr_process_module_t const * process_module
Public interface to the process_mi.
int virtual_servers_bootstrap(CONF_SECTION *config)
Load protocol modules and call their bootstrap methods.
module_instance_t * process_mi
The process_* module for a virtual server.
const conf_parser_t virtual_servers_on_read_config[]
fr_dict_t const * virtual_server_dict_by_name(char const *virtual_server)
Return the namespace for the named virtual server.
static int server_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
static int virtual_server_compile_sections(virtual_server_t *vs, tmpl_rules_t const *rules)
Compile sections for a virtual server.
CONF_SECTION * server_cs
The server section.
module_instance_t * virtual_server_listener_by_data(void const *data)
Resolve proto data to a module instance.
fr_rb_tree_t * sections
List of sections that need to be compiled.
static int namespace_on_read(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
section_name_t const ** virtual_server_section_methods(virtual_server_t const *vs, section_name_t const *section)
Find the component for a section.
fr_dict_attr_autoload_t virtual_server_dict_attr_autoload[]
int virtual_servers_open(fr_schedule_t *sc)
Open all the listen sockets.
CONF_SECTION * timeout_cs
int virtual_server_cf_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Wrapper for the config parser to allow pass1 resolution of virtual servers.
static module_list_t * process_modules
List of process modules we've loaded.
int virtual_server_has_namespace(CONF_SECTION **out, char const *virtual_server, fr_dict_t const *namespace, CONF_ITEM *ci)
Verify that a given virtual_server exists and is of a particular namespace.
static fr_dict_t const * dict_freeradius
int virtual_server_listen_transport_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic conf_parser_t func for loading drivers.
const conf_parser_t virtual_servers_config[]
static CONF_SECTION * virtual_server_root
CONF_SECTION holding all the virtual servers.
static const conf_parser_t server_config[]
virtual_server_t const * virtual_server_find(char const *name)
Return virtual server matching the specified name.
static fr_dict_t const * virtual_server_local_dict(CONF_SECTION *server_cs, fr_dict_t const *dict_def)
fr_dict_t const * virtual_server_dict_by_child_ci(CONF_ITEM const *ci)
Return the namespace for a given virtual server specified by a CONF_ITEM within the virtual server.
fr_virtual_listen_t ** listeners
Listeners in this virtual server.
static int8_t virtual_server_compile_name_cmp(void const *a, void const *b)
fr_listen_t * listen_find_any(fr_listen_t *li)
See if another global listener is using a particular IP / port.
static virtual_server_t ** virtual_servers
Top level structure holding all virtual servers.
static fr_dict_attr_t const * attr_auth_type
int virtual_server_section_attribute_define(CONF_SECTION *server_cs, char const *subcs_name, fr_dict_attr_t const *da)
Define a values for Auth-Type attributes by the sections present in a virtual-server.
unlang_action_t virtual_server_push(request_t *request, CONF_SECTION *server_cs, bool top_frame)
Set the request processing function.
void virtual_servers_thread_detach(void)
Free thread-specific data for all process modules and listeners.
static fr_cmd_table_t cmd_table[]
void virtual_server_process_debug(void)
Print all the loaded process module instances.
fr_time_delta_t timeout_delay
for timeout sections
CONF_SECTION * virtual_server_cs(virtual_server_t const *vs)
Return the configuration section for a virtual server.
fr_dict_t const * virtual_server_dict_by_cs(CONF_SECTION const *server_cs)
Return the namespace for the virtual server specified by a config section.
int virtual_servers_init(void)
Performs global initialisation for the virtual server code.
static fr_rb_tree_t * listen_addr_root
void virtual_server_listen_debug(void)
Print all the loaded listener instances.
fr_log_t * log
log destination
static int define_server_attrs(CONF_SECTION *cs, fr_dict_t *dict, fr_dict_attr_t *parent, fr_dict_attr_t const *root)
static int8_t listen_addr_cmp(void const *one, void const *two)
Compare listeners by app_io_addr.
static module_list_t * proto_modules
List of proto modules we've loaded.
static int _virtual_servers_atexit(UNUSED void *uctx)
static int listen_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
int virtual_servers_instantiate(void)
Instantiate all the virtual servers.
static void server_signal_remove_log_destination(request_t *request, UNUSED fr_signal_t action, void *uctx)
virtual_server_t const * virtual_server_by_child(CONF_ITEM const *ci)
Find a virtual server using one of its sections.
int virtual_servers_free(void)
static unlang_mod_actions_t const mod_actions_timeout
static int namespace_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
static int add_compile_list(virtual_server_t *vs, CONF_SECTION *cs, virtual_server_compile_t const *compile_list, char const *name)
static unlang_action_t server_remove_log_destination(UNUSED rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
module_instance_t * proto_mi
The proto_* module for a listen section.
int virtual_servers_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Perform thread instantiation for all process modules and listeners.
static int cmd_show_server_list(FILE *fp, UNUSED FILE *fp_err, UNUSED void *ctx, UNUSED fr_cmd_info_t const *info)
void * timeout_instruction
the timeout instruction
static int define_server_values(CONF_SECTION *cs, fr_dict_attr_t *parent)
fr_app_t const * proto_module
Public interface to the proto_mi.
char const * log_name
name of log destination
struct virtual_server_s virtual_server_t
section_name_t const * section
Identifier for the section.
size_t offset
where the CONF_SECTION pointer is written
section_name_t const ** methods
list of auxilliary module methods which are allowed in if the main name doesn't match.
Processing sections which are allowed in this virtual server.
fr_time_delta_t max_request_time
maximum time a request can be processed
Definition worker.h:67