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