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