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: b20891d8220e0ae3a295e7638a9dca839b4b190f $
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: b20891d8220e0ae3a295e7638a9dca839b4b190f $")
28
29#include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
30#include <freeradius-devel/server/base.h>
31#include <freeradius-devel/server/process_types.h>
32#include <freeradius-devel/server/virtual_servers.h>
33#include <freeradius-devel/server/cf_util.h>
34
35#include <freeradius-devel/unlang/compile.h>
36#include <freeradius-devel/unlang/function.h>
37#include <freeradius-devel/unlang/finally.h>
38#include <freeradius-devel/unlang/interpret.h>
39
40#include <freeradius-devel/io/application.h>
41#include <freeradius-devel/io/master.h>
42#include <freeradius-devel/io/listen.h>
43
44#include <freeradius-devel/util/debug.h>
45#include <freeradius-devel/util/dict.h>
46#include <freeradius-devel/util/pair.h>
47#include <freeradius-devel/util/talloc.h>
48#include <freeradius-devel/util/types.h>
49#include <freeradius-devel/util/value.h>
50
51typedef struct {
52 module_instance_t *proto_mi; //!< The proto_* module for a listen section.
53 fr_app_t const *proto_module; //!< Public interface to the proto_mi.
54 ///< cached for convenience.
56
58 CONF_SECTION *server_cs; //!< The server section.
59 virtual_server_listen_t **listeners; //!< Listeners in this virtual server.
60
61 module_instance_t *process_mi; //!< The process_* module for a virtual server.
62 ///< Contains the dictionary used by the virtual
63 ///< server and the entry point for the state machine.
64 fr_process_module_t const *process_module; //!< Public interface to the process_mi.
65 ///< cached for convenience.
66
67 fr_rb_tree_t *sections; //!< List of sections that need to be compiled.
68
69 fr_log_t *log; //!< log destination
70 char const *log_name; //!< name of log destination
71
72 void **finally_by_packet_type; //!< Finalise instruction by packet type.
73 void *finally_default; //!< Default finally instruction.
74};
75
77
79
85
92
93/** List of process modules we've loaded
94 *
95 * This is global for all virtual servers. Must be initialised
96 * _before_ the configuration is loaded.
97 */
99
100/** List of proto modules we've loaded
101 *
102 * This is global for all virtual servers. Must be initialised
103 * _before_ the configuration is loaded.
104 */
106
107/** Top level structure holding all virtual servers
108 *
109 */
111
112/** CONF_SECTION holding all the virtual servers
113 *
114 * Set during the call to virtual_server_bootstrap and used by
115 * other virtual server functions.
116 */
118
120
121static int namespace_on_read(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
122
123static int namespace_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
124static int listen_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
125static int server_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule);
126
133
135 /*
136 * Not really ok if it's missing but we want to
137 * let logic elsewhere handle the issue.
138 */
140 .subcs_size = sizeof(virtual_server_t), .subcs_type = "virtual_server_t",
141 .subcs = (void const *) server_on_read_config, .name2 = CF_IDENT_ANY,
142 .on_read = cf_null_on_read },
143
145};
146
147static const conf_parser_t server_config[] = {
150
152 virtual_server_t, listeners),
153 .name2 = CF_IDENT_ANY,
154 .subcs_size = sizeof(virtual_server_listen_t), .subcs_type = "virtual_server_listen_t",
155 .func = listen_parse },
156
157 { FR_CONF_OFFSET("log", virtual_server_t, log_name), },
158
160};
161
163 /*
164 * Not really ok if it's missing but we want to
165 * let logic elsewhere handle the issue.
166 */
168 .subcs_size = sizeof(virtual_server_t), .subcs_type = "virtual_server_t",
169 .subcs = (void const *) server_config, .name2 = CF_IDENT_ANY,
170 .func = server_parse },
171
173};
174
175/** Print all the loaded listener instances
176 *
177 */
182
183/** Print all the loaded process module instances
184 *
185 */
190
191/** Resolve proto data to a module instance
192 *
193 * @param[in] data Pointer to the proto data.
194 * @return
195 * - The module instance for the proto data.
196 * - NULL if no data matches.
197 */
202
203/** Generic conf_parser_t func for loading drivers
204 *
205 */
206int virtual_server_listen_transport_parse(TALLOC_CTX *ctx, void *out, void *parent,
207 CONF_ITEM *ci, conf_parser_t const *rule)
208{
209 conf_parser_t our_rule = *rule;
210
211 our_rule.uctx = &proto_modules;
212
213 return module_submodule_parse(ctx, out, parent, ci, &our_rule);
214}
215
216/** Parse a "namespace" parameter
217 *
218 * We need to load the process module before continuing to parse the virtual server contents
219 * as we need to know the namespace so that we can resolve attribute names.
220 *
221 * We also need the compilation list from the proto module to figure out which sections we
222 * need to compile.
223 *
224 * @param[in] ctx to allocate data in.
225 * @param[out] out always NULL
226 * @param[in] parent Base structure address.
227 * @param[in] ci #CONF_SECTION containing the listen section.
228 * @param[in] rule unused.
229 * @return
230 * - 0 on success.
231 * - -1 on failure.
232 */
233static int namespace_on_read(TALLOC_CTX *ctx, UNUSED void *out, UNUSED void *parent,
234 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
235{
236 CONF_PAIR *cp = cf_item_to_pair(ci);
237 CONF_SECTION *server_cs = cf_item_to_section(cf_parent(ci));
239 char const *namespace;
240 char *module_name, *p, *end;
241 char const *inst_name;
242 fr_process_module_t const *process;
243
245 "virtual_servers_init MUST be called before reading virtual server config");
246
247 namespace = cf_pair_value(cp);
248 module_name = talloc_strdup(ctx, namespace);
249
250 /*
251 * Smush all hyphens to underscores for module names
252 */
253 for (p = module_name, end = module_name + talloc_strlen(module_name);
254 p < end;
255 p++) if (*p == '-') *p = '_';
256
257 if (module_instance_name_from_conf(&inst_name, server_cs) < 0) return -1;
258
259 /*
260 * The module being loaded is the namespace with all '-'
261 * transformed to '_'.
262 *
263 * The instance name is the virtual server name.
264 */
266 module_name, inst_name,
267 0);
268 talloc_free(module_name);
269 if (mi == NULL) {
270 error:
271 cf_log_perr(ci, "Failed loading process module");
272 return -1;
273 }
274 if (unlikely(module_instance_conf_parse(mi, mi->conf) < 0)) {
275 talloc_free(mi);
276 goto error;
277 }
278
279 process = (fr_process_module_t const *)mi->module->exported;
280 if (!*(process->dict)) {
281 cf_log_err(ci, "Process module is invalid - missing namespace dictionary");
282 talloc_free(mi);
283 return -1;
284 }
285 cf_data_add(server_cs, mi, "process_module", false);
286 cf_data_add(server_cs, *(process->dict), "dict", false);
287
288 return 0;
289}
290
291static inline CC_HINT(always_inline)
293{
294 int i;
296
297 if (!compile_list) return 0;
298
299 for (i = 0; list[i].section; i++) {
300#ifndef NDEBUG
301 /*
302 * We can't have a wildcard for name1. It MUST be a real name.
303 *
304 * The wildcard was allowed previously for ideas which later didn't turn out.
305 */
306 if (list[i].section->name1 == CF_IDENT_ANY) {
307 fr_assert(0);
308 continue;
309 }
310
311#endif
312 if (virtual_server_section_register(vs, &list[i]) < 0) {
313 cf_log_err(cs, "Failed registering processing section name %s for %s",
314 list[i].section->name1, name);
315 return -1;
316 }
317 }
318
319 return 0;
320}
321
322/** dl_open a process_* module
323 *
324 * @param[in] ctx to allocate data in.
325 * @param[out] out Where to our listen configuration. Is a #fr_virtual_listen_t structure.
326 * @param[in] parent Base structure address.
327 * @param[in] ci #CONF_SECTION containing the listen section.
328 * @param[in] rule unused.
329 * @return
330 * - 0 on success.
331 * - -1 on failure.
332 */
333static int namespace_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
334{
335 CONF_PAIR *cp = cf_item_to_pair(ci);
336 CONF_SECTION *server_cs = cf_item_to_section(cf_parent(ci));
337 CONF_SECTION *process_cs;
338 virtual_server_t *server = talloc_get_type_abort(((uint8_t *) out) - offsetof(virtual_server_t, process_mi), virtual_server_t);
339 char const *namespace = cf_pair_value(cp);
340 module_instance_t *mi = cf_data_value(cf_data_find(server_cs, module_instance_t, "process_module"));
341
342 /*
343 * We don't have access to virtual_server_t
344 * in the onread callback, so we need to do the
345 * fixups here.
346 */
347 server->process_mi = mi;
348 server->process_module = (fr_process_module_t const *)mi->module->exported;
349
350 *(module_instance_t const **)out = mi;
351
352 /*
353 * Enforce that the protocol process configuration is in
354 * a subsection named for the protocol.
355 */
356 process_cs = cf_section_find(server_cs, namespace, NULL);
357 if (!process_cs) {
358 process_cs = cf_section_alloc(server_cs, server_cs, namespace, NULL);
359 }
360
361 if (module_instance_conf_parse(mi, process_cs) < 0) {
362 cf_log_perr(ci, "Failed bootstrapping process module");
363 cf_data_remove(server_cs, module_instance_t, "process_module");
364 cf_data_remove(server_cs, fr_dict_t, "dict");
365 TALLOC_FREE(server->process_mi);
366 return -1;
367 }
368
369 /*
370 * Pull the list of sections we need to compile out of
371 * the process module's public struct.
372 */
373 add_compile_list(server, server->process_mi->conf, server->process_module->compile_list, namespace);
374
375 return 0;
376}
377
378/** dl_open a proto_* module
379 *
380 * @param[in] ctx to allocate data in.
381 * @param[out] out Where to our listen configuration. Is a #fr_virtual_listen_t structure.
382 * @param[in] parent Base structure address.
383 * @param[in] ci #CONF_SECTION containing the listen section.
384 * @param[in] rule unused.
385 * @return
386 * - 0 on success.
387 * - -1 on failure.
388 */
389static int listen_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
390{
391 virtual_server_listen_t *listener = talloc_get_type_abort(out, virtual_server_listen_t); /* Pre-allocated for us */
392 CONF_SECTION *listener_cs = cf_item_to_section(ci);
393 CONF_SECTION *server_cs = cf_item_to_section(cf_parent(ci));
394 CONF_PAIR *namespace = cf_pair_find(server_cs, "namespace");
395
396 CONF_PAIR *cp;
397 char const *module, *name2, *p;
398 fr_sbuff_t *agg;
399
401
403 "virtual_servers_init MUST be called before reading virtual server config");
404
405 if (!namespace) {
406 cf_log_err(server_cs, "No 'namespace' set for virtual server");
407 cf_log_err(server_cs, "Please add 'namespace = <protocol>' inside of the 'server %s { ... }' section",
408 cf_section_name2(server_cs));
409 return -1;
410 }
411
412 /*
413 * The module we load comes from the 'handler' or 'proto' configuration. This configuration item
414 * allows us to have multi-protocol listen module, such as "detail".
415 *
416 * If there isn't a multi-protocol listen module, then load the one for this namespace, such as
417 * "radius".
418 */
419 cp = cf_pair_find(listener_cs, "handler");
420 if (!cp) cp = cf_pair_find(listener_cs, "proto");
421 if (cp) {
422 module = cf_pair_value(cp);
423 if (!module) {
424 cf_log_err(cp, "Missing value");
425 return -1;
426 }
427 } else {
428 module = cf_pair_value(namespace);
429 }
430
431 /*
432 * The proto modules go into a global tree, so we qualify their name (second name) with the name
433 * of the virtual server, followed by the transport, followed by any transport-specific
434 * configuration.
435 */
437
438 name2 = cf_section_name2(listener_cs);
439
440 /*
441 * A 'listen foo' in this virtual server helps it to be unique. We load the "radius" module,
442 * instance "default.foo". This naming scheme is a little counter-intuitive, but it is required
443 * due to the listen module list being global, and loading the leading module name e.g. "radius".
444 *
445 * Since the virtual server names are unique, we don't have to qualify the listen section names
446 * by anything else.
447 */
448 if (name2) {
449 /*
450 * We do some duplicate checks here, because that gives better errors than if we use the
451 * mangled names below.
452 */
453 if (module_instance_name_valid(name2) < 0) {
454 cf_log_perr(listener_cs, "Invalid name in 'listen %s'", name2);
455 return -1;
456 }
457
458 /*
459 * Load "radius", instance "default.foo".
460 */
461 FR_SBUFF_IN_CHAR_RETURN(agg, '.');
462 FR_SBUFF_IN_STRCPY_RETURN(agg, name2);
463 }
464
465 /*
466 * Further qualify the name by transport and port. This helps it to be more unique.
467 */
468 cp = cf_pair_find(listener_cs, "transport");
469 if (!cp || ((p = cf_pair_value(cp)) == NULL)) {
470 cf_log_err(listener_cs, "Invalid 'listen' section - No 'transport = ...' definition was found.");
471 return -1;
472 }
473 FR_SBUFF_IN_CHAR_RETURN(agg, '.');
475
476 cp = cf_pair_find(listener_cs, "port");
477 if (cp && ((p = cf_pair_value(cp)) != NULL)) {
478 FR_SBUFF_IN_CHAR_RETURN(agg, '.');
480 }
481
483 cf_log_perr(listener_cs, "Failed loading listen section.");
484 return -1;
485 }
486
488 if (!mi) {
489 cf_log_perr(listener_cs, "Failed creating listen section");
490 return -1;
491 }
492
493 if (unlikely(module_instance_conf_parse(mi, listener_cs) < 0)) {
494 talloc_free(mi);
495 cf_log_perr(listener_cs, "Failed parsing listen section");
496 return -1;
497 }
498
499 listener->proto_mi = mi;
500 listener->proto_module = (fr_app_t const *)listener->proto_mi->module->exported;
501 cf_data_add(listener_cs, mi, "proto_module", false);
502
503 /*
504 * The listener doesn't have to contain a 'type = foo' configuration. But if it does, there MUST
505 * also be a 'recv foo' section.
506 */
507 for (cp = cf_pair_find(listener_cs, "type");
508 cp != NULL;
509 cp = cf_pair_find_next(listener_cs, cp, "type")) {
510 char const *type = cf_pair_value(cp);
511
512 if (!type) continue;
513
514 if (!cf_section_find(server_cs, "recv", type)) {
515 cf_log_err(cp, "Listener has 'type = %s', but there is no 'recv %s { ... }' section defined.",
516 type, type);
517 return -1;
518 }
519 }
520
521 return 0;
522}
523
524static int8_t virtual_server_compile_name_cmp(void const *a, void const *b)
525{
526 virtual_server_compile_t const *sa = a;
527 virtual_server_compile_t const *sb = b;
528
529 return section_name_cmp(sa->section, sb->section);
530}
531
532/** Callback to validate the server section
533 *
534 * @param[in] ctx to allocate data in.
535 * @param[out] out Where to our listen configuration. Is a #virtual_server_t structure.
536 * @param[in] parent Base structure address.
537 * @param[in] ci #CONF_SECTION containing the listen section.
538 * @param[in] rule unused.
539 * @return
540 * - 0 on success.
541 * - -1 on failure.
542 */
543static int server_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
544 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
545{
546 virtual_server_t *server = talloc_get_type_abort(out, virtual_server_t);
547 CONF_SECTION *server_cs = cf_item_to_section(ci);
548 CONF_PAIR *namespace;
549
550 namespace = cf_pair_find(server_cs, "namespace");
551 if (!namespace) {
552 cf_log_err(server_cs, "virtual server %s MUST contain a 'namespace' option",
553 cf_section_name2(server_cs));
554 return -1;
555 }
556
558 server->server_cs = server_cs;
559
560 /*
561 * Now parse the listeners
562 */
563 if (cf_section_parse(out, server, server_cs) < 0) return -1;
564
565 /*
566 * And cache this struct for later referencing.
567 */
568 cf_data_add(server_cs, server, NULL, false);
569
570 return 0;
571}
572
573/** Return the namespace for the named virtual server
574 *
575 * @param[in] virtual_server to look for namespace in.
576 * @return
577 * - NULL on error.
578 * - Namespace on success.
579 */
580fr_dict_t const *virtual_server_dict_by_name(char const *virtual_server)
581{
582 virtual_server_t const *vs;
583
584 vs = virtual_server_find(virtual_server);
585 if (!vs) return NULL;
586
588}
589
590/** Return the namespace for the virtual server specified by a config section
591 *
592 * @param[in] server_cs to look for namespace in.
593 * @return
594 * - NULL on error.
595 * - Namespace on success.
596 */
598{
599 CONF_DATA const *cd;
600 fr_dict_t *dict;
601
602 cd = cf_data_find(server_cs, fr_dict_t, "dict");
603 if (!cd) return NULL;
604
605 dict = cf_data_value(cd);
606 (void) talloc_get_type_abort(dict, fr_dict_t);
607
608 return dict;
609}
610
611/** Return the namespace for a given virtual server specified by a CONF_ITEM within the virtual server
612 *
613 * @param[in] ci to look for namespace in.
614 * @return
615 * - NULL on error.
616 * - Namespace on success.
617 */
619{
620 CONF_DATA const *cd;
621 fr_dict_t *dict;
622
623 cd = cf_data_find_in_parent(ci, fr_dict_t, "dict");
624 if (!cd) return NULL;
625
626 dict = cf_data_value(cd);
627 (void) talloc_get_type_abort(dict, fr_dict_t);
628
629 return dict;
630}
631
632/** Verify that a given virtual_server exists and is of a particular namespace
633 *
634 * Mostly used by modules to check virtual servers specified by their configs.
635 *
636 * @param[out] out we found. May be NULL if just checking for existence.
637 * @param[in] virtual_server to check.
638 * @param[in] namespace the virtual server must belong to.
639 * @param[in] ci to log errors against. May be NULL if caller
640 * doesn't want errors logged.
641 * @return
642 * - 0 on success.
643 * - -1 if no virtual server could be found.
644 * - -2 if virtual server is not of the correct namespace.
645 */
647 char const *virtual_server, fr_dict_t const *namespace, CONF_ITEM *ci)
648{
649 virtual_server_t const *vs;
650 CONF_SECTION *server_cs;
651 fr_dict_t const *dict;
652
653 if (out) *out = NULL;
654
655 vs = virtual_server_find(virtual_server);
656 if (!vs) {
657 if (ci) cf_log_err(ci, "Can't find virtual server \"%s\"", virtual_server);
658 return -1;
659 }
660 server_cs = virtual_server_cs(vs);
661
662 dict = virtual_server_dict_by_name(virtual_server);
663 if (!dict) {
664 /*
665 * Not sure this is even a valid state?
666 */
667 if (ci) cf_log_err(ci, "No namespace found in virtual server \"%s\"", virtual_server);
668 return -2;
669 }
670
671 if (dict != namespace) {
672 if (ci) {
673 cf_log_err(ci,
674 "Expected virtual server \"%s\" to be of namespace \"%s\", got namespace \"%s\"",
675 virtual_server, fr_dict_root(namespace)->name, fr_dict_root(dict)->name);
676 }
677 return -2;
678 }
679
680 if (out) *out = server_cs;
681
682 return 0;
683}
684
685/*
686 * If we pushed a log destination, we need to pop it/
687 */
689 request_t *request, void *uctx)
690{
691 virtual_server_t *server = uctx;
692
693 request_log_prepend(request, server->log, L_DBG_LVL_DISABLE);
694
696}
697
698static void server_signal_remove_log_destination(request_t *request, UNUSED fr_signal_t action, void *uctx)
699{
700 virtual_server_t *server = uctx;
701
702 request_log_prepend(request, server->log, L_DBG_LVL_DISABLE);
703}
704
705/** Push a finally section onto the stack
706 *
707 * The finally instruction cannot be cancelled and will always execute as the stack is unwound.
708 *
709 * @param[in] request request to push the finally section onto.
710 * @param[in] vs virtual server to push the finally section for.
711 * @param[in,out] top_frame mutate the top frame value to indicate that future
712 * pushes should be subframes.
713 * @return
714 * - 0 on success.
715 * - -1 on failure.
716 */
717static inline CC_HINT(always_inline) int virtual_server_push_finally(request_t *request, virtual_server_t const *vs, bool *top_frame)
718{
719 /*
720 * Don't bother finding the packet type unless there
721 * are finally sections registered.
722 */
723 if (vs->finally_by_packet_type) {
724 fr_pair_t *vp = fr_pair_find_by_da(&request->request_pairs, NULL,
726 fr_value_box_t key;
727 void *instruction;
728
729 if (!vp) goto check_default; /* No packet type found, still allow default finally section */
730
731 if (fr_value_box_cast(NULL, &key, FR_TYPE_UINT16, NULL, &vp->data) < 0) return -1;
732
733 if (key.vb_uint16 >= talloc_array_length(vs->finally_by_packet_type) ||
734 !(instruction = vs->finally_by_packet_type[key.vb_uint16])) goto check_default;
735
736 if (unlikely(unlang_finally_push_instruction(request, instruction,
737 fr_time_delta_from_sec(5), *top_frame) < 0)) return -1;
738
739 *top_frame = UNLANG_SUB_FRAME; /* switch to SUB_FRAME after the first instruction */
740
741 return 0;
742 }
743
744check_default:
745 if (vs->finally_default) {
747 fr_time_delta_from_sec(5), *top_frame) < 0)) return -1;
748
749 *top_frame = UNLANG_SUB_FRAME; /* switch to SUB_FRAME after the first instruction */
750 }
751
752 return 0;
753}
754
755/** Set the request processing function.
756 *
757 * Short-term hack
758 */
759unlang_action_t virtual_server_push(unlang_result_t *p_result, request_t *request, virtual_server_t const *vs, bool top_frame)
760{
761 /*
762 * Add a log destination specific to this virtual server.
763 *
764 * If we add a log destination, make sure to remove it when we walk back up the stack.
765 * But ONLY if we're not at the top of the stack.
766 *
767 * When a brand new request comes in, it has a "call" frame pushed, and then this function is
768 * called. So if we're at the top of the stack, we don't need to pop any logging function,
769 * because the request will die immediately after the top "call" frame is popped.
770 *
771 * However, if we're being reached from a "call" frame in the middle of the stack, then
772 * we do have to pop the log destination when we return.
773 */
774 if (vs->log) {
775 request_log_prepend(request, vs->log, fr_debug_lvl);
776
777 if (unlang_interpret_stack_depth(request) > 1) {
778 unlang_action_t action;
779
780 action = unlang_function_push_with_result(unlang_interpret_result(request), /* transparent */
781 request,
782 NULL, /* don't call it immediately */
783 server_remove_log_destination, /* but when we pop the frame */
785 top_frame,
786 UNCONST(void *, vs));
787 if (action != UNLANG_ACTION_PUSHED_CHILD) return action;
788
789 top_frame = UNLANG_SUB_FRAME; /* switch to SUB_FRAME after the first instruction */
790 }
791 }
792
793 /*
794 * Push an uncancellable finally instruction to the stack.
795 */
796 if (virtual_server_push_finally(request, vs, &top_frame) < 0) return UNLANG_ACTION_FAIL;
797
798 /*
799 * Bootstrap the stack with a module instance.
800 */
801 if (unlang_module_push(p_result, request, vs->process_mi,
802 vs->process_module->process, top_frame) < 0) return UNLANG_ACTION_FAIL;
803
805}
806
807static int cmd_show_server_list(FILE *fp, UNUSED FILE *fp_err, UNUSED void *ctx, UNUSED fr_cmd_info_t const *info)
808{
809 size_t i, server_cnt = virtual_servers ? talloc_array_length(virtual_servers) : 0;
810
811 if (!server_cnt) return 0;
812
813 for (i = 0; i < server_cnt; i++) {
814 fprintf(fp, "%-30snamespace = %s\n", cf_section_name2(virtual_servers[i]->server_cs),
815 fr_dict_root(*(virtual_servers[i]->process_module->dict))->name);
816 }
817
818 return 0;
819}
820
822 {
823 .parent = "show",
824 .name = "server",
825 .help = "Show virtual server settings.",
826 .read_only = true,
827 },
828
829 {
830 .parent = "show server",
831 .name = "list",
832 .func = cmd_show_server_list,
833 .help = "Show the list of virtual servers loaded in the server.",
834 .read_only = true,
835 },
836
838
839};
840
841/** Compare listeners by app_io_addr
842 *
843 * Only works for IP addresses, and will blow up on file names
844 */
845static int8_t listen_addr_cmp(void const *one, void const *two)
846{
847 fr_listen_t const *a = one;
848 fr_listen_t const *b = two;
849 fr_ipaddr_t aip, bip;
850 int ret;
851
852 /*
853 * The caller must ensure that the address field is set.
854 */
855 if (!a->app_io_addr && !b->app_io_addr) return 0;
856 if (!a->app_io_addr && b->app_io_addr) return -1;
857 if (a->app_io_addr && !b->app_io_addr) return +1;
858
859 /*
860 * Address family
861 */
862 CMP_RETURN(a, b, app_io_addr->af);
863
864 fr_assert((a->app_io_addr->af == AF_INET) || ((a->app_io_addr->af == AF_INET6)));
865
866 /*
867 * UDP vs TCP
868 */
869 CMP_RETURN(a, b, app_io_addr->type);
870
871 /*
872 * Check ports.
873 */
874 CMP_RETURN(a, b, app_io_addr->inet.src_port);
875
876 /*
877 * Don't call fr_ipaddr_cmp(), as we need to do our own
878 * checks here. We have various wildcard checks which
879 * aren't globally applicable.
880 */
881
882 /*
883 * Different address families.
884 */
885 CMP_RETURN(a, b, app_io_addr->inet.src_ipaddr.af);
886
887 /*
888 * If both are bound to interfaces, AND the interfaces
889 * are different, then there is no conflict.
890 */
891 if (a->app_io_addr->inet.src_ipaddr.scope_id && b->app_io_addr->inet.src_ipaddr.scope_id) {
892 CMP_RETURN(a, b, app_io_addr->inet.src_ipaddr.scope_id);
893 }
894
895 ret = a->app_io_addr->inet.src_ipaddr.prefix - b->app_io_addr->inet.src_ipaddr.prefix;
896 aip = a->app_io_addr->inet.src_ipaddr;
897 bip = b->app_io_addr->inet.src_ipaddr;
898
899 /*
900 * Mask out the longer prefix to match the shorter
901 * prefix.
902 */
903 if (ret < 0) {
904 fr_ipaddr_mask(&bip, a->app_io_addr->inet.src_ipaddr.prefix);
905
906 } else if (ret > 0) {
907 fr_ipaddr_mask(&aip, b->app_io_addr->inet.src_ipaddr.prefix);
908
909 }
910
911 return fr_ipaddr_cmp(&aip, &bip);
912}
913
914/** See if another global listener is using a particular IP / port
915 *
916 */
918{
919 if (!listen_addr_root) return NULL;
920
921 return fr_rb_find(listen_addr_root, li);
922}
923
924
925/** Record that we're listening on a particular IP / port
926 *
927 */
929{
930 if (!listen_addr_root) return false;
931
932 if (!li->app_io_addr) return true;
933
934 if (listen_find_any(li) != NULL) return false;
935
936 return fr_rb_insert(listen_addr_root, li);
937}
938
939/** Return the configuration section for a virtual server
940 *
941 * @param[in] vs to return conf section for
942 * @return
943 * - The CONF_SECTION of the virtual server.
944 */
946{
947 return vs->server_cs;
948}
949
950/** Resolve a CONF_SECTION to a virtual server
951 *
952 */
954{
956
957 vs = cf_data_value(cf_data_find(server_cs, virtual_server_t, NULL));
958 if (!vs) {
959 cf_log_err(server_cs, "server_cs does not contain virtual server data");
960 return NULL;
961 }
962
963 return vs;
964}
965
966/** Return virtual server matching the specified name
967 *
968 * @note May be called in bootstrap or instantiate as all servers should be present.
969 *
970 * @param[in] name of virtual server.
971 * @return
972 * - NULL if no virtual server was found.
973 * - The CONF_SECTION of the named virtual server.
974 */
976{
977 CONF_SECTION *server_cs = cf_section_find(virtual_server_root, "server", name);
978 CONF_DATA const *cd;
979
980 if (unlikely(server_cs == NULL)) return NULL;
981
982 cd = cf_data_find(server_cs, virtual_server_t, NULL);
983 if (unlikely(cd == NULL)) return NULL;
984
985 return cf_data_value(cd);
986}
987
988/** Find a virtual server using one of its sections
989 *
990 * @param[in] ci to find parent virtual server for.
991 * @return
992 * - The virtual server section on success.
993 * - NULL if the child isn't associated with any virtual server section.
994 */
996{
997 CONF_SECTION *cs;
998 CONF_DATA const *cd;
999
1000 cs = cf_section_find_parent(ci, "server", CF_IDENT_ANY);
1001 if (unlikely(!cs)) {
1002 cf_log_err(ci, "Child section is not associated with a virtual server");
1003 return NULL;
1004 }
1005
1006 cd = cf_data_find(cs, virtual_server_t, NULL);
1007 if (unlikely(!cd)) {
1008 cf_log_err(ci, "Virtual server section missing virtual_server_t data");
1009 return NULL;
1010 }
1011
1012 return cf_data_value(cd);
1013}
1014
1015/** Return the packet type attribute for a virtual server specified by a config section
1016 *
1017 * @param[in] server_cs to look for packet type attribute in.
1018 * @return
1019 * - NULL on error.
1020 * - packet type dict attr on success.
1021 */
1023{
1024 virtual_server_t const *vs = virtual_server_from_cs(server_cs);
1025
1026 if (unlikely(!vs || !vs->process_module || !vs->process_module->packet_type)) return NULL;
1027 return *vs->process_module->packet_type;
1028}
1029
1030/** Wrapper for the config parser to allow pass1 resolution of virtual servers
1031 *
1032 */
1033int virtual_server_cf_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
1034 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
1035{
1036 virtual_server_t const *vs;
1037 virtual_server_cf_parse_uctx_t const *uctx = rule->uctx;
1038
1040 if (!vs) {
1041 cf_log_err(ci, "virtual-server \"%s\" not found", cf_pair_value(cf_item_to_pair(ci)));
1042 return -1;
1043 }
1044
1045 /*
1046 * Validation checks
1047 */
1048 if (uctx) {
1049 /*
1050 * Check the module name
1051 *
1052 * FIXME: ...at some point in the distance future. Names
1053 * are icky, we should compare based on dl_module_t, but
1054 * ordering issues make this difficult currently.
1055 */
1056 if (uctx->process_module_name) {
1057 /* catch users doing stupid things */
1058 if (strcmp(uctx->process_module_name, vs->process_mi->module->name) != 0) {
1059 cf_log_err(ci, "virtual server \"%s\" must be of type \"%s\", "
1060 "got type \"%s\"",
1062 uctx->process_module_name, vs->process_mi->module->name);
1063 return -1;
1064 }
1065 }
1066
1067 /*
1068 * It's theoretically possible for the same module to be used
1069 * with multiple namespaces, so we need this check too.
1070 */
1071 if (uctx->required_dict) {
1072 fr_dict_t *required_dict = *uctx->required_dict;
1073
1074 if (!fr_cond_assert_msg(required_dict != NULL,
1075 "dict not resolved before virtual server reference")) {
1076 goto done;
1077 }
1078
1079 if (required_dict != *vs->process_module->dict) {
1080 cf_log_err(ci, "virtual server \"%s\" must use namespace \"%s\", "
1081 "got namespace \"%s\"",
1083 fr_dict_root(required_dict)->name,
1084 fr_dict_root(*vs->process_module->dict)->name);
1085 return -1;
1086 }
1087 }
1088 }
1089
1090done:
1091 *((virtual_server_t const **)out) = vs;
1092
1093 return 0;
1094}
1095
1096static inline CC_HINT(always_inline) int virtual_server_compile_finally_sections(virtual_server_t *vs, tmpl_rules_t const *rules, int *found)
1097{
1098 static unlang_mod_actions_t const mod_actions_finally = {
1099 .actions = {
1109 },
1110 .retry = RETRY_INIT,
1111 };
1112
1113 fr_dict_attr_t const *da;
1114 fr_dict_attr_t const **da_p = vs->process_module->packet_type;
1115 CONF_SECTION *subcs;
1116
1117 if (!da_p || !*da_p) {
1118 subcs = cf_section_find(vs->server_cs, "finally", CF_IDENT_ANY);
1119 if (!subcs) return 0;
1120
1121 cf_log_err(subcs, "Invalid 'finally' section - virtual server does not define a 'packet_type'");
1122 return -1;
1123 }
1124
1125 da = *da_p;
1126
1127 /*
1128 * Iterate over all the finally sections, trying to resolve
1129 * the name2 to packet types.
1130 */
1131 for (subcs = cf_section_find(vs->server_cs, "finally", CF_IDENT_ANY);
1132 subcs;
1133 subcs = cf_section_find_next(vs->server_cs, subcs, "finally", CF_IDENT_ANY)) {
1134 char const *packet_type = cf_section_name2(subcs);
1135 fr_dict_enum_value_t const *ev;
1136 fr_value_box_t key;
1137 int ret;
1138 void *instruction;
1139
1140 if (!packet_type) {
1141 if (vs->finally_default) {
1142 cf_log_err(subcs, "Duplicate 'finally { ... }' section");
1143 return -1;
1144 }
1145
1146 ret = unlang_compile(vs, subcs, &mod_actions_finally, rules, &instruction);
1147 if (ret < 0) return -1;
1148
1149 vs->finally_default = instruction;
1150 (*found)++;
1151
1152 continue;
1153 }
1154
1155 /*
1156 * FIXME: This would allow response packet types too
1157 * We don't have anything that lists request/response
1158 * types, so we can't check that here.
1159 */
1160 ev = fr_dict_enum_by_name(da, packet_type, talloc_strlen(packet_type));
1161 if (!ev) {
1162 cf_log_err(subcs, "Invalid 'finally %s { ... }' section, "
1163 "does not match any Packet-Type value", packet_type);
1164 return -1;
1165 }
1166
1167 /*
1168 * This is... unlikely, as protocols usually use small
1169 * packet types.
1170 */
1172 forbid:
1173 if (da) {
1174 cf_log_err(subcs, "'finally %s { ... }' section, "
1175 "not supported for this protocol. %s is a %s", packet_type,
1176 da->name, fr_type_to_str(ev->value->type));
1177 } else {
1178
1179 cf_log_err(subcs, "'finally %s { ... }' section, "
1180 "not supported for this protocol", packet_type);
1181 }
1182 return -1;
1183 }
1184
1185 if (fr_value_box_cast(NULL, &key, FR_TYPE_UINT16, NULL, ev->value) < 0) {
1186 goto forbid;
1187 }
1188
1189 if (key.vb_uint16 >= talloc_array_length(vs->finally_by_packet_type)) {
1191 void *, key.vb_uint16 + 1));
1192 }
1193
1194 if (vs->finally_by_packet_type[key.vb_uint16]) {
1195 cf_log_err(subcs, "Duplicate 'finally %s { ... }' section", packet_type);
1196 return -1;
1197 }
1198
1199 ret = unlang_compile(vs, subcs, &mod_actions_finally, rules, &instruction);
1200 if (ret < 0) return -1;
1201
1202 vs->finally_by_packet_type[key.vb_uint16] = instruction;
1203
1204 (*found)++;
1205 }
1206
1207 return 0;
1208}
1209
1210/** Compile sections for a virtual server.
1211 *
1212 * When the "proto_foo" module calls fr_app_process_instantiate(), it
1213 * loads the compile list from the #fr_app_worker_t, and calls this
1214 * function.
1215 *
1216 * This function walks down the registration table, compiling each
1217 * named section.
1218 *
1219 * @param[in] vs to to compile sections for.
1220 * @param[in] rules to apply for pass1.
1221 */
1223{
1225 void *instance = vs->process_mi->data;
1226 CONF_SECTION *server = vs->server_cs;
1227 int i, found;
1228 bool fail;
1229 CONF_SECTION *subcs = NULL;
1230 char const *name, *name2;
1231
1232 found = 0;
1233
1234 /*
1235 * Complain about v3 things being used in v4.
1236 *
1237 * Don't complain when running in normal mode, because the server will just ignore the new
1238 * sections. But the check_config stuff is generally run before the service starts, and we
1239 * definitely want to tell people when running in debug mode.
1240 */
1241 if (check_config || DEBUG_ENABLED) {
1242 fail = false;
1243
1244 while ((subcs = cf_section_next(server, subcs)) != NULL) {
1245 if (cf_section_name2(subcs) != NULL) continue;
1246
1247 name = cf_section_name1(subcs);
1248 if ((strcmp(name, "authorize") == 0) ||
1249 (strcmp(name, "authenticate") == 0) ||
1250 (strcmp(name, "post-auth") == 0) ||
1251 (strcmp(name, "preacct") == 0) ||
1252 (strcmp(name, "accounting") == 0) ||
1253 (strcmp(name, "pre-proxy") == 0) ||
1254 (strcmp(name, "post-proxy") == 0)) {
1255 cf_log_err(subcs, "Version 3 processing section '%s' is not valid in version 4.",
1256 name);
1257 fail = true;
1258 }
1259 }
1260
1261 /*
1262 * Complain about _all_ of the sections, and not just the first one.
1263 */
1264 if (fail) return -1;
1265 }
1266
1267 /*
1268 * The sections are in trees, so this isn't as bad as it
1269 * looks. It's not O(n^2), but O(n logn). But it could
1270 * still be improved.
1271 */
1272 for (i = 0; list[i].section; i++) {
1273 int rcode;
1274 CONF_SECTION *bad;
1275
1276 /*
1277 * We are looking for a specific subsection.
1278 * Warn if it isn't found, or compile it if
1279 * found.
1280 */
1281 if (list[i].section->name2 != CF_IDENT_ANY) {
1282 void *instruction = NULL;
1283
1284 subcs = cf_section_find(server, list[i].section->name1, list[i].section->name2);
1285 if (!subcs) {
1286 DEBUG3("Warning: Skipping %s %s { ... } as it was not found.",
1287 list[i].section->name1, list[i].section->name2);
1288 /*
1289 * Initialise CONF_SECTION pointer for missing section
1290 */
1291 if ((instance) && !list[i].dont_cache) {
1292 *(CONF_SECTION **) (((uint8_t *) instance) + list[i].offset) = NULL;
1293 }
1294 continue;
1295 }
1296
1297 /*
1298 * Duplicate sections are forbidden.
1299 */
1300 bad = cf_section_find_next(server, subcs, list[i].section->name1, list[i].section->name2);
1301 if (bad) {
1302 forbidden:
1303 cf_log_err(bad, "Duplicate sections are forbidden.");
1304 cf_log_err(subcs, "Previous definition occurs here.");
1305 return -1;
1306 }
1307
1308 rcode = unlang_compile(vs, subcs, list[i].actions, rules, &instruction);
1309 if (rcode < 0) return -1;
1310
1311 /*
1312 * Cache the CONF_SECTION which was found.
1313 */
1314 if (instance) {
1315 if (!list[i].dont_cache) {
1316 *(CONF_SECTION **) (((uint8_t *) instance) + list[i].offset) = subcs;
1317 }
1318 if (list[i].instruction > 0) {
1319 *(void **) (((uint8_t *) instance) + list[i].instruction) = instruction;
1320 }
1321 }
1322
1323 found++;
1324 continue;
1325 }
1326
1327 /*
1328 * Reset this so that we start from the beginning
1329 * again, instead of starting from the last "send
1330 * foo" block.
1331 */
1332 subcs = NULL;
1333
1334 /*
1335 * Find all subsections with the given first name
1336 * and compile them.
1337 */
1338 while ((subcs = cf_section_find_next(server, subcs, list[i].section->name1, CF_IDENT_ANY))) {
1339 name2 = cf_section_name2(subcs);
1340 if (!name2) {
1341 cf_log_err(subcs, "Invalid '%s { ... }' section, it must have a name", list[i].section->name1);
1342 return -1;
1343 }
1344
1345 /*
1346 * Duplicate sections are forbidden.
1347 */
1348 bad = cf_section_find_next(server, subcs, list[i].section->name1, name2);
1349 if (bad) goto forbidden;
1350
1351 rcode = unlang_compile(vs, subcs, list[i].actions, rules, NULL);
1352 if (rcode < 0) return -1;
1353
1354 /*
1355 * Note that we don't store the
1356 * CONF_SECTION here, as it's a wildcard.
1357 *
1358 * @todo - count number of subsections
1359 * and store them in an array?
1360 */
1361 found++;
1362 }
1363 }
1364
1365 /*
1366 * Compile finally sections, these are special
1367 * sections and always execute before the request
1368 * exits from the virtual server.
1369 */
1370 if (unlikely(virtual_server_compile_finally_sections(vs, rules, &found) < 0)) {
1371 cf_log_err(server, "Failed to compile finally sections");
1372 return -1;
1373 }
1374
1375 /*
1376 * Didn't find any processing sections. Note that we don't count "finally" sections here. They
1377 * are only run after the packet has been processed through the normal sections. A virtual
1378 * server with only a "finally" section doesn't make sense.
1379 *
1380 * i.e. if people want to accept packets without responding, they need a "recv foo" section which
1381 * contains a "do_not_respond" policy.
1382 */
1383 if (!found) {
1384 cf_log_err(server, "No processing sections are defined for this virtual server");
1385 cf_log_err(server, "The server WILL NOT be able to process packets until the configuration is fixed");
1386 return -1;
1387 }
1388
1389 if (!check_config && !DEBUG_ENABLED) return found;
1390
1391 fail = false;
1392
1393 /*
1394 * Check for 'send FOO' and 'recv BAR' which are unused.
1395 */
1396 for (subcs = cf_section_first(server);
1397 subcs != NULL;
1398 subcs = cf_section_next(server, subcs)) {
1399 if (cf_item_is_parsed(subcs)) continue;
1400
1401 name = cf_section_name1(subcs);
1402
1403 /*
1404 * Allow them to "comment out" an entire block by prefixing the name with "-", ala
1405 * "-sql".
1406 */
1407 if (*name == '-') continue;
1408
1409 /*
1410 * Local clients are parsed by the listener after the virtual server is bootstrapped. So
1411 * we just ignore them here.
1412 */
1413 if (strcmp(name, "client") == 0) continue;
1414
1415 name2 = cf_section_name2(subcs);
1416
1417 /*
1418 * When checking the configuration, it is an error to have an unused "send FOO" or "recv
1419 * BAR" section.
1420 */
1421 if (check_config && ((strcmp(name, "recv") == 0) || (strcmp(name, "send") == 0))) {
1422 if (!name2) {
1423 cf_log_err(subcs, "Unused processing section' %s {'", name);
1424 cf_log_err(subcs, "If this is intentional, please rename it to '-%s { ...'", name);
1425 } else {
1426 cf_log_err(subcs, "Unused processing section '%s %s {'", name, name2);
1427 cf_log_err(subcs, "If this is intentional, please rename it to '-%s %s { ...'",
1428 name, name2);
1429 }
1430
1431 fail = true;
1432 continue;
1433 }
1434
1435 /*
1436 * Print warnings if it's unused. If there's an issue with case sensitivity, then that's
1437 * an error, even if we're not running check_config.
1438 */
1439 name2 = cf_section_name2(subcs);
1440 if (!name2) {
1441 cf_log_warn(subcs, "Ignoring '%s {' - it is unused", name);
1442 } else {
1443 const char *realname = NULL;
1444
1445 /*
1446 * See if it's a case-sensitive issue.
1447 *
1448 * The dictionaries are case insensitive. The configuration files are
1449 * case sensitive.
1450 */
1451 for (i = 0; list[i].section; i++) {
1452 if (list[i].section->name2 == CF_IDENT_ANY) continue;
1453
1454 if (strcasecmp(list[i].section->name2, name2) == 0) {
1455 realname = list[i].section->name2;
1456 break;
1457 }
1458 }
1459
1460 if (realname) {
1461 cf_log_err(subcs, "Unused processing section '%s %s {'", name, name2);
1462 cf_log_err(subcs, "Do you mean '%s %s { ...' ? ", name, realname);
1463 fail = true;
1464 break;
1465 }
1466
1467 cf_log_warn(subcs, "Ignoring %s %s { - it is unused", name, name2);
1468 }
1469 }
1470
1471 /*
1472 * Be nice to people, and complaing about ALL unused processing sections. That way they don't
1473 * have to run the server many, many, times to see all of the errors.
1474 */
1475 if (fail) return -1;
1476
1477 return found;
1478}
1479
1480/** Register name1 / name2 as allowed processing sections
1481 *
1482 * This function is called from the virtual server bootstrap routine,
1483 * which happens before module_bootstrap();
1484 */
1486{
1488
1489 old = fr_rb_find(vs->sections, entry);
1490 if (old) return 0;
1491
1492#ifndef NDEBUG
1493 /*
1494 * Catch stupid programmers.
1495 *
1496 * Processing sections can't allow "*" for module
1497 * methods, because otherwise you would be allowed to run
1498 * DHCP things in a RADIUS accounting section. And that
1499 * would be bad.
1500 */
1501 if (entry->methods) {
1502 int i;
1503
1504 for (i = 0; entry->methods[i]; i++) {
1505 if (entry->methods[i]->name1 == CF_IDENT_ANY) {
1506 ERROR("Processing sections cannot allow \"*\"");
1507 return -1;
1508 }
1509
1510 if (entry->methods[i]->name2 == CF_IDENT_ANY) {
1511 ERROR("Processing sections cannot allow \"%s *\"",
1512 entry->methods[i]->name1);
1513 return -1;
1514 }
1515 }
1516 }
1517#endif
1518
1519 if (!fr_rb_insert(vs->sections, entry)) {
1520 fr_strerror_const("Failed inserting entry into internal tree");
1521 return -1;
1522 }
1523
1524 return 0;
1525}
1526
1527/** Find the component for a section
1528 *
1529 */
1531{
1533
1534 /*
1535 * Look up the specific name first. That way we can
1536 * define both "accounting on", and "accounting *".
1537 */
1538 if (section->name2 != CF_IDENT_ANY) {
1539 entry = fr_rb_find(vs->sections,
1541 .section = section
1542 });
1543 if (entry) return entry->methods;
1544 }
1545
1546 /*
1547 * Then look up the wildcard, if we didn't find any matching name2.
1548 */
1549 entry = fr_rb_find(vs->sections,
1551 .section = SECTION_NAME(section->name1, CF_IDENT_ANY)
1552 });
1553 if (!entry) return NULL;
1554
1555 return entry->methods;
1556}
1557
1558/** Define a values for Auth-Type attributes by the sections present in a virtual-server
1559 *
1560 * The.name2 value of any sections found will be converted into values of the specified da.
1561 *
1562 * @param[in] server_cs The virtual server containing the sections.
1563 * @param[in] subcs_name of the subsection to search for.
1564 * @param[in] da to add enumeration values for.
1565 * @return
1566 * - 0 all values added successfully.
1567 * - -1 an error occurred.
1568 */
1569int virtual_server_section_attribute_define(CONF_SECTION *server_cs, char const *subcs_name, fr_dict_attr_t const *da)
1570{
1571 int rcode = 0;
1572 CONF_SECTION *subcs = NULL;
1573
1574 fr_assert(strcmp(cf_section_name1(server_cs), "server") == 0);
1575
1576 while ((subcs = cf_section_find_next(server_cs, subcs, subcs_name, CF_IDENT_ANY))) {
1577 char const *name2;
1578 fr_dict_enum_value_t const *dv;
1579
1580 name2 = cf_section_name2(subcs);
1581 if (!name2) {
1582 cf_log_err(subcs, "Invalid '%s { ... }' section, it must have a name", subcs_name);
1583 return -1;
1584 }
1585
1586 /*
1587 * If the value already exists, don't
1588 * create it again.
1589 */
1590 dv = fr_dict_enum_by_name(da, name2, -1);
1591 if (dv) continue;
1592
1593 cf_log_debug(subcs, "Creating %s = %s", da->name, name2);
1594
1595 /*
1596 * Create a new unique value with a meaningless
1597 * number. You can't look at it from outside of
1598 * this code, so it doesn't matter. The only
1599 * requirement is that it's unique.
1600 */
1602 PERROR("Failed adding section value");
1603 return -1;
1604 }
1605
1606 rcode = 1;
1607 }
1608
1609 return rcode;
1610}
1611
1613{
1614 char const *ref;
1615 fr_dict_attr_t const *da;
1616 CONF_ITEM *ci = NULL;
1617
1618 ref = cf_section_name2(cs);
1619 if (!ref) {
1620 cf_log_err(cs, "Expected 'values <name> { ... }'");
1621 return -1;
1622 }
1623
1624 da = fr_dict_attr_by_name(NULL, parent, ref);
1625 if (!da) {
1626 cf_log_err(cs, "No such attribute \"%s\"", ref);
1627 return -1;
1628 }
1629
1630 if (fr_type_is_structural(da->type)) {
1631 cf_log_err(cs, "Cannot define value for structural attribute \"%s\"", ref);
1632 return -1;
1633 }
1634
1635 /*
1636 * This both does not make any sense, and does not get
1637 * parsed correctly if the string contains backslashes.
1638 */
1639 if (da->type == FR_TYPE_STRING) {
1640 cf_log_err(cs, "Cannot define value for 'string' attribute \"%s\"", ref);
1641 return -1;
1642 }
1643
1644 while ((ci = cf_item_next(cs, ci))) {
1645 ssize_t slen, len;
1646 char const *attr, *value;
1647 CONF_PAIR *cp;
1648 fr_dict_enum_value_t const *dv;
1649 fr_value_box_t box;
1650
1651 if (cf_item_is_section(ci)) {
1652 cf_log_err(ci, "Unexpected subsection");
1653 return -1;
1654 }
1655
1656 if (!cf_item_is_pair(ci)) continue;
1657
1658 cp = cf_item_to_pair(ci);
1659 fr_assert(cp != NULL);
1660
1661 /*
1662 * =* is a hack by the cf parser to say "no operator"
1663 */
1664 if ((cf_pair_operator(cp) != T_OP_EQ) ||
1666 cf_log_err(ci, "Definition is not in 'name = value' format");
1667 return -1;
1668 }
1669
1670 attr = cf_pair_attr(cp);
1671 value = cf_pair_value(cp);
1672
1673 dv = fr_dict_enum_by_name(da, attr, talloc_strlen(attr));
1674 if (dv) {
1675 cf_log_err(cp, "Duplicate value name");
1676 return -1;
1677 }
1678
1680
1681 len = talloc_strlen(value);
1682
1683 /*
1684 * @todo - unescape for double quoted strings. Whoops.
1685 */
1686 slen = fr_value_box_from_str(NULL, &box, da->type, da, value, len, NULL);
1687 if (slen < 0) {
1688 cf_log_err(cp, "Failed parsing value - %s", fr_strerror());
1689 return -1;
1690 }
1691
1692 if (slen != len) {
1693 cf_log_err(cp, "Unexpected text after value");
1694 return -1;
1695 }
1696
1697 if (fr_dict_enum_add_name(UNCONST(fr_dict_attr_t *, da), attr, &box, false, false) < 0) {
1698 cf_log_err(cp, "Failed adding value - %s", fr_strerror());
1699 return -1;
1700 }
1701
1702 fr_value_box_clear(&box);
1703 }
1704
1705 return 0;
1706}
1707
1708
1710{
1711 CONF_ITEM *ci = NULL;
1712
1713 fr_dict_attr_flags_t flags = {
1714 .internal = true,
1715 .name_only = true,
1716 .local = true,
1717 };
1718
1719 fr_assert(dict != NULL);
1720 fr_assert(parent != NULL);
1721
1722 while ((ci = cf_item_next(cs, ci))) {
1724 char const *attr, *value;
1725 CONF_PAIR *cp;
1726 CONF_SECTION *subcs = NULL;
1727
1728 if (cf_item_is_section(ci)) {
1729 subcs = cf_item_to_section(ci);
1730 fr_assert(subcs != NULL);
1731
1732 attr = cf_section_name1(subcs);
1733
1734 if (strcmp(attr, "values") == 0) {
1735 if (define_server_values(subcs, parent) < 0) return -1;
1736 continue;
1737 }
1738
1739 if (strcmp(attr, "tlv") != 0) goto invalid_type;
1740
1741 value = cf_section_name2(subcs);
1742 if (!value) {
1743 cf_log_err(ci, "Definition is not in 'tlv name { ... }' format");
1744 return -1;
1745 }
1746
1747 type = FR_TYPE_TLV;
1748 goto check_for_dup;
1749 }
1750
1751 if (!cf_item_is_pair(ci)) continue;
1752
1753 cp = cf_item_to_pair(ci);
1754 fr_assert(cp != NULL);
1755
1756 /*
1757 * =* is a hack by the cf parser to say "no operator"
1758 */
1759 if ((cf_pair_operator(cp) != T_OP_CMP_TRUE) ||
1762 cf_log_err(ci, "Definition is not in 'type name' format");
1763 return -1;
1764 }
1765
1766 attr = cf_pair_attr(cp);
1767 value = cf_pair_value(cp);
1768
1770 if (type == FR_TYPE_NULL) {
1772 cf_log_err(ci, "Invalid data type '%s'", attr);
1773 return -1;
1774 }
1775
1776 /*
1777 * Leaf and group are OK. TLV, Vendor, Struct, VSA, etc. are not as variable definitions.
1778 */
1779 if (!(fr_type_is_leaf(type) || (type == FR_TYPE_GROUP))) goto invalid_type;
1780
1781 /*
1782 * No duplicates are allowed.
1783 */
1784 check_for_dup:
1785 if (root && (fr_dict_attr_by_name(NULL, root, value) != NULL)) {
1786 cf_log_err(ci, "Local variable '%s' duplicates a dictionary attribute.", value);
1787 return -1;
1788 }
1789
1790 if (fr_dict_attr_by_name(NULL, parent, value) != NULL) {
1791 cf_log_err(ci, "Local variable '%s' duplicates a previous local attribute.", value);
1792 return -1;
1793 }
1794
1795 if (fr_dict_attr_add_name_only(dict, parent, value, type, &flags) < 0) {
1796 cf_log_err(ci, "Failed adding local variable '%s' - %s", value, fr_strerror());
1797 return -1;
1798 }
1799
1800 if (type == FR_TYPE_TLV) {
1801 fr_dict_attr_t const *da;
1802
1803 if (!subcs) return -1; /* shouldn't happen, but shut up compiler */
1804
1805 da = fr_dict_attr_by_name(NULL, parent, value);
1806 fr_assert(da != NULL);
1807
1808 if (define_server_attrs(subcs, dict, UNCONST(fr_dict_attr_t *, da), NULL) < 0) return -1;
1809 }
1810 }
1811
1812 return 0;
1813}
1814
1815static fr_dict_t const *virtual_server_local_dict(CONF_SECTION *server_cs, fr_dict_t const *dict_def)
1816{
1817 fr_dict_t *dict;
1818 CONF_SECTION *cs;
1819
1820 cs = cf_section_find(server_cs, "dictionary", NULL);
1821 if (!cs) return dict_def;
1822
1823 dict = fr_dict_protocol_alloc(dict_def);
1824 if (!dict) {
1825 cf_log_err(cs, "Failed allocating local dictionary");
1826 return NULL;
1827 }
1828
1829 if (define_server_attrs(cs, dict, UNCONST(fr_dict_attr_t *, fr_dict_root(dict)), fr_dict_root(dict_def)) < 0){
1830 talloc_free(dict);
1831 return NULL;
1832 }
1833
1834 /*
1835 * Replace the original dictionary with the new one.
1836 */
1837 cf_data_remove(server_cs, fr_dict_t, "dict");
1838 cf_data_add(server_cs, dict, "dict", false);
1840
1841 return dict;
1842}
1843
1844
1845/** Open all the listen sockets
1846 *
1847 * @param[in] sc Scheduler to add I/O paths to.
1848 * @return
1849 * - 0 on success.
1850 * - -1 on failure.
1851 */
1853{
1854 size_t i, server_cnt = virtual_servers ? talloc_array_length(virtual_servers) : 0;
1855 int opened = 0;
1856
1858
1859 DEBUG2("#### Opening listener interfaces ####");
1861
1862 for (i = 0; i < server_cnt; i++) {
1863 virtual_server_listen_t **listeners;
1864 size_t j, listener_cnt;
1865
1866 listeners = virtual_servers[i]->listeners;
1867 if (!listeners) continue; /* servers can have no listeners */
1868
1869 listener_cnt = talloc_array_length(listeners);
1870
1871 for (j = 0; j < listener_cnt; j++) {
1872 int ret;
1873 virtual_server_listen_t *listener = listeners[j];
1874
1875 fr_assert(listener != NULL);
1876 fr_assert(listener->proto_mi != NULL);
1877 fr_assert(listener->proto_module != NULL);
1878
1879 fr_assert(listener->proto_module->open != NULL);
1880
1881 /*
1882 * The socket is opened with app_instance,
1883 * but all subsequent calls (network.c, etc.) use app_io_instance.
1884 *
1885 * The reason is that we call (for example) proto_radius to
1886 * open the socket, and proto_radius is responsible for setting up
1887 * proto_radius_udp, and then calling proto_radius_udp->open.
1888 *
1889 * Even then, proto_radius usually calls fr_master_io_listen() in order
1890 * to create the fr_listen_t structure.
1891 */
1892
1893 /*
1894 * Sometimes the open function needs to modify instance
1895 * data, so we need to temporarily remove the protection.
1896 */
1898 ret = listener->proto_module->open(listener->proto_mi->data, sc,
1899 listener->proto_mi->conf);
1901 if (unlikely(ret < 0)) {
1902 return -1;
1903 }
1904
1905 opened++;
1906
1907 /*
1908 * Socket information is printed out by
1909 * the socket handlers. e.g. proto_radius_udp
1910 */
1911 DEBUG3("Opened listener for %s", listener->proto_module->common.name);
1912 }
1913 }
1914
1915 if (!opened) {
1916 ERROR("There are no 'listen' sections defined.");
1917 ERROR("Refusing to start, as the server will never process any packets.");
1918 return -1;
1919 }
1920
1921 return 0;
1922}
1923
1924/** Free thread-specific data for all process modules and listeners
1925 *
1926 */
1932
1933/** Perform thread instantiation for all process modules and listeners
1934 *
1935 */
1937{
1938 if (modules_thread_instantiate(ctx, process_modules, el) < 0) return -1;
1941 return -1;
1942 }
1943 return 0;
1944}
1945
1946/** Instantiate all the virtual servers
1947 *
1948 * @return
1949 * - 0 on success.
1950 * - -1 on failure.
1951 */
1953{
1954 size_t i, server_cnt;
1955
1956 /*
1957 * User didn't specify any "server" sections
1958 */
1959 if (unlikely(!virtual_servers)) {
1960 ERROR("No virtual servers configured");
1961 return -1;
1962 }
1963
1964 server_cnt = talloc_array_length(virtual_servers);
1965
1966 DEBUG2("#### Instantiating listeners ####");
1967
1969 PERROR("Failed registering radmin commands for virtual servers");
1970 return -1;
1971 }
1972
1973 for (i = 0; i < server_cnt; i++) {
1974 CONF_ITEM *ci = NULL;
1975 CONF_SECTION *server_cs = virtual_servers[i]->server_cs;
1976 fr_dict_t const *dict;
1978 fr_process_module_t const *process = (fr_process_module_t const *)
1979 vs->process_mi->module->exported;
1980
1981 /*
1982 * Set up logging before doing anything else.
1983 */
1984 if (vs->log_name) {
1985 vs->log = log_dst_by_name(vs->log_name);
1986 if (!vs->log) {
1987 CONF_PAIR *cp = cf_pair_find(server_cs, "log");
1988
1989 if (cp) {
1990 cf_log_err(cp, "Unknown log destination '%s'", vs->log_name);
1991 } else {
1992 cf_log_err(server_cs, "Unknown log destination '%s'", vs->log_name);
1993 }
1994
1995 return -1;
1996 }
1997 }
1998
1999 dict = virtual_server_local_dict(server_cs, *(process)->dict);
2000 if (!dict) return -1;
2001
2002 DEBUG("Compiling policies in server %s { ... }", cf_section_name2(server_cs));
2003
2004 fr_assert(virtual_servers[i]->process_mi);
2005
2006 /*
2007 * Compile the processing sections indicated by
2008 * the process module. This must be done before
2009 * module_instantiate is called, as the instance
2010 * data is protected after this call.
2011 */
2012 if (process->compile_list) {
2013 tmpl_rules_t parse_rules = {
2014 .attr = {
2015 .dict_def = dict,
2016 .list_def = request_attr_request,
2017 },
2018
2019 .literals_safe_for = FR_VALUE_BOX_SAFE_FOR_ANY,
2020 };
2021
2022 fr_assert(parse_rules.attr.dict_def != NULL);
2023
2024 if (virtual_server_compile_sections(virtual_servers[i], &parse_rules) < 0) {
2025 return -1;
2026 }
2027 }
2028
2029 /*
2030 * Print out warnings for unused "recv" and
2031 * "send" sections.
2032 *
2033 * @todo - check against the "compile_list"
2034 * registered for this virtual server, instead of hard-coding stuff.
2035 */
2036 while ((ci = cf_item_next(server_cs, ci))) {
2037 char const *name;
2038 CONF_SECTION *subcs;
2039
2040 if (!cf_item_is_section(ci)) continue;
2041
2042 subcs = cf_item_to_section(ci);
2043 name = cf_section_name1(subcs);
2044
2045 /*
2046 * Skip known "other" sections
2047 */
2048 if ((strcmp(name, "listen") == 0) || (strcmp(name, "client") == 0)) continue;
2049
2050 /*
2051 * For every other section, warn if it hasn't
2052 * been compiled.
2053 */
2054 if (!cf_data_find(subcs, unlang_group_t, NULL)) {
2055 char const *name2;
2056
2057 name2 = cf_section_name2(subcs);
2058 if (!name2) name2 = "";
2059
2060 cf_log_warn(subcs, "%s %s { ... } section is unused", name, name2);
2061 }
2062 }
2063 }
2064
2066 PERROR("Failed instantiating process modules");
2067 return -1;
2068 }
2070 PERROR("Failed instantiating protocol modules");
2071 return -1;
2072 }
2073
2074 return 0;
2075}
2076
2077/** Load protocol modules and call their bootstrap methods
2078 *
2079 * @param[in] config section containing the virtual servers to bootstrap.
2080 * @return
2081 * - 0 on success.
2082 * - -1 on failure.
2083 */
2085{
2087
2088 /*
2089 * Ensure any libraries the modules depend on are instantiated
2090 */
2092
2094 PERROR("Failed instantiating process modules");
2095 return -1;
2096 }
2098 PERROR("Failed instantiating protocol modules");
2099 return -1;
2100 }
2101
2102 return 0;
2103}
2104
2106{
2107 if (talloc_free(listen_addr_root) < 0) return -1;
2108 listen_addr_root = NULL;
2109 if (talloc_free(process_modules) < 0) return -1;
2110 process_modules = NULL;
2111 if (talloc_free(proto_modules) < 0) return -1;
2112 proto_modules = NULL;
2114
2115 return 0;
2116}
2117
2118static int _virtual_servers_atexit(UNUSED void *uctx)
2119{
2120 return virtual_servers_free();
2121}
2122
2123/** Performs global initialisation for the virtual server code
2124 *
2125 * This has to be done separately and explicitly, because the above code makes
2126 * use of "onread" callbacks.
2127 *
2128 * Will automatically free module lists on exit, but all modules should have
2129 * been removed from this list by the point that happens.
2130 */
2132{
2134 PERROR("%s", __FUNCTION__);
2135 return -1;
2136 }
2138 PERROR("%s", __FUNCTION__);
2140 return -1;
2141 }
2142
2144
2145 /*
2146 * FIXME - We should be able to turn on write protection,
2147 * but there are too many proto modules that hang things
2148 * off of their instance data.
2149 */
2150 MEM(proto_modules = module_list_alloc(NULL, &module_list_type_global, "protocol", false));
2151 MEM(listen_addr_root = fr_rb_inline_alloc(NULL, fr_listen_t, virtual_server_node, listen_addr_cmp, NULL));
2152
2153 /*
2154 * Create a list to hold all the proto_* modules
2155 * that get loaded during startup.
2156 */
2158
2159 return 0;
2160}
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:487
#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:66
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
Definition cf_parse.c:1208
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:1750
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:660
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition cf_parse.h:614
void const * uctx
User data accessible by the cf_parse_t func.
Definition cf_parse.h:620
#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:283
char const * name2
Second identifier for CONF_SECTION.
Definition cf_parse.h:599
#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:337
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:617
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:432
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
Definition cf_parse.h:449
@ CONF_FLAG_OK_MISSING
OK if it's missing.
Definition cf_parse.h:457
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:426
#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:597
Internal data that is associated with a configuration section.
Definition cf_priv.h:125
Common header for all CONF_* types.
Definition cf_priv.h:49
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:72
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:1603
CONF_PAIR * cf_pair_find_next(CONF_SECTION const *cs, CONF_PAIR const *prev, char const *attr)
Find a pair with a name matching attr, after specified pair.
Definition cf_util.c:1433
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:1743
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:1419
fr_token_t cf_pair_operator(CONF_PAIR const *pair)
Return the operator of a pair.
Definition cf_util.c:1588
fr_token_t cf_pair_value_quote(CONF_PAIR const *pair)
Return the value (rhs) quoting of a pair.
Definition cf_util.c:1618
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
Definition cf_util.c:617
CONF_SECTION * cf_section_first(CONF_SECTION const *cs)
Return the first child in a CONF_SECTION.
Definition cf_util.c:983
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:1574
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
Definition cf_util.c:1558
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:288
#define cf_data_add(_cf, _data, _name, _free)
Definition cf_util.h:254
#define cf_data_find(_cf, _type, _name)
Definition cf_util.h:243
#define cf_item_is_parsed(_cf)
Definition cf_util.h:139
#define cf_data_remove(_cf, _type, _name)
Remove an item from a parent by type and name.
Definition cf_util.h:266
#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:295
#define cf_section_find_parent(_cf, _name1, _name2)
Definition cf_util.h:181
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition cf_util.h:146
#define cf_data_find_in_parent(_cf, _type, _name)
Definition cf_util.h:249
#define cf_log_warn(_cf, _fmt,...)
Definition cf_util.h:289
#define cf_log_debug(_cf, _fmt,...)
Definition cf_util.h:291
#define cf_item_mark_parsed(_cf)
Definition cf_util.h:136
#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:2199
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:148
#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:2218
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:2007
#define fr_dict_autofree(_to_free)
Definition dict.h:917
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:3529
fr_dict_attr_t * fr_dict_attr_unconst(fr_dict_attr_t const *da)
Coerce to non-const.
Definition dict_util.c:4916
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2666
unsigned int internal
Internal attribute, should not be received in protocol packets, should not be encoded.
Definition dict.h:90
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:294
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:307
fr_value_box_t const * value
Enum value (what name maps to).
Definition dict.h:259
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:2230
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:4396
#define fr_dict_autoload(_to_load)
Definition dict.h:914
#define DICT_AUTOLOAD_TERMINATOR
Definition dict.h:313
fr_dict_t * fr_dict_protocol_alloc(fr_dict_t const *parent)
Allocate a new local dictionary.
Definition dict_util.c:4267
fr_dict_enum_value_t const * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Definition dict_util.c:3702
Specifies an attribute which must be present for the module to function.
Definition dict.h:293
Values of the encryption flags.
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:306
Value of an enumerated attribute.
Definition dict.h:255
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
int unlang_finally_push_instruction(request_t *request, void *instruction, fr_time_delta_t min_time, bool top_frame)
Push a finally instructtion on the stack, to be evaluated as the stack is unwound.
Definition finally.c:129
#define unlang_function_push_with_result(_result_p, _request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack that produces a result.
Definition function.h:144
int global_lib_instantiate(void)
Walk the tree of libraries and instantiate any which are pending.
Definition global_lib.c:218
talloc_free(hp)
int8_t fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
Compare two ip addresses.
Definition inet.c:1354
void fr_ipaddr_mask(fr_ipaddr_t *addr, uint8_t prefix)
Zeroes out the host portion of an fr_ipaddr_t.
Definition inet.c:219
IPv4/6 prefix.
unlang_result_t * unlang_interpret_result(request_t *request)
Get the last instruction result OR the last frame that was popped.
Definition interpret.c:1583
int unlang_interpret_stack_depth(request_t *request)
Return the depth of the request's stack.
Definition interpret.c:1551
#define UNLANG_SUB_FRAME
Definition interpret.h:37
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:1082
#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
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
fr_type_t
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ 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
int strcasecmp(char *s1, char *s2)
Definition missing.c:66
@ MOD_ACTION_RETURN
stop processing the section, and return the rcode with unset priority
Definition mod_action.h:41
#define MOD_PRIORITY(_x)
Definition mod_action.h:34
unlang_mod_action_t actions[RLM_MODULE_NUMCODES]
Definition mod_action.h:69
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition pair.c:707
static const virtual_server_compile_t compile_list[]
Definition base.c:214
static const conf_parser_t config[]
Definition base.c:169
fr_dict_attr_t const ** packet_type
Request packet types to look for finally sections for.
virtual_server_compile_t const * compile_list
list of processing sections
module_method_t process
Process packets.
fr_dict_t const ** dict
pointer to local fr_dict_t *
Common public symbol definition for all process modules.
#define fr_assert(_expr)
Definition rad_assert.h:38
#define DEBUG2(fmt,...)
static bool done
Definition radclient.c:83
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_MODULE_INVALID
The module considers the request invalid.
Definition rcode.h:51
@ RLM_MODULE_OK
The module is OK, continue.
Definition rcode.h:49
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition rcode.h:48
@ RLM_MODULE_DISALLOW
Reject the request (user is locked out).
Definition rcode.h:52
@ RLM_MODULE_REJECT
Immediately reject the request.
Definition rcode.h:47
@ RLM_MODULE_NOTFOUND
User not found.
Definition rcode.h:53
@ RLM_MODULE_UPDATED
OK (pairs modified).
Definition rcode.h:55
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition rcode.h:54
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
Definition rcode.h:50
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
#define fr_sbuff_start(_sbuff_or_marker)
#define FR_SBUFF_IN_CHAR_RETURN(_sbuff,...)
#define FR_SBUFF_IN_STRCPY_RETURN(...)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
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
char const * name
Instance name e.g. user_database.
Definition module.h:355
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:349
void * data
Module's instance data.
Definition module.h:291
#define MODULE_INSTANCE_LEN_MAX
The maximum size of a module instance.
Definition module.h:148
module_t * exported
Public module structure.
Definition module.h:296
Module instance data.
Definition module.h:285
A list of modules.
Definition module.h:405
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition tmpl.h:339
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:336
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
void module_list_debug(module_list_t const *ml)
Print the contents of a module list.
Definition module.c:620
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:1650
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:734
void modules_thread_detach(module_list_t *ml)
Remove thread-specific data for a given module list.
Definition module.c:1008
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:1159
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:956
int modules_instantiate(module_list_t const *ml)
Completes instantiation of modules.
Definition module.c:1280
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:1856
fr_slen_t module_instance_name_valid(char const *inst_name)
Check to see if a module instance name is valid.
Definition module.c:1590
module_list_type_t const module_list_type_global
Callbacks for a global module list.
Definition module.c:533
int module_instance_data_protect(module_instance_t *mi)
Mark module data as read only.
Definition module.c:698
int modules_bootstrap(module_list_t const *ml)
Bootstrap any modules which have not been bootstrapped already.
Definition module.c:1371
int module_instance_data_unprotect(module_instance_t *mi)
Mark module data as read/write.
Definition module.c:710
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:846
int module_instance_conf_parse(module_instance_t *mi, CONF_SECTION *conf)
Covert a CONF_SECTION into parsed module instance data.
Definition module.c:763
int unlang_module_push(unlang_result_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:50
fr_aka_sim_id_type_t type
fr_pair_t * vp
Definition log.h:96
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Definition tmpl.h:273
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
#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
#define talloc_strdup(_ctx, _str)
Definition talloc.h:145
#define talloc_realloc_zero(_ctx, _ptr, _type, _count)
Definition talloc.h:214
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
Definition talloc.h:139
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition time.h:590
@ 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:858
#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:393
#define fr_type_is_integer_except_bool(_x)
Definition types.h:381
#define fr_type_is_leaf(_x)
Definition types.h:394
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:455
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
Definition value.c:3961
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:6079
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition value.c:4392
static fr_slen_t data
Definition value.h:1340
fr_type_t _CONST type
Type and flags should appear together for packing efficiency.
Definition value.h:191
#define fr_value_box_init_null(_vb)
Initialise an empty/null box that will be filled later.
Definition value.h:616
static size_t char ** out
Definition value.h:1030
#define FR_VALUE_BOX_SAFE_FOR_ANY
Definition value.h:173
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.
void * finally_default
Default finally instruction.
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[]
virtual_server_t const * virtual_server_from_cs(CONF_SECTION const *server_cs)
Resolve a CONF_SECTION to a virtual server.
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)
unlang_action_t virtual_server_push(unlang_result_t *p_result, request_t *request, virtual_server_t const *vs, bool top_frame)
Set the request processing function.
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)
fr_app_t const * proto_module
Public interface to the proto_mi.
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.
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 int virtual_server_compile_finally_sections(virtual_server_t *vs, tmpl_rules_t const *rules, int *found)
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.
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.
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.
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 virtual_server_push_finally(request_t *request, virtual_server_t const *vs, bool *top_frame)
Push a finally section onto the stack.
static unlang_action_t server_remove_log_destination(UNUSED unlang_result_t *p_result, request_t *request, void *uctx)
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.
module_instance_t * proto_mi
The proto_* module for a listen section.
void ** finally_by_packet_type
Finalise instruction by packet type.
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 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)
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)
static int define_server_values(CONF_SECTION *cs, fr_dict_attr_t *parent)
char const * log_name
name of log destination
virtual_server_listen_t ** listeners
Listeners in this virtual server.
fr_dict_attr_t const * virtual_server_packet_type_by_cs(CONF_SECTION const *server_cs)
Return the packet type attribute for a virtual server specified by a config section.
section_name_t const * section
Identifier for the section.
char const * process_module_name
Virtual server we find must use this this process module.
size_t offset
where the CONF_SECTION pointer is written
fr_dict_t ** required_dict
Virtual server we find must have this dictionary.
struct virtual_server_s virtual_server_t
section_name_t const ** methods
list of auxilliary module methods which are allowed in if the main name doesn't match.
Additional validation rules for virtual server lookup.
Processing sections which are allowed in this virtual server.