The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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: b0c846459ca03d29d3812adb8c234af8413b7390 $
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  */
27 RCSID("$Id: b0c846459ca03d29d3812adb8c234af8413b7390 $")
28 
29 #include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
30 #include <freeradius-devel/server/base.h>
31 #include <freeradius-devel/server/cf_util.h>
32 #include <freeradius-devel/server/command.h>
33 #include <freeradius-devel/server/module.h>
34 #include <freeradius-devel/server/dl_module.h>
35 #include <freeradius-devel/server/global_lib.h>
36 #include <freeradius-devel/server/modpriv.h>
37 #include <freeradius-devel/server/process.h>
38 #include <freeradius-devel/server/protocol.h>
39 #include <freeradius-devel/server/section.h>
40 #include <freeradius-devel/server/virtual_servers.h>
41 
42 #include <freeradius-devel/unlang/compile.h>
43 #include <freeradius-devel/unlang/function.h>
44 
45 #include <freeradius-devel/io/application.h>
46 #include <freeradius-devel/io/master.h>
47 #include <freeradius-devel/io/listen.h>
48 
49 typedef struct {
50  module_instance_t *proto_mi; //!< The proto_* module for a listen section.
51  fr_app_t const *proto_module; //!< Public interface to the proto_mi.
52  ///< cached for convenience.
54 
56  CONF_SECTION *server_cs; //!< The server section.
57  fr_virtual_listen_t **listeners; //!< Listeners in this virtual server.
58 
59  module_instance_t *process_mi; //!< The process_* module for a virtual server.
60  ///< Contains the dictionary used by the virtual
61  ///< server and the entry point for the state machine.
62  fr_process_module_t const *process_module; //!< Public interface to the process_mi.
63  ///< cached for convenience.
64 
65  fr_rb_tree_t *sections; //!< List of sections that need to be compiled.
66 
67  fr_log_t *log; //!< log destination
68  char const *log_name; //!< name of log destination
69 };
70 
71 static fr_dict_t const *dict_freeradius;
72 
74 
77  { .out = &dict_freeradius, .proto = "freeradius" },
78  { NULL }
79 };
80 
83  { .out = &attr_auth_type, .name = "Auth-Type", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
84 
85  { NULL }
86 };
87 
88 /** List of process modules we've loaded
89  *
90  * This is global for all virtual servers. Must be initialised
91  * _before_ the configuration is loaded.
92  */
94 
95 /** List of proto modules we've loaded
96  *
97  * This is global for all virtual servers. Must be initialised
98  * _before_ the configuration is loaded.
99  */
101 
102 /** Top level structure holding all virtual servers
103  *
104  */
106 
107 /** CONF_SECTION holding all the virtual servers
108  *
109  * Set during the call to virtual_server_bootstrap and used by
110  * other virtual server functions.
111  */
113 
115 
116 static int namespace_on_read(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
117 static int server_on_read(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule);
118 
119 static int namespace_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
120 static int listen_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
121 static int server_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule);
122 
125  .on_read = namespace_on_read },
126 
128 };
129 
131  /*
132  * Not really ok if it's missing but we want to
133  * let logic elsewhere handle the issue.
134  */
136  .subcs_size = sizeof(virtual_server_t), .subcs_type = "virtual_server_t",
137  .subcs = (void const *) server_on_read_config, .name2 = CF_IDENT_ANY,
138  .on_read = server_on_read },
139 
141 };
142 
143 static const conf_parser_t server_config[] = {
145  .func = namespace_parse },
146 
148  virtual_server_t, listeners),
149  .name2 = CF_IDENT_ANY,
150  .subcs_size = sizeof(fr_virtual_listen_t), .subcs_type = "fr_virtual_listen_t",
151  .func = listen_parse },
152 
153  { FR_CONF_OFFSET("log", virtual_server_t, log_name), },
154 
156 };
157 
159  /*
160  * Not really ok if it's missing but we want to
161  * let logic elsewhere handle the issue.
162  */
164  .subcs_size = sizeof(virtual_server_t), .subcs_type = "virtual_server_t",
165  .subcs = (void const *) server_config, .name2 = CF_IDENT_ANY,
166  .func = server_parse },
167 
169 };
170 
171 /** Print all the loaded listener instances
172  *
173  */
175 {
177 }
178 
179 /** Print all the loaded process module instances
180  *
181  */
183 {
185 }
186 
187 /** Resolve proto data to a module instance
188  *
189  * @param[in] data Pointer to the proto data.
190  * @return
191  * - The module instance for the proto data.
192  * - NULL if no data matches.
193  */
195 {
197 }
198 
199 /** Generic conf_parser_t func for loading drivers
200  *
201  */
202 int virtual_server_listen_transport_parse(TALLOC_CTX *ctx, void *out, void *parent,
203  CONF_ITEM *ci, conf_parser_t const *rule)
204 {
205  conf_parser_t our_rule = *rule;
206 
207  our_rule.uctx = &proto_modules;
208 
209  return module_submodule_parse(ctx, out, parent, ci, &our_rule);
210 }
211 
212 /** Parse a "namespace" parameter
213  *
214  * We need to load the process module before continuing to parse the virtual server contents
215  * as we need to know the namespace so that we can resolve attribute names.
216  *
217  * We also need the compilation list from the proto module to figure out which sections we
218  * need to compile.
219  *
220  * @param[in] ctx to allocate data in.
221  * @param[out] out always NULL
222  * @param[in] parent Base structure address.
223  * @param[in] ci #CONF_SECTION containing the listen section.
224  * @param[in] rule unused.
225  * @return
226  * - 0 on success.
227  * - -1 on failure.
228  */
229 static int namespace_on_read(TALLOC_CTX *ctx, UNUSED void *out, UNUSED void *parent,
230  CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
231 {
232  CONF_PAIR *cp = cf_item_to_pair(ci);
233  CONF_SECTION *server_cs = cf_item_to_section(cf_parent(ci));
234  module_instance_t *mi;
235  char const *namespace;
236  char *module_name, *p, *end;
237  char const *inst_name;
238  fr_process_module_t const *process;
239 
241  "virtual_servers_init MUST be called before reading virtual server config");
242 
243  namespace = cf_pair_value(cp);
244  module_name = talloc_strdup(ctx, namespace);
245 
246  /*
247  * Smush all hyphens to underscores for module names
248  */
249  for (p = module_name, end = module_name + talloc_array_length(module_name) - 1;
250  p < end;
251  p++) if (*p == '-') *p = '_';
252 
253  if (module_instance_name_from_conf(&inst_name, server_cs) < 0) return -1;
254 
255  /*
256  * The module being loaded is the namespace with all '-'
257  * transformed to '_'.
258  *
259  * The instance name is the virtual server name.
260  */
262  module_name, inst_name,
263  0);
264  talloc_free(module_name);
265  if (mi == NULL) {
266  error:
267  cf_log_perr(ci, "Failed loading process module");
268  return -1;
269  }
270  if (unlikely(module_instance_conf_parse(mi, mi->conf) < 0)) goto error;
271 
272  process = (fr_process_module_t const *)mi->module->exported;
273  if (!*(process->dict)) {
274  cf_log_err(ci, "Process module is invalid - missing namespace dictionary");
275  talloc_free(mi);
276  return -1;
277  }
278  cf_data_add(server_cs, mi, "process_module", false);
279  cf_data_add(server_cs, *(process->dict), "dict", false);
280 
281  return 0;
282 }
283 
284 /** Callback when a "server" section is created.
285  *
286  * This callback exists only as a place-holder to ensure that the
287  * listen_on_read function is called. The conf file routines won't
288  * recurse into every conf_parser_t section to check if there's an
289  * "on_read" callback. So this place-holder is a signal.
290  *
291  * @param[in] ctx to allocate data in.
292  * @param[out] out Unused
293  * @param[in] parent Base structure address.
294  * @param[in] ci #CONF_SECTION containing the server section.
295  * @param[in] rule unused.
296  * @return
297  * - 0 on success.
298  * - -1 on failure.
299  */
300 static int server_on_read(UNUSED TALLOC_CTX *ctx, UNUSED void *out, UNUSED void *parent,
301  UNUSED CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
302 {
303  return 0;
304 }
305 
306 static inline CC_HINT(always_inline)
308 {
309  int i;
311 
312  if (!compile_list) return 0;
313 
314  for (i = 0; list[i].section; i++) {
315 #ifndef NDEBUG
316  /*
317  * We can't have a wildcard for name1. It MUST be a real name.
318  *
319  * The wildcard was allowed previously for ideas which later didn't turn out.
320  */
321  if (list[i].section->name1 == CF_IDENT_ANY) {
322  fr_assert(0);
323  continue;
324  }
325 
326 #endif
327  if (virtual_server_section_register(vs, &list[i]) < 0) {
328  cf_log_err(cs, "Failed registering processing section name %s for %s",
329  list[i].section->name1, name);
330  return -1;
331  }
332  }
333 
334  return 0;
335 }
336 
337 /** dl_open a process_* module
338  *
339  * @param[in] ctx to allocate data in.
340  * @param[out] out Where to our listen configuration. Is a #fr_virtual_listen_t structure.
341  * @param[in] parent Base structure address.
342  * @param[in] ci #CONF_SECTION containing the listen section.
343  * @param[in] rule unused.
344  * @return
345  * - 0 on success.
346  * - -1 on failure.
347  */
348 static int namespace_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
349 {
350  CONF_PAIR *cp = cf_item_to_pair(ci);
351  CONF_SECTION *server_cs = cf_item_to_section(cf_parent(ci));
352  CONF_SECTION *process_cs;
353  virtual_server_t *server = talloc_get_type_abort(((uint8_t *) out) - offsetof(virtual_server_t, process_mi), virtual_server_t);
354  char const *namespace = cf_pair_value(cp);
355  module_instance_t *mi = cf_data_value(cf_data_find(server_cs, module_instance_t, "process_module"));
356 
357  /*
358  * We don't have access to virtual_server_t
359  * in the onread callback, so we need to do the
360  * fixups here.
361  */
362  server->process_mi = mi;
363  server->process_module = (fr_process_module_t const *)mi->module->exported;
364 
365  *(module_instance_t const **)out = mi;
366 
367  /*
368  * Enforce that the protocol process configuration is in
369  * a subsection named for the protocol.
370  */
371  process_cs = cf_section_find(server_cs, namespace, NULL);
372  if (!process_cs) {
373  process_cs = cf_section_alloc(server_cs, server_cs, namespace, NULL);
374  }
375 
376  if (module_instance_conf_parse(mi, process_cs) < 0) {
377  cf_log_perr(ci, "Failed bootstrapping process module");
378  cf_data_remove(server_cs, module_instance_t, "process_module");
379  cf_data_remove(server_cs, fr_dict_t, "dict");
380  TALLOC_FREE(server->process_mi);
381  return -1;
382  }
383 
384  /*
385  * Pull the list of sections we need to compile out of
386  * the process module's public struct.
387  */
388  add_compile_list(server, server->process_mi->conf, server->process_module->compile_list, namespace);
389 
390  return 0;
391 }
392 
393 /** dl_open a proto_* module
394  *
395  * @param[in] ctx to allocate data in.
396  * @param[out] out Where to our listen configuration. Is a #fr_virtual_listen_t structure.
397  * @param[in] parent Base structure address.
398  * @param[in] ci #CONF_SECTION containing the listen section.
399  * @param[in] rule unused.
400  * @return
401  * - 0 on success.
402  * - -1 on failure.
403  */
404 static int listen_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
405 {
406  fr_virtual_listen_t *listener = talloc_get_type_abort(out, fr_virtual_listen_t); /* Pre-allocated for us */
407  CONF_SECTION *listener_cs = cf_item_to_section(ci);
408  CONF_SECTION *server_cs = cf_item_to_section(cf_parent(ci));
409  CONF_PAIR *namespace = cf_pair_find(server_cs, "namespace");
410 
411  CONF_PAIR *proto;
412  char const *mod_name;
413  char const *inst_name;
414  char *qual_inst_name;
415 
416  module_instance_t *mi;
417 
419  "virtual_servers_init MUST be called before reading virtual server config");
420 
421  if (!namespace) {
422  cf_log_err(server_cs, "No 'namespace' set for virtual server");
423  cf_log_err(server_cs, "Please add 'namespace = <protocol>' inside of the 'server %s { ... }' section",
424  cf_section_name2(server_cs));
425  return -1;
426  }
427 
428  /*
429  * Module name comes from the 'proto' pair if the
430  * listen section has one else it comes from the
431  * namespace of the virtual server.
432  *
433  * The following results in proto_radius being loaded:
434  *
435  * server foo {
436  * namespace = radius
437  * listen {
438  *
439  * }
440  * }
441  *
442  * The following results in proto_load being loaded:
443  *
444  * server foo {
445  * namespace = radius
446  * listen {
447  * proto = load
448  *
449  * }
450  * }
451  *
452  * In this way the server behaves reasonably out
453  * of the box, but allows foreign or generic listeners
454  * to be included in the server.
455  *
456  */
457  proto = cf_pair_find(listener_cs, "proto");
458  if (proto) {
460  } else {
461  mod_name = cf_pair_value(namespace);
462  }
463 
464  /*
465  * Inst name comes from the 'listen' name2
466  * or from the module name.
467  *
468  * The inst name is qualified with the name
469  * of the server the listener appears in.
470  *
471  * The following results in the instance name of 'foo.radius':
472  *
473  * server foo {
474  * namespace = radius
475  * listen {
476  *
477  * }
478  * }
479  *
480  * The following results in the instance name 'foo.my_network':
481  *
482  * server foo {
483  * namespace = radius
484  * listen my_network {
485  *
486  * }
487  * }
488  */
489  inst_name = cf_section_name2(listener_cs);
490  if (!inst_name) inst_name = mod_name;
491 
492  if (module_instance_name_valid(inst_name) < 0) {
493  error:
494  cf_log_err(listener_cs, "Failed loading listener");
495  return -1;
496  }
497 
498  MEM(qual_inst_name = talloc_asprintf(NULL, "%s.%s", cf_section_name2(server_cs), inst_name));
499  mi = module_instance_alloc(proto_modules, NULL, DL_MODULE_TYPE_PROTO, mod_name, qual_inst_name, 0);
500  talloc_free(qual_inst_name);
501  if (!mi) goto error;
502 
503  if (unlikely(module_instance_conf_parse(mi, listener_cs) < 0)) goto error;
504 
505  if (DEBUG_ENABLED4) cf_log_debug(ci, "Loading %s listener into %p", inst_name, out);
506 
507  listener->proto_mi = mi;
508  listener->proto_module = (fr_app_t const *)listener->proto_mi->module->exported;
509  cf_data_add(listener_cs, mi, "proto_module", false);
510 
511  return 0;
512 }
513 
514 static int8_t virtual_server_compile_name_cmp(void const *a, void const *b)
515 {
516  virtual_server_compile_t const *sa = a;
517  virtual_server_compile_t const *sb = b;
518 
519  return section_name_cmp(sa->section, sb->section);
520 }
521 
522 /** Callback to validate the server section
523  *
524  * @param[in] ctx to allocate data in.
525  * @param[out] out Where to our listen configuration. Is a #virtual_server_t structure.
526  * @param[in] parent Base structure address.
527  * @param[in] ci #CONF_SECTION containing the listen section.
528  * @param[in] rule unused.
529  * @return
530  * - 0 on success.
531  * - -1 on failure.
532  */
533 static int server_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
534  CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
535 {
536  virtual_server_t *server = talloc_get_type_abort(out, virtual_server_t);
537  CONF_SECTION *server_cs = cf_item_to_section(ci);
538  CONF_PAIR *namespace;
539 
540  namespace = cf_pair_find(server_cs, "namespace");
541  if (!namespace) {
542  cf_log_err(server_cs, "virtual server %s MUST contain a 'namespace' option",
543  cf_section_name2(server_cs));
544  return -1;
545  }
546 
547  MEM(server->sections = fr_rb_alloc(server, virtual_server_compile_name_cmp, NULL));
548  server->server_cs = server_cs;
549 
550  /*
551  * Now parse the listeners
552  */
553  if (cf_section_parse(out, server, server_cs) < 0) return -1;
554 
555  /*
556  * And cache this struct for later referencing.
557  */
558  cf_data_add(server_cs, server, NULL, false);
559 
560  return 0;
561 }
562 
563 /** Return the namespace for the named virtual server
564  *
565  * @param[in] virtual_server to look for namespace in.
566  * @return
567  * - NULL on error.
568  * - Namespace on success.
569  */
570 fr_dict_t const *virtual_server_dict_by_name(char const *virtual_server)
571 {
572  virtual_server_t const *vs;
573 
574  vs = virtual_server_find(virtual_server);
575  if (!vs) return NULL;
576 
578 }
579 
580 /** Return the namespace for the virtual server specified by a config section
581  *
582  * @param[in] server_cs to look for namespace in.
583  * @return
584  * - NULL on error.
585  * - Namespace on success.
586  */
588 {
589  CONF_DATA const *cd;
590  fr_dict_t *dict;
591 
592  cd = cf_data_find(server_cs, fr_dict_t, "dict");
593  if (!cd) return NULL;
594 
595  dict = cf_data_value(cd);
596  (void) talloc_get_type_abort(dict, fr_dict_t);
597 
598  return dict;
599 }
600 
601 /** Return the namespace for a given virtual server specified by a CONF_ITEM within the virtual server
602  *
603  * @param[in] ci to look for namespace in.
604  * @return
605  * - NULL on error.
606  * - Namespace on success.
607  */
609 {
610  CONF_DATA const *cd;
611  fr_dict_t *dict;
612 
613  cd = cf_data_find_in_parent(ci, fr_dict_t, "dict");
614  if (!cd) return NULL;
615 
616  dict = cf_data_value(cd);
617  (void) talloc_get_type_abort(dict, fr_dict_t);
618 
619  return dict;
620 }
621 
622 /** Verify that a given virtual_server exists and is of a particular namespace
623  *
624  * Mostly used by modules to check virtual servers specified by their configs.
625  *
626  * @param[out] out we found. May be NULL if just checking for existence.
627  * @param[in] virtual_server to check.
628  * @param[in] namespace the virtual server must belong to.
629  * @param[in] ci to log errors against. May be NULL if caller
630  * doesn't want errors logged.
631  * @return
632  * - 0 on success.
633  * - -1 if no virtual server could be found.
634  * - -2 if virtual server is not of the correct namespace.
635  */
637  char const *virtual_server, fr_dict_t const *namespace, CONF_ITEM *ci)
638 {
639  virtual_server_t const *vs;
640  CONF_SECTION *server_cs;
641  fr_dict_t const *dict;
642 
643  if (out) *out = NULL;
644 
645  vs = virtual_server_find(virtual_server);
646  if (!vs) {
647  if (ci) cf_log_err(ci, "Can't find virtual server \"%s\"", virtual_server);
648  return -1;
649  }
650  server_cs = virtual_server_cs(vs);
651 
652  dict = virtual_server_dict_by_name(virtual_server);
653  if (!dict) {
654  /*
655  * Not sure this is even a valid state?
656  */
657  if (ci) cf_log_err(ci, "No namespace found in virtual server \"%s\"", virtual_server);
658  return -2;
659  }
660 
661  if (dict != namespace) {
662  if (ci) {
663  cf_log_err(ci,
664  "Expected virtual server \"%s\" to be of namespace \"%s\", got namespace \"%s\"",
665  virtual_server, fr_dict_root(namespace)->name, fr_dict_root(dict)->name);
666  }
667  return -2;
668  }
669 
670  if (out) *out = server_cs;
671 
672  return 0;
673 }
674 
675 /*
676  * If we pushed a log destination, we need to pop it/
677  */
679  request_t *request, void *uctx)
680 {
681  virtual_server_t *server = uctx;
682 
683  request_log_prepend(request, server->log, L_DBG_LVL_DISABLE);
684 
686 }
687 
689 {
690  virtual_server_t *server = uctx;
691 
692  request_log_prepend(request, server->log, L_DBG_LVL_DISABLE);
693 }
694 
695 /** Set the request processing function.
696  *
697  * Short-term hack
698  */
699 unlang_action_t virtual_server_push(request_t *request, CONF_SECTION *server_cs, bool top_frame)
700 {
701  virtual_server_t *server;
702 
703  server = cf_data_value(cf_data_find(server_cs, virtual_server_t, NULL));
704  if (!server) {
705  cf_log_err(server_cs, "server_cs does not contain virtual server data");
706  return UNLANG_ACTION_FAIL;
707  }
708 
709  /*
710  * Add a log destination specific to this virtual server.
711  *
712  * If we add a log destination, make sure to remove it when we walk back up the stack.
713  * But ONLY if we're not at the top of the stack.
714  *
715  * When a brand new request comes in, it has a "call" frame pushed, and then this function is
716  * called. So if we're at the top of the stack, we don't need to pop any logging function,
717  * because the request will die immediately after the top "call" frame is popped.
718  *
719  * However, if we're being reached from a "call" frame in the middle of the stack, then
720  * we do have to pop the log destination when we return.
721  */
722  if (server->log) {
723  request_log_prepend(request, server->log, fr_debug_lvl);
724 
725  if (unlang_interpret_stack_depth(request) > 1) {
726  unlang_action_t action;
727 
728  action = unlang_function_push(request, NULL, /* don't call it immediately */
729  server_remove_log_destination, /* but when we pop the frame */
730  server_signal_remove_log_destination, FR_SIGNAL_CANCEL,
731  top_frame, server);
732  if (action != UNLANG_ACTION_PUSHED_CHILD) return action;
733 
734  /*
735  * The pushed function may be a top frame, but the virtual server
736  * we're about to push is now definitely a sub frame.
737  */
738  top_frame = UNLANG_SUB_FRAME;
739  }
740  }
741 
742  /*
743  * Bootstrap the stack with a module instance.
744  */
745  if (unlang_module_push(&request->rcode, request, server->process_mi,
746  server->process_module->process, top_frame) < 0) return UNLANG_ACTION_FAIL;
747 
749 }
750 
751 static int cmd_show_server_list(FILE *fp, UNUSED FILE *fp_err, UNUSED void *ctx, UNUSED fr_cmd_info_t const *info)
752 {
753  size_t i, server_cnt = virtual_servers ? talloc_array_length(virtual_servers) : 0;
754 
755  if (!server_cnt) return 0;
756 
757  for (i = 0; i < server_cnt; i++) {
758  fprintf(fp, "%-30snamespace = %s\n", cf_section_name2(virtual_servers[i]->server_cs),
759  fr_dict_root(*(virtual_servers[i]->process_module->dict))->name);
760  }
761 
762  return 0;
763 }
764 
766  {
767  .parent = "show",
768  .name = "server",
769  .help = "Show virtual server settings.",
770  .read_only = true,
771  },
772 
773  {
774  .parent = "show server",
775  .name = "list",
776  .func = cmd_show_server_list,
777  .help = "Show the list of virtual servers loaded in the server.",
778  .read_only = true,
779  },
780 
782 
783 };
784 
785 /** Compare listeners by app_io_addr
786  *
787  * Only works for IP addresses, and will blow up on file names
788  */
789 static int8_t listen_addr_cmp(void const *one, void const *two)
790 {
791  fr_listen_t const *a = one;
792  fr_listen_t const *b = two;
793  fr_ipaddr_t aip, bip;
794  int ret;
795 
796  /*
797  * The caller must ensure that the address field is set.
798  */
799  if (!a->app_io_addr && !b->app_io_addr) return 0;
800  if (!a->app_io_addr && b->app_io_addr) return -1;
801  if (a->app_io_addr && !b->app_io_addr) return +1;
802 
803  /*
804  * Address family
805  */
806  CMP_RETURN(a, b, app_io_addr->af);
807 
808  fr_assert((a->app_io_addr->af == AF_INET) || ((a->app_io_addr->af == AF_INET6)));
809 
810  /*
811  * UDP vs TCP
812  */
813  CMP_RETURN(a, b, app_io_addr->type);
814 
815  /*
816  * Check ports.
817  */
818  CMP_RETURN(a, b, app_io_addr->inet.src_port);
819 
820  /*
821  * Don't call fr_ipaddr_cmp(), as we need to do our own
822  * checks here. We have various wildcard checks which
823  * aren't globally applicable.
824  */
825 
826  /*
827  * Different address families.
828  */
829  CMP_RETURN(a, b, app_io_addr->inet.src_ipaddr.af);
830 
831  /*
832  * If both are bound to interfaces, AND the interfaces
833  * are different, then there is no conflict.
834  */
835  if (a->app_io_addr->inet.src_ipaddr.scope_id && b->app_io_addr->inet.src_ipaddr.scope_id) {
836  CMP_RETURN(a, b, app_io_addr->inet.src_ipaddr.scope_id);
837  }
838 
839  ret = a->app_io_addr->inet.src_ipaddr.prefix - b->app_io_addr->inet.src_ipaddr.prefix;
840  aip = a->app_io_addr->inet.src_ipaddr;
841  bip = b->app_io_addr->inet.src_ipaddr;
842 
843  /*
844  * Mask out the longer prefix to match the shorter
845  * prefix.
846  */
847  if (ret < 0) {
848  fr_ipaddr_mask(&bip, a->app_io_addr->inet.src_ipaddr.prefix);
849 
850  } else if (ret > 0) {
851  fr_ipaddr_mask(&aip, b->app_io_addr->inet.src_ipaddr.prefix);
852 
853  }
854 
855  return fr_ipaddr_cmp(&aip, &bip);
856 }
857 
858 /** See if another global listener is using a particular IP / port
859  *
860  */
862 {
863  if (!listen_addr_root) return false;
864 
865  return fr_rb_find(listen_addr_root, li);
866 }
867 
868 
869 /** Record that we're listening on a particular IP / port
870  *
871  */
873 {
874  if (!listen_addr_root) return false;
875 
876  if (!li->app_io_addr) return true;
877 
878  if (listen_find_any(li) != NULL) return false;
879 
880  return fr_rb_insert(listen_addr_root, li);
881 }
882 
883 /** Return the configuration section for a virtual server
884  *
885  * @param[in] vs to return conf section for
886  * @return
887  * - The CONF_SECTION of the virtual server.
888  */
890 {
891  return vs->server_cs;
892 }
893 
894 /** Return virtual server matching the specified name
895  *
896  * @note May be called in bootstrap or instantiate as all servers should be present.
897  *
898  * @param[in] name of virtual server.
899  * @return
900  * - NULL if no virtual server was found.
901  * - The CONF_SECTION of the named virtual server.
902  */
904 {
905  CONF_SECTION *server_cs = cf_section_find(virtual_server_root, "server", name);
906  CONF_DATA const *cd;
907 
908  if (unlikely(server_cs == NULL)) return NULL;
909 
910  cd = cf_data_find(server_cs, virtual_server_t, NULL);
911  if (unlikely(cd == NULL)) return NULL;
912 
913  return cf_data_value(cd);
914 }
915 
916 /** Find a virtual server using one of its sections
917  *
918  * @param[in] ci to find parent virtual server for.
919  * @return
920  * - The virtual server section on success.
921  * - NULL if the child isn't associated with any virtual server section.
922  */
924 {
925  CONF_SECTION *cs;
926  CONF_DATA const *cd;
927 
928  cs = cf_section_find_parent(ci, "server", CF_IDENT_ANY);
929  if (unlikely(!cs)) {
930  cf_log_err(ci, "Child section is not associated with a virtual server");
931  return NULL;
932  }
933 
934  cd = cf_data_find(cs, virtual_server_t, NULL);
935  if (unlikely(!cd)) {
936  cf_log_err(ci, "Virtual server section missing virtual_server_t data");
937  return NULL;
938  }
939 
940  return cf_data_value(cd);
941 }
942 
943 /** Wrapper for the config parser to allow pass1 resolution of virtual servers
944  *
945  */
946 int virtual_server_cf_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
947  CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
948 {
949  virtual_server_t const *vs;
950 
952  if (!vs) {
953  cf_log_err(ci, "virtual-server \"%s\" not found", cf_pair_value(cf_item_to_pair(ci)));
954  return -1;
955  }
956 
957  *((CONF_SECTION **)out) = vs->server_cs;
958 
959  return 0;
960 }
961 
962 /** Compile sections for a virtual server.
963  *
964  * When the "proto_foo" module calls fr_app_process_instantiate(), it
965  * loads the compile list from the #fr_app_worker_t, and calls this
966  * function.
967  *
968  * This function walks down the registration table, compiling each
969  * named section.
970  *
971  * @param[in] vs to to compile sections for.
972  * @param[in] rules to apply for pass1.
973  */
975 {
977  void *instance = vs->process_mi->data;
978  CONF_SECTION *server = vs->server_cs;
979  int i, found;
980  CONF_SECTION *subcs = NULL;
981 
982  found = 0;
983 
984  /*
985  * The sections are in trees, so this isn't as bad as it
986  * looks. It's not O(n^2), but O(n logn). But it could
987  * still be improved.
988  */
989  for (i = 0; list[i].section; i++) {
990  int rcode;
991  CONF_SECTION *bad;
992 
993  /*
994  * We are looking for a specific subsection.
995  * Warn if it isn't found, or compile it if
996  * found.
997  */
998  if (list[i].section->name2 != CF_IDENT_ANY) {
999  void *instruction = NULL;
1000 
1001  subcs = cf_section_find(server, list[i].section->name1, list[i].section->name2);
1002  if (!subcs) {
1003  DEBUG3("Warning: Skipping %s %s { ... } as it was not found.",
1004  list[i].section->name1, list[i].section->name2);
1005  /*
1006  * Initialise CONF_SECTION pointer for missing section
1007  */
1008  if ((instance) && !list[i].dont_cache) {
1009  *(CONF_SECTION **) (((uint8_t *) instance) + list[i].offset) = NULL;
1010  }
1011  continue;
1012  }
1013 
1014  /*
1015  * Duplicate sections are forbidden.
1016  */
1017  bad = cf_section_find_next(server, subcs, list[i].section->name1, list[i].section->name2);
1018  if (bad) {
1019  forbidden:
1020  cf_log_err(bad, "Duplicate sections are forbidden.");
1021  cf_log_err(subcs, "Previous definition occurs here.");
1022  return -1;
1023  }
1024 
1025  rcode = unlang_compile(vs, subcs, list[i].actions, rules, &instruction);
1026  if (rcode < 0) return -1;
1027 
1028  /*
1029  * Cache the CONF_SECTION which was found.
1030  */
1031  if (instance) {
1032  if (!list[i].dont_cache) {
1033  *(CONF_SECTION **) (((uint8_t *) instance) + list[i].offset) = subcs;
1034  }
1035  if (list[i].instruction > 0) {
1036  *(void **) (((uint8_t *) instance) + list[i].instruction) = instruction;
1037  }
1038  }
1039 
1040  found++;
1041  continue;
1042  }
1043 
1044  /*
1045  * Reset this so that we start from the beginning
1046  * again, instead of starting from the last "send
1047  * foo" block.
1048  */
1049  subcs = NULL;
1050 
1051  /*
1052  * Find all subsections with the given first name
1053  * and compile them.
1054  */
1055  while ((subcs = cf_section_find_next(server, subcs, list[i].section->name1, CF_IDENT_ANY))) {
1056  char const *name2;
1057 
1058  name2 = cf_section_name2(subcs);
1059  if (!name2) {
1060  cf_log_err(subcs, "Invalid '%s { ... }' section, it must have a name", list[i].section->name1);
1061  return -1;
1062  }
1063 
1064  /*
1065  * Duplicate sections are forbidden.
1066  */
1067  bad = cf_section_find_next(server, subcs, list[i].section->name1, name2);
1068  if (bad) goto forbidden;
1069 
1070  rcode = unlang_compile(vs, subcs, list[i].actions, rules, NULL);
1071  if (rcode < 0) return -1;
1072 
1073  /*
1074  * Note that we don't store the
1075  * CONF_SECTION here, as it's a wildcard.
1076  *
1077  * @todo - count number of subsections
1078  * and store them in an array?
1079  */
1080  found++;
1081  }
1082  }
1083 
1084  return found;
1085 }
1086 
1087 /** Register name1 / name2 as allowed processing sections
1088  *
1089  * This function is called from the virtual server bootstrap routine,
1090  * which happens before module_bootstrap();
1091  */
1093 {
1095 
1096  old = fr_rb_find(vs->sections, entry);
1097  if (old) return 0;
1098 
1099 #ifndef NDEBUG
1100  /*
1101  * Catch stupid programmers.
1102  *
1103  * Processing sections can't allow "*" for module
1104  * methods, because otherwise you would be allowed to run
1105  * DHCP things in a RADIUS accounting section. And that
1106  * would be bad.
1107  */
1108  if (entry->methods) {
1109  int i;
1110 
1111  for (i = 0; entry->methods[i]; i++) {
1112  if (entry->methods[i]->name1 == CF_IDENT_ANY) {
1113  ERROR("Processing sections cannot allow \"*\"");
1114  return -1;
1115  }
1116 
1117  if (entry->methods[i]->name2 == CF_IDENT_ANY) {
1118  ERROR("Processing sections cannot allow \"%s *\"",
1119  entry->methods[i]->name1);
1120  return -1;
1121  }
1122  }
1123  }
1124 #endif
1125 
1126  if (!fr_rb_insert(vs->sections, entry)) {
1127  fr_strerror_const("Failed inserting entry into internal tree");
1128  return -1;
1129  }
1130 
1131  return 0;
1132 }
1133 
1134 /** Find the component for a section
1135  *
1136  */
1138 {
1139  virtual_server_compile_t *entry;
1140 
1141  /*
1142  * Look up the specific name first. That way we can
1143  * define both "accounting on", and "accounting *".
1144  */
1145  if (section->name2 != CF_IDENT_ANY) {
1146  entry = fr_rb_find(vs->sections,
1148  .section = section
1149  });
1150  if (entry) return entry->methods;
1151  }
1152 
1153  /*
1154  * Then look up the wildcard, if we didn't find any matching name2.
1155  */
1156  entry = fr_rb_find(vs->sections,
1158  .section = SECTION_NAME(section->name1, CF_IDENT_ANY)
1159  });
1160  if (!entry) return NULL;
1161 
1162  return entry->methods;
1163 }
1164 
1165 /** Define a values for Auth-Type attributes by the sections present in a virtual-server
1166  *
1167  * The.name2 value of any sections found will be converted into values of the specified da.
1168  *
1169  * @param[in] server_cs The virtual server containing the sections.
1170  * @param[in] subcs_name of the subsection to search for.
1171  * @param[in] da to add enumeration values for.
1172  * @return
1173  * - 0 all values added successfully.
1174  * - -1 an error occurred.
1175  */
1176 int virtual_server_section_attribute_define(CONF_SECTION *server_cs, char const *subcs_name, fr_dict_attr_t const *da)
1177 {
1178  int rcode = 0;
1179  CONF_SECTION *subcs = NULL;
1180 
1181  fr_assert(strcmp(cf_section_name1(server_cs), "server") == 0);
1182 
1183  while ((subcs = cf_section_find_next(server_cs, subcs, subcs_name, CF_IDENT_ANY))) {
1184  char const *name2;
1186 
1187  name2 = cf_section_name2(subcs);
1188  if (!name2) {
1189  cf_log_err(subcs, "Invalid '%s { ... }' section, it must have a name", subcs_name);
1190  return -1;
1191  }
1192 
1193  /*
1194  * If the value already exists, don't
1195  * create it again.
1196  */
1197  dv = fr_dict_enum_by_name(da, name2, -1);
1198  if (dv) continue;
1199 
1200  cf_log_debug(subcs, "Creating %s = %s", da->name, name2);
1201 
1202  /*
1203  * Create a new unique value with a meaningless
1204  * number. You can't look at it from outside of
1205  * this code, so it doesn't matter. The only
1206  * requirement is that it's unique.
1207  */
1208  if (fr_dict_enum_add_name_next(fr_dict_attr_unconst(da), name2) < 0) {
1209  PERROR("Failed adding section value");
1210  return -1;
1211  }
1212 
1213  rcode = 1;
1214  }
1215 
1216  return rcode;
1217 }
1218 
1220 {
1221  char const *ref;
1222  fr_dict_attr_t const *da;
1223  CONF_ITEM *ci = NULL;
1224 
1225  ref = cf_section_name2(cs);
1226  if (!ref) {
1227  cf_log_err(cs, "Expected 'values <name> { ... }'");
1228  return -1;
1229  }
1230 
1231  da = fr_dict_attr_by_name(NULL, parent, ref);
1232  if (!da) {
1233  cf_log_err(cs, "No such attribute \"%s\"", ref);
1234  return -1;
1235  }
1236 
1237  if (fr_type_is_structural(da->type)) {
1238  cf_log_err(cs, "Cannot define value for structural attribute \"%s\"", ref);
1239  return -1;
1240  }
1241 
1242  /*
1243  * This both does not make any sense, and does not get
1244  * parsed correctly if the string contains backslashes.
1245  */
1246  if (da->type == FR_TYPE_STRING) {
1247  cf_log_err(cs, "Cannot define value for 'string' attribute \"%s\"", ref);
1248  return -1;
1249  }
1250 
1251  while ((ci = cf_item_next(cs, ci))) {
1252  ssize_t slen, len;
1253  char const *attr, *value;
1254  CONF_PAIR *cp;
1256  fr_value_box_t box;
1257 
1258  if (cf_item_is_section(ci)) {
1259  cf_log_err(ci, "Unexpected subsection");
1260  return -1;
1261  }
1262 
1263  if (!cf_item_is_pair(ci)) continue;
1264 
1265  cp = cf_item_to_pair(ci);
1266  fr_assert(cp != NULL);
1267 
1268  /*
1269  * =* is a hack by the cf parser to say "no operator"
1270  */
1271  if ((cf_pair_operator(cp) != T_OP_EQ) ||
1272  (cf_pair_attr_quote(cp) != T_BARE_WORD)) {
1273  cf_log_err(ci, "Definition is not in 'name = value' format");
1274  return -1;
1275  }
1276 
1277  attr = cf_pair_attr(cp);
1278  value = cf_pair_value(cp);
1279 
1280  dv = fr_dict_enum_by_name(parent, attr, talloc_array_length(attr) - 1);
1281  if (dv) {
1282  cf_log_err(cp, "Duplicate value name");
1283  return -1;
1284  }
1285 
1286  fr_value_box_init_null(&box);
1287 
1288  len = talloc_array_length(value) - 1;
1289 
1290  /*
1291  * @todo - unescape for double quoted strings. Whoops.
1292  */
1293  slen = fr_value_box_from_str(NULL, &box, da->type, da, value, len, NULL, false);
1294  if (slen < 0) {
1295  cf_log_err(cp, "Failed parsing value - %s", fr_strerror());
1296  return -1;
1297  }
1298 
1299  if (slen != len) {
1300  cf_log_err(cp, "Unexpected text after value");
1301  return -1;
1302  }
1303 
1304  if (fr_dict_enum_add_name(UNCONST(fr_dict_attr_t *, da), attr, &box, false, false) < 0) {
1305  cf_log_err(cp, "Failed adding value - %s", fr_strerror());
1306  return -1;
1307  }
1308 
1309  fr_value_box_clear(&box);
1310  }
1311 
1312  return 0;
1313 }
1314 
1315 
1317 {
1318  CONF_ITEM *ci = NULL;
1319 
1320  fr_dict_attr_flags_t flags = {
1321  .internal = true,
1322  .name_only = true,
1323  .local = true,
1324  };
1325 
1326  fr_assert(dict != NULL);
1327  fr_assert(parent != NULL);
1328 
1329  while ((ci = cf_item_next(cs, ci))) {
1330  fr_type_t type;
1331  char const *attr, *value;
1332  CONF_PAIR *cp;
1333  CONF_SECTION *subcs = NULL;
1334 
1335  if (cf_item_is_section(ci)) {
1336  subcs = cf_item_to_section(ci);
1337  fr_assert(subcs != NULL);
1338 
1339  attr = cf_section_name1(subcs);
1340 
1341  if (strcmp(attr, "values") == 0) {
1342  if (define_server_values(subcs, parent) < 0) return -1;
1343  continue;
1344  }
1345 
1346  if (strcmp(attr, "tlv") != 0) goto invalid_type;
1347 
1348  value = cf_section_name2(subcs);
1349  if (!value) {
1350  cf_log_err(ci, "Definition is not in 'tlv name { ... }' format");
1351  return -1;
1352  }
1353 
1354  type = FR_TYPE_TLV;
1355  goto check_for_dup;
1356  }
1357 
1358  if (!cf_item_is_pair(ci)) continue;
1359 
1360  cp = cf_item_to_pair(ci);
1361  fr_assert(cp != NULL);
1362 
1363  /*
1364  * =* is a hack by the cf parser to say "no operator"
1365  */
1366  if ((cf_pair_operator(cp) != T_OP_CMP_TRUE) ||
1367  (cf_pair_attr_quote(cp) != T_BARE_WORD) ||
1368  (cf_pair_value_quote(cp) != T_BARE_WORD)) {
1369  cf_log_err(ci, "Definition is not in 'type name' format");
1370  return -1;
1371  }
1372 
1373  attr = cf_pair_attr(cp);
1374  value = cf_pair_value(cp);
1375 
1377  if (type == FR_TYPE_NULL) {
1378  invalid_type:
1379  cf_log_err(ci, "Invalid data type '%s'", attr);
1380  return -1;
1381  }
1382 
1383  /*
1384  * Leaf and group are OK. TLV, Vendor, Struct, VSA, etc. are not as variable definitions.
1385  */
1386  if (!(fr_type_is_leaf(type) || (type == FR_TYPE_GROUP))) goto invalid_type;
1387 
1388  /*
1389  * No duplicates are allowed.
1390  */
1391  check_for_dup:
1392  if (root && (fr_dict_attr_by_name(NULL, root, value) != NULL)) {
1393  cf_log_err(ci, "Local variable '%s' duplicates a dictionary attribute.", value);
1394  return -1;
1395  }
1396 
1397  if (fr_dict_attr_by_name(NULL, parent, value) != NULL) {
1398  cf_log_err(ci, "Local variable '%s' duplicates a previous local attribute.", value);
1399  return -1;
1400  }
1401 
1402  if (fr_dict_attr_add_name_only(dict, parent, value, type, &flags) < 0) {
1403  cf_log_err(ci, "Failed adding local variable '%s' - %s", value, fr_strerror());
1404  return -1;
1405  }
1406 
1407  if (type == FR_TYPE_TLV) {
1408  fr_dict_attr_t const *da;
1409 
1410  if (!subcs) return -1; /* shouldn't happen, but shut up compiler */
1411 
1412  da = fr_dict_attr_by_name(NULL, parent, value);
1413  fr_assert(da != NULL);
1414 
1415  if (define_server_attrs(subcs, dict, UNCONST(fr_dict_attr_t *, da), NULL) < 0) return -1;
1416  }
1417  }
1418 
1419  return 0;
1420 }
1421 
1422 static fr_dict_t const *virtual_server_local_dict(CONF_SECTION *server_cs, fr_dict_t const *dict_def)
1423 {
1424  fr_dict_t *dict;
1425  CONF_SECTION *cs;
1426 
1427  cs = cf_section_find(server_cs, "dictionary", NULL);
1428  if (!cs) return dict_def;
1429 
1430  dict = fr_dict_protocol_alloc(dict_def);
1431  if (!dict) {
1432  cf_log_err(cs, "Failed allocating local dictionary");
1433  return NULL;
1434  }
1435 
1436  if (define_server_attrs(cs, dict, UNCONST(fr_dict_attr_t *, fr_dict_root(dict)), fr_dict_root(dict_def)) < 0) return NULL;
1437 
1438  /*
1439  * Replace the original dictionary with the new one.
1440  */
1441  cf_data_remove(server_cs, fr_dict_t, "dict");
1442  cf_data_add(server_cs, dict, "dict", false);
1443 
1444  return dict;
1445 }
1446 
1447 
1448 /** Open all the listen sockets
1449  *
1450  * @param[in] sc Scheduler to add I/O paths to.
1451  * @return
1452  * - 0 on success.
1453  * - -1 on failure.
1454  */
1456 {
1457  size_t i, server_cnt = virtual_servers ? talloc_array_length(virtual_servers) : 0;
1458 
1460 
1461  DEBUG2("#### Opening listener interfaces ####");
1463 
1464  for (i = 0; i < server_cnt; i++) {
1465  fr_virtual_listen_t **listeners;
1466  size_t j, listener_cnt;
1467 
1468  listeners = virtual_servers[i]->listeners;
1469  listener_cnt = talloc_array_length(listeners);
1470 
1471  for (j = 0; j < listener_cnt; j++) {
1472  fr_virtual_listen_t *listener = listeners[j];
1473 
1474  fr_assert(listener != NULL);
1475  fr_assert(listener->proto_mi != NULL);
1476  fr_assert(listener->proto_module != NULL);
1477 
1478  /*
1479  * The socket is opened with app_instance,
1480  * but all subsequent calls (network.c, etc.) use app_io_instance.
1481  *
1482  * The reason is that we call (for example) proto_radius to
1483  * open the socket, and proto_radius is responsible for setting up
1484  * proto_radius_udp, and then calling proto_radius_udp->open.
1485  *
1486  * Even then, proto_radius usually calls fr_master_io_listen() in order
1487  * to create the fr_listen_t structure.
1488  */
1489  if (listener->proto_module->open) {
1490  int ret;
1491 
1492  /*
1493  * Sometimes the open function needs to modify instance
1494  * data, so we need to temporarily remove the protection.
1495  */
1497  ret = listener->proto_module->open(listener->proto_mi->data, sc,
1498  listener->proto_mi->conf);
1500  if (unlikely(ret < 0)) {
1501  cf_log_err(listener->proto_mi->conf,
1502  "Opening %s I/O interface failed",
1503  listener->proto_module->common.name);
1504 
1505  return -1;
1506  }
1507 
1508  }
1509 
1510  /*
1511  * Socket information is printed out by
1512  * the socket handlers. e.g. proto_radius_udp
1513  */
1514  DEBUG3("Opened listener for %s", listener->proto_module->common.name);
1515  }
1516  }
1517 
1518  return 0;
1519 }
1520 
1521 /** Free thread-specific data for all process modules and listeners
1522  *
1523  */
1525 {
1528 }
1529 
1530 /** Perform thread instantiation for all process modules and listeners
1531  *
1532  */
1534 {
1535  if (modules_thread_instantiate(ctx, process_modules, el) < 0) return -1;
1536  if (modules_thread_instantiate(ctx, proto_modules, el) < 0) {
1538  return -1;
1539  }
1540  return 0;
1541 }
1542 
1543 /** Instantiate all the virtual servers
1544  *
1545  * @return
1546  * - 0 on success.
1547  * - -1 on failure.
1548  */
1550 {
1551  size_t i, server_cnt;
1552 
1553  /*
1554  * User didn't specify any "server" sections
1555  */
1556  if (unlikely(!virtual_servers)) {
1557  ERROR("No virtual servers configured");
1558  return -1;
1559  }
1560 
1561  server_cnt = talloc_array_length(virtual_servers);
1562 
1563  DEBUG2("#### Instantiating listeners ####");
1564 
1565  if (fr_command_register_hook(NULL, NULL, virtual_server_root, cmd_table) < 0) {
1566  PERROR("Failed registering radmin commands for virtual servers");
1567  return -1;
1568  }
1569 
1570  for (i = 0; i < server_cnt; i++) {
1571  CONF_ITEM *ci = NULL;
1572  CONF_SECTION *server_cs = virtual_servers[i]->server_cs;
1573  fr_dict_t const *dict;
1575  fr_process_module_t const *process = (fr_process_module_t const *)
1576  vs->process_mi->module->exported;
1577 
1578  /*
1579  * Set up logging before doing anything else.
1580  */
1581  if (vs->log_name) {
1582  vs->log = log_dst_by_name(vs->log_name);
1583  if (!vs->log) {
1584  CONF_PAIR *cp = cf_pair_find(server_cs, "log");
1585 
1586  if (cp) {
1587  cf_log_err(cp, "Unknown log destination '%s'", vs->log_name);
1588  } else {
1589  cf_log_err(server_cs, "Unknown log destination '%s'", vs->log_name);
1590  }
1591 
1592  return -1;
1593  }
1594  }
1595 
1596  dict = virtual_server_local_dict(server_cs, *(process)->dict);
1597  if (!dict) return -1;
1598 
1599  DEBUG("Compiling policies in server %s { ... }", cf_section_name2(server_cs));
1600 
1601  fr_assert(virtual_servers[i]->process_mi);
1602 
1603  /*
1604  * Compile the processing sections indicated by
1605  * the process module. This must be done before
1606  * module_instantiate is called, as the instance
1607  * data is protected after this call.
1608  */
1609  if (process->compile_list) {
1610  tmpl_rules_t parse_rules = {
1611  .attr = {
1612  .dict_def = dict,
1613  .list_def = request_attr_request,
1614  },
1615  };
1616 
1617  fr_assert(parse_rules.attr.dict_def != NULL);
1618 
1619  if (virtual_server_compile_sections(virtual_servers[i], &parse_rules) < 0) {
1620  return -1;
1621  }
1622  }
1623 
1624  /*
1625  * Print out warnings for unused "recv" and
1626  * "send" sections.
1627  *
1628  * @todo - check against the "compile_list"
1629  * registered for this virtual server, instead of hard-coding stuff.
1630  */
1631  while ((ci = cf_item_next(server_cs, ci))) {
1632  char const *name;
1633  CONF_SECTION *subcs;
1634 
1635  if (!cf_item_is_section(ci)) continue;
1636 
1637  subcs = cf_item_to_section(ci);
1638  name = cf_section_name1(subcs);
1639 
1640  /*
1641  * Skip known "other" sections
1642  */
1643  if ((strcmp(name, "listen") == 0) || (strcmp(name, "client") == 0)) continue;
1644 
1645  /*
1646  * For every other section, warn if it hasn't
1647  * been compiled.
1648  */
1649  if (!cf_data_find(subcs, unlang_group_t, NULL)) {
1650  char const *name2;
1651 
1652  name2 = cf_section_name2(subcs);
1653  if (!name2) name2 = "";
1654 
1655  cf_log_warn(subcs, "%s %s { ... } section is unused", name, name2);
1656  }
1657  }
1658  }
1659 
1661  PERROR("Failed instantiating process modules");
1662  return -1;
1663  }
1665  PERROR("Failed instantiating protocol modules");
1666  return -1;
1667  }
1668 
1669  return 0;
1670 }
1671 
1672 /** Load protocol modules and call their bootstrap methods
1673  *
1674  * @param[in] config section containing the virtual servers to bootstrap.
1675  * @return
1676  * - 0 on success.
1677  * - -1 on failure.
1678  */
1680 {
1682 
1683  /*
1684  * Ensure any libraries the modules depend on are instantiated
1685  */
1687 
1689  PERROR("Failed instantiating process modules");
1690  return -1;
1691  }
1692  if (modules_bootstrap(proto_modules) < 0) {
1693  PERROR("Failed instantiating protocol modules");
1694  return -1;
1695  }
1696 
1697  return 0;
1698 }
1699 
1701 {
1702  if (talloc_free(listen_addr_root) < 0) return -1;
1703  listen_addr_root = NULL;
1704  if (talloc_free(process_modules) < 0) return -1;
1705  process_modules = NULL;
1706  if (talloc_free(proto_modules) < 0) return -1;
1707  proto_modules = NULL;
1708  if (fr_dict_autofree(virtual_server_dict_autoload) < 0) return -1;
1709 
1710  return 0;
1711 }
1712 
1714 {
1715  return virtual_servers_free();
1716 }
1717 
1718 /** Performs global initialisation for the virtual server code
1719  *
1720  * This has to be done separately and explicitly, because the above code makes
1721  * use of "onread" callbacks.
1722  *
1723  * Will automatically free module lists on exit, but all modules should have
1724  * been removed from this list by the point that happens.
1725  */
1727 {
1729  PERROR("%s", __FUNCTION__);
1730  return -1;
1731  }
1733  PERROR("%s", __FUNCTION__);
1735  return -1;
1736  }
1737 
1738  MEM(process_modules = module_list_alloc(NULL, &module_list_type_global, "process", true));
1739 
1740  /*
1741  * FIXME - We should be able to turn on write protection,
1742  * but there are too many proto modules that hang things
1743  * off of their instance data.
1744  */
1745  MEM(proto_modules = module_list_alloc(NULL, &module_list_type_global, "protocol", false));
1746  MEM(listen_addr_root = fr_rb_inline_alloc(NULL, fr_listen_t, virtual_server_node, listen_addr_cmp, NULL));
1747 
1748  /*
1749  * Create a list to hold all the proto_* modules
1750  * that get loaded during startup.
1751  */
1753 
1754  return 0;
1755 }
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
static fr_dict_t * dict
Definition: fuzzer.c:46
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition: build.h:165
#define RCSID(id)
Definition: build.h:481
#define CMP_RETURN(_a, _b, _field)
Return if the comparison is not 0 (is unequal)
Definition: build.h:119
#define unlikely(_x)
Definition: build.h:379
#define UNUSED
Definition: build.h:313
static int invalid_type(fr_type_t type)
Definition: calc.c:698
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
Definition: cf_parse.c:985
#define CONF_PARSER_TERMINATOR
Definition: cf_parse.h:627
void const * uctx
User data accessible by the cf_parse_t func.
Definition: cf_parse.h:587
#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:268
char const * name2
Second identifier for CONF_SECTION.
Definition: cf_parse.h:566
#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:310
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition: cf_parse.h:405
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
Definition: cf_parse.h:419
@ CONF_FLAG_OK_MISSING
OK if it's missing.
Definition: cf_parse.h:427
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition: cf_parse.h:399
#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:564
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:632
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition: cf_util.c:664
fr_token_t cf_pair_attr_quote(CONF_PAIR const *pair)
Return the value (lhs) quoting of a pair.
Definition: cf_util.c:1623
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
Definition: cf_util.c:1578
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:1028
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:1439
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition: cf_util.c:1185
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition: cf_util.c:1594
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
Definition: cf_util.c:1763
fr_token_t cf_pair_operator(CONF_PAIR const *pair)
Return the operator of a pair.
Definition: cf_util.c:1608
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition: cf_util.c:684
fr_token_t cf_pair_value_quote(CONF_PAIR const *pair)
Return the value (rhs) quoting of a pair.
Definition: cf_util.c:1638
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:1049
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
Definition: cf_util.c:618
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition: cf_util.c:1171
#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_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_item_next(_ci, _curr)
Definition: cf_util.h:92
#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:5022
fr_dcursor_eval_t void const * uctx
Definition: dcursor.h:546
#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 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:1941
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:1738
fr_dict_attr_t * fr_dict_attr_unconst(fr_dict_attr_t const *da)
Coerce to non-const.
Definition: dict_util.c:4597
#define fr_dict_autofree(_to_free)
Definition: dict.h:850
fr_dict_t * fr_dict_protocol_alloc(fr_dict_t const *parent)
Allocate a new local dictionary.
Definition: dict_util.c:3961
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:3263
unsigned int internal
Internal attribute, should not be received in protocol packets, should not be encoded.
Definition: dict.h:86
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition: dict.h:267
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition: dict.h:280
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition: dict_util.c:2400
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:1953
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:4090
fr_dict_enum_value_t * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Definition: dict_util.c:3395
#define fr_dict_autoload(_to_load)
Definition: dict.h:847
Specifies an attribute which must be present for the module to function.
Definition: dict.h:266
Values of the encryption flags.
Definition: merged_model.c:139
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition: dict.h:279
Value of an enumerated attribute.
Definition: dict.h:226
Test enumeration values.
Definition: dict_test.h:92
dl_module_common_t * exported
Symbol exported by the module, containing its public functions, name and behaviour control flags.
Definition: dl_module.h:128
@ DL_MODULE_TYPE_PROTO
Protocol module.
Definition: dl_module.h:67
@ DL_MODULE_TYPE_PROCESS
protocol processor.
Definition: dl_module.h:68
if(rcode > 0)
Definition: fd_read.h:9
#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:1346
void fr_ipaddr_mask(fr_ipaddr_t *addr, uint8_t prefix)
Zeroes out the host portion of an fr_ipaddr_t.
Definition: inet.c:217
IPv4/6 prefix.
Definition: merged_model.c:272
int unlang_interpret_stack_depth(request_t *request)
Return the depth of the request's stack.
Definition: interpret.c:1275
#define UNLANG_SUB_FRAME
Definition: interpret.h:36
fr_socket_t * app_io_addr
for tracking duplicate sockets
Definition: listen.h:35
fr_log_t * log_dst_by_name(char const *name)
Get a logging destination by name.
Definition: log.c:1074
#define PERROR(_fmt,...)
Definition: log.h:228
#define DEBUG3(_fmt,...)
Definition: log.h:266
#define DEBUG_ENABLED4
True if global debug level 1-3 messages are enabled.
Definition: log.h:260
talloc_free(reap)
Stores all information relating to an event list.
Definition: event.c:411
int fr_debug_lvl
Definition: log.c:43
@ L_DBG_LVL_DISABLE
Don't print messages.
Definition: log.h:68
static char const * mod_name(fr_listen_t *li)
Definition: master.c:2729
fr_type_t
Definition: merged_model.c:80
@ FR_TYPE_TLV
Contains nested attributes.
Definition: merged_model.c:118
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
Definition: merged_model.c:81
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
@ FR_TYPE_VOID
User data.
Definition: merged_model.c:127
@ FR_TYPE_GROUP
A grouping of other attributes.
Definition: merged_model.c:124
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
static const virtual_server_compile_t compile_list[]
Definition: base.c:205
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
Common public symbol definition for all process modules.
Definition: process.h:54
#define DEBUG2(fmt,...)
Definition: radclient.h:43
static char const * proto(int id, int porttype)
Definition: radwho.c:85
#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
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
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
fr_dict_attr_t const * request_attr_request
Definition: request.c:45
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:100
static char const * name
The scheduler.
Definition: schedule.c:125
int8_t section_name_cmp(void const *one, void const *two)
Compare two sections.
Definition: section.c:48
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:329
void * data
Module's instance data.
Definition: module.h:271
dl_module_t * module
Dynamic loader handle.
Definition: module.h:286
Module instance data.
Definition: module.h:265
A list of modules.
Definition: module.h:385
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
Definition: tmpl.h:344
Optional arguments passed to vp_tmpl functions.
Definition: tmpl.h:341
fr_signal_t
Definition: signal.h:48
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:699
void module_list_debug(module_list_t const *ml)
Print the contents of a module list.
Definition: module.c:623
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:735
void modules_thread_detach(module_list_t *ml)
Remove thread-specific data for a given module list.
Definition: module.c:1009
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:1160
int modules_instantiate(module_list_t const *ml)
Completes instantiation of modules.
Definition: module.c:1281
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:957
fr_slen_t module_instance_name_valid(char const *inst_name)
Check to see if a module instance name is valid.
Definition: module.c:1591
int module_instance_data_unprotect(module_instance_t const *mi)
Mark module data as read/write.
Definition: module.c:711
module_list_type_t const module_list_type_global
Callbacks for a global module list.
Definition: module.c:536
int modules_bootstrap(module_list_t const *ml)
Bootstrap any modules which have not been bootstrapped already.
Definition: module.c:1372
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:847
int module_instance_conf_parse(module_instance_t *mi, CONF_SECTION *conf)
Covert a CONF_SECTION into parsed module instance data.
Definition: module.c:764
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:1651
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:1857
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:53
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
fr_aka_sim_id_type_t type
Definition: log.h:96
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
Definition: tmpl.h:285
#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
@ 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.
Definition: unlang_priv.h:145
static fr_slen_t parent
Definition: pair.h:851
int af
AF_INET, AF_INET6, or AF_UNIX.
Definition: socket.h:78
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
Definition: strerror.c:577
char const * fr_strerror(void)
Get the last library error.
Definition: strerror.c:554
#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:371
#define fr_type_is_leaf(_x)
Definition: types.h:372
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, bool tainted)
Definition: value.c:5315
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition: value.c:3723
static fr_slen_t data
Definition: value.h:1265
#define fr_value_box_init_null(_vb)
Initialise an empty/null box that will be filled later.
Definition: value.h:593
static size_t char ** out
Definition: value.h:997
static int server_on_read(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
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.
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.
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.
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[]
static int server_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
CONF_SECTION * server_cs
The server section.
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)
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 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[]
fr_virtual_listen_t ** listeners
Listeners in this virtual server.
static fr_dict_t const * virtual_server_local_dict(CONF_SECTION *server_cs, fr_dict_t const *dict_def)
static int8_t virtual_server_compile_name_cmp(void const *a, void const *b)
static virtual_server_t ** virtual_servers
Top level structure holding all virtual servers.
static fr_dict_attr_t const * attr_auth_type
virtual_server_t const * virtual_server_by_child(CONF_ITEM const *ci)
Find a virtual server using one of its sections.
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.
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 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.
int virtual_server_compile_sections(virtual_server_t const *vs, tmpl_rules_t const *rules)
Compile sections for a virtual server.
static module_list_t * proto_modules
List of proto modules we've loaded.
fr_listen_t * listen_find_any(fr_listen_t *li)
See if another global listener is using a particular IP / port.
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)
fr_dict_t const * virtual_server_dict_by_name(char const *virtual_server)
Return the namespace for the named virtual server.
int virtual_servers_instantiate(void)
Instantiate all the virtual servers.
static void server_signal_remove_log_destination(request_t *request, UNUSED fr_signal_t action, void *uctx)
module_instance_t * virtual_server_listener_by_data(void const *data)
Resolve proto data to a module instance.
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)
module_instance_t * proto_mi
The proto_* module for a listen section.
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)
CONF_SECTION * virtual_server_cs(virtual_server_t const *vs)
Return the configuration section for a virtual server.
static int define_server_values(CONF_SECTION *cs, fr_dict_attr_t *parent)
fr_app_t const * proto_module
Public interface to the proto_mi.
char const * log_name
name of log destination
virtual_server_t const * virtual_server_find(char const *name)
Return virtual server matching the specified name.
struct virtual_server_s virtual_server_t
section_name_t const * section
Identifier for the section.
size_t offset
where the CONF_SECTION pointer is written
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.