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