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