The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
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: d3fed13facfdd0b1a3de45cafe9c88488a83a550 $
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: d3fed13facfdd0b1a3de45cafe9c88488a83a550 $")
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,
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. We don't know if
347 * the process code needs this, so we just mark it as
348 * parsed, in order to avoid spurious complaints.
349 */
350 process_cs = cf_section_find(server_cs, namespace, NULL);
351 if (!process_cs) {
352 MEM(process_cs = cf_section_alloc(server_cs, server_cs, namespace, NULL));
353 cf_item_mark_parsed(process_cs);
354 }
355
356 if (module_instance_conf_parse(mi, process_cs) < 0) {
357 cf_log_perr(ci, "Failed bootstrapping process module");
358 cf_data_remove(server_cs, module_instance_t, "process_module");
359 cf_data_remove(server_cs, fr_dict_t, "dict");
360 TALLOC_FREE(server->process_mi);
361 return -1;
362 }
363
364 /*
365 * Pull the list of sections we need to compile out of
366 * the process module's public struct.
367 */
368 return add_compile_list(server, server->process_mi->conf, server->process_module->compile_list, namespace);
369}
370
371/** dl_open a proto_* module
372 *
373 * @param[in] ctx to allocate data in.
374 * @param[out] out Where to our listen configuration. Is a #fr_virtual_listen_t structure.
375 * @param[in] parent Base structure address.
376 * @param[in] ci #CONF_SECTION containing the listen section.
377 * @param[in] rule unused.
378 * @return
379 * - 0 on success.
380 * - -1 on failure.
381 */
382static int listen_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
383{
384 virtual_server_listen_t *listener = talloc_get_type_abort(out, virtual_server_listen_t); /* Pre-allocated for us */
385 CONF_SECTION *listener_cs = cf_item_to_section(ci);
386 CONF_SECTION *server_cs = cf_item_to_section(cf_parent(ci));
387 CONF_PAIR *namespace = cf_pair_find(server_cs, "namespace");
388
389 CONF_PAIR *cp;
390 char const *module, *name2, *p;
391 fr_sbuff_t *agg;
392
394
396 "virtual_servers_init MUST be called before reading virtual server config");
397
398 if (!namespace) {
399 cf_log_err(server_cs, "No 'namespace' set for virtual server");
400 cf_log_err(server_cs, "Please add 'namespace = <protocol>' inside of the 'server %s { ... }' section",
401 cf_section_name2(server_cs));
402 return -1;
403 }
404
405 /*
406 * The module we load comes from the 'handler' or 'proto' configuration. This configuration item
407 * allows us to have multi-protocol listen module, such as "detail".
408 *
409 * If there isn't a multi-protocol listen module, then load the one for this namespace, such as
410 * "radius".
411 */
412 cp = cf_pair_find(listener_cs, "handler");
413 if (!cp) cp = cf_pair_find(listener_cs, "proto");
414 if (cp) {
415 module = cf_pair_value(cp);
416 if (!module) {
417 cf_log_err(cp, "Missing value");
418 return -1;
419 }
420 } else {
421 module = cf_pair_value(namespace);
422 }
423
424 /*
425 * The proto modules go into a global tree, so we qualify their name (second name) with the name
426 * of the virtual server, followed by the transport, followed by any transport-specific
427 * configuration.
428 */
430
431 name2 = cf_section_name2(listener_cs);
432
433 /*
434 * A 'listen foo' in this virtual server helps it to be unique. We load the "radius" module,
435 * instance "default.foo". This naming scheme is a little counter-intuitive, but it is required
436 * due to the listen module list being global, and loading the leading module name e.g. "radius".
437 *
438 * Since the virtual server names are unique, we don't have to qualify the listen section names
439 * by anything else.
440 */
441 if (name2) {
442 /*
443 * We do some duplicate checks here, because that gives better errors than if we use the
444 * mangled names below.
445 */
446 if (module_instance_name_valid(name2) < 0) {
447 cf_log_perr(listener_cs, "Invalid name in 'listen %s'", name2);
448 return -1;
449 }
450
451 /*
452 * Load "radius", instance "default.foo".
453 */
454 if ((fr_sbuff_in_char(agg, '.') < 0) || (fr_sbuff_in_strcpy(agg, name2) < 0)) goto name_too_long;
455 }
456
457 /*
458 * Further qualify the name by transport and port. This helps it to be more unique.
459 */
460 cp = cf_pair_find(listener_cs, "transport");
461 if (!cp || ((p = cf_pair_value(cp)) == NULL)) {
462 cf_log_err(listener_cs, "Invalid 'listen' section - No 'transport = ...' definition was found.");
463 return -1;
464 }
465 if ((fr_sbuff_in_char(agg, '.') < 0) || (fr_sbuff_in_strcpy(agg, p) < 0)) {
466 name_too_long:
467 cf_log_err(listener_cs, "Listener name is too long");
468 return -1;
469 }
470
471 cp = cf_pair_find(listener_cs, "port");
472 if (cp && ((p = cf_pair_value(cp)) != NULL)) {
473 if ((fr_sbuff_in_char(agg, '.') < 0) || (fr_sbuff_in_strcpy(agg, p) < 0)) goto name_too_long;
474 }
475
477 cf_log_perr(listener_cs, "Failed loading listen section.");
478 return -1;
479 }
480
482 if (!mi) {
483 cf_log_perr(listener_cs, "Failed creating listen section");
484 return -1;
485 }
486
487 if (unlikely(module_instance_conf_parse(mi, listener_cs) < 0)) {
488 talloc_free(mi);
489 cf_log_perr(listener_cs, "Failed parsing listen section");
490 return -1;
491 }
492
493 listener->proto_mi = mi;
494 listener->proto_module = (fr_app_t const *)listener->proto_mi->module->exported;
495 cf_data_add(listener_cs, mi, "proto_module", false);
496
497 /*
498 * The listener doesn't have to contain a 'type = foo' configuration. But if it does, there MUST
499 * also be a 'recv foo' section.
500 */
501 for (cp = cf_pair_find(listener_cs, "type");
502 cp != NULL;
503 cp = cf_pair_find_next(listener_cs, cp, "type")) {
504 char const *type = cf_pair_value(cp);
505
506 if (!type) continue;
507
508 if (!cf_section_find(server_cs, "recv", type)) {
509 cf_log_err(cp, "Listener has 'type = %s', but there is no 'recv %s { ... }' section defined.",
510 type, type);
511 return -1;
512 }
513 }
514
515 return 0;
516}
517
518static fr_cmp_ret_t virtual_server_compile_name_cmp(void const *a, void const *b)
519{
520 virtual_server_compile_t const *sa = a;
521 virtual_server_compile_t const *sb = b;
522
523 return section_name_cmp(sa->section, sb->section);
524}
525
526/** Callback to validate the server section
527 *
528 * @param[in] ctx to allocate data in.
529 * @param[out] out Where to our listen configuration. Is a #virtual_server_t structure.
530 * @param[in] parent Base structure address.
531 * @param[in] ci #CONF_SECTION containing the listen section.
532 * @param[in] rule unused.
533 * @return
534 * - 0 on success.
535 * - -1 on failure.
536 */
537static int server_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
538 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
539{
540 virtual_server_t *server = talloc_get_type_abort(out, virtual_server_t);
541 CONF_SECTION *server_cs = cf_item_to_section(ci);
542 CONF_PAIR *namespace;
543
544 namespace = cf_pair_find(server_cs, "namespace");
545 if (!namespace) {
546 cf_log_err(server_cs, "virtual server %s MUST contain a 'namespace' option",
547 cf_section_name2(server_cs));
548 return -1;
549 }
550
552 server->server_cs = server_cs;
553
554 /*
555 * Now parse the listeners
556 */
557 if (cf_section_parse(out, server, server_cs) < 0) return -1;
558
559 /*
560 * And cache this struct for later referencing.
561 */
562 cf_data_add(server_cs, server, NULL, false);
563
564 return 0;
565}
566
567/** Return the namespace for the named virtual server
568 *
569 * @param[in] virtual_server to look for namespace in.
570 * @return
571 * - NULL on error.
572 * - Namespace on success.
573 */
574fr_dict_t const *virtual_server_dict_by_name(char const *virtual_server)
575{
576 virtual_server_t const *vs;
577
578 vs = virtual_server_find(virtual_server);
579 if (!vs) return NULL;
580
582}
583
584/** Return the namespace for specified CONF_SECTION
585 *
586 * @param[in] cs to look for namespace in.
587 * @return
588 * - NULL on error.
589 * - Namespace on success.
590 */
592{
593 CONF_DATA const *cd;
595
596 cd = cf_data_find(cs, fr_dict_t, "dict");
597 if (!cd) return NULL;
598
599 dict = cf_data_value(cd);
600 (void) talloc_get_type_abort(dict, fr_dict_t);
601
602 return dict;
603}
604
605/** Return the namespace for a given virtual server specified by a CONF_ITEM within the virtual server
606 *
607 * @param[in] ci to look for namespace in.
608 * @return
609 * - NULL on error.
610 * - Namespace on success.
611 */
613{
614 CONF_DATA const *cd;
616
617 cd = cf_data_find_in_parent(ci, fr_dict_t, "dict");
618 if (!cd) return NULL;
619
620 dict = cf_data_value(cd);
621 (void) talloc_get_type_abort(dict, fr_dict_t);
622
623 return dict;
624}
625
626/** Verify that a given virtual_server exists and is of a particular namespace
627 *
628 * Mostly used by modules to check virtual servers specified by their configs.
629 *
630 * @param[out] out we found. May be NULL if just checking for existence.
631 * @param[in] virtual_server to check.
632 * @param[in] namespace the virtual server must belong to.
633 * @param[in] ci to log errors against. May be NULL if caller
634 * doesn't want errors logged.
635 * @return
636 * - 0 on success.
637 * - -1 if no virtual server could be found.
638 * - -2 if virtual server is not of the correct namespace.
639 */
641 char const *virtual_server, fr_dict_t const *namespace, CONF_ITEM *ci)
642{
643 virtual_server_t const *vs;
644 CONF_SECTION *server_cs;
645 fr_dict_t const *dict;
646
647 if (out) *out = NULL;
648
649 vs = virtual_server_find(virtual_server);
650 if (!vs) {
651 if (ci) cf_log_err(ci, "Can't find virtual server \"%s\"", virtual_server);
652 return -1;
653 }
654 server_cs = virtual_server_cs(vs);
655
656 dict = virtual_server_dict_by_name(virtual_server);
657 if (!dict) {
658 /*
659 * Not sure this is even a valid state?
660 */
661 if (ci) cf_log_err(ci, "No namespace found in virtual server \"%s\"", virtual_server);
662 return -2;
663 }
664
665 if (dict != namespace) {
666 if (ci) {
667 cf_log_err(ci,
668 "Expected virtual server \"%s\" to be of namespace \"%s\", got namespace \"%s\"",
669 virtual_server, fr_dict_root(namespace)->name, fr_dict_root(dict)->name);
670 }
671 return -2;
672 }
673
674 if (out) *out = server_cs;
675
676 return 0;
677}
678
679/*
680 * If we pushed a log destination, we need to pop it.
681 */
691
693{
694 virtual_server_t *server = uctx;
695
697}
698
699/** Push a finally section onto the stack
700 *
701 * The finally instruction cannot be cancelled and will always execute as the stack is unwound.
702 *
703 * @param[in] request request to push the finally section onto.
704 * @param[in] vs virtual server to push the finally section for.
705 * @param[in,out] top_frame mutate the top frame value to indicate that future
706 * pushes should be subframes.
707 * @return
708 * - 0 on success.
709 * - -1 on failure.
710 */
711static inline CC_HINT(always_inline) int virtual_server_push_finally(request_t *request, virtual_server_t const *vs, bool *top_frame)
712{
713 /*
714 * Don't bother finding the packet type unless there
715 * are finally sections registered.
716 */
717 if (vs->finally_by_packet_type) {
718 fr_pair_t *vp = fr_pair_find_by_da(&request->request_pairs, NULL,
720 fr_value_box_t key;
721 void *instruction;
722
723 if (!vp) goto check_default; /* No packet type found, still allow default finally section */
724
725 if (fr_value_box_cast(NULL, &key, FR_TYPE_UINT16, NULL, &vp->data) < 0) return -1;
726
727 if (key.vb_uint16 >= talloc_array_length(vs->finally_by_packet_type) ||
728 !(instruction = vs->finally_by_packet_type[key.vb_uint16])) goto check_default;
729
731 fr_time_delta_from_sec(5), *top_frame) < 0)) return -1;
732
733 *top_frame = UNLANG_SUB_FRAME; /* switch to SUB_FRAME after the first instruction */
734
735 return 0;
736 }
737
738check_default:
739 if (vs->finally_default) {
741 fr_time_delta_from_sec(5), *top_frame) < 0)) return -1;
742
743 *top_frame = UNLANG_SUB_FRAME; /* switch to SUB_FRAME after the first instruction */
744 }
745
746 return 0;
747}
748
749/** Set the request processing function.
750 *
751 * Short-term hack
752 */
754{
755 /*
756 * Add a log destination specific to this virtual server.
757 *
758 * If we add a log destination, make sure to remove it when we walk back up the stack.
759 * But ONLY if we're not at the top of the stack.
760 *
761 * When a brand new request comes in, it has a "call" frame pushed, and then this function is
762 * called. So if we're at the top of the stack, we don't need to pop any logging function,
763 * because the request will die immediately after the top "call" frame is popped.
764 *
765 * However, if we're being reached from a "call" frame in the middle of the stack, then
766 * we do have to pop the log destination when we return.
767 */
768 if (vs->log) {
770
772 unlang_action_t action;
773
775 request,
776 NULL, /* don't call it immediately */
777 server_remove_log_destination, /* but when we pop the frame */
779 top_frame,
780 UNCONST(void *, vs));
781 if (action != UNLANG_ACTION_PUSHED_CHILD) return action;
782
783 top_frame = UNLANG_SUB_FRAME; /* switch to SUB_FRAME after the first instruction */
784 }
785 }
786
787 /*
788 * Push an uncancellable finally instruction to the stack.
789 */
790 if (virtual_server_push_finally(request, vs, &top_frame) < 0) return UNLANG_ACTION_FAIL;
791
792 /*
793 * Bootstrap the stack with a module instance.
794 */
795 if (unlang_module_push(p_result, request, vs->process_mi,
796 vs->process_module->process, top_frame) < 0) return UNLANG_ACTION_FAIL;
797
799}
800
801static int cmd_show_server_list(FILE *fp, UNUSED FILE *fp_err, UNUSED void *ctx, UNUSED fr_cmd_info_t const *info)
802{
803 size_t i, server_cnt = virtual_servers ? talloc_array_length(virtual_servers) : 0;
804
805 if (!server_cnt) return 0;
806
807 for (i = 0; i < server_cnt; i++) {
808 fprintf(fp, "%-30snamespace = %s\n", cf_section_name2(virtual_servers[i]->server_cs),
809 fr_dict_root(*(virtual_servers[i]->process_module->dict))->name);
810 }
811
812 return 0;
813}
814
816 {
817 .parent = "show",
818 .name = "server",
819 .help = "Show virtual server settings.",
820 .read_only = true,
821 },
822
823 {
824 .parent = "show server",
825 .name = "list",
826 .func = cmd_show_server_list,
827 .help = "Show the list of virtual servers loaded in the server.",
828 .read_only = true,
829 },
830
832
833};
834
835/** Compare listeners by app_io_addr
836 *
837 * Only works for IP addresses, and will blow up on file names
838 */
839static fr_cmp_ret_t listen_addr_cmp(void const *one, void const *two)
840{
841 fr_listen_instance_t const *a = one;
842 fr_listen_instance_t const *b = two;
843 fr_ipaddr_t aip, bip;
844 int ret;
845
846 /*
847 * The caller must ensure that the address field is set.
848 */
849 if (!a->app_io_addr && !b->app_io_addr) return CMP_EQ;
850 if (!a->app_io_addr && b->app_io_addr) return CMP_LT;
851 if (a->app_io_addr && !b->app_io_addr) return CMP_GT;
852
853 /*
854 * Address family
855 */
856 CMP_RETURN(a, b, app_io_addr->af);
857
858 fr_assert((a->app_io_addr->af == AF_INET) || ((a->app_io_addr->af == AF_INET6)));
859
860 /*
861 * UDP vs TCP
862 */
863 CMP_RETURN(a, b, app_io_addr->type);
864
865 /*
866 * Check ports.
867 */
868 CMP_RETURN(a, b, app_io_addr->inet.src_port);
869
870 /*
871 * Don't call fr_ipaddr_cmp(), as we need to do our own
872 * checks here. We have various wildcard checks which
873 * aren't globally applicable.
874 */
875
876 /*
877 * Different address families.
878 */
879 CMP_RETURN(a, b, app_io_addr->inet.src_ipaddr.af);
880
881 /*
882 * If both are bound to interfaces, AND the interfaces
883 * are different, then there is no conflict.
884 */
885 if (a->app_io_addr->inet.src_ipaddr.scope_id && b->app_io_addr->inet.src_ipaddr.scope_id) {
886 CMP_RETURN(a, b, app_io_addr->inet.src_ipaddr.scope_id);
887 }
888
889 ret = a->app_io_addr->inet.src_ipaddr.prefix - b->app_io_addr->inet.src_ipaddr.prefix;
890 aip = a->app_io_addr->inet.src_ipaddr;
891 bip = b->app_io_addr->inet.src_ipaddr;
892
893 /*
894 * Mask out the longer prefix to match the shorter
895 * prefix.
896 */
897 if (ret < 0) {
898 fr_ipaddr_mask(&bip, a->app_io_addr->inet.src_ipaddr.prefix);
899
900 } else if (ret > 0) {
901 fr_ipaddr_mask(&aip, b->app_io_addr->inet.src_ipaddr.prefix);
902
903 }
904
905 return fr_ipaddr_cmp(&aip, &bip);
906}
907
908/** See if another global listener is using a particular IP / port
909 *
910 */
912{
914
915 if (!listen_addr_root) return NULL;
916
917 fr_rb_find((void **)&found, listen_addr_root, li);
918
919 return found;
920}
921
922
923/** Record that we're listening on a particular IP / port
924 *
925 */
927{
928 if (!listen_addr_root) return false;
929
930 if (!li->app_io_addr) return true;
931
932 if (listen_find_any(li) != NULL) return false;
933
934 return fr_rb_insert(listen_addr_root, li) == 0;
935}
936
937/** Return the configuration section for a virtual server
938 *
939 * @param[in] vs to return conf section for
940 * @return
941 * - The CONF_SECTION of the virtual server.
942 */
944{
945 return vs->server_cs;
946}
947
948/** Resolve a CONF_SECTION to a virtual server
949 *
950 */
952{
954
955 vs = cf_data_value(cf_data_find(server_cs, virtual_server_t, NULL));
956 if (!vs) {
957 cf_log_err(server_cs, "server_cs does not contain virtual server data");
958 return NULL;
959 }
960
961 return vs;
962}
963
964/** Return virtual server matching the specified name
965 *
966 * @note May be called in bootstrap or instantiate as all servers should be present.
967 *
968 * @param[in] name of virtual server.
969 * @return
970 * - NULL if no virtual server was found.
971 * - The CONF_SECTION of the named virtual server.
972 */
974{
975 CONF_SECTION *server_cs = cf_section_find(virtual_server_root, "server", name);
976 CONF_DATA const *cd;
977
978 if (unlikely(server_cs == NULL)) return NULL;
979
980 cd = cf_data_find(server_cs, virtual_server_t, NULL);
981 if (unlikely(cd == NULL)) return NULL;
982
983 return cf_data_value(cd);
984}
985
986/** Find a virtual server using one of its sections
987 *
988 * @param[in] ci to find parent virtual server for.
989 * @return
990 * - The virtual server section on success.
991 * - NULL if the child isn't associated with any virtual server section.
992 */
994{
995 CONF_SECTION *cs;
996 CONF_DATA const *cd;
997
998 cs = cf_section_find_parent(ci, "server", CF_IDENT_ANY);
999 if (unlikely(!cs)) {
1000 cf_log_err(ci, "Child section is not associated with a virtual server");
1001 return NULL;
1002 }
1003
1004 cd = cf_data_find(cs, virtual_server_t, NULL);
1005 if (unlikely(!cd)) {
1006 cf_log_err(ci, "Virtual server section missing virtual_server_t data");
1007 return NULL;
1008 }
1009
1010 return cf_data_value(cd);
1011}
1012
1013/** Return the packet type attribute for a virtual server specified by a config section
1014 *
1015 * @param[in] server_cs to look for packet type attribute in.
1016 * @return
1017 * - NULL on error.
1018 * - packet type dict attr on success.
1019 */
1021{
1022 virtual_server_t const *vs = virtual_server_from_cs(server_cs);
1023
1024 if (unlikely(!vs || !vs->process_module || !vs->process_module->packet_type)) return NULL;
1025 return *vs->process_module->packet_type;
1026}
1027
1028/** Wrapper for the config parser to allow pass1 resolution of virtual servers
1029 *
1030 */
1031int virtual_server_cf_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
1032 CONF_ITEM *ci, conf_parser_t const *rule)
1033{
1034 virtual_server_t const *vs;
1035 virtual_server_cf_parse_uctx_t const *uctx = rule->uctx;
1036
1038 if (!vs) {
1039 cf_log_err(ci, "virtual-server \"%s\" not found", cf_pair_value(cf_item_to_pair(ci)));
1040 return -1;
1041 }
1042
1043 /*
1044 * Validation checks
1045 */
1046 if (uctx) {
1047 /*
1048 * Check the module name
1049 *
1050 * FIXME: ...at some point in the distance future. Names
1051 * are icky, we should compare based on dl_module_t, but
1052 * ordering issues make this difficult currently.
1053 */
1054 if (uctx->process_module_name) {
1055 /* catch users doing stupid things */
1056 if (strcmp(uctx->process_module_name, vs->process_mi->module->name) != 0) {
1057 cf_log_err(ci, "virtual server \"%s\" must be of type \"%s\", "
1058 "got type \"%s\"",
1060 uctx->process_module_name, vs->process_mi->module->name);
1061 return -1;
1062 }
1063 }
1064
1065 /*
1066 * It's theoretically possible for the same module to be used
1067 * with multiple namespaces, so we need this check too.
1068 */
1069 if (uctx->required_dict) {
1070 fr_dict_t *required_dict = *uctx->required_dict;
1071
1072 if (!fr_cond_assert_msg(required_dict != NULL,
1073 "dict not resolved before virtual server reference")) {
1074 return -1;
1075 }
1076
1077 if (required_dict != *vs->process_module->dict) {
1078 cf_log_err(ci, "virtual server \"%s\" must use namespace \"%s\", "
1079 "got namespace \"%s\"",
1081 fr_dict_root(required_dict)->name,
1082 fr_dict_root(*vs->process_module->dict)->name);
1083 return -1;
1084 }
1085 }
1086 }
1087
1088 *((virtual_server_t const **)out) = vs;
1089
1090 return 0;
1091}
1092
1093static inline CC_HINT(always_inline) int virtual_server_compile_finally_sections(virtual_server_t *vs, tmpl_rules_t const *rules, int *found)
1094{
1095 static unlang_mod_actions_t const mod_actions_finally = {
1096 .actions = {
1097 [RLM_MODULE_REJECT] = MOD_PRIORITY_3,
1098 [RLM_MODULE_FAIL] = MOD_PRIORITY_1,
1099 [RLM_MODULE_OK] = MOD_PRIORITY_4,
1101 [RLM_MODULE_INVALID] = MOD_PRIORITY_2,
1102 [RLM_MODULE_DISALLOW] = MOD_PRIORITY_5,
1103 [RLM_MODULE_NOTFOUND] = MOD_PRIORITY_6,
1104 [RLM_MODULE_NOOP] = MOD_PRIORITY_8,
1105 [RLM_MODULE_UPDATED] = MOD_PRIORITY_7
1106 },
1107 .retry = RETRY_INIT,
1108 };
1109
1110 fr_dict_attr_t const *da;
1111 fr_dict_attr_t const **da_p = vs->process_module->packet_type;
1112 CONF_SECTION *subcs;
1113
1114 if (!da_p || !*da_p) {
1115 subcs = cf_section_find(vs->server_cs, "finally", CF_IDENT_ANY);
1116 if (!subcs) return 0;
1117
1118 cf_log_err(subcs, "Invalid 'finally' section - virtual server does not define a 'packet_type'");
1119 return -1;
1120 }
1121
1122 da = *da_p;
1123
1124 /*
1125 * Iterate over all the finally sections, trying to resolve
1126 * the name2 to packet types.
1127 */
1128 for (subcs = cf_section_find(vs->server_cs, "finally", CF_IDENT_ANY);
1129 subcs;
1130 subcs = cf_section_find_next(vs->server_cs, subcs, "finally", CF_IDENT_ANY)) {
1131 char const *packet_type = cf_section_name2(subcs);
1132 fr_dict_enum_value_t const *ev;
1133 fr_value_box_t key;
1134 int ret;
1135 void *instruction;
1136
1137 if (!packet_type) {
1138 if (vs->finally_default) {
1139 cf_log_err(subcs, "Duplicate 'finally { ... }' section");
1140 return -1;
1141 }
1142
1143 ret = unlang_compile(vs, subcs, &mod_actions_finally, rules, &instruction);
1144 if (ret < 0) return -1;
1145
1146 vs->finally_default = instruction;
1147 (*found)++;
1148
1149 continue;
1150 }
1151
1152 /*
1153 * FIXME: This would allow response packet types too
1154 * We don't have anything that lists request/response
1155 * types, so we can't check that here.
1156 */
1157 ev = fr_dict_enum_by_name(da, packet_type, talloc_strlen(packet_type));
1158 if (!ev) {
1159 cf_log_err(subcs, "Invalid 'finally %s { ... }' section, "
1160 "does not match any Packet-Type value", packet_type);
1161 return -1;
1162 }
1163
1164 /*
1165 * This is... unlikely, as protocols usually use small
1166 * packet types.
1167 */
1169 forbid:
1170 fr_assert(da);
1171 cf_log_err(subcs, "'finally %s { ... }' section, "
1172 "not supported for this protocol. %s is a %s", packet_type,
1173 da->name, fr_type_to_str(ev->value->type));
1174 return -1;
1175 }
1176
1177 if (fr_value_box_cast(NULL, &key, FR_TYPE_UINT16, NULL, ev->value) < 0) {
1178 goto forbid;
1179 }
1180
1181 if (key.vb_uint16 >= talloc_array_length(vs->finally_by_packet_type)) {
1183 void *, key.vb_uint16 + 1));
1184 }
1185
1186 if (vs->finally_by_packet_type[key.vb_uint16]) {
1187 cf_log_err(subcs, "Duplicate 'finally %s { ... }' section", packet_type);
1188 return -1;
1189 }
1190
1191 ret = unlang_compile(vs, subcs, &mod_actions_finally, rules, &instruction);
1192 if (ret < 0) return -1;
1193
1194 vs->finally_by_packet_type[key.vb_uint16] = instruction;
1195
1196 (*found)++;
1197 }
1198
1199 return 0;
1200}
1201
1202/*
1203 * Check for 'send FOO' and 'recv BAR' which are unused.
1204 */
1206{
1207 bool fail = false;
1208
1209 cf_section_foreach(server, subcs) {
1210 char const *name, *name2;
1211
1212 if (cf_item_is_parsed(subcs)) continue;
1213
1214 name = cf_section_name1(subcs);
1215
1216 /*
1217 * Allow them to "comment out" an entire block by prefixing the name with "-", ala
1218 * "-sql".
1219 */
1220 if (*name == '-') continue;
1221
1222 /*
1223 * Local clients are parsed by the listener after the virtual server is bootstrapped. So
1224 * we just ignore them here.
1225 */
1226 if (strcmp(name, "client") == 0) continue;
1227
1228 name2 = cf_section_name2(subcs);
1229
1230 /*
1231 * When checking the configuration, it is an error to have an unused "send FOO" or "recv
1232 * BAR" section.
1233 */
1234 if (check_config && ((strcmp(name, "recv") == 0) || (strcmp(name, "send") == 0))) {
1235 if (!name2) {
1236 cf_log_err(subcs, "Unused processing section' %s {'", name);
1237 cf_log_err(subcs, "If this is intentional, please rename it to '-%s { ...'", name);
1238 } else {
1239 cf_log_err(subcs, "Unused processing section '%s %s {'", name, name2);
1240 cf_log_err(subcs, "If this is intentional, please rename it to '-%s %s { ...'",
1241 name, name2);
1242 }
1243
1244 fail = true;
1245 continue;
1246 }
1247
1248 /*
1249 * Print warnings if it's unused. If there's an issue with case sensitivity, then that's
1250 * an error, even if we're not running check_config.
1251 */
1252 name2 = cf_section_name2(subcs);
1253 if (!name2) {
1254 cf_log_warn(subcs, "Ignoring '%s {' - it is unused", name);
1255
1256 } else if (list) {
1257 int i;
1258 const char *realname = NULL;
1259
1260 /*
1261 * See if it's a case-sensitive issue.
1262 *
1263 * The dictionaries are case insensitive. The configuration files are
1264 * case sensitive.
1265 */
1266 for (i = 0; list[i].section; i++) {
1267 if (list[i].section->name2 == CF_IDENT_ANY) continue;
1268
1269 if (strcasecmp(list[i].section->name2, name2) == 0) {
1270 realname = list[i].section->name2;
1271 break;
1272 }
1273 }
1274
1275 if (realname) {
1276 cf_log_err(subcs, "Unused processing section '%s %s {'", name, name2);
1277 cf_log_err(subcs, "Do you mean '%s %s { ...' ? ", name, realname);
1278 fail = true;
1279 break;
1280 }
1281
1282 cf_log_warn(subcs, "Ignoring %s %s { - it is unused", name, name2);
1283 }
1284 }
1285
1286 return fail;
1287}
1288
1289/** Compile sections for a virtual server.
1290 *
1291 * When the "proto_foo" module calls fr_app_process_instantiate(), it
1292 * loads the compile list from the #fr_app_worker_t, and calls this
1293 * function.
1294 *
1295 * This function walks down the registration table, compiling each
1296 * named section.
1297 *
1298 * @param[in] vs to compile sections for.
1299 * @param[in] rules to apply for pass1.
1300 */
1302{
1304 void *instance = vs->process_mi->data;
1305 CONF_SECTION *server = vs->server_cs;
1306 int i, found;
1307 bool fail;
1308 CONF_SECTION *subcs = NULL;
1309 char const *name, *name2;
1310
1311 found = 0;
1312
1313 /*
1314 * Complain about v3 things being used in v4.
1315 *
1316 * Don't complain when running in normal mode, because the server will just ignore the new
1317 * sections. But the check_config stuff is generally run before the service starts, and we
1318 * definitely want to tell people when running in debug mode.
1319 */
1320 if (check_config || DEBUG_ENABLED) {
1321 fail = false;
1322
1323 while ((subcs = cf_section_next(server, subcs)) != NULL) {
1324 if (cf_section_name2(subcs) != NULL) continue;
1325
1326 name = cf_section_name1(subcs);
1327 if ((strcmp(name, "authorize") == 0) ||
1328 (strcmp(name, "authenticate") == 0) ||
1329 (strcmp(name, "post-auth") == 0) ||
1330 (strcmp(name, "preacct") == 0) ||
1331 (strcmp(name, "accounting") == 0) ||
1332 (strcmp(name, "pre-proxy") == 0) ||
1333 (strcmp(name, "post-proxy") == 0)) {
1334 cf_log_err(subcs, "Version 3 processing section '%s' is not valid in version 4.",
1335 name);
1336 fail = true;
1337 }
1338 }
1339
1340 /*
1341 * Complain about _all_ of the sections, and not just the first one.
1342 */
1343 if (fail) return -1;
1344 }
1345
1346 /*
1347 * The sections are in trees, so this isn't as bad as it
1348 * looks. It's not O(n^2), but O(n logn). But it could
1349 * still be improved.
1350 */
1351 for (i = 0; list[i].section; i++) {
1352 int rcode;
1353 CONF_SECTION *bad;
1354
1355 /*
1356 * We are looking for a specific subsection.
1357 * Warn if it isn't found, or compile it if
1358 * found.
1359 */
1360 if (list[i].section->name2 != CF_IDENT_ANY) {
1361 void *instruction = NULL;
1362
1363 subcs = cf_section_find(server, list[i].section->name1, list[i].section->name2);
1364 if (!subcs) {
1365 DEBUG3("Warning: Skipping %s %s { ... } as it was not found.",
1366 list[i].section->name1, list[i].section->name2);
1367 /*
1368 * Initialise CONF_SECTION pointer for missing section
1369 */
1370 if ((instance) && !list[i].dont_cache) {
1371 *(CONF_SECTION **) (((uint8_t *) instance) + list[i].offset) = NULL;
1372 }
1373 continue;
1374 }
1375
1376 /*
1377 * Duplicate sections are forbidden.
1378 */
1379 bad = cf_section_find_next(server, subcs, list[i].section->name1, list[i].section->name2);
1380 if (bad) {
1381 forbidden:
1382 cf_log_err(bad, "Duplicate sections are forbidden.");
1383 cf_log_err(subcs, "Previous definition occurs here.");
1384 return -1;
1385 }
1386
1387 rcode = unlang_compile(vs, subcs, list[i].actions, rules, &instruction);
1388 if (rcode < 0) return -1;
1389
1390 /*
1391 * Cache the CONF_SECTION which was found.
1392 */
1393 if (instance) {
1394 if (!list[i].dont_cache) {
1395 *(CONF_SECTION **) (((uint8_t *) instance) + list[i].offset) = subcs;
1396 }
1397 if (list[i].instruction > 0) {
1398 *(void **) (((uint8_t *) instance) + list[i].instruction) = instruction;
1399 }
1400 }
1401
1402 found++;
1403 continue;
1404 }
1405
1406 /*
1407 * Reset this so that we start from the beginning
1408 * again, instead of starting from the last "send
1409 * foo" block.
1410 */
1411 subcs = NULL;
1412
1413 /*
1414 * Find all subsections with the given first name
1415 * and compile them.
1416 */
1417 while ((subcs = cf_section_find_next(server, subcs, list[i].section->name1, CF_IDENT_ANY))) {
1418 name2 = cf_section_name2(subcs);
1419 if (!name2) {
1420 cf_log_err(subcs, "Invalid '%s { ... }' section, it must have a name", list[i].section->name1);
1421 return -1;
1422 }
1423
1424 /*
1425 * Duplicate sections are forbidden.
1426 */
1427 bad = cf_section_find_next(server, subcs, list[i].section->name1, name2);
1428 if (bad) goto forbidden;
1429
1430 rcode = unlang_compile(vs, subcs, list[i].actions, rules, NULL);
1431 if (rcode < 0) return -1;
1432
1433 /*
1434 * Note that we don't store the
1435 * CONF_SECTION here, as it's a wildcard.
1436 *
1437 * @todo - count number of subsections
1438 * and store them in an array?
1439 */
1440 found++;
1441 }
1442 }
1443
1444 /*
1445 * Compile finally sections, these are special
1446 * sections and always execute before the request
1447 * exits from the virtual server.
1448 */
1449 if (unlikely(virtual_server_compile_finally_sections(vs, rules, &found) < 0)) {
1450 cf_log_err(server, "Failed to compile finally sections");
1451 return -1;
1452 }
1453
1454 /*
1455 * Didn't find any processing sections. Note that we don't count "finally" sections here. They
1456 * are only run after the packet has been processed through the normal sections. A virtual
1457 * server with only a "finally" section doesn't make sense.
1458 *
1459 * i.e. if people want to accept packets without responding, they need a "recv foo" section which
1460 * contains a "do_not_respond" policy.
1461 */
1462 if (!found) {
1463 cf_log_err(server, "No processing sections are defined for this virtual server");
1464 cf_log_err(server, "The server WILL NOT be able to process packets until the configuration is fixed");
1465 return -1;
1466 }
1467
1468 if (!check_config && !DEBUG_ENABLED) return found;
1469
1470 fail = virtual_server_warn_unused(server, list);
1471
1472 /*
1473 * Be nice to people, and complaining about ALL unused processing sections. That way they don't
1474 * have to run the server many, many, times to see all of the errors.
1475 */
1476 if (fail) return -1;
1477
1478 return found;
1479}
1480
1481/** Register name1 / name2 as allowed processing sections
1482 *
1483 * This function is called from the virtual server bootstrap routine,
1484 * which happens before module_bootstrap();
1485 */
1487{
1489
1490 fr_rb_find((void **)&old, vs->sections, entry);
1491 if (old) return 0;
1492
1493#ifndef NDEBUG
1494 /*
1495 * Catch stupid programmers.
1496 *
1497 * Processing sections can't allow "*" for module
1498 * methods, because otherwise you would be allowed to run
1499 * DHCP things in a RADIUS accounting section. And that
1500 * would be bad.
1501 */
1502 if (entry->methods) {
1503 int i;
1504
1505 for (i = 0; entry->methods[i]; i++) {
1506 if (entry->methods[i]->name1 == CF_IDENT_ANY) {
1507 ERROR("Processing sections cannot allow \"*\"");
1508 return -1;
1509 }
1510
1511 if (entry->methods[i]->name2 == CF_IDENT_ANY) {
1512 ERROR("Processing sections cannot allow \"%s *\"",
1513 entry->methods[i]->name1);
1514 return -1;
1515 }
1516 }
1517 }
1518#endif
1519
1520 if (fr_rb_insert(vs->sections, entry) != 0) {
1521 fr_strerror_const("Failed inserting entry into internal tree");
1522 return -1;
1523 }
1524
1525 return 0;
1526}
1527
1528/** Find the component for a section
1529 *
1530 */
1532{
1534
1535 /*
1536 * Look up the specific name first. That way we can
1537 * define both "accounting on", and "accounting *".
1538 */
1539 if (section->name2 != CF_IDENT_ANY) {
1540 fr_rb_find((void **)&entry, vs->sections,
1542 .section = section
1543 });
1544 if (entry) return entry->methods;
1545 }
1546
1547 /*
1548 * Then look up the wildcard, if we didn't find any matching name2.
1549 */
1550 fr_rb_find((void **)&entry, vs->sections,
1552 .section = SECTION_NAME(section->name1, CF_IDENT_ANY)
1553 });
1554 if (!entry) return NULL;
1555
1556 return entry->methods;
1557}
1558
1559/** Define a values for Auth-Type attributes by the sections present in a virtual-server
1560 *
1561 * The.name2 value of any sections found will be converted into values of the specified da.
1562 *
1563 * @param[in] server_cs The virtual server containing the sections.
1564 * @param[in] subcs_name of the subsection to search for.
1565 * @param[in] da to add enumeration values for.
1566 * @return
1567 * - 0 all values added successfully.
1568 * - -1 an error occurred.
1569 */
1570int virtual_server_section_attribute_define(CONF_SECTION *server_cs, char const *subcs_name, fr_dict_attr_t const *da)
1571{
1572 int rcode = 0;
1573 CONF_SECTION *subcs = NULL;
1574
1575 fr_assert(strcmp(cf_section_name1(server_cs), "server") == 0);
1576
1577 while ((subcs = cf_section_find_next(server_cs, subcs, subcs_name, CF_IDENT_ANY))) {
1578 char const *name2;
1579 fr_dict_enum_value_t const *dv;
1580
1581 name2 = cf_section_name2(subcs);
1582 if (!name2) {
1583 cf_log_err(subcs, "Invalid '%s { ... }' section, it must have a name", subcs_name);
1584 return -1;
1585 }
1586
1587 /*
1588 * If the value already exists, don't
1589 * create it again.
1590 */
1591 dv = fr_dict_enum_by_name(da, name2, -1);
1592 if (dv) continue;
1593
1594 cf_log_debug(subcs, "Creating %s = %s", da->name, name2);
1595
1596 /*
1597 * Create a new unique value with a meaningless
1598 * number. You can't look at it from outside of
1599 * this code, so it doesn't matter. The only
1600 * requirement is that it's unique.
1601 */
1603 PERROR("Failed adding section value");
1604 return -1;
1605 }
1606
1607 rcode = 1;
1608 }
1609
1610 return rcode;
1611}
1612
1614{
1615 char const *ref;
1616 fr_dict_attr_t const *da;
1617 CONF_ITEM *ci = NULL;
1618
1619 ref = cf_section_name2(cs);
1620 if (!ref) {
1621 cf_log_err(cs, "Expected 'values <name> { ... }'");
1622 return -1;
1623 }
1624
1625 da = fr_dict_attr_by_name(NULL, parent, ref);
1626 if (!da) {
1627 cf_log_err(cs, "No such attribute \"%s\"", ref);
1628 return -1;
1629 }
1630
1631 if (fr_type_is_structural(da->type)) {
1632 cf_log_err(cs, "Cannot define value for structural attribute \"%s\"", ref);
1633 return -1;
1634 }
1635
1636 /*
1637 * This both does not make any sense, and does not get
1638 * parsed correctly if the string contains backslashes.
1639 */
1640 if (da->type == FR_TYPE_STRING) {
1641 cf_log_err(cs, "Cannot define value for 'string' attribute \"%s\"", ref);
1642 return -1;
1643 }
1644
1645 while ((ci = cf_item_next(cs, ci))) {
1646 fr_slen_t slen;
1647 ssize_t len;
1648 char const *attr, *value;
1649 CONF_PAIR *cp;
1650 fr_dict_enum_value_t const *dv;
1651 fr_value_box_t box;
1652
1653 if (cf_item_is_section(ci)) {
1654 cf_log_err(ci, "Unexpected subsection");
1655 return -1;
1656 }
1657
1658 if (!cf_item_is_pair(ci)) continue;
1659
1660 cp = cf_item_to_pair(ci);
1661 fr_assert(cp != NULL);
1662
1663 /*
1664 * =* is a hack by the cf parser to say "no operator"
1665 */
1666 if ((cf_pair_operator(cp) != T_OP_EQ) ||
1668 cf_log_err(ci, "Definition is not in 'name = value' format");
1669 return -1;
1670 }
1671
1672 attr = cf_pair_attr(cp);
1673 value = cf_pair_value(cp);
1674
1675 dv = fr_dict_enum_by_name(da, attr, talloc_strlen(attr));
1676 if (dv) {
1677 cf_log_err(cp, "Duplicate value name");
1678 return -1;
1679 }
1680
1682
1684
1685 /*
1686 * @todo - unescape for double quoted strings. Whoops.
1687 */
1688 slen = fr_value_box_from_str(NULL, &box, da->type, da, value, len, NULL);
1689 if (slen < 0) {
1690 cf_log_err(cp, "Failed parsing value - %s", fr_strerror());
1691 return -1;
1692 }
1693
1694 if (slen != len) {
1695 cf_log_err(cp, "Unexpected text after value");
1696 fr_value_box_clear(&box);
1697 return -1;
1698 }
1699
1700 if (fr_dict_enum_add_name(UNCONST(fr_dict_attr_t *, da), attr, &box, false, false) < 0) {
1701 cf_log_err(cp, "Failed adding value - %s", fr_strerror());
1702 fr_value_box_clear(&box);
1703 return -1;
1704 }
1705
1706 fr_value_box_clear(&box);
1707 }
1708
1709 return 0;
1710}
1711
1712
1714{
1715 CONF_ITEM *ci = NULL;
1716
1717 fr_dict_attr_flags_t flags = {
1718 .internal = true,
1719 .name_only = true,
1720 .local = true,
1721 };
1722
1723 fr_assert(dict != NULL);
1724 fr_assert(parent != NULL);
1725
1726 while ((ci = cf_item_next(cs, ci))) {
1728 char const *attr, *value;
1729 CONF_PAIR *cp;
1730 CONF_SECTION *subcs = NULL;
1731
1732 if (cf_item_is_section(ci)) {
1733 subcs = cf_item_to_section(ci);
1734 fr_assert(subcs != NULL);
1735
1736 attr = cf_section_name1(subcs);
1737
1738 if (strcmp(attr, "values") == 0) {
1739 if (define_server_values(subcs, parent) < 0) return -1;
1740 continue;
1741 }
1742
1743 if (strcmp(attr, "tlv") != 0) goto invalid_type;
1744
1745 value = cf_section_name2(subcs);
1746 if (!value) {
1747 cf_log_err(ci, "Definition is not in 'tlv name { ... }' format");
1748 return -1;
1749 }
1750
1751 type = FR_TYPE_TLV;
1752 goto check_for_dup;
1753 }
1754
1755 if (!cf_item_is_pair(ci)) continue;
1756
1757 cp = cf_item_to_pair(ci);
1758 fr_assert(cp != NULL);
1759
1760 /*
1761 * =* is a hack by the cf parser to say "no operator"
1762 */
1763 if ((cf_pair_operator(cp) != T_OP_CMP_TRUE) ||
1766 cf_log_err(ci, "Definition is not in 'type name' format");
1767 return -1;
1768 }
1769
1770 attr = cf_pair_attr(cp);
1771 value = cf_pair_value(cp);
1772
1774 if (type == FR_TYPE_NULL) {
1776 cf_log_err(ci, "Invalid data type '%s'", attr);
1777 return -1;
1778 }
1779
1780 /*
1781 * Leaf and group are OK. TLV, Vendor, Struct, VSA, etc. are not as variable definitions.
1782 */
1783 if (!(fr_type_is_leaf(type) || (type == FR_TYPE_GROUP))) goto invalid_type;
1784
1785 /*
1786 * No duplicates are allowed.
1787 */
1788 check_for_dup:
1789 if (root && (fr_dict_attr_by_name(NULL, root, value) != NULL)) {
1790 cf_log_err(ci, "Local variable '%s' duplicates a dictionary attribute.", value);
1791 return -1;
1792 }
1793
1794 if (fr_dict_attr_by_name(NULL, parent, value) != NULL) {
1795 cf_log_err(ci, "Local variable '%s' duplicates a previous local attribute.", value);
1796 return -1;
1797 }
1798
1799 if (fr_dict_attr_add_name_only(dict, parent, value, type, &flags) < 0) {
1800 cf_log_err(ci, "Failed adding local variable '%s' - %s", value, fr_strerror());
1801 return -1;
1802 }
1803
1804 if (type == FR_TYPE_TLV) {
1805 fr_dict_attr_t const *da;
1806
1807 if (!subcs) return -1; /* shouldn't happen, but shut up compiler */
1808
1809 da = fr_dict_attr_by_name(NULL, parent, value);
1810 fr_assert(da != NULL);
1811
1812 if (define_server_attrs(subcs, dict, UNCONST(fr_dict_attr_t *, da), NULL) < 0) return -1;
1813 }
1814 }
1815
1816 return 0;
1817}
1818
1819static fr_dict_t const *virtual_server_local_dict(CONF_SECTION *server_cs, fr_dict_t const *dict_def)
1820{
1821 fr_dict_t *dict;
1822 CONF_SECTION *cs;
1823
1824 cs = cf_section_find(server_cs, "dictionary", NULL);
1825 if (!cs) return dict_def;
1826
1827 dict = fr_dict_protocol_alloc(dict_def);
1828 if (!dict) {
1829 cf_log_err(cs, "Failed allocating local dictionary");
1830 return NULL;
1831 }
1832
1835 return NULL;
1836 }
1837
1838 /*
1839 * Replace the original dictionary with the new one.
1840 */
1841 cf_data_remove(server_cs, fr_dict_t, "dict");
1842 cf_data_add(server_cs, dict, "dict", false);
1844
1845 return dict;
1846}
1847
1848
1849/** Open all the listen sockets
1850 *
1851 * @param[in] sc Scheduler to add I/O paths to.
1852 * @return
1853 * - 0 on success.
1854 * - -1 on failure.
1855 */
1857{
1858 size_t i, server_cnt = virtual_servers ? talloc_array_length(virtual_servers) : 0;
1859 int opened = 0;
1860
1862
1863 DEBUG2("#### Opening listener interfaces ####");
1865
1866 for (i = 0; i < server_cnt; i++) {
1867 virtual_server_listen_t **listeners;
1868 size_t j, listener_cnt;
1869
1870 listeners = virtual_servers[i]->listeners;
1871 if (!listeners) continue; /* servers can have no listeners */
1872
1873 listener_cnt = talloc_array_length(listeners);
1874
1875 for (j = 0; j < listener_cnt; j++) {
1876 int ret;
1877 virtual_server_listen_t *listener = listeners[j];
1878
1879 fr_assert(listener != NULL);
1880 fr_assert(listener->proto_mi != NULL);
1881 fr_assert(listener->proto_module != NULL);
1882
1883 fr_assert(listener->proto_module->open != NULL);
1884
1885 /*
1886 * The socket is opened with app_instance,
1887 * but all subsequent calls (network.c, etc.) use app_io_instance.
1888 *
1889 * The reason is that we call (for example) proto_radius to
1890 * open the socket, and proto_radius is responsible for setting up
1891 * proto_radius_udp, and then calling proto_radius_udp->open.
1892 *
1893 * Even then, proto_radius usually calls fr_master_io_listen() in order
1894 * to create the fr_listen_instance_t structure.
1895 */
1896
1897 /*
1898 * Sometimes the open function needs to modify instance
1899 * data, so we need to temporarily remove the protection.
1900 */
1902 ret = listener->proto_module->open(listener->proto_mi->data, sc,
1903 listener->proto_mi->conf);
1905 if (unlikely(ret < 0)) {
1906 return -1;
1907 }
1908
1909 opened++;
1910
1911 /*
1912 * Socket information is printed out by
1913 * the socket handlers. e.g. proto_radius_udp
1914 */
1915 DEBUG3("Opened listener for %s", listener->proto_module->common.name);
1916 }
1917 }
1918
1919 if (!opened) {
1920 ERROR("There are no 'listen' sections defined.");
1921 ERROR("Refusing to start, as the server will never process any packets.");
1922 return -1;
1923 }
1924
1925 return 0;
1926}
1927
1928/** Free thread-specific data for all process modules and listeners
1929 *
1930 */
1936
1937/** Perform thread instantiation for all process modules and listeners
1938 *
1939 */
1941{
1942 if (modules_thread_instantiate(ctx, process_modules, el) < 0) return -1;
1945 return -1;
1946 }
1947 return 0;
1948}
1949
1950/** Instantiate all the virtual servers
1951 *
1952 * @return
1953 * - 0 on success.
1954 * - -1 on failure.
1955 */
1957{
1958 size_t i, server_cnt;
1959 CONF_SECTION *cs;
1961
1962 /*
1963 * User didn't specify any "server" sections
1964 */
1965 if (unlikely(!virtual_servers)) {
1966 ERROR("No virtual servers configured");
1967 return -1;
1968 }
1969
1970 server_cnt = talloc_array_length(virtual_servers);
1971
1972 DEBUG2("#### Instantiating listeners ####");
1973
1975 PERROR("Failed registering radmin commands for virtual servers");
1976 return -1;
1977 }
1978
1979 for (i = 0; i < server_cnt; i++) {
1980 CONF_SECTION *server_cs = virtual_servers[i]->server_cs;
1981 fr_dict_t const *dict;
1983 fr_process_module_t const *process = (fr_process_module_t const *)
1984 vs->process_mi->module->exported;
1985
1986 /*
1987 * Set up logging before doing anything else.
1988 */
1989 if (vs->log_name) {
1990 vs->log = log_dst_by_name(vs->log_name);
1991 if (!vs->log) {
1992 CONF_PAIR *cp = cf_pair_find(server_cs, "log");
1993
1994 if (cp) {
1995 cf_log_err(cp, "Unknown log destination '%s'", vs->log_name);
1996 } else {
1997 cf_log_err(server_cs, "Unknown log destination '%s'", vs->log_name);
1998 }
1999
2000 return -1;
2001 }
2002 }
2003
2004 dict = virtual_server_local_dict(server_cs, *(process)->dict);
2005 if (!dict) return -1;
2006
2007 DEBUG("Compiling policies in server %s { ... }", cf_section_name2(server_cs));
2008
2009 fr_assert(virtual_servers[i]->process_mi);
2010
2011 /*
2012 * Compile the processing sections indicated by
2013 * the process module. This must be done before
2014 * module_instantiate is called, as the instance
2015 * data is protected after this call.
2016 */
2017 if (process->compile_list) {
2018 tmpl_rules_t parse_rules = {
2019 .attr = {
2020 .dict_def = dict,
2021 .list_def = request_attr_request,
2022 },
2023
2024 .literals_safe_for = FR_VALUE_BOX_SAFE_FOR_ANY,
2025 };
2026
2027 fr_assert(parse_rules.attr.dict_def != NULL);
2028
2029 if (virtual_server_compile_sections(virtual_servers[i], &parse_rules) < 0) {
2030 return -1;
2031 }
2032 }
2033
2034 (void) virtual_server_warn_unused(server_cs, process->compile_list);
2035 }
2036
2037 /*
2038 * Iterate over virtual modules to see if we can compile them.
2039 */
2040 for (cs = module_rlm_virtual_iter_init(&iter);
2041 cs != NULL;
2042 cs = module_rlm_virtual_iter_next(&iter)) {
2043 fr_dict_t const *dict;
2044
2045 dict = virtual_server_dict_by_cs(cs); /* cheating! */
2046 if (!dict) continue;
2047
2048 if (unlang_compile_virtual_module(cs, dict) < 0) return -1;
2049 }
2050
2052 PERROR("Failed instantiating process modules");
2053 return -1;
2054 }
2056 PERROR("Failed instantiating protocol modules");
2057 return -1;
2058 }
2059
2060 return 0;
2061}
2062
2063/** Load protocol modules and call their bootstrap methods
2064 *
2065 * @param[in] config section containing the virtual servers to bootstrap.
2066 * @return
2067 * - 0 on success.
2068 * - -1 on failure.
2069 */
2071{
2073
2074 /*
2075 * Ensure any libraries the modules depend on are instantiated
2076 */
2077 if (global_lib_instantiate() < 0) return -1;
2078
2080 PERROR("Failed bootstrapping process modules");
2081 return -1;
2082 }
2084 PERROR("Failed bootstrapping protocol modules");
2085 return -1;
2086 }
2087
2088 return 0;
2089}
2090
2092{
2093 if (talloc_free(listen_addr_root) < 0) return -1;
2094 listen_addr_root = NULL;
2095 if (talloc_free(process_modules) < 0) return -1;
2096 process_modules = NULL;
2097 if (talloc_free(proto_modules) < 0) return -1;
2098 proto_modules = NULL;
2100
2101 return 0;
2102}
2103
2104static int _virtual_servers_atexit(UNUSED void *uctx)
2105{
2106 return virtual_servers_free();
2107}
2108
2109/** Performs global initialisation for the virtual server code
2110 *
2111 * This has to be done separately and explicitly, because the above code makes
2112 * use of "onread" callbacks.
2113 *
2114 * Will automatically free module lists on exit, but all modules should have
2115 * been removed from this list by the point that happens.
2116 */
2118{
2120 PERROR("%s", __FUNCTION__);
2121 return -1;
2122 }
2124 PERROR("%s", __FUNCTION__);
2126 return -1;
2127 }
2128
2130
2131 /*
2132 * FIXME - We should be able to turn on write protection,
2133 * but there are too many proto modules that hang things
2134 * off of their instance data.
2135 */
2136 MEM(proto_modules = module_list_alloc(NULL, &module_list_type_global, "protocol", false));
2138 NULL));
2139
2140 /*
2141 * Create a list to hold all the proto_* modules
2142 * that get loaded during startup.
2143 */
2145
2146 return 0;
2147}
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:40
@ 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:38
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 open its listeners and register it with the scheduler so we can rec...
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
static uint8_t request[4]
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:203
#define RCSID(id)
Definition build.h:603
#define CMP_RETURN(_a, _b, _field)
Return if the comparison is not 0 (is unequal)
Definition build.h:139
#define unlikely(_x)
Definition build.h:486
#define UNUSED
Definition build.h:415
fr_cmp_ret_t
Result of an ordering comparison.
Definition build.h:113
@ CMP_GT
a > b
Definition build.h:117
@ CMP_LT
a < b
Definition build.h:115
@ CMP_EQ
a == b
Definition build.h:116
static int invalid_type(fr_type_t type)
Definition calc.c:699
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:1360
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:1951
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:722
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition cf_parse.h:666
void const * uctx
User data accessible by the cf_parse_t func.
Definition cf_parse.h:672
#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:651
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:466
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
Definition cf_parse.h:483
@ CONF_FLAG_OK_MISSING
OK if it's missing.
Definition cf_parse.h:491
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:460
#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:350
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:669
#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:649
Internal data that is associated with a configuration section.
Definition cf_priv.h:195
Common header for all CONF_* types.
Definition cf_priv.h:54
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:77
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:106
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
Definition cf_util.c:619
fr_token_t cf_pair_attr_quote(CONF_PAIR const *pair)
Return the value (lhs) quoting of a pair.
Definition cf_util.c:1787
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:1654
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1405
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
Definition cf_util.c:1922
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:1216
char const * cf_section_name1(CONF_SECTION const *cs)
Return the first identifier of a CONF_SECTION.
Definition cf_util.c:1391
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:1247
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition cf_util.c:671
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:1640
fr_token_t cf_pair_operator(CONF_PAIR const *pair)
Return the operator of a pair.
Definition cf_util.c:1772
fr_token_t cf_pair_value_quote(CONF_PAIR const *pair)
Return the value (rhs) quoting of a pair.
Definition cf_util.c:1802
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
Definition cf_util.c:605
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:651
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:1268
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1758
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
Definition cf_util.c:1742
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:340
#define cf_section_foreach(_parent, _iter)
Definition cf_util.h:210
#define cf_data_add(_cf, _data, _name, _free)
Definition cf_util.h:306
#define cf_data_find(_cf, _type, _name)
Definition cf_util.h:295
#define cf_item_is_parsed(_cf)
Definition cf_util.h:191
#define cf_data_remove(_cf, _type, _name)
Remove an item from a parent by type and name.
Definition cf_util.h:318
#define cf_parent(_cf)
Definition cf_util.h:115
#define cf_item_next(_parent, _curr)
Definition cf_util.h:91
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:347
#define cf_section_find_parent(_cf, _name1, _name2)
Definition cf_util.h:233
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition cf_util.h:198
#define cf_data_find_in_parent(_cf, _type, _name)
Definition cf_util.h:301
#define cf_log_warn(_cf, _fmt,...)
Definition cf_util.h:341
#define cf_log_debug(_cf, _fmt,...)
Definition cf_util.h:343
#define cf_item_mark_parsed(_cf)
Definition cf_util.h:188
#define CF_IDENT_ANY
Definition cf_util.h:80
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
fr_dict_t * dict
Definition common.c:31
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:2214
int unlang_compile_virtual_module(CONF_SECTION *cs, fr_dict_t const *dict)
Compile an unlang section for a virtual module.
Definition compile.c:2283
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:194
#define MEM(x)
Definition debug.h:38
#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:2269
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:2059
#define fr_dict_autofree(_to_free)
Definition dict.h:937
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:3600
fr_dict_attr_t * fr_dict_attr_unconst(fr_dict_attr_t const *da)
Coerce to non-const.
Definition dict_util.c:5052
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2717
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:316
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:329
fr_value_box_t const * value
Enum value (what name maps to).
Definition dict.h:281
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:2281
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:4532
#define fr_dict_autoload(_to_load)
Definition dict.h:934
#define DICT_AUTOLOAD_TERMINATOR
Definition dict.h:335
fr_dict_t * fr_dict_protocol_alloc(fr_dict_t const *parent)
Allocate a new local dictionary.
Definition dict_util.c:4396
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:3778
Specifies an attribute which must be present for the module to function.
Definition dict.h:315
Values of the encryption flags.
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:328
Value of an enumerated attribute.
Definition dict.h:277
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:127
#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:146
int global_lib_instantiate(void)
Walk the tree of libraries and instantiate any which are pending.
Definition global_lib.c:218
talloc_free(hp)
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
fr_cmp_ret_t fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
Compare two ip addresses.
Definition inet.c:1353
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:1962
int unlang_interpret_stack_depth(request_t *request)
Return the depth of the request's stack.
Definition interpret.c:1930
#define UNLANG_SUB_FRAME
Definition interpret.h:37
fr_log_t * log_dst_by_name(char const *name)
Get a logging destination by name.
Definition log.c:1132
#define PERROR(_fmt,...)
Definition log.h:233
#define DEBUG3(_fmt,...)
Definition log.h:271
#define DEBUG_ENABLED
True if global debug level 1 messages are enabled.
Definition log.h:262
Stores all information relating to an event list.
Definition event.c:375
int fr_debug_lvl
Definition log.c:41
@ L_DBG_LVL_DISABLE
Don't print messages.
Definition log.h:65
fr_socket_t * app_io_addr
for tracking duplicate sockets
Definition listen.h:71
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
ssize_t fr_slen_t
int strcasecmp(char *s1, char *s2)
Definition missing.c:65
unlang_mod_action_t actions[RLM_MODULE_NUMCODES]
Definition mod_action.h:69
@ MOD_ACTION_RETURN
stop processing the section, and return the rcode with unset priority
Definition mod_action.h:41
CONF_SECTION * module_rlm_virtual_iter_init(fr_rb_iter_inorder_t *iter)
Iterate over the virtual modules.
CONF_SECTION * module_rlm_virtual_iter_next(fr_rb_iter_inorder_t *iter)
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:194
static const conf_parser_t config[]
Definition base.c:162
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,...)
int fr_rb_find(void **found, fr_rb_tree_t const *tree, void const *data)
Find an element in the tree, returning the data, not the node.
Definition rb.c:586
int fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
Definition rb.c:637
#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
Iterator structure for in-order traversal of an rbtree.
Definition rb.h:319
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
ssize_t fr_sbuff_in_strcpy(fr_sbuff_t *sbuff, char const *str)
Copy bytes into the sbuff up to the first \0.
Definition sbuff.c:1529
#define fr_sbuff_start(_sbuff_or_marker)
#define fr_sbuff_in_char(_sbuff,...)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
The scheduler.
Definition schedule.c:77
fr_cmp_ret_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:361
@ MODULE_INSTANCE_NONE
Not yet bootstrapped.
Definition module.h:269
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:355
void * data
Module's instance data.
Definition module.h:297
#define MODULE_INSTANCE_LEN_MAX
The maximum size of a module instance.
Definition module.h:149
module_t * exported
Public module structure.
Definition module.h:302
Module instance data.
Definition module.h:291
A list of modules.
Definition module.h:421
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition tmpl.h:346
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:343
#define FR_SIGNAL_ALLOW(_signals)
Signal mask which blocks every signal except the ones in _signals.
Definition signal.h:58
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:1721
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:1339
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:1927
fr_slen_t module_instance_name_valid(char const *inst_name)
Check to see if a module instance name is valid.
Definition module.c:1661
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:1430
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:280
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:685
#define talloc_strdup(_ctx, _str)
Definition talloc.h:149
#define talloc_realloc_zero(_ctx, _ptr, _type, _count)
Definition talloc.h:219
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
Definition talloc.h:143
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition time.h:599
@ 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:864
#define RETRY_INIT
Definition retry.h:39
int af
AF_INET, AF_INET6, or AF_UNIX.
Definition socket.h:83
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:558
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
Definition strerror.c:581
#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
fr_slen_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:6256
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:4071
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition value.c:4509
static fr_slen_t data
Definition value.h:1366
fr_type_t _CONST type
Type and flags should appear together for packing efficiency.
Definition value.h:212
#define fr_value_box_init_null(_vb)
Initialise an empty/null box that will be filled later.
Definition value.h:640
static fr_sbuff_err_t char ** out
Definition value.h:1061
static fr_sbuff_err_t char size_t * len
Definition value.h:1061
#define FR_VALUE_BOX_SAFE_FOR_ANY
Definition value.h:178
fr_dict_autoload_t virtual_server_dict_autoload[]
static const conf_parser_t server_on_read_config[]
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.
fr_dict_t const * virtual_server_dict_by_cs(CONF_SECTION const *cs)
Return the namespace for specified CONF_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.
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.
bool listen_record(fr_listen_instance_t *li)
Record that we're listening on 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
static fr_cmp_ret_t virtual_server_compile_name_cmp(void const *a, void const *b)
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.
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 module_list_t * proto_modules
List of proto modules we've loaded.
static fr_cmp_ret_t listen_addr_cmp(void const *one, void const *two)
Compare listeners by app_io_addr.
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_server_cf_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Wrapper for the config parser to allow pass1 resolution of virtual servers.
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)
fr_listen_instance_t * listen_find_any(fr_listen_instance_t *li)
See if another global listener is using a particular IP / port.
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.