#if 0
+extern const CONF_PARSER virtual_servers_on_read_config[];
+
/** Callback to automatically load dictionaries required by modules
*
* @param[in] module being loaded.
*/
main_config.talloc_pool_size = 8 * 1024; /* default */
+#if 0
/*
- * @todo - the proto_FOO modules are loaded via the
- * CONF_SECTION parser callbacks. Which means that the
- * fr_dict_autoload() and fr_dict_attr_autoload()
- * functions need to be call from here, before the
- * configuration is parsed. Right now, those rules are
- * added in modules_bootstrap(). At that point, the
- * proto_FOO modules have already been loaded. So any
- * autoload they have is ignored.
+ * @todo - not quite done yet... these dictionaries have
+ * to be loaded from radius_dir. But the
+ * fr_dict_autoload_t has a base_dir pointer
+ * there... it's probably best to pass radius_dir into
+ * fr_dict_autoload() and have it use that instead.
*
- * Except that we ALSO need to load raddb/dictionary,
- * ideally BEFORE instantiating the modules, but AFTER
- * loading the various proto_FOO.
+ * Once that's done, the proto_foo dictionaries SHOULD be
+ * autoloaded, AND loaded before the configuration files
+ * are read.
*
- * This likely means moving the DICT_READ_OPTIONAL stuff
- * to after the "parsing main configuration" stage.
- */
-
- /*
- * Read the distribution dictionaries first, then
- * the ones in raddb.
+ * And then all of the modules have to be updated to use
+ * their local dict pointer, instead of NULL.
*/
-#if 0
- (void) dl_init();
+ if (cf_section_rules_push(cs, virtual_servers_on_read_config) < 0) return -1;
/*
* Register dictionary autoload callbacks
dl_symbol_init_cb_register(DL_DICT_PRIORITY, "dict", _module_dict_autoload, NULL);
dl_symbol_free_cb_register(DL_DICT_PRIORITY, "dict", _module_dict_autofree, NULL);
dl_symbol_init_cb_register(DL_DICT_ATTR_PRIORITY, "dict_attr", _module_dict_attr_autoload, NULL);
-#else
+#endif
+ /*
+ * Read the distribution dictionaries first, then
+ * the ones in raddb.
+ */
DEBUG2("Including dictionary file \"%s/%s\"", main_config.dictionary_dir, FR_DICTIONARY_FILE);
if (fr_dict_from_file(NULL, &main_config.dict, main_config.dictionary_dir, FR_DICTIONARY_FILE, "radius") != 0) {
fr_log_perror(&default_log, L_ERR, "Failed to initialize the dictionaries");
return -1;
}
-#endif
#define DICT_READ_OPTIONAL(_d, _n) \
do {\
*/
static CONF_SECTION *virtual_server_root;
+static int listen_on_read(TALLOC_CTX *ctx, void *out, CONF_ITEM *ci, CONF_PARSER const *rule);
+static int server_on_read(TALLOC_CTX *ctx, void *out, CONF_ITEM *ci, UNUSED CONF_PARSER const *rule);
+
static int listen_parse(TALLOC_CTX *ctx, void *out, CONF_ITEM *ci, CONF_PARSER const *rule);
static int server_parse(TALLOC_CTX *ctx, void *out, CONF_ITEM *ci, UNUSED CONF_PARSER const *rule);
+static const CONF_PARSER listen_on_read_config[] = {
+ { FR_CONF_OFFSET("listen", FR_TYPE_SUBSECTION | FR_TYPE_MULTI | FR_TYPE_OK_MISSING | FR_TYPE_ON_READ,
+ fr_virtual_server_t, listener), \
+ .subcs_size = sizeof(fr_virtual_listen_t), .subcs_type = "fr_virtual_listen_t",
+ .func = listen_on_read },
+
+ CONF_PARSER_TERMINATOR
+};
+
+const CONF_PARSER virtual_servers_on_read_config[] = {
+ /*
+ * Not really ok if it's missing but we want to
+ * let logic elsewhere handle the issue.
+ */
+ { FR_CONF_POINTER("server", FR_TYPE_SUBSECTION | FR_TYPE_MULTI | FR_TYPE_OK_MISSING | FR_TYPE_ON_READ, &virtual_servers), \
+ .subcs_size = sizeof(fr_virtual_server_t), .subcs_type = "fr_virtual_server_t",
+ .subcs = (void const *) listen_on_read_config, .ident2 = CF_IDENT_ANY,
+ .func = server_on_read },
+
+ CONF_PARSER_TERMINATOR
+};
+
static const CONF_PARSER server_config[] = {
{ FR_CONF_OFFSET("namespace", FR_TYPE_STRING, fr_virtual_server_t, namespace) },
CONF_PARSER_TERMINATOR
};
+
+/** dl_open a proto_* module
+ *
+ * @param[in] ctx to allocate data in.
+ * @param[out] out always NULL
+ * @param[in] ci #CONF_SECTION containing the listen section.
+ * @param[in] rule unused.
+ * @return
+ * - 0 on success.
+ * - -1 on failure.
+ */
+static int listen_on_read(UNUSED TALLOC_CTX *ctx, UNUSED void *out, CONF_ITEM *ci, UNUSED CONF_PARSER const *rule)
+{
+ CONF_SECTION *listen_cs = cf_item_to_section(ci);
+ CONF_SECTION *server_cs = cf_item_to_section(cf_parent(ci));
+ CONF_PAIR *namespace = cf_pair_find(server_cs, "namespace");
+
+ if (DEBUG_ENABLED4) cf_log_debug(ci, "Loading proto_%s", cf_pair_value(namespace));
+
+ if (!dl_module(listen_cs, NULL, cf_pair_value(namespace), DL_TYPE_PROTO)) {
+ cf_log_err(listen_cs, "Failed loading proto_%s module", cf_pair_value(namespace));
+ return -1;
+ }
+
+ return 0;
+}
+
+/** Callback to set up listen_on_read
+ *
+ * @param[in] ctx to allocate data in.
+ * @param[out] out Where to our listen configuration. Is a #fr_virtual_server_t structure.
+ * @param[in] ci #CONF_SECTION containing the listen section.
+ * @param[in] rule unused.
+ * @return
+ * - 0 on success.
+ * - -1 on failure.
+ */
+static int server_on_read(UNUSED TALLOC_CTX *ctx, UNUSED void *out, CONF_ITEM *ci, UNUSED CONF_PARSER const *rule)
+{
+ CONF_SECTION *server_cs = cf_item_to_section(ci);
+ CONF_PAIR *namespace;
+
+ namespace = cf_pair_find(server_cs, "namespace");
+ if (!namespace) {
+ cf_log_err(server_cs, "virtual server %s MUST contain a 'namespace' option",
+ cf_section_name2(server_cs));
+ return -1;
+ }
+
+ return 0;
+}
+
+
/** dl_open a proto_* module
*
* @param[in] ctx to allocate data in.