From: Arran Cudbard-Bell Date: Tue, 13 Jun 2017 14:12:46 +0000 (-0400) Subject: Remove many type specific functions from the conf_file api X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e8d698e4b2d1890a82abda1921c19dd16a4d5a24;p=thirdparty%2Ffreeradius-server.git Remove many type specific functions from the conf_file api Rework the internals of CONF_ITEMs, CONF_SECTIONs, CONF_DATA so they're simple/sane. Allow nested CONF_DATA Provide functions to iterate over CONF_DATA of the same type Get CONF_DATA by type only Get CONF_DATA by name only --- diff --git a/src/include/conf_file.h b/src/include/conf_file.h index 1ac9d50ed98..31e83071392 100644 --- a/src/include/conf_file.h +++ b/src/include/conf_file.h @@ -43,8 +43,8 @@ extern "C" { */ typedef struct cf_item CONF_ITEM; //!< Generic configuration element, extended to become ///< a #CONF_PAIR, a #CONF_SECTION or #CONF_DATA. -typedef struct cf_pair CONF_PAIR; //!< #CONF_ITEM with an attribute, an operator and a value. typedef struct cf_section CONF_SECTION; //!< #CONF_ITEM used to group multiple #CONF_PAIR and #CONF_SECTION, together. +typedef struct cf_pair CONF_PAIR; //!< #CONF_ITEM with an attribute, an operator and a value. typedef struct cf_data CONF_DATA; //!< #CONF_ITEM used to associate arbitrary data ///< with a #CONF_PAIR or #CONF_SECTION. @@ -426,118 +426,179 @@ typedef struct CONF_PARSER { #define CONF_PARSER_PARTIAL_TERMINATOR { .name = NULL, .type = ~(UINT32_MAX - 1), \ .offset = 1, .data = NULL, .dflt = NULL, .quote = T_INVALID } +#define CF_FILE_NONE (0) +#define CF_FILE_ERROR (1) +#define CF_FILE_CONFIG (1 << 2) +#define CF_FILE_MODULE (1 << 3) + +/** Auto cast from the input type to CONF_ITEM (which is the base type) + * + * Automatically casts: + * - #CONF_SECTION + * - #CONF_PAIR + * - #CONF_DATA + * + * To a #CONF_ITEM, whilst performing talloc type checks. + */ +#define CF_TO_ITEM(_cf) \ +_Generic((_cf), \ + CONF_SECTION *: cf_section_to_item((CONF_SECTION const *)_cf), \ + CONF_SECTION const *: cf_section_to_item((CONF_SECTION const *)_cf), \ + CONF_PAIR *: cf_pair_to_item((CONF_PAIR const *)_cf), \ + CONF_PAIR const *: cf_pair_to_item((CONF_PAIR const *)_cf), \ + CONF_DATA *: cf_data_to_item((CONF_DATA const *)_cf), \ + CONF_DATA const *: cf_data_to_item((CONF_DATA const *)_cf), \ + default: _cf \ +) + typedef int (*cf_walker_t)(void *data, void *ctx); +extern char const *CF_IDENT_ANY; + +/* + * Config file parsing + */ +int cf_file_read(CONF_SECTION *cs, char const *file); +void cf_file_free(CONF_SECTION *cs); + void cf_file_check_user(uid_t uid, gid_t gid); +int cf_file_changed(CONF_SECTION *cs, rb_walker_t callback); -CONF_PAIR *cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value, - FR_TOKEN op, FR_TOKEN lhs_type, FR_TOKEN rhs_type); -CONF_PAIR *cf_pair_dup(CONF_SECTION *parent, CONF_PAIR *cp); -void cf_pair_add(CONF_SECTION *parent, CONF_PAIR *cp); +/* + * Config file writing + */ +#ifdef WITH_CONF_WRITE +size_t cf_section_write(FILE *fp, CONF_SECTION *cs, int depth); +#endif -CONF_SECTION *cf_section_alloc(CONF_SECTION *parent, char const *name1, char const *name2); -CONF_SECTION *cf_section_dup(CONF_SECTION *parent, CONF_SECTION const *cs, - char const *name1, char const *name2, bool copy_meta); -void cf_section_add(CONF_SECTION *parent, CONF_SECTION *cs); -int cf_pair_replace(CONF_SECTION *cs, CONF_PAIR *cp, char const *value); -int cf_pair_parse(TALLOC_CTX *ctx, CONF_SECTION *cs, char const *name, unsigned int type, void *data, - char const *dflt, FR_TOKEN dflt_quote); +/* + * Type validation and conversion + */ +int cf_pair_parse(TALLOC_CTX *ctx, CONF_SECTION *cs, char const *name, + unsigned int type, void *data, char const *dflt, FR_TOKEN dflt_quote); int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs, CONF_PARSER const *variables); int cf_section_parse_pass2(void *base, CONF_SECTION *cs, CONF_PARSER const *variables); -const CONF_PARSER *cf_section_parse_table(CONF_SECTION *cs); -int cf_file_read(CONF_SECTION *cs, char const *file); -void cf_file_free(CONF_SECTION *cs); +CONF_PARSER const *cf_section_parse_table(CONF_SECTION *cs); -CONF_PAIR *cf_pair_find(CONF_SECTION const *, char const *name); -CONF_PAIR *cf_pair_find_next(CONF_SECTION const *, CONF_PAIR const *, char const *name); -CONF_SECTION *cf_section_find_name2(CONF_SECTION const *section, - char const *name1, char const *name2); -CONF_SECTION *cf_subsection_find(CONF_SECTION const *, char const *name); -CONF_SECTION *cf_subsection_find_name2(CONF_SECTION const *, char const *name1, char const *name2); -char const *cf_section_value_find(CONF_SECTION const *, char const *attr); -CONF_SECTION *cf_top_section(CONF_SECTION *cs); +CONF_ITEM *cf_reference_item(CONF_SECTION const *parentcs, CONF_SECTION const *outercs, char const *ptr); -#define cf_data_find(_cs, _type, _name) (_type *)_cf_data_find(_cs, #_type, _name) -void *_cf_data_find(CONF_SECTION const *cs, char const *type, char const *name); +/* + * Generic functions that apply to all types of #CONF_ITEM + */ +#define cf_item_add(_parent, _child) _cf_item_add(CF_TO_ITEM(_parent), _child) +void _cf_item_add(CONF_ITEM *parent, CONF_ITEM *child); -#define cf_data_add(_cs, _data, _name, _free) _cf_data_add(_cs, _data, _name, _free) -int _cf_data_add(CONF_SECTION *cs, void const *data, char const *name, bool free); +#define cf_item_next(_ci, _prev) _cf_item_next(CF_TO_ITEM(_ci), _prev) +CONF_ITEM *_cf_item_next(CONF_ITEM const *ci, CONF_ITEM const *prev); -#define cf_data_remove(_cs, _type, _name) (_type *)_cf_data_remove(_cs, #_type, _name) -void *_cf_data_remove(CONF_SECTION *cs, char const *type, char const *name); +#define cf_root(_cf) _cf_root(CF_TO_ITEM(_cf)) +CONF_SECTION *_cf_root(CONF_ITEM const *ci); -#define cf_data_walk(_cs, _type, _cb, _ctx) _cf_data_walk(_cs, #_type, _cb, _ctx) -int _cf_data_walk(CONF_SECTION *cs, char const *type, cf_walker_t cb, void *ctx); +#define cf_parent(_cf) _cf_parent(CF_TO_ITEM(_cf)) +CONF_ITEM *_cf_parent(CONF_ITEM const *ci); -char const *cf_pair_attr(CONF_PAIR const *pair); -char const *cf_pair_value(CONF_PAIR const *pair); -FR_TOKEN cf_pair_operator(CONF_PAIR const *pair); -FR_TOKEN cf_pair_attr_type(CONF_PAIR const *pair); -FR_TOKEN cf_pair_value_type(CONF_PAIR const *pair); +#define cf_lineno(_cf) _cf_lineno(CF_TO_ITEM(_cf)) +int _cf_lineno(CONF_ITEM const *ci); + +#define cf_filename(_cf) _cf_filename(CF_TO_ITEM(_cf)) +char const *_cf_filename(CONF_ITEM const *ci); + +bool cf_item_is_section(CONF_ITEM const *ci); +bool cf_item_is_pair(CONF_ITEM const *ci); +bool cf_item_is_data(CONF_ITEM const *ci); + +CONF_PAIR *cf_item_to_pair(CONF_ITEM const *ci); +CONF_SECTION *cf_item_to_section(CONF_ITEM const *ci); +CONF_DATA *cf_item_to_data(CONF_ITEM const *ci); + +CONF_ITEM *cf_pair_to_item(CONF_PAIR const *cp); +CONF_ITEM *cf_section_to_item(CONF_SECTION const *cs); +CONF_ITEM *cf_data_to_item(CONF_DATA const *cs); + +/* + * Section manipulation and searching + */ +CONF_SECTION *cf_section_alloc(CONF_SECTION *parent, char const *name1, char const *name2); +CONF_SECTION *cf_section_dup(CONF_SECTION *parent, CONF_SECTION const *cs, + char const *name1, char const *name2, bool copy_meta); +void cf_section_add(CONF_SECTION *parent, CONF_SECTION *cs); +CONF_SECTION *cf_section_next(CONF_SECTION const *cs, CONF_SECTION const *prev); +CONF_SECTION *cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2); +CONF_SECTION *cf_section_find_next(CONF_SECTION const *cs, CONF_SECTION const *subcs, + char const *name1, char const *name2); + +char const *cf_section_value_find(CONF_SECTION const *, char const *attr); char const *cf_section_name1(CONF_SECTION const *cs); char const *cf_section_name2(CONF_SECTION const *cs); char const *cf_section_name(CONF_SECTION const *cs); char const *cf_section_argv(CONF_SECTION const *cs, int argc); -FR_TOKEN cf_section_name2_type(CONF_SECTION const *cs); -FR_TOKEN cf_section_argv_type(CONF_SECTION const *cs, int argc); - -CONF_SECTION *cf_subsection_find_next(CONF_SECTION const *section, - CONF_SECTION const *subsection, - char const *name1); -CONF_SECTION *cf_section_find_next(CONF_SECTION const *section, - CONF_SECTION const *subsection, - char const *name1); - -int cf_section_lineno(CONF_SECTION const *section); -int cf_pair_lineno(CONF_PAIR const *pair); -char const *cf_pair_filename(CONF_PAIR const *pair); -char const *cf_section_filename(CONF_SECTION const *section); -CONF_ITEM *cf_item_find_next(CONF_SECTION const *section, CONF_ITEM const *item); +FR_TOKEN cf_section_name2_quote(CONF_SECTION const *cs); +FR_TOKEN cf_section_argv_quote(CONF_SECTION const *cs, int argc); + +/* + * Pair manipulation and searching + */ +CONF_PAIR *cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value, + FR_TOKEN op, FR_TOKEN lhs_type, FR_TOKEN rhs_type); +CONF_PAIR *cf_pair_dup(CONF_SECTION *parent, CONF_PAIR *cp); +int cf_pair_replace(CONF_SECTION *cs, CONF_PAIR *cp, char const *value); +void cf_pair_add(CONF_SECTION *parent, CONF_PAIR *cp); +CONF_PAIR *cf_pair_next(CONF_SECTION const *cs, CONF_PAIR const *prev); +CONF_PAIR *cf_pair_find(CONF_SECTION const *cs, char const *name); +CONF_PAIR *cf_pair_find_next(CONF_SECTION const *cs, CONF_PAIR const *prev, char const *name); int cf_pair_count(CONF_SECTION const *cs); -CONF_ITEM *cf_item_parent(CONF_ITEM const *ci); -CONF_SECTION *cf_section_parent(CONF_SECTION const *cs); -CONF_SECTION *cf_pair_parent(CONF_PAIR const *cp); -CONF_SECTION *cf_item_root(CONF_ITEM const *ci); +char const *cf_pair_attr(CONF_PAIR const *pair); +char const *cf_pair_value(CONF_PAIR const *pair); +FR_TOKEN cf_pair_operator(CONF_PAIR const *pair); + +FR_TOKEN cf_pair_attr_quote(CONF_PAIR const *pair); +FR_TOKEN cf_pair_value_quote(CONF_PAIR const *pair); -bool cf_item_is_section(CONF_ITEM const *item); -bool cf_item_is_pair(CONF_ITEM const *item); -CONF_PAIR *cf_item_to_pair(CONF_ITEM const *item); -CONF_SECTION *cf_item_to_section(CONF_ITEM const *item); -CONF_ITEM *cf_pair_to_item(CONF_PAIR const *cp); -CONF_ITEM *cf_section_to_item(CONF_SECTION const *cs); +/* + * Data manipulation and searching + */ +#define cf_data_find(_cf, _type, _name) _cf_data_find(CF_TO_ITEM(_cf), #_type, _name) +CONF_DATA const *_cf_data_find(CONF_ITEM const *ci, char const *type, char const *name); + +#define cf_data_find_next(_cf, _prev, _type, _name) _cf_data_find(CF_TO_ITEM(_cf), CF_TO_ITEM(_prev), #_type, _name) +CONF_DATA const *_cf_data_find_next(CONF_ITEM const *ci, CONF_ITEM const *prev, char const *type, char const *name); + +void *cf_data_value(CONF_DATA const *cd); + +#define cf_data_add(_cf, _data, _name, _free) _cf_data_add(CF_TO_ITEM(_cf), _data, _name, _free) +CONF_DATA const *_cf_data_add(CONF_ITEM *ci, void const *data, char const *name, bool free); + +#define cf_data_remove(_cf, _cd) _cf_data_remove(CF_TO_ITEM(_cf), _cd); +void *_cf_data_remove(CONF_ITEM *ci, CONF_DATA const *_cd); + +#define cf_data_walk(_cf, _type, _cb, _ctx) _cf_data_walk(CF_TO_ITEM(_cf), #_type, _cb, _ctx) +int _cf_data_walk(CONF_ITEM *ci, char const *type, cf_walker_t cb, void *ctx); /* - * Log an error related to a section + * Error logging */ -void cf_log_err(CONF_ITEM const *ci, char const *fmt, ...) CC_HINT(format (printf, 2, 3)); -void cf_log_err_cs(CONF_SECTION const *cs, char const *fmt, ...) CC_HINT(format (printf, 2, 3)); -void cf_log_perr_cs(CONF_SECTION const *cs, char const *fmt, ...) CC_HINT(format (printf, 2, 3)); -void cf_log_err_cp(CONF_PAIR const *cp, char const *fmt, ...) CC_HINT(format (printf, 2, 3)); -void cf_log_perr_cp(CONF_PAIR const *cp, char const *fmt, ...) CC_HINT(format (printf, 2, 3)); -void cf_log_err_by_name(CONF_SECTION const *parent, - char const *name, char const *fmt, ...) CC_HINT(format (printf, 3, 4)); -void cf_log_warn_cp(CONF_PAIR const *cp, char const *fmt, ...) CC_HINT(format (printf, 2, 3)); -void cf_log_warn(CONF_SECTION const *cs, char const *fmt, ...) CC_HINT(format (printf, 2, 3)); -void cf_log_info(CONF_SECTION const *cs, char const *fmt, ...) CC_HINT(format (printf, 2, 3)); -void cf_log_module(CONF_SECTION const *cs, char const *fmt, ...) CC_HINT(format (printf, 2, 3)); +#define cf_log_err(_cf, _fmt, ...) _cf_log_err(CF_TO_ITEM(_cf), _fmt, ## __VA_ARGS__) +void _cf_log_err(CONF_ITEM const *ci, char const *fmt, ...) CC_HINT(format (printf, 2, 3)); -void cf_item_add(CONF_SECTION *cs, CONF_ITEM *ci); -CONF_ITEM *cf_reference_item(CONF_SECTION const *parentcs, - CONF_SECTION const *outercs, - char const *ptr); +#define cf_log_perr(_cf, _fmt, ...) _cf_log_perr(CF_TO_ITEM(_cf), _fmt, ## __VA_ARGS__) +void _cf_log_perr(CONF_ITEM const *ci, char const *fmt, ...) CC_HINT(format (printf, 2, 3)); -#ifdef WITH_CONF_WRITE -size_t cf_section_write(FILE *fp, CONF_SECTION *cs, int depth); -#endif +#define cf_log_warn(_cf, _fmt, ...) _cf_log_warn(CF_TO_ITEM(_cf), _fmt, ## __VA_ARGS__) +void _cf_log_warn(CONF_ITEM const *ci, char const *fmt, ...) CC_HINT(format (printf, 2, 3)); -#define CF_FILE_NONE (0) -#define CF_FILE_ERROR (1) -#define CF_FILE_CONFIG (1 << 2) -#define CF_FILE_MODULE (1 << 3) -int cf_file_changed(CONF_SECTION *cs, rb_walker_t callback); +#define cf_log_info(_cf, _fmt, ...) _cf_log_info(CF_TO_ITEM(_cf), _fmt, ## __VA_ARGS__) +void _cf_log_info(CONF_ITEM const *ci, char const *fmt, ...) CC_HINT(format (printf, 2, 3)); + +#define cf_log_debug(_cf, _fmt, ...) _cf_log_debug(CF_TO_ITEM(_cf), _fmt, ## __VA_ARGS__) +void _cf_log_debug(CONF_ITEM const *ci, char const *fmt, ...) CC_HINT(format (printf, 2, 3)); + +void cf_log_err_by_name(CONF_SECTION const *parent, + char const *name, char const *fmt, ...) CC_HINT(format (printf, 3, 4)); +#define cf_debug(_cf) _cf_debug(CF_TO_ITEM(_cf)) +void _cf_debug(CONF_ITEM const *ci); #ifdef __cplusplus } #endif diff --git a/src/include/cursor.h b/src/include/cursor.h index 7f1b48d96cc..bdc01e21236 100644 --- a/src/include/cursor.h +++ b/src/include/cursor.h @@ -49,7 +49,7 @@ typedef struct fr_cursor_s { char const *type; //!< If set, used for explicit runtime type safety checks. } fr_cursor_t; -void fr_cursor_copy(fr_cursor_t *out, fr_cursor_t *in) CC_HINT(nonnull); +void fr_cursor_copy(fr_cursor_t *out, fr_cursor_t const *in) CC_HINT(nonnull); void *fr_cursor_head(fr_cursor_t *cursor) CC_HINT(nonnull); diff --git a/src/include/rbtree.h b/src/include/rbtree.h index eea96d6a2fe..adf03acef8a 100644 --- a/src/include/rbtree.h +++ b/src/include/rbtree.h @@ -51,7 +51,7 @@ typedef void (*rb_free_t)(void *data); rbtree_t *rbtree_create(TALLOC_CTX *ctx, rb_comparator_t compare, rb_free_t node_free, int flags); void rbtree_node_talloc_free(void *data); -bool rbtree_insert(rbtree_t *tree, void *data); +bool rbtree_insert(rbtree_t *tree, void const *data); rbnode_t *rbtree_insert_node(rbtree_t *tree, void *data); void rbtree_delete(rbtree_t *tree, rbnode_t *z); bool rbtree_deletebydata(rbtree_t *tree, void const *data); diff --git a/src/include/token.h b/src/include/token.h index c2faccc63b3..07bccdf5026 100644 --- a/src/include/token.h +++ b/src/include/token.h @@ -71,6 +71,7 @@ typedef struct FR_NAME_NUMBER { } FR_NAME_NUMBER; extern const FR_NAME_NUMBER fr_tokens_table[]; +extern const FR_NAME_NUMBER fr_token_quotes_table[]; extern const char *fr_tokens[]; extern const char fr_token_quote[]; extern const bool fr_assignment_op[]; diff --git a/src/include/xlat.h b/src/include/xlat.h index f46d9113a5d..a346a3eb490 100644 --- a/src/include/xlat.h +++ b/src/include/xlat.h @@ -97,7 +97,7 @@ int xlat_register(void *mod_inst, char const *name, void xlat_unregister(void *mod_inst, char const *name, xlat_func_t func); void xlat_unregister_module(void *instance); -bool xlat_register_redundant(CONF_SECTION *cs); +int xlat_register_redundant(CONF_SECTION *cs); void xlat_free(void); #ifdef __cplusplus diff --git a/src/lib/util/cursor.c b/src/lib/util/cursor.c index ad6e6a50542..02b69ab829d 100644 --- a/src/lib/util/cursor.c +++ b/src/lib/util/cursor.c @@ -117,7 +117,7 @@ static inline void *cursor_tail(void **prev, fr_cursor_t *cursor, void *current) * @param[out] out Where to copy the cursor to. * @param[in] in cursor to copy. */ -void fr_cursor_copy(fr_cursor_t *out, fr_cursor_t *in) +void fr_cursor_copy(fr_cursor_t *out, fr_cursor_t const *in) { memcpy(out, in, sizeof(*out)); } diff --git a/src/lib/util/rbtree.c b/src/lib/util/rbtree.c index 0a0664849b7..9998f642b43 100644 --- a/src/lib/util/rbtree.c +++ b/src/lib/util/rbtree.c @@ -279,7 +279,6 @@ rbnode_t *rbtree_insert_node(rbtree_t *tree, void *data) rbnode_t *current, *parent, *x; if (!tree->root) return NULL; - if (tree->lock) pthread_mutex_lock(&tree->mutex); /* find where node belongs */ @@ -347,11 +346,15 @@ rbnode_t *rbtree_insert_node(rbtree_t *tree, void *data) return x; } -bool rbtree_insert(rbtree_t *tree, void *data) +bool rbtree_insert(rbtree_t *tree, void const *data) { + void *mutable; + if (!tree->root) return NULL; - if (rbtree_insert_node(tree, data)) return true; + memcpy(&mutable, &data, sizeof(mutable)); + + if (rbtree_insert_node(tree, mutable)) return true; return false; } diff --git a/src/lib/util/token.c b/src/lib/util/token.c index f6542c54034..28709f13cf9 100644 --- a/src/lib/util/token.c +++ b/src/lib/util/token.c @@ -53,6 +53,13 @@ const FR_NAME_NUMBER fr_tokens_table[] = { { NULL, 0, }, }; +const FR_NAME_NUMBER fr_token_quotes_table[] = { + { "", T_BARE_WORD }, + { "'", T_SINGLE_QUOTED_STRING }, + { "\"", T_DOUBLE_QUOTED_STRING }, + { "`", T_BACK_QUOTED_STRING }, + { NULL, 0 }, +}; /* * This is a hack, and has to be kept in sync with tokens.h diff --git a/src/main/client.c b/src/main/client.c index c2b408b39bf..6a9cdb2a095 100644 --- a/src/main/client.c +++ b/src/main/client.c @@ -219,7 +219,7 @@ bool client_add(RADCLIENT_LIST *clients, RADCLIENT *client) CONF_SECTION *cs; CONF_SECTION *subcs; - cs = cf_subsection_find_name2(main_config.config, "server", client->server); + cs = cf_section_find(main_config.config, "server", client->server); if (!cs) { ERROR("Failed to find virtual server %s", client->server); return false; @@ -229,14 +229,14 @@ bool client_add(RADCLIENT_LIST *clients, RADCLIENT *client) * If this server has no "listen" section, add the clients * to the global client list. */ - subcs = cf_subsection_find(cs, "listen"); + subcs = cf_section_find(cs, "listen", NULL); if (!subcs) goto global_clients; /* * If the client list already exists, use that. * Otherwise, create a new client list. */ - clients = cf_data_find(cs, RADCLIENT_LIST, NULL); + clients = cf_data_value(cf_data_find(cs, RADCLIENT_LIST, NULL)); if (!clients) { clients = client_list_init(cs); if (!clients) { @@ -519,7 +519,7 @@ RADCLIENT_LIST *client_list_parse_section(CONF_SECTION *section, UNUSED bool tls #endif { bool global = false; - CONF_SECTION *cs; + CONF_SECTION *cs = NULL; RADCLIENT *c = NULL; RADCLIENT_LIST *clients = NULL; CONF_SECTION *server_cs = NULL; @@ -528,7 +528,7 @@ RADCLIENT_LIST *client_list_parse_section(CONF_SECTION *section, UNUSED bool tls * Be forgiving. If there's already a clients, return * it. Otherwise create a new one. */ - clients = cf_data_find(section, RADCLIENT_LIST, NULL); + clients = cf_data_value(cf_data_find(section, RADCLIENT_LIST, NULL)); if (clients) return clients; /* @@ -542,7 +542,7 @@ RADCLIENT_LIST *client_list_parse_section(CONF_SECTION *section, UNUSED bool tls * the global client list, else it's virtual server * specific client list. */ - if (cf_top_section(section) == section) global = true; + if (cf_root(section) == section) global = true; if (strcmp("server", cf_section_name1(section)) == 0) server_cs = section; @@ -550,9 +550,7 @@ RADCLIENT_LIST *client_list_parse_section(CONF_SECTION *section, UNUSED bool tls * Iterate over all the clients in the section, adding * them to the client list. */ - for (cs = cf_subsection_find_next(section, NULL, "client"); - cs; - cs = cf_subsection_find_next(section, cs, "client")) { + while ((cs = cf_section_find_next(section, cs, "client", CF_IDENT_ANY))) { c = client_afrom_cs(cs, cs, server_cs, false); if (!c) { error: @@ -567,7 +565,7 @@ RADCLIENT_LIST *client_list_parse_section(CONF_SECTION *section, UNUSED bool tls * non-TLS clients CANNOT use TLS listeners. */ if (tls_required != c->tls_required) { - cf_log_err_cs(cs, "Client does not have the same TLS configuration as the listener"); + cf_log_err(cs, "Client does not have the same TLS configuration as the listener"); goto error; } #endif @@ -596,7 +594,7 @@ RADCLIENT_LIST *client_list_parse_section(CONF_SECTION *section, UNUSED bool tls value = cf_pair_value(cp); if (!value) { - cf_log_err_cs(cs, "The \"directory\" entry must not be empty"); + cf_log_err(cs, "The \"directory\" entry must not be empty"); goto error; } @@ -604,7 +602,7 @@ RADCLIENT_LIST *client_list_parse_section(CONF_SECTION *section, UNUSED bool tls dir = opendir(value); if (!dir) { - cf_log_err_cs(cs, "Error reading directory %s: %s", value, fr_syserror(errno)); + cf_log_err(cs, "Error reading directory %s: %s", value, fr_syserror(errno)); goto error; } @@ -635,7 +633,7 @@ RADCLIENT_LIST *client_list_parse_section(CONF_SECTION *section, UNUSED bool tls dc = client_read(buf2, server_cs, true); if (!dc) { - cf_log_err_cs(cs, "Failed reading client file \"%s\"", buf2); + cf_log_err(cs, "Failed reading client file \"%s\"", buf2); closedir(dir); goto error; } @@ -655,7 +653,7 @@ RADCLIENT_LIST *client_list_parse_section(CONF_SECTION *section, UNUSED bool tls add_client: #endif /* WITH_DYNAMIC_CLIENTS */ if (!client_add(clients, c)) { - cf_log_err_cs(cs, "Failed to add client %s", cf_section_name2(cs)); + cf_log_err(cs, "Failed to add client %s", cf_section_name2(cs)); goto error; } @@ -665,7 +663,7 @@ RADCLIENT_LIST *client_list_parse_section(CONF_SECTION *section, UNUSED bool tls * Associate the clients structure with the section. */ if (cf_data_add(section, clients, NULL, false) < 0) { - cf_log_err_cs(section, "Failed to associate clients with section %s", cf_section_name1(section)); + cf_log_err(section, "Failed to associate clients with section %s", cf_section_name1(section)); talloc_free(clients); return NULL; } @@ -734,7 +732,7 @@ bool client_add_dynamic(RADCLIENT_LIST *clients, RADCLIENT *master, RADCLIENT *c c->server_cs = master->server_cs; } else if (c->server) { - c->server_cs = cf_subsection_find_name2(main_config.config, "server", c->server); + c->server_cs = cf_section_find(main_config.config, "server", c->server); if (!c->server_cs) { ERROR("Failed to find virtual server %s", c->server); goto error; @@ -788,9 +786,9 @@ int client_map_section(CONF_SECTION *out, CONF_SECTION const *map, client_value_ { CONF_ITEM const *ci; - for (ci = cf_item_find_next(map, NULL); + for (ci = cf_item_next(map, NULL); ci != NULL; - ci = cf_item_find_next(map, ci)) { + ci = cf_item_next(map, ci)) { CONF_PAIR const *cp; CONF_PAIR *old; char *value; @@ -806,7 +804,7 @@ int client_map_section(CONF_SECTION *out, CONF_SECTION const *map, client_value_ /* * Use pre-existing section or alloc a new one */ - cc = cf_subsection_find_name2(out, cf_section_name1(cs), cf_section_name2(cs)); + cc = cf_section_find(out, cf_section_name1(cs), cf_section_name2(cs)); if (!cc) { cc = cf_section_alloc(out, cf_section_name1(cs), cf_section_name2(cs)); cf_section_add(out, cc); @@ -827,7 +825,7 @@ int client_map_section(CONF_SECTION *out, CONF_SECTION const *map, client_value_ * Or return -1 in which case we error out. */ if (func(&value, cp, data) < 0) { - cf_log_err_cs(out, "Failed performing mapping \"%s\" = \"%s\"", attr, cf_pair_value(cp)); + cf_log_err(out, "Failed performing mapping \"%s\" = \"%s\"", attr, cf_pair_value(cp)); return -1; } if (!value) continue; @@ -847,7 +845,7 @@ int client_map_section(CONF_SECTION *out, CONF_SECTION const *map, client_value_ */ cp = cf_pair_alloc(out, attr, value, T_OP_SET, T_BARE_WORD, T_SINGLE_QUOTED_STRING); if (!cp) { - cf_log_err_cs(out, "Failed allocing pair \"%s\" = \"%s\"", attr, value); + cf_log_err(out, "Failed allocing pair \"%s\" = \"%s\"", attr, value); talloc_free(value); return -1; } @@ -874,7 +872,7 @@ RADCLIENT *client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, CONF_SECTION *serv name2 = cf_section_name2(cs); if (!name2) { - cf_log_err_cs(cs, "Missing client name"); + cf_log_err(cs, "Missing client name"); return NULL; } @@ -886,7 +884,7 @@ RADCLIENT *client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, CONF_SECTION *serv memset(&cl_ipaddr, 0, sizeof(cl_ipaddr)); if (cf_section_parse(c, c, cs, client_config) < 0) { - cf_log_err_cs(cs, "Error parsing client section"); + cf_log_err(cs, "Error parsing client section"); error: client_free(c); #ifdef WITH_TCP @@ -902,13 +900,13 @@ RADCLIENT *client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, CONF_SECTION *serv */ if (c->server) { if (server_cs) { - cf_log_err_cs(cs, "Clients inside of a 'server' section cannot point to a server"); + cf_log_err(cs, "Clients inside of a 'server' section cannot point to a server"); goto error; } - c->server_cs = cf_subsection_find_name2(main_config.config, "server", c->server); + c->server_cs = cf_section_find(main_config.config, "server", c->server); if (!c->server_cs) { - cf_log_err_cs(cs, "Failed to find virtual server %s", c->server); + cf_log_err(cs, "Failed to find virtual server %s", c->server); goto error; } @@ -944,7 +942,7 @@ RADCLIENT *client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, CONF_SECTION *serv * No "ipaddr" or "ipv6addr", use old-style "client {" syntax. */ } else { - cf_log_err_cs(cs, "No 'ipaddr' or 'ipv4addr' or 'ipv6addr' configuration " + cf_log_err(cs, "No 'ipaddr' or 'ipv4addr' or 'ipv6addr' configuration " "directive found in client %s", name2); goto error; } @@ -974,7 +972,7 @@ RADCLIENT *client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, CONF_SECTION *serv c->proto = IPPROTO_IP; /* fake for dual */ #endif } else { - cf_log_err_cs(cs, "Unknown proto \"%s\".", hs_proto); + cf_log_err(cs, "Unknown proto \"%s\".", hs_proto); goto error; } } @@ -989,14 +987,14 @@ RADCLIENT *client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, CONF_SECTION *serv switch (c->ipaddr.af) { case AF_INET: if (fr_inet_pton4(&c->src_ipaddr, cl_srcipaddr, -1, true, false, true) < 0) { - cf_log_err_cs(cs, "Failed parsing src_ipaddr: %s", fr_strerror()); + cf_log_err(cs, "Failed parsing src_ipaddr: %s", fr_strerror()); goto error; } break; case AF_INET6: if (fr_inet_pton6(&c->src_ipaddr, cl_srcipaddr, -1, true, false, true) < 0) { - cf_log_err_cs(cs, "Failed parsing src_ipaddr: %s", fr_strerror()); + cf_log_err(cs, "Failed parsing src_ipaddr: %s", fr_strerror()); goto error; } break; @@ -1029,13 +1027,13 @@ RADCLIENT *client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, CONF_SECTION *serv if (((c->ipaddr.af == AF_INET) && (c->ipaddr.prefix == 32)) || ((c->ipaddr.af == AF_INET6) && (c->ipaddr.prefix == 128))) { - cf_log_err_cs(cs, "Dynamic clients MUST be a network, not a single IP address"); + cf_log_err(cs, "Dynamic clients MUST be a network, not a single IP address"); goto error; } - c->client_server_cs = cf_subsection_find_name2(main_config.config, "server", c->client_server); + c->client_server_cs = cf_section_find(main_config.config, "server", c->client_server); if (!c->client_server_cs) { - cf_log_err_cs(cs, "Unknown virtual server '%s'", c->client_server); + cf_log_err(cs, "Unknown virtual server '%s'", c->client_server); goto error; } @@ -1068,7 +1066,7 @@ RADCLIENT *client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, CONF_SECTION *serv #endif { - cf_log_err_cs(cs, "secret must be at least 1 character long"); + cf_log_err(cs, "secret must be at least 1 character long"); goto error; } } @@ -1090,7 +1088,7 @@ RADCLIENT *client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, CONF_SECTION *serv c->coa_server = home_server_byname(c->coa_name, HOME_TYPE_COA); } if (!c->coa_pool && !c->coa_server) { - cf_log_err_cs(cs, "No such home_server or home_server_pool \"%s\"", c->coa_name); + cf_log_err(cs, "No such home_server or home_server_pool \"%s\"", c->coa_name); goto error; } /* @@ -1099,7 +1097,7 @@ RADCLIENT *client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, CONF_SECTION *serv * create a home server CONF_SECTION and then parse * it into a home_server_t. */ - } else if (with_coa || cf_subsection_find(cs, "coa_server")) { + } else if (with_coa || cf_section_find(cs, "coa_server", NULL), NULL) { CONF_SECTION *server; home_server_t *home; @@ -1379,7 +1377,7 @@ RADCLIENT *client_afrom_request(RADCLIENT_LIST *clients, REQUEST *request) goto error; } - if (cf_pair_attr_type(cp) == T_SINGLE_QUOTED_STRING) { + if (cf_pair_attr_quote(cp) == T_SINGLE_QUOTED_STRING) { RDEBUG2("%s = '%s'", cf_pair_attr(cp), cf_pair_value(cp)); } else { RDEBUG2("%s = %s", cf_pair_attr(cp), cf_pair_value(cp)); @@ -1492,7 +1490,7 @@ RADCLIENT *client_read(char const *filename, CONF_SECTION *server_cs, bool check return NULL; } - cs = cf_subsection_find(cs, "client"); + cs = cf_section_find(cs, "client", NULL); if (!cs) { ERROR("No \"client\" section found in client file"); return NULL; diff --git a/src/main/command.c b/src/main/command.c index e96c3772396..26ca46071e9 100644 --- a/src/main/command.c +++ b/src/main/command.c @@ -842,7 +842,7 @@ static int command_hup(rad_listen_t *listener, int argc, char *argv[]) return CMD_OK; } - cs = cf_subsection_find(main_config.config, "modules"); + cs = cf_section_find(main_config.config, "modules", NULL); if (!cs) return CMD_FAIL; instance = module_find(cs, argv[0]); @@ -1009,7 +1009,7 @@ static int command_show_module_config(rad_listen_t *listener, int argc, char *ar return CMD_FAIL; } - cs = cf_subsection_find(main_config.config, "modules"); + cs = cf_section_find(main_config.config, "modules", NULL); if (!cs) return CMD_FAIL; instance = module_find(cs, argv[0]); @@ -1046,7 +1046,7 @@ static int command_show_module_methods(rad_listen_t *listener, int argc, char *a return CMD_FAIL; } - cs = cf_subsection_find(main_config.config, "modules"); + cs = cf_section_find(main_config.config, "modules", NULL); if (!cs) return CMD_FAIL; instance = module_find(cs, argv[0]); @@ -1073,7 +1073,7 @@ static int command_show_module_flags(rad_listen_t *listener, int argc, char *arg return CMD_FAIL; } - cs = cf_subsection_find(main_config.config, "modules"); + cs = cf_section_find(main_config.config, "modules", NULL); if (!cs) return CMD_FAIL; instance = module_find(cs, argv[0]); @@ -1097,7 +1097,7 @@ static int command_show_module_status(rad_listen_t *listener, int argc, char *ar return CMD_FAIL; } - cs = cf_subsection_find(main_config.config, "modules"); + cs = cf_section_find(main_config.config, "modules", NULL); if (!cs) return CMD_FAIL; instance = module_find(cs, argv[0]); @@ -1124,11 +1124,11 @@ static int command_show_modules(rad_listen_t *listener, UNUSED int argc, UNUSED { CONF_SECTION *cs, *subcs; - cs = cf_subsection_find(main_config.config, "modules"); + cs = cf_section_find(main_config.config, "modules", NULL); if (!cs) return CMD_FAIL; subcs = NULL; - while ((subcs = cf_subsection_find_next(cs, subcs, NULL)) != NULL) { + while ((subcs = cf_section_next(cs, subcs)) != NULL) { char const *name1 = cf_section_name1(subcs); char const *name2 = cf_section_name2(subcs); @@ -2482,7 +2482,7 @@ static int command_set_module_config(rad_listen_t *listener, int argc, char *arg return 0; } - cs = cf_subsection_find(main_config.config, "modules"); + cs = cf_section_find(main_config.config, "modules", NULL); if (!cs) return 0; instance = module_find(cs, argv[0]); @@ -2560,7 +2560,7 @@ static int command_set_module_status(rad_listen_t *listener, int argc, char *arg return 0; } - cs = cf_subsection_find(main_config.config, "modules"); + cs = cf_section_find(main_config.config, "modules", NULL); if (!cs) return 0; instance = module_find(cs, argv[0]); @@ -3243,7 +3243,7 @@ static int command_socket_parse(CONF_SECTION *cs, rad_listen_t *this) #ifdef WITH_TLS if (this->tls) { - cf_log_err_cs(cs, + cf_log_err(cs, "TLS is not supported for control sockets"); return -1; } @@ -3251,7 +3251,7 @@ static int command_socket_parse(CONF_SECTION *cs, rad_listen_t *this) sock = this->data; if (sock->proto != IPPROTO_TCP) { - cf_log_err_cs(cs, + cf_log_err(cs, "UDP is not supported for control sockets"); return -1; } diff --git a/src/main/conf_file.c b/src/main/conf_file.c index e6cfa280335..cdb5af6a373 100644 --- a/src/main/conf_file.c +++ b/src/main/conf_file.c @@ -1,12 +1,4 @@ /* - * conf_file.c Read the radiusd.conf file. - * - * Yep I should learn to use lex & yacc, or at least - * write a decent parser. I know how to do that, really :) - * miquels@cistron.nl - * - * Version: $Id$ - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -20,24 +12,39 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * - * Copyright 2000,2006 The FreeRADIUS server project - * Copyright 2000 Miquel van Smoorenburg - * Copyright 2000 Alan DeKok */ +/** + * $Id$ + * @file conf_file.c + * @brief Read the radiusd.conf file. + * + * @note Yep I should learn to use lex & yacc, or at least + * write a decent parser. I know how to do that, really :) + * miquels@cistron.nl + * + * @copyright 2017 Arran Cudbard-Bell (a.cudbardb@freeradius.org) + * @copyright 2000,2006 The FreeRADIUS server project + * @copyright 2000 Miquel van Smoorenburg + * @copyright 2000 Alan DeKok + */ RCSID("$Id$") #include #include #include +#include + +#include +#include +#include #ifdef HAVE_DIRENT_H -#include +# include #endif #ifdef HAVE_SYS_STAT_H -#include +# include #endif #include @@ -48,6 +55,8 @@ static uid_t conf_check_uid = (uid_t)-1; static gid_t conf_check_gid = (gid_t)-1; static CONF_PARSER conf_term = CONF_PARSER_TERMINATOR; +char const *CF_IDENT_ANY = ""; + typedef enum conf_property { CONF_PROPERTY_INVALID = 0, CONF_PROPERTY_NAME, @@ -72,12 +81,24 @@ typedef enum conf_type { #endif } CONF_ITEM_TYPE; +/** Common header for all CONF_* types + * + */ struct cf_item { - struct cf_item *next; //!< Sibling. - struct cf_item *parent; //!< Parent. + CONF_ITEM_TYPE type; //!< Whether the config item is a config_pair, conf_section or cf_data. + + CONF_ITEM *next; //!< Sibling. + CONF_ITEM *parent; //!< Parent. + + CONF_ITEM *child; //!< The head of the ordered list of children. + fr_cursor_t cursor; //!< Cursor to iterate over children. Maintains a 'tail' pointer for + //!< efficient insertion. + + rbtree_t *ident1; //!< Tree to store the first identifier (name1 || type || attr). + rbtree_t *ident2; //!< Tree to store the second identifier (name2 || name). + int lineno; //!< The line number the config item began on. char const *filename; //!< The file the config item was parsed from. - CONF_ITEM_TYPE type; //!< Whether the config item is a config_pair, conf_section or cf_data. }; /** Configuration AVP similar to a VALUE_PAIR @@ -91,9 +112,11 @@ struct cf_pair { char const *orig_value; /* original value */ #endif char const *value; //!< Attribute value + FR_TOKEN op; //!< Operator e.g. =, := - FR_TOKEN lhs_type; //!< Name quoting style T_(DOUBLE|SINGLE|BACK)_QUOTE_STRING or T_BARE_WORD. - FR_TOKEN rhs_type; //!< Value Quoting style T_(DOUBLE|SINGLE|BACK)_QUOTE_STRING or T_BARE_WORD. + FR_TOKEN lhs_quote; //!< Name quoting style T_(DOUBLE|SINGLE|BACK)_QUOTE_STRING or T_BARE_WORD. + FR_TOKEN rhs_quote; //!< Value Quoting style T_(DOUBLE|SINGLE|BACK)_QUOTE_STRING or T_BARE_WORD. + bool pass2; //!< do expansion in pass2. bool parsed; //!< Was this item used during parsing? }; @@ -107,24 +130,16 @@ struct cf_section { char const *name1; //!< First name token. Given ``foo bar {}`` would be ``foo``. char const *name2; //!< Second name token. Given ``foo bar {}`` would be ``bar``. - FR_TOKEN name2_type; //!< The type of quoting around name2. + FR_TOKEN name2_quote; //!< The type of quoting around name2. int argc; //!< number of additional arguments char const **argv; //!< additional arguments - FR_TOKEN *argv_type; - - CONF_ITEM *children; - CONF_ITEM *tail; //!< For speed. - CONF_SECTION *template; - - rbtree_t *pair_tree; //!< and a partridge.. - rbtree_t *section_tree; //!< no jokes here. - rbtree_t *name2_tree; //!< for sections of the same name2 - rbtree_t *data_tree; + FR_TOKEN *argv_quote; void *base; int depth; + CONF_SECTION *template; CONF_PARSER const *variables; //!< the section was parsed with. }; @@ -136,8 +151,9 @@ struct cf_data { char const *type; //!< C type of data being stored. char const *name; //!< Additional qualification of type. + void const *data; //!< User data. - bool free; //!< Free user data function. + bool free; //!< If true, free data with talloc if parent node is freed. }; typedef enum cf_include_type { @@ -148,182 +164,367 @@ typedef enum cf_include_type { #ifdef WITH_CONF_WRITE typedef struct conf_comment { - CONF_ITEM item; - char const *comment; + CONF_ITEM item; + char const *comment; } CONF_COMMENT; typedef struct conf_include { - CONF_ITEM item; - char const *filename; - CONF_INCLUDE_TYPE file_type; + CONF_ITEM item; + char const *filename; + CONF_INCLUDE_TYPE file_type; } CONF_INCLUDE; #endif typedef struct cf_file_t { - char const *filename; - CONF_SECTION *cs; - struct stat buf; + char const *filename; + CONF_SECTION *cs; + struct stat buf; } cf_file_t; - -static char const *cf_expand_variables(char const *cf, int *lineno, - CONF_SECTION *outercs, - char *output, size_t outsize, - char const *input, bool *soft_fail); +static inline int cf_ident2_cmp(void const *a, void const *b); +static int _cf_ident1_cmp(void const *a, void const *b); +static int _cf_ident2_cmp(void const *a, void const *b); static int cf_file_include(CONF_SECTION *cs, char const *filename_in, CONF_INCLUDE_TYPE file_type, char *buff[7]); - - /* - * Isolate the scary casts in these tiny provably-safe functions - */ - -/** Cast a CONF_ITEM to a CONF_PAIR - * + * Expand the variables in an input string. */ -CONF_PAIR *cf_item_to_pair(CONF_ITEM const *ci) +static char const *cf_expand_variables(char const *cf, int *lineno, + CONF_SECTION *outer_cs, + char *output, size_t outsize, + char const *input, bool *soft_fail) { - CONF_PAIR *out; - - if (ci == NULL) return NULL; + char *p; + char const *end, *ptr; + CONF_SECTION const *parent_cs; + char name[8192]; - rad_assert(ci->type == CONF_ITEM_PAIR); + if (soft_fail) *soft_fail = false; - memcpy(&out, &ci, sizeof(out)); - return out; -} + /* + * Find the master parent conf section. + * We can't use main_config.config, because we're in the + * process of re-building it, and it isn't set up yet... + */ + parent_cs = cf_root(outer_cs); -/** Cast a CONF_ITEM to a CONF_SECTION - * - */ -CONF_SECTION *cf_item_to_section(CONF_ITEM const *ci) -{ - CONF_SECTION *out; + p = output; + ptr = input; + while (*ptr) { + /* + * Ignore anything other than "${" + */ + if ((*ptr == '$') && (ptr[1] == '{')) { + CONF_ITEM *ci; + CONF_PAIR *cp; + char *q; - if (ci == NULL) return NULL; + /* + * FIXME: Add support for ${foo:-bar}, + * like in xlat.c + */ - rad_assert(ci->type == CONF_ITEM_SECTION); + /* + * Look for trailing '}', and log a + * warning for anything that doesn't match, + * and exit with a fatal error. + */ + end = strchr(ptr, '}'); + if (end == NULL) { + *p = '\0'; + INFO("%s[%d]: Variable expansion missing }", + cf, *lineno); + return NULL; + } - memcpy(&out, &ci, sizeof(out)); - return out; -} + ptr += 2; -/** Cast a CONF_PAIR to a CONF_ITEM - * - */ -CONF_ITEM *cf_pair_to_item(CONF_PAIR const *cp) -{ - CONF_ITEM *out; + /* + * Can't really happen because input lines are + * capped at 8k, which is sizeof(name) + */ + if ((size_t) (end - ptr) >= sizeof(name)) { + ERROR("%s[%d]: Reference string is too large", + cf, *lineno); + return NULL; + } - if (cp == NULL) return NULL; + memcpy(name, ptr, end - ptr); + name[end - ptr] = '\0'; - memcpy(&out, &cp, sizeof(out)); - return out; -} + q = strchr(name, ':'); + if (q) { + *(q++) = '\0'; + } -/** Cast a CONF_SECTION to a CONF_ITEM - * - */ -CONF_ITEM *cf_section_to_item(CONF_SECTION const *cs) -{ - CONF_ITEM *out; + ci = cf_reference_item(parent_cs, outer_cs, name); + if (!ci) { + if (soft_fail) *soft_fail = true; + ERROR("%s[%d]: Reference \"${%s}\" not found", cf, *lineno, name); + return NULL; + } - if (cs == NULL) return NULL; + /* + * The expansion doesn't refer to another item or section + * it's the property of a section. + */ + if (q) { + CONF_SECTION *find = cf_item_to_section(ci); - memcpy(&out, &cs, sizeof(out)); - return out; -} + if (ci->type != CONF_ITEM_SECTION) { + ERROR("%s[%d]: Can only reference properties of sections", cf, *lineno); + return NULL; + } -/** Cast CONF_DATA to a CONF_ITEM - * - */ -static CONF_ITEM *cf_data_to_item(CONF_DATA const *cd) -{ - CONF_ITEM *out; + switch (fr_str2int(conf_property_name, q, CONF_PROPERTY_INVALID)) { + case CONF_PROPERTY_NAME: + strcpy(p, find->name1); + break; - if (cd == NULL) { - return NULL; - } + case CONF_PROPERTY_INSTANCE: + strcpy(p, find->name2 ? find->name2 : find->name1); + break; - memcpy(&out, &cd, sizeof(out)); - return out; -} + default: + ERROR("%s[%d]: Invalid property '%s'", cf, *lineno, q); + return NULL; + } + p += strlen(p); + ptr = end + 1; -static int _cd_free(CONF_DATA *cd) -{ - void *to_free; + } else if (ci->type == CONF_ITEM_PAIR) { + /* + * Substitute the value of the variable. + */ + cp = cf_item_to_pair(ci); - memcpy(&to_free, cd->data, sizeof(to_free)); + /* + * If the thing we reference is + * marked up as being expanded in + * pass2, don't expand it now. + * Let it be expanded in pass2. + */ + if (cp->pass2) { + if (soft_fail) *soft_fail = true; - if (cd->free) talloc_free(to_free); + ERROR("%s[%d]: Reference \"%s\" points to a variable which has not been expanded.", + cf, *lineno, input); + return NULL; + } - return 0; -} + if (!cp->value) { + ERROR("%s[%d]: Reference \"%s\" has no value", + cf, *lineno, input); + return NULL; + } -/* - * rbtree callback function - */ -static int pair_cmp(void const *a, void const *b) -{ - CONF_PAIR const *one = a; - CONF_PAIR const *two = b; + if (p + strlen(cp->value) >= output + outsize) { + ERROR("%s[%d]: Reference \"%s\" is too long", + cf, *lineno, input); + return NULL; + } - return strcmp(one->attr, two->attr); -} + strcpy(p, cp->value); + p += strlen(p); + ptr = end + 1; + } else if (ci->type == CONF_ITEM_SECTION) { + CONF_SECTION *subcs; -/* - * rbtree callback function - */ -static int section_cmp(void const *a, void const *b) -{ - CONF_SECTION const *one = a; - CONF_SECTION const *two = b; + /* + * Adding an entry again to a + * section is wrong. We don't + * want an infinite loop. + */ + if (cf_item_to_section(ci->parent) == outer_cs) { + ERROR("%s[%d]: Cannot reference different item in same section", cf, *lineno); + return NULL; + } - return strcmp(one->name1, two->name1); -} + /* + * Copy the section instead of + * referencing it. + */ + subcs = cf_item_to_section(ci); + subcs = cf_section_dup(outer_cs, subcs, + cf_section_name1(subcs), cf_section_name2(subcs), + false); + if (!subcs) { + ERROR("%s[%d]: Failed copying reference %s", cf, *lineno, name); + return NULL; + } + subcs->item.filename = ci->filename; + subcs->item.lineno = ci->lineno; + cf_item_add(outer_cs, &(subcs->item)); -/* - * rbtree callback function - */ -static int name2_cmp(void const *a, void const *b) -{ - CONF_SECTION const *one = a; - CONF_SECTION const *two = b; + ptr = end + 1; - rad_assert(strcmp(one->name1, two->name1) == 0); + } else { + ERROR("%s[%d]: Reference \"%s\" type is invalid", cf, *lineno, input); + return NULL; + } + } else if (memcmp(ptr, "$ENV{", 5) == 0) { + char *env; - if (!one->name2 && !two->name2) return 0; - if (one->name2 && !two->name2) return -1; - if (!one->name2 && two->name2) return +1; + ptr += 5; - return strcmp(one->name2, two->name2); -} + /* + * Look for trailing '}', and log a + * warning for anything that doesn't match, + * and exit with a fatal error. + */ + end = strchr(ptr, '}'); + if (end == NULL) { + *p = '\0'; + INFO("%s[%d]: Environment variable expansion missing }", + cf, *lineno); + return NULL; + } + /* + * Can't really happen because input lines are + * capped at 8k, which is sizeof(name) + */ + if ((size_t) (end - ptr) >= sizeof(name)) { + ERROR("%s[%d]: Environment variable name is too large", + cf, *lineno); + return NULL; + } + + memcpy(name, ptr, end - ptr); + name[end - ptr] = '\0'; + + /* + * Get the environment variable. + * If none exists, then make it an empty string. + */ + env = getenv(name); + if (env == NULL) { + *name = '\0'; + env = name; + } + + if (p + strlen(env) >= output + outsize) { + ERROR("%s[%d]: Reference \"%s\" is too long", + cf, *lineno, input); + return NULL; + } + + strcpy(p, env); + p += strlen(p); + ptr = end + 1; + + } else { + /* + * Copy it over verbatim. + */ + *(p++) = *(ptr++); + } + + + if (p >= (output + outsize)) { + ERROR("%s[%d]: Reference \"%s\" is too long", + cf, *lineno, input); + return NULL; + } + } /* loop over all of the input string. */ + + *p = '\0'; + + return output; +} /* - * rbtree callback function + * Merge the template so everyting else "just works". */ -static int data_cmp(void const *a, void const *b) +static bool cf_template_merge(CONF_SECTION *cs, CONF_SECTION const *template) { - CONF_DATA const *one = a; - CONF_DATA const *two = b; - int ret; + CONF_ITEM *ci; + + if (!cs || !template) return true; + + cs->template = NULL; + + /* + * Walk over the template, adding its' entries to the + * current section. But only if the entries don't + * already exist in the current section. + */ + for (ci = template->item.child; ci; ci = ci->next) { + if (ci->type == CONF_ITEM_PAIR) { + CONF_PAIR *cp1, *cp2; + + /* + * It exists, don't over-write it. + */ + cp1 = cf_item_to_pair(ci); + if (cf_pair_find(cs, cp1->attr)) { + continue; + } + + /* + * Create a new pair with all of the data + * of the old one. + */ + cp2 = cf_pair_dup(cs, cp1); + if (!cp2) return false; + + cp2->item.filename = cp1->item.filename; + cp2->item.lineno = cp1->item.lineno; + + cf_item_add(cs, &(cp2->item)); + continue; + } + + if (ci->type == CONF_ITEM_SECTION) { + CONF_SECTION *subcs1, *subcs2; + + subcs1 = cf_item_to_section(ci); + rad_assert(subcs1 != NULL); + + subcs2 = cf_section_find(cs, subcs1->name1, subcs1->name2); + if (subcs2) { + /* + * sub-sections get merged. + */ + if (!cf_template_merge(subcs2, subcs1)) { + return false; + } + continue; + } + + /* + * Our section doesn't have a matching + * sub-section. Copy it verbatim from + * the template. + */ + subcs2 = cf_section_dup(cs, subcs1, + cf_section_name1(subcs1), cf_section_name2(subcs1), + false); + if (!subcs2) return false; + + subcs2->item.filename = subcs1->item.filename; + subcs2->item.lineno = subcs1->item.lineno; - if (one->type && !two->type) return +1; - if (!one->type && two->type) return -1; + cf_item_add(cs, &(subcs2->item)); + continue; + } - if (one->type && two->type) { - ret = strcmp(one->type, two->type); - if (ret != 0) return ret; + /* ignore everything else */ } - if (one->name && !two->name) return +1; - if (!one->name && two->name) return -1; + return true; +} + +static int _cd_free(CONF_DATA *cd) +{ + void *to_free; + + memcpy(&to_free, cd->data, sizeof(to_free)); - if (one->name && two->name) return strcmp(one->name, two->name); + if (cd->free) talloc_free(to_free); return 0; } @@ -331,7 +532,7 @@ static int data_cmp(void const *a, void const *b) /* * Functions for tracking filenames. */ -static int filename_cmp(void const *a, void const *b) +static int _filename_cmp(void const *a, void const *b) { cf_file_t const *one = a; cf_file_t const *two = b; @@ -353,24 +554,19 @@ static FILE *cf_file_open(CONF_SECTION *cs, char const *filename) int fd; FILE *fp; - top = cf_top_section(cs); - tree = cf_data_find(top, rbtree_t, "filename"); - if (!tree) return NULL; + top = cf_root(cs); + tree = cf_data_value(cf_data_find(top, rbtree_t, "filename")); + rad_assert(tree); fp = fopen(filename, "r"); if (!fp) { - ERROR("Unable to open file \"%s\": %s", - filename, fr_syserror(errno)); + ERROR("Unable to open file \"%s\": %s", filename, fr_syserror(errno)); return NULL; } fd = fileno(fp); - file = talloc(tree, cf_file_t); - if (!file) { - fclose(fp); - return NULL; - } + MEM(file = talloc(tree, cf_file_t)); file->filename = filename; file->cs = cs; @@ -394,29 +590,11 @@ static FILE *cf_file_open(CONF_SECTION *cs, char const *filename) * * Though the admin should really use templates for that. */ - if (!rbtree_insert(tree, file)) { - talloc_free(file); - } + if (!rbtree_insert(tree, file)) talloc_free(file); return fp; } -/** Set the euid/egid used when performing file checks - * - * Sets the euid, and egid used when cf_file_check is called to check - * permissions on conf items of type #FR_TYPE_FILE_INPUT. - * - * @note This is probably only useful for the freeradius daemon itself. - * - * @param uid to set, (uid_t)-1 to use current euid. - * @param gid to set, (gid_t)-1 to use current egid. - */ -void cf_file_check_user(uid_t uid, gid_t gid) -{ - if (uid != 0) conf_check_uid = uid; - if (gid != 0) conf_check_gid = gid; -} - /** Do some checks on the file as an "input" file. i.e. one read by a module. * * @note Must be called with super user privileges. @@ -436,8 +614,8 @@ static bool cf_file_check(CONF_SECTION *cs, char const *filename, bool check_per rbtree_t *tree; int fd = -1; - top = cf_top_section(cs); - tree = cf_data_find(top, rbtree_t, "filename"); + top = cf_root(cs); + tree = cf_data_value(cf_data_find(top, rbtree_t, "filename")); if (!tree) return false; file = talloc(tree, cf_file_t); @@ -519,22 +697,20 @@ static bool cf_file_check(CONF_SECTION *cs, char const *filename, bool check_per return true; } - typedef struct cf_file_callback_t { int rcode; rb_walker_t callback; CONF_SECTION *modules; } cf_file_callback_t; - /* * Return 0 for keep going, 1 for stop. */ -static int file_callback(void *ctx, void *data) +static int _file_callback(void *ctx, void *data) { - cf_file_callback_t *cb = ctx; - cf_file_t *file = data; - struct stat buf; + cf_file_callback_t *cb = ctx; + cf_file_t *file = data; + struct stat buf; /* * The file doesn't exist or we can no longer read it. @@ -548,7 +724,6 @@ static int file_callback(void *ctx, void *data) * The file changed, we'll need to re-read it. */ if (buf.st_mtime != file->buf.st_mtime) { - if (cb->callback(cb->modules, file->cs)) { cb->rcode |= CF_FILE_MODULE; DEBUG3("HUP: Changed module file %s", file->filename); @@ -561,3263 +736,3435 @@ static int file_callback(void *ctx, void *data) return 0; } - /* - * See if any of the files have changed. + * Do variable expansion in pass2. + * + * This is a breadth-first expansion. "deep */ -int cf_file_changed(CONF_SECTION *cs, rb_walker_t callback) +static int cf_section_pass2(CONF_SECTION *cs) { - CONF_SECTION *top; - cf_file_callback_t cb; - rbtree_t *tree; + CONF_ITEM *ci; - top = cf_top_section(cs); - tree = cf_data_find(top, rbtree_t, "filename"); - if (!tree) return true; + for (ci = cs->item.child; ci; ci = ci->next) { + char const *value; + CONF_PAIR *cp; + char buffer[8192]; - cb.rcode = CF_FILE_NONE; - cb.callback = callback; - cb.modules = cf_subsection_find(cs, "modules"); + if (ci->type != CONF_ITEM_PAIR) continue; - (void) rbtree_walk(tree, RBTREE_IN_ORDER, file_callback, &cb); + cp = cf_item_to_pair(ci); + if (!cp->value || !cp->pass2) continue; - return cb.rcode; -} + rad_assert((cp->rhs_quote == T_BARE_WORD) || + (cp->rhs_quote == T_DOUBLE_QUOTED_STRING) || + (cp->rhs_quote == T_BACK_QUOTED_STRING)); -static int _cf_section_free(CONF_SECTION *cs) -{ - /* - * Name1 and name2 are allocated contiguous with - * cs. - */ - if (cs->pair_tree) { - talloc_free(cs->pair_tree); - cs->pair_tree = NULL; - } - if (cs->section_tree) { - talloc_free(cs->section_tree); - cs->section_tree = NULL; - } - if (cs->name2_tree) { - talloc_free(cs->name2_tree); - cs->name2_tree = NULL; + value = cf_expand_variables(ci->filename, &ci->lineno, cs, buffer, sizeof(buffer), cp->value, NULL); + if (!value) return -1; + + talloc_const_free(cp->value); + cp->value = talloc_typed_strdup(cp, value); } - if (cs->data_tree) { - talloc_free(cs->data_tree); - cs->data_tree = NULL; + + for (ci = cs->item.child; ci; ci = ci->next) { + if (ci->type != CONF_ITEM_SECTION) continue; + + if (cf_section_pass2(cf_item_to_section(ci)) < 0) return -1; } return 0; } -/** Allocate a #CONF_PAIR - * - * @param parent #CONF_SECTION to hang this #CONF_PAIR off of. - * @param attr name. - * @param value of #CONF_PAIR. - * @param op #T_OP_EQ, #T_OP_SET etc. - * @param lhs_type #T_BARE_WORD, #T_DOUBLE_QUOTED_STRING, #T_BACK_QUOTED_STRING - * @param rhs_type #T_BARE_WORD, #T_DOUBLE_QUOTED_STRING, #T_BACK_QUOTED_STRING - * @return - * - NULL on error. - * - A new #CONF_SECTION parented by parent. - */ -CONF_PAIR *cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value, - FR_TOKEN op, FR_TOKEN lhs_type, FR_TOKEN rhs_type) + +static char const *cf_local_file(char const *base, char const *filename, + char *buffer, size_t bufsize) { - CONF_PAIR *cp; + size_t dirsize; + char *p; - rad_assert(fr_equality_op[op] || fr_assignment_op[op]); - if (!attr) return NULL; + strlcpy(buffer, base, bufsize); - cp = talloc_zero(parent, CONF_PAIR); - if (!cp) return NULL; + p = strrchr(buffer, FR_DIR_SEP); + if (!p) return filename; + if (p[1]) { /* ./foo */ + p[1] = '\0'; + } - cp->item.type = CONF_ITEM_PAIR; - cp->item.parent = cf_section_to_item(parent); - cp->lhs_type = lhs_type; - cp->rhs_type = rhs_type; - cp->op = op; - cp->item.filename = ""; /* will be over-written if necessary */ + dirsize = (p - buffer) + 1; - cp->attr = talloc_typed_strdup(cp, attr); - if (!cp->attr) { - error: - talloc_free(cp); + if ((dirsize + strlen(filename)) >= bufsize) { return NULL; } - if (value) { -#ifdef WITH_CONF_WRITE - cp->orig_value = talloc_typed_strdup(cp, value); -#endif - cp->value = talloc_typed_strdup(cp, value); - if (!cp->value) goto error; - } + strlcpy(p + 1, filename, bufsize - dirsize); - return cp; + return buffer; } -/** Duplicate a #CONF_PAIR - * - * @param parent to allocate new pair in. - * @param cp to duplicate. - * @return - * - NULL on error. - * - A duplicate of the input pair. - */ -CONF_PAIR *cf_pair_dup(CONF_SECTION *parent, CONF_PAIR *cp) +static bool invalid_location(CONF_SECTION *this, char const *name, char const *filename, int lineno) { - CONF_PAIR *new; - - rad_assert(parent); - rad_assert(cp); - - new = cf_pair_alloc(parent, cp->attr, cf_pair_value(cp), - cp->op, cp->lhs_type, cp->rhs_type); - if (!new) return NULL; - - new->parsed = cp->parsed; - new->item.lineno = cp->item.lineno; - new->item.filename = cp->item.filename; - - return new; -} - -/** Add a configuration pair to a section - * - * @param parent section to add pair to. - * @param cp to add. - */ -void cf_pair_add(CONF_SECTION *parent, CONF_PAIR *cp) -{ - cf_item_add(parent, cf_pair_to_item(cp)); -} - -/** Allocate a #CONF_SECTION - * - * @param parent #CONF_SECTION to hang this #CONF_SECTION off of. - * @param name1 Primary name. - * @param name2 Secondary name. - * @return - * - NULL on error. - * - A new #CONF_SECTION parented by parent. - */ -CONF_SECTION *cf_section_alloc(CONF_SECTION *parent, char const *name1, char const *name2) -{ - CONF_SECTION *cs; - char buffer[1024]; - - if (!name1) return NULL; - - if (name2 && parent) { - if (strchr(name2, '$')) { - name2 = cf_expand_variables(parent->item.filename, - &parent->item.lineno, - parent, - buffer, sizeof(buffer), name2, NULL); - if (!name2) { - ERROR("Failed expanding section name"); - return NULL; - } - } - } - - cs = talloc_zero(parent, CONF_SECTION); - if (!cs) return NULL; - - cs->item.type = CONF_ITEM_SECTION; - cs->item.parent = cf_section_to_item(parent); - cs->item.filename = ""; /* will be over-written if necessary */ - - cs->name1 = talloc_typed_strdup(cs, name1); - if (!cs->name1) { - error: - talloc_free(cs); - return NULL; - } - - if (name2) { - cs->name2 = talloc_typed_strdup(cs, name2); - if (!cs->name2) goto error; - } - - cs->pair_tree = rbtree_create(cs, pair_cmp, NULL, 0); - if (!cs->pair_tree) goto error; - - talloc_set_destructor(cs, _cf_section_free); - - /* - * Don't create a data tree, it may not be needed. - */ + /* + * if / elsif MUST be inside of a + * processing section, which MUST in turn + * be inside of a "server" directive. + */ + if (!this || !this->item.parent) { + invalid_location: + ERROR("%s[%d]: Invalid location for '%s'", + filename, lineno, name); + return true; + } /* - * Don't create the section tree here, it may not - * be needed. + * Can only have "if" in 3 named sections. */ - - if (parent) cs->depth = parent->depth + 1; - - return cs; -} - -/** Duplicate a configuration section - * - * @note recursively duplicates any child sections. - * @note does not duplicate any data associated with a section, or its child sections. - * - * @param parent section (may be NULL). - * @param cs to duplicate. - * @param name1 of new section. - * @param name2 of new section. - * @param copy_meta Copy additional meta data for a section (like template, base, depth and variables). - * @return - * - A duplicate of the existing section. - * - NULL on error. - */ -CONF_SECTION *cf_section_dup(CONF_SECTION *parent, CONF_SECTION const *cs, - char const *name1, char const *name2, bool copy_meta) -{ - CONF_SECTION *new, *subcs; - CONF_PAIR *cp; - CONF_ITEM *ci; - - new = cf_section_alloc(parent, name1, name2); - - if (copy_meta) { - new->template = cs->template; - new->base = cs->base; - new->depth = cs->depth; - new->variables = cs->variables; + this = cf_item_to_section(this->item.parent); + while ((strcmp(this->name1, "server") != 0) && + (strcmp(this->name1, "policy") != 0) && + (strcmp(this->name1, "instantiate") != 0)) { + this = cf_item_to_section(this->item.parent); + if (!this) goto invalid_location; } - new->item.lineno = cs->item.lineno; - new->item.filename = cs->item.filename; - - for (ci = cs->children; ci; ci = ci->next) { - switch (ci->type) { - case CONF_ITEM_SECTION: - subcs = cf_item_to_section(ci); - subcs = cf_section_dup(new, subcs, - cf_section_name1(subcs), cf_section_name2(subcs), - copy_meta); - if (!subcs) { - talloc_free(new); - return NULL; - } - cf_section_add(new, subcs); - break; - - case CONF_ITEM_PAIR: - cp = cf_pair_dup(new, cf_item_to_pair(ci)); - if (!cp) { - talloc_free(new); - return NULL; - } - cf_pair_add(new, cp); - break; + return false; +} - case CONF_ITEM_DATA: /* Skip data */ #ifdef WITH_CONF_WRITE - case CONF_ITEM_COMMENT: - case CONF_ITEM_INCLUDE: -#endif - break; +static void cf_comment_add(CONF_SECTION *cs, int lineno, char const *ptr) +{ + CONF_COMMENT *cc; - case CONF_ITEM_INVALID: - rad_assert(0); - } - } + cc = talloc_zero(cs, CONF_COMMENT); + cc->item.type = CONF_ITEM_COMMENT; + cc->item.parent = cs; + cc->item.filename = cs->item.filename; + cc->item.lineno = lineno; + cc->comment = talloc_typed_strdup(cc, ptr); - return new; -} -void cf_section_add(CONF_SECTION *parent, CONF_SECTION *cs) -{ - cf_item_add(parent, &(cs->item)); + cf_item_add(cs, &(cc->item)); } -/** Replace pair in a given section with a new pair, of the given value. - * - * @param cs to replace pair in. - * @param cp to replace. - * @param value New value to assign to cp. - * @return - * - 0 on success. - * - -1 on failure. - */ -int cf_pair_replace(CONF_SECTION *cs, CONF_PAIR *cp, char const *value) +static void cf_include_add(CONF_SECTION *cs, char const *filename, CONF_INCLUDE_TYPE file_type) { - CONF_PAIR *newp; - CONF_ITEM *ci, *cn, **last; - - newp = cf_pair_alloc(cs, cp->attr, value, cp->op, cp->lhs_type, cp->rhs_type); - if (!newp) return -1; - - ci = &(cp->item); - cn = &(newp->item); - - /* - * Find the old one from the linked list, and replace it - * with the new one. - */ - for (last = &cs->children; (*last) != NULL; last = &(*last)->next) { - if (*last == ci) { - cn->next = (*last)->next; - *last = cn; - ci->next = NULL; - break; - } - } - - rbtree_deletebydata(cs->pair_tree, ci); + CONF_INCLUDE *cc; - rbtree_insert(cs->pair_tree, cn); + cc = talloc_zero(cs, CONF_INCLUDE); + cc->item.type = CONF_ITEM_INCLUDE; + cc->item.parent = cs; + cc->item.filename = cs->item.filename; + cc->item.lineno = 0; + cc->filename = talloc_typed_strdup(cc, filename); + cc->file_type = file_type; - return 0; + cf_item_add(cs, &(cc->item)); } - +#endif /* - * Add an item to a configuration section. + * Read a part of the config file. */ -void cf_item_add(CONF_SECTION *cs, CONF_ITEM *ci) +static int cf_section_read(char const *filename, int *lineno, FILE *fp, + CONF_SECTION *current, char *buff[7]) + { -#ifndef NDEBUG - CONF_ITEM *first = ci; + CONF_SECTION *this, *css; + CONF_PAIR *cpn; + char const *ptr; + char const *value; +#ifdef WITH_CONF_WRITE + char const *orig_value = NULL; #endif - rad_assert((void *)cs != (void *)ci); + FR_TOKEN t1 = T_INVALID, t2, t3; + bool has_spaces = false; + bool pass2; + char *cbuff; + size_t len; - if (!cs || !ci) return; + this = current; /* add items here */ - if (!cs->children) { - rad_assert(cs->tail == NULL); - cs->children = ci; - } else { - rad_assert(cs->tail != NULL); - cs->tail->next = ci; - } + cbuff = buff[0]; /* - * Update the trees (and tail) for each item added. + * Read, checking for line continuations ('\\' at EOL) */ - for (/* nothing */; ci != NULL; ci = ci->next) { - rad_assert(ci->next != first); /* simple cycle detection */ - - cs->tail = ci; + for (;;) { + int at_eof; + css = NULL; /* - * For fast lookups, pairs and sections get - * added to rbtree's. + * Get data, and remember if we are at EOF. */ - switch (ci->type) { - case CONF_ITEM_PAIR: - if (!rbtree_insert(cs->pair_tree, ci)) { - CONF_PAIR *cp = cf_item_to_pair(ci); + at_eof = (fgets(cbuff, talloc_array_length(buff[0]) - (cbuff - buff[0]), fp) == NULL); + (*lineno)++; - if (strcmp(cp->attr, "confdir") == 0) break; - if (!cp->value) break; /* module name, "ok", etc. */ - } - break; + /* + * We read the entire 8k worth of data: complain. + * Note that we don't care if the last character + * is \n: it's still forbidden. This means that + * the maximum allowed length of text is 8k-1, which + * should be plenty. + */ + len = strlen(cbuff); + if ((cbuff + len + 1) >= (buff[0] + talloc_array_length(buff[0]))) { + ERROR("%s[%d]: Line too long", filename, *lineno); + error: + return -1; + } - case CONF_ITEM_SECTION: { - CONF_SECTION *cs_new = cf_item_to_section(ci); - CONF_SECTION *name1_cs; + if (has_spaces) { + ptr = cbuff; + while (isspace((int) *ptr)) ptr++; - if (!cs->section_tree) { - cs->section_tree = rbtree_create(cs, section_cmp, NULL, 0); - if (!cs->section_tree) { - ERROR("Out of memory"); - fr_exit_now(1); - } + if (ptr > cbuff) { + memmove(cbuff, ptr, len - (ptr - cbuff)); + len -= (ptr - cbuff); } + } - name1_cs = rbtree_finddata(cs->section_tree, cs_new); - if (!name1_cs) { - if (!rbtree_insert(cs->section_tree, cs_new)) { - ERROR("Failed inserting section into tree"); - fr_exit_now(1); - } - break; - } + /* + * Not doing continuations: check for edge + * conditions. + */ + if (cbuff == buff[0]) { + if (at_eof) break; - /* - * We already have a section of - * this "name1". Add a new - * sub-section based on name2. - */ - if (!name1_cs->name2_tree) { - name1_cs->name2_tree = rbtree_create(name1_cs, name2_cmp, NULL, 0); - if (!name1_cs->name2_tree) { - ERROR("Out of memory"); - fr_exit_now(1); - } - } + ptr = buff[0]; + while (*ptr && isspace((int) *ptr)) ptr++; +#ifdef WITH_CONF_WRITE /* - * We don't care if this fails. - * If the user tries to create - * two sections of the same - * name1/name2, the duplicate - * section is just silently - * ignored. + * This is where all of the comments are handled */ - rbtree_insert(name1_cs->name2_tree, cs_new); - break; - } /* was a section */ - - case CONF_ITEM_DATA: - if (!cs->data_tree) { - cs->data_tree = rbtree_create(cs, data_cmp, NULL, 0); - } - if (cs->data_tree) { - rbtree_insert(cs->data_tree, ci); + if (*ptr == '#') { + cf_comment_add(this, *lineno, ptr + 1); } - break; +#endif - default: /* FIXME: assert & error! */ - break; - - } /* switch over conf types */ - } /* loop over ci */ -} - - -CONF_ITEM *cf_reference_item(CONF_SECTION const *parentcs, - CONF_SECTION const *outercs, - char const *ptr) -{ - CONF_PAIR *cp; - CONF_SECTION *next; - CONF_SECTION const *cs = outercs; - char name[8192]; - char *p; - - if (!cs) goto no_such_item; - - strlcpy(name, ptr, sizeof(name)); - p = name; - - /* - * ".foo" means "foo from the current section" - */ - if (*p == '.') { - p++; + if (!*ptr || (*ptr == '#')) continue; - /* - * Just '.' means the current section - */ - if (*p == '\0') { - return cf_section_to_item(cs); + } else if (at_eof || (len == 0)) { + ERROR("%s[%d]: Continuation at EOF is illegal", filename, *lineno); + goto error; } /* - * ..foo means "foo from the section - * enclosing this section" (etc.) + * See if there's a continuation. */ - while (*p == '.') { - if (cs->item.parent) { - cs = cf_item_to_section(cs->item.parent); - } + while ((len > 0) && + ((cbuff[len - 1] == '\n') || (cbuff[len - 1] == '\r'))) { + len--; + cbuff[len] = '\0'; + } + if ((len > 0) && (cbuff[len - 1] == '\\')) { /* - * .. means the section - * enclosing this section + * Check for "suppress spaces" magic. */ - if (!*++p) { - return cf_section_to_item(cs); + if (!has_spaces && (len > 2) && (cbuff[len - 2] == '"')) { + has_spaces = true; } - } - - /* - * "foo.bar.baz" means "from the root" - */ - } else if (strchr(p, '.') != NULL) { - if (!parentcs) goto no_such_item; - - cs = parentcs; - } - while (*p) { - char *q, *r; + cbuff[len - 1] = '\0'; + cbuff += len - 1; + continue; + } - r = strchr(p, '['); - q = strchr(p, '.'); - if (!r && !q) break; + ptr = cbuff = buff[0]; + has_spaces = false; - if (r && q > r) q = NULL; - if (q && q < r) r = NULL; + get_more: + pass2 = false; /* - * Split off name2. + * The parser is getting to be evil. */ - if (r) { - q = strchr(r + 1, ']'); - if (!q) return NULL; /* parse error */ - - /* - * Points to foo[bar]xx: parse error, - * it should be foo[bar] or foo[bar].baz - */ - if (q[1] && q[1] != '.') goto no_such_item; + while ((*ptr == ' ') || (*ptr == '\t')) ptr++; - *r = '\0'; - *q = '\0'; - next = cf_subsection_find_name2(cs, p, r + 1); - *r = '['; - *q = ']'; + if (((ptr[0] == '%') && (ptr[1] == '{')) || + (ptr[0] == '`')) { + ssize_t slen; - /* - * Points to a named instance of a section. - */ - if (!q[1]) { - if (!next) goto no_such_item; - return &(next->item); + if (ptr[0] == '%') { + slen = rad_copy_variable(buff[1], ptr); + } else { + slen = rad_copy_string(buff[1], ptr); } + if (slen <= 0) { + char *spaces, *text; - q++; /* ensure we skip the ']' and '.' */ + fr_canonicalize_error(current, &spaces, &text, slen, ptr); - } else { - *q = '\0'; - next = cf_subsection_find(cs, p); - *q = '.'; - } + ERROR("%s[%d]: %s", filename, *lineno, text); + ERROR("%s[%d]: %s^ Invalid expansion", filename, *lineno, spaces); - if (!next) break; /* it MAY be a pair in this section! */ + talloc_free(spaces); + talloc_free(text); - cs = next; - p = q + 1; - } + goto error; + } - if (!*p) goto no_such_item; + ptr += slen; - retry: - /* - * Find it in the current referenced - * section. - */ - cp = cf_pair_find(cs, p); - if (cp) { - cp->parsed = true; /* conf pairs which are referenced count as parsed */ - return &(cp->item); - } + t2 = gettoken(&ptr, buff[2], talloc_array_length(buff[2]), true); + switch (t2) { + case T_HASH: + case T_EOL: + goto do_bare_word; - next = cf_subsection_find(cs, p); - if (next) return &(next->item); + default: + ERROR("%s[%d]: Invalid expansion: %s", filename, *lineno, ptr); + goto error; + } + } else { + t1 = gettoken(&ptr, buff[1], talloc_array_length(buff[1]), true); + } - /* - * "foo" is "in the current section, OR in main". - */ - if ((p == name) && (parentcs != NULL) && (cs != parentcs)) { - cs = parentcs; - goto retry; - } + /* + * The caller eats "name1 name2 {", and calls us + * for the data inside of the section. So if we + * receive a closing brace, then it must mean the + * end of the section. + */ + if (t1 == T_RCBRACE) { + if (this == current) { + ERROR("%s[%d]: Too many closing braces", filename, *lineno); + goto error; + } -no_such_item: - return NULL; -} + /* + * Merge the template into the existing + * section. This uses more memory, but + * means that templates now work with + * sub-sections, etc. + */ + if (!cf_template_merge(this, this->template)) goto error; + this = cf_item_to_section(this->item.parent); + goto check_for_more; + } -CONF_SECTION *cf_top_section(CONF_SECTION *cs) -{ - if (!cs) return NULL; + if (t1 != T_BARE_WORD) goto skip_keywords; - while (cs->item.parent != NULL) cs = cf_item_to_section(cs->item.parent); + /* + * Allow for $INCLUDE files + * + * This *SHOULD* work for any level include. + * I really really really hate this file. -cparker + */ + if ((strcasecmp(buff[1], "$INCLUDE") == 0) || + (strcasecmp(buff[1], "$-INCLUDE") == 0)) { + bool relative = true; - return cs; -} + t2 = getword(&ptr, buff[2], talloc_array_length(buff[2]), true); + if (t2 != T_EOL) { + ERROR("%s[%d]: Unexpected text after $INCLUDE", filename, *lineno); + goto error; + } + if (buff[2][0] == '$') relative = false; -/* - * Expand the variables in an input string. - */ -static char const *cf_expand_variables(char const *cf, int *lineno, - CONF_SECTION *outercs, - char *output, size_t outsize, - char const *input, bool *soft_fail) -{ - char *p; - char const *end, *ptr; - CONF_SECTION const *parentcs; - char name[8192]; + value = cf_expand_variables(filename, lineno, this, buff[4], talloc_array_length(buff[4]), + buff[2], NULL); + if (!value) goto error; - if (soft_fail) *soft_fail = false; + if (!FR_DIR_IS_RELATIVE(value)) relative = false; - /* - * Find the master parent conf section. - * We can't use main_config.config, because we're in the - * process of re-building it, and it isn't set up yet... - */ - parentcs = cf_top_section(outercs); + if (relative) { + value = cf_local_file(filename, value, buff[3], talloc_array_length(buff[3])); + if (!value) { + ERROR("%s[%d]: Directories too deep", filename, *lineno); + goto error; + } + } - p = output; - ptr = input; - while (*ptr) { - /* - * Ignore anything other than "${" - */ - if ((*ptr == '$') && (ptr[1] == '{')) { - CONF_ITEM *ci; - CONF_PAIR *cp; - char *q; +#ifdef HAVE_DIRENT_H /* - * FIXME: Add support for ${foo:-bar}, - * like in xlat.c + * $INCLUDE foo/ + * + * Include ALL non-"dot" files in the directory. + * careful! */ + if (value[strlen(value) - 1] == '/') { + DIR *dir; + struct dirent *dp; + struct stat stat_buf; + char *my_directory; - /* - * Look for trailing '}', and log a - * warning for anything that doesn't match, - * and exit with a fatal error. - */ - end = strchr(ptr, '}'); - if (end == NULL) { - *p = '\0'; - INFO("%s[%d]: Variable expansion missing }", - cf, *lineno); - return NULL; - } + my_directory = talloc_strdup(this, value); - ptr += 2; + cf_log_debug(current, "Including files in directory \"%s\"", my_directory); - /* - * Can't really happen because input lines are - * capped at 8k, which is sizeof(name) - */ - if ((size_t) (end - ptr) >= sizeof(name)) { - ERROR("%s[%d]: Reference string is too large", - cf, *lineno); - return NULL; - } +#ifdef WITH_CONF_WRITE + /* + * We print this out, but don't + * actually open a file based on + * it. + */ + cf_include_add(this, my_directory, CONF_INCLUDE_DIR); +#endif - memcpy(name, ptr, end - ptr); - name[end - ptr] = '\0'; +#ifdef S_IWOTH + /* + * Security checks. + */ + if (stat(my_directory, &stat_buf) < 0) { + ERROR("%s[%d]: Failed reading directory %s: %s", filename, *lineno, + my_directory, fr_syserror(errno)); + talloc_free(my_directory); + goto error; + } - q = strchr(name, ':'); - if (q) { - *(q++) = '\0'; - } + if ((stat_buf.st_mode & S_IWOTH) != 0) { + ERROR("%s[%d]: Directory %s is globally writable. Refusing to start due to " + "insecure configuration", filename, *lineno, my_directory); + talloc_free(my_directory); + goto error; + } +#endif + dir = opendir(my_directory); + if (!dir) { + ERROR("%s[%d]: Error reading directory %s: %s", + filename, *lineno, value, + fr_syserror(errno)); + talloc_free(my_directory); + goto error; + } - ci = cf_reference_item(parentcs, outercs, name); - if (!ci) { - if (soft_fail) *soft_fail = true; - ERROR("%s[%d]: Reference \"${%s}\" not found", cf, *lineno, name); - return NULL; - } + /* + * Read the directory, ignoring "." files. + */ + while ((dp = readdir(dir)) != NULL) { + char const *p; - /* - * The expansion doesn't refer to another item or section - * it's the property of a section. - */ - if (q) { - CONF_SECTION *mycs = cf_item_to_section(ci); + if (dp->d_name[0] == '.') continue; - if (ci->type != CONF_ITEM_SECTION) { - ERROR("%s[%d]: Can only reference properties of sections", cf, *lineno); - return NULL; - } + /* + * Check for valid characters + */ + for (p = dp->d_name; *p != '\0'; p++) { + if (isalpha((int)*p) || + isdigit((int)*p) || + (*p == '-') || + (*p == '_') || + (*p == '.')) continue; + break; + } + if (*p != '\0') continue; - switch (fr_str2int(conf_property_name, q, CONF_PROPERTY_INVALID)) { - case CONF_PROPERTY_NAME: - strcpy(p, mycs->name1); - break; - case CONF_PROPERTY_INSTANCE: - strcpy(p, mycs->name2 ? mycs->name2 : mycs->name1); - break; + snprintf(buff[2], talloc_array_length(buff[2]), "%s%s", + my_directory, dp->d_name); + if ((stat(buff[2], &stat_buf) != 0) || + S_ISDIR(stat_buf.st_mode)) continue; - default: - ERROR("%s[%d]: Invalid property '%s'", cf, *lineno, q); - return NULL; + /* + * Read the file into the current + * configuration section. + */ + if (cf_file_include(this, buff[2], CONF_INCLUDE_FROMDIR, buff) < 0) { + closedir(dir); + goto error; + } } - p += strlen(p); - ptr = end + 1; - - } else if (ci->type == CONF_ITEM_PAIR) { - /* - * Substitute the value of the variable. - */ - cp = cf_item_to_pair(ci); + closedir(dir); + talloc_free(my_directory); - /* - * If the thing we reference is - * marked up as being expanded in - * pass2, don't expand it now. - * Let it be expanded in pass2. - */ - if (cp->pass2) { - if (soft_fail) *soft_fail = true; + } else +#endif + { /* it was a normal file */ + if (buff[1][1] == '-') { + struct stat statbuf; - ERROR("%s[%d]: Reference \"%s\" points to a variable which has not been expanded.", - cf, *lineno, input); - return NULL; + if (stat(value, &statbuf) < 0) { + WARN("Not including file %s: %s", value, fr_syserror(errno)); + continue; + } } - if (!cp->value) { - ERROR("%s[%d]: Reference \"%s\" has no value", - cf, *lineno, input); - return NULL; - } + if (cf_file_include(this, value, CONF_INCLUDE_FILE, buff) < 0) goto error; + } + continue; + } /* we were in an include */ - if (p + strlen(cp->value) >= output + outsize) { - ERROR("%s[%d]: Reference \"%s\" is too long", - cf, *lineno, input); - return NULL; - } + if (strcasecmp(buff[1], "$template") == 0) { + CONF_ITEM *ci; + CONF_SECTION *parent_cs, *templatecs; + t2 = getword(&ptr, buff[2], talloc_array_length(buff[2]), true); - strcpy(p, cp->value); - p += strlen(p); - ptr = end + 1; + if (t2 != T_EOL) { + ERROR("%s[%d]: Unexpected text after $TEMPLATE", filename, *lineno); + goto error; + } - } else if (ci->type == CONF_ITEM_SECTION) { - CONF_SECTION *subcs; + parent_cs = cf_root(current); - /* - * Adding an entry again to a - * section is wrong. We don't - * want an infinite loop. - */ - if (cf_item_to_section(ci->parent) == outercs) { - ERROR("%s[%d]: Cannot reference different item in same section", cf, *lineno); - return NULL; - } + templatecs = cf_section_find(parent_cs, "templates", NULL); + if (!templatecs) { + ERROR("%s[%d]: No \"templates\" section for reference \"%s\"", filename, *lineno, buff[2]); + goto error; + } - /* - * Copy the section instead of - * referencing it. - */ - subcs = cf_item_to_section(ci); - subcs = cf_section_dup(outercs, subcs, - cf_section_name1(subcs), cf_section_name2(subcs), - false); - if (!subcs) { - ERROR("%s[%d]: Failed copying reference %s", cf, *lineno, name); - return NULL; - } + ci = cf_reference_item(parent_cs, templatecs, buff[2]); + if (!ci || (ci->type != CONF_ITEM_SECTION)) { + ERROR("%s[%d]: Reference \"%s\" not found", filename, *lineno, buff[2]); + goto error; + } - subcs->item.filename = ci->filename; - subcs->item.lineno = ci->lineno; - cf_item_add(outercs, &(subcs->item)); + if (!this) { + ERROR("%s[%d]: Internal sanity check error in template reference", filename, *lineno); + goto error; + } - ptr = end + 1; + if (this->template) { + ERROR("%s[%d]: Section already has a template", filename, *lineno); + goto error; + } - } else { - ERROR("%s[%d]: Reference \"%s\" type is invalid", cf, *lineno, input); - return NULL; - } - } else if (memcmp(ptr, "$ENV{", 5) == 0) { - char *env; + this->template = cf_item_to_section(ci); + continue; + } - ptr += 5; + /* + * Ensure that the user can't add CONF_PAIRs + * with 'internal' names; + */ + if (buff[1][0] == '_') { + ERROR("%s[%d]: Illegal configuration pair name \"%s\"", filename, *lineno, buff[1]); + goto error; + } + + /* + * Handle if/elsif specially. + */ + if ((strcmp(buff[1], "if") == 0) || (strcmp(buff[1], "elsif") == 0)) { + ssize_t slen; + char const *error = NULL; + char *p; + fr_cond_t *cond = NULL; + + if (invalid_location(this, buff[1], filename, *lineno)) goto error; /* - * Look for trailing '}', and log a - * warning for anything that doesn't match, - * and exit with a fatal error. + * Skip (...) to find the { */ - end = strchr(ptr, '}'); - if (end == NULL) { - *p = '\0'; - INFO("%s[%d]: Environment variable expansion missing }", - cf, *lineno); - return NULL; + slen = fr_cond_tokenize(this, cf_section_to_item(this), ptr, &cond, + &error, FR_COND_TWO_PASS); + memcpy(&p, &ptr, sizeof(p)); + + if (slen < 0) { + if (p[-slen] != '{') goto cond_error; + slen = -slen; } + TALLOC_FREE(cond); /* - * Can't really happen because input lines are - * capped at 8k, which is sizeof(name) + * This hack is so that the NEXT stage + * doesn't go "too far" in expanding the + * variable. We can parse the conditions + * without expanding the ${...} stuff. + * BUT we don't want to expand all of the + * stuff AFTER the condition. So we do + * two passes. + * + * The first pass is to discover the end + * of the condition. We then expand THAT + * string, and do a second pass parsing + * the expanded condition. */ - if ((size_t) (end - ptr) >= sizeof(name)) { - ERROR("%s[%d]: Environment variable name is too large", - cf, *lineno); - return NULL; - } - - memcpy(name, ptr, end - ptr); - name[end - ptr] = '\0'; + p += slen; + *p = '\0'; /* - * Get the environment variable. - * If none exists, then make it an empty string. + * Nuke trailing spaces. This hack + * really belongs in the parser. */ - env = getenv(name); - if (env == NULL) { - *name = '\0'; - env = name; - } - - if (p + strlen(env) >= output + outsize) { - ERROR("%s[%d]: Reference \"%s\" is too long", - cf, *lineno, input); - return NULL; + while ((p > ptr) && (isspace((int) p[-1]))) { + p--; + *p = '\0'; } - strcpy(p, env); - p += strlen(p); - ptr = end + 1; - - } else { /* - * Copy it over verbatim. + * If there's a ${...}. If so, expand it. */ - *(p++) = *(ptr++); - } + if (strchr(ptr, '$') != NULL) { + ptr = cf_expand_variables(filename, lineno, + this, + buff[3], talloc_array_length(buff[3]), + ptr, NULL); + if (!ptr) { + ERROR("%s[%d]: Parse error expanding ${...} in condition", + filename, *lineno); + goto error; + } + } /* else leave it alone */ + css = cf_section_alloc(this, buff[1], ptr); + if (!css) { + ERROR("%s[%d]: Failed allocating memory for section", filename, *lineno); + goto error; + } + css->item.filename = filename; + css->item.lineno = *lineno; - if (p >= (output + outsize)) { - ERROR("%s[%d]: Reference \"%s\" is too long", - cf, *lineno, input); - return NULL; - } - } /* loop over all of the input string. */ + slen = fr_cond_tokenize(css, cf_section_to_item(css), ptr, &cond, + &error, FR_COND_TWO_PASS); + *p = '{'; /* put it back */ - *p = '\0'; + cond_error: + if (slen < 0) { + char *spaces, *text; - return output; -} + fr_canonicalize_error(this, &spaces, &text, slen, ptr); -static char const parse_spaces[] = " "; + ERROR("%s[%d]: Parse error in condition", + filename, *lineno); + ERROR("%s[%d]: %s", filename, *lineno, text); + ERROR("%s[%d]: %s^ %s", filename, *lineno, spaces, error); -/** Validation function for ipaddr conf_file types - * - */ -static inline int fr_item_validate_ipaddr(CONF_SECTION *cs, char const *name, fr_type_t type, char const *value, - fr_ipaddr_t *ipaddr) -{ - char ipbuf[128]; + talloc_free(spaces); + talloc_free(text); + talloc_free(css); + goto error; + } - if (strcmp(value, "*") == 0) { - cf_log_info(cs, "%.*s\t%s = *", cs->depth, parse_spaces, name); - } else if (strspn(value, ".0123456789abdefABCDEF:%[]/") == strlen(value)) { - cf_log_info(cs, "%.*s\t%s = %s", cs->depth, parse_spaces, name, value); - } else { - cf_log_info(cs, "%.*s\t%s = %s IPv%s address [%s]", cs->depth, parse_spaces, name, value, - (ipaddr->af == AF_INET ? "4" : " 6"), fr_inet_ntoh(ipaddr, ipbuf, sizeof(ipbuf))); - } + if ((size_t) slen >= (talloc_array_length(buff[2]) - 1)) { + talloc_free(css); + ERROR("%s[%d]: Condition is too large after \"%s\"", filename, *lineno, buff[1]); + goto error; + } - switch (type) { - case FR_TYPE_IPV4_ADDR: - case FR_TYPE_IPV6_ADDR: - case FR_TYPE_COMBO_IP_ADDR: - switch (ipaddr->af) { - case AF_INET: - if (ipaddr->prefix != 32) { - ERROR("Invalid IPv4 mask length \"/%i\". Only \"/32\" permitted for non-prefix types", - ipaddr->prefix); + /* + * Copy the expanded and parsed condition + * into buff[2]. Then, parse the text after + * the condition, which now MUST be a '{. + * + * If it wasn't '{' it would have been + * caught in the first pass of + * conditional parsing, above. + */ + memcpy(buff[2], ptr, slen); + buff[2][slen] = '\0'; + ptr = p; - return -1; - } - break; + if ((t3 = gettoken(&ptr, buff[3], talloc_array_length(buff[3]), true)) != T_LCBRACE) { + talloc_free(css); + ERROR("%s[%d]: Expected '{' %d", filename, *lineno, t3); + goto error; + } - case AF_INET6: - if (ipaddr->prefix != 128) { - ERROR("Invalid IPv6 mask length \"/%i\". Only \"/128\" permitted for non-prefix types", - ipaddr->prefix); + /* + * Swap the condition with trailing stuff for + * the final condition. + */ + memcpy(&p, &css->name2, sizeof(css->name2)); + talloc_free(p); + css->name2 = talloc_typed_strdup(css, buff[2]); - return -1; - } - break; + cf_data_add(css, cond, NULL, false); - default: - return -1; + add_section: + cf_item_add(this, &(css->item)); + + /* + * The current section is now the child section. + */ + this = css; + css = NULL; + goto check_for_more; } - default: - return 0; - } -} + /* + * "map" sections have three arguments! + */ + if (strcmp(buff[1], "map") == 0) { + char const *mod; + char const *exp = NULL; + char const *p; -/** Fixup xlat expansions and attributes - * - * @note Despite the name, this is really the second phase of #cf_pair_parse. - * - * @param[out] base start of structure to write #vp_tmpl_t s to. - * @param[in] cs CONF_SECTION to fixup. - * @param[in] variables Array of CONF_PARSER structs to process. - * @return - * - 0 on success. - * - -1 on failure (parse errors etc...). - */ -int cf_section_parse_pass2(void *base, CONF_SECTION *cs, CONF_PARSER const variables[]) -{ + t2 = gettoken(&ptr, buff[2], talloc_array_length(buff[2]), false); - int i; + if (invalid_location(this, buff[1], filename, *lineno)) { + if (t2 != T_LCBRACE) { + ERROR("%s[%d]: Invalid syntax for 'map'", filename, *lineno); + goto error; + } - /* - * Handle the known configuration parameters. - */ - for (i = 0; variables[i].name != NULL; i++) { - bool attribute, multi, is_tmpl, is_xlat; - CONF_PAIR *cp; - void *data; + goto alloc_section; + } - char const *name = variables[i].name; - int type = variables[i].type; + if (t2 != T_BARE_WORD) { + ERROR("%s[%d]: Expected module name after 'map'", filename, *lineno); + goto error; + } - is_tmpl = (type & FR_TYPE_TMPL); - is_xlat = (type & FR_TYPE_XLAT); - attribute = (type & FR_TYPE_ATTRIBUTE); - multi = (type & FR_TYPE_MULTI); + mod = cf_expand_variables(filename, lineno, + this, + buff[3], talloc_array_length(buff[3]), + buff[2], NULL); + if (!mod) { + ERROR("%s[%d]: Parse error expanding ${...} in map module name", + filename, *lineno); + goto error; + } - type = FR_BASE_TYPE(type); /* normal types are small */ + p = ptr; + t3 = gettoken(&p, buff[4], talloc_array_length(buff[4]), false); + if (fr_str_tok[t3]) { + ptr = p; - /* - * It's a section, recurse! - */ - if (type == FR_TYPE_SUBSECTION) { - uint8_t *subcs_base; - CONF_SECTION *subcs = cf_subsection_find(cs, name); + exp = cf_expand_variables(filename, lineno, + this, + buff[5], talloc_array_length(buff[5]), + buff[4], NULL); + if (!exp) { + ERROR("%s[%d]: Parse error expanding ${...} in map module name", + filename, *lineno); + goto error; + } + } + + if (gettoken(&ptr, buff[6], talloc_array_length(buff[6]), false) != T_LCBRACE) { + ERROR("%s[%d]: Expecting section start brace '{' in 'map' definition", + filename, *lineno); + goto error; + } /* - * Select base by whether this is a nested struct, - * or a pointer to another struct. + * Allocate the section */ - if (!base) { - subcs_base = NULL; - } else if (multi) { - size_t j, len; - uint8_t **array; + css = cf_section_alloc(this, buff[1], mod); + if (!css) { + ERROR("%s[%d]: Failed allocating memory for section", filename, *lineno); + goto error; + } + css->item.filename = filename; + css->item.lineno = *lineno; + css->name2_quote = T_BARE_WORD; - array = (uint8_t **)((uint8_t *)base) + variables[i].offset; - len = talloc_array_length(array); + css->argc = 0; + if (exp) { + css->argv = talloc_array(css, char const *, 1); + css->argv[0] = talloc_typed_strdup(css->argv, exp); + css->argv_quote = talloc_array(css, FR_TOKEN, 1); + css->argv_quote[0] = t3; + css->argc++; + } - for (j = 0; j < len; j++) { - if (cf_section_parse_pass2(array[j], subcs, - (CONF_PARSER const *)variables[i].dflt) < 0) { - return -1; - } - } - continue; - } else if (variables[i].subcs_size) { - subcs_base = (*(uint8_t **)((uint8_t *)base) + variables[i].offset); - } else { - subcs_base = (uint8_t *)base + variables[i].offset; - } - - if (cf_section_parse_pass2(subcs_base, subcs, - (CONF_PARSER const *)variables[i].dflt) < 0) return -1; - - continue; + goto add_section; } + skip_keywords: /* - * Find the CONF_PAIR, may still not exist if there was - * no default set for the CONF_PARSER. - */ - cp = cf_pair_find(cs, name); - if (!cp) continue; - - /* - * Figure out which data we need to fix. - */ - data = variables[i].data; /* prefer this. */ - if (!data && base) data = ((char *)base) + variables[i].offset; - if (!data) continue; - - /* - * Non-xlat expansions shouldn't have xlat! + * Grab the next token. */ - if (!is_xlat && !is_tmpl) { - /* - * Ignore %{... in shared secrets. - * They're never dynamically expanded. - */ - if ((variables[i].type & FR_TYPE_SECRET) != 0) continue; + t2 = gettoken(&ptr, buff[2], talloc_array_length(buff[2]), false); + switch (t2) { + case T_HASH: + case T_EOL: + case T_COMMA: + do_bare_word: + t3 = t2; + t2 = T_OP_EQ; + value = NULL; + goto do_set; - if (strstr(cp->value, "%{") != NULL) { - cf_log_err(&cp->item, "Found dynamic expansion in string which " - "will not be dynamically expanded"); - return -1; + case T_OP_INCRM: + case T_OP_ADD: + case T_OP_SUB: + case T_OP_NE: + case T_OP_GE: + case T_OP_GT: + case T_OP_LE: + case T_OP_LT: + case T_OP_CMP_EQ: + case T_OP_CMP_FALSE: + if (!this || ((strcmp(this->name1, "update") != 0) && (strcmp(this->name1, "map") != 0))) { + ERROR("%s[%d]: Invalid operator in assignment", + filename, *lineno); + goto error; } - continue; - } - - /* - * Parse (and throw away) the xlat string (for validation). - * - * FIXME: All of these should be converted from FR_TYPE_XLAT - * to FR_TYPE_TMPL. - */ - if (is_xlat) { - char const *error; - ssize_t slen; - char *value; - xlat_exp_t *xlat; + /* FALL-THROUGH */ - redo: - xlat = NULL; + case T_OP_EQ: + case T_OP_SET: + while (isspace((int) *ptr)) ptr++; /* - * xlat expansions should be parseable. + * New parser: non-quoted strings are + * bare words, and we parse everything + * until the next newline, or the next + * comma. If they have { or } in a bare + * word, well... too bad. */ - value = talloc_strdup(cs, cp->value); /* modified by xlat_tokenize */ - slen = xlat_tokenize(cs, value, &xlat, &error); - if (slen < 0) { - char *spaces, *text; + switch (*ptr) { + case '"': + case '\'': + case '`': + case '/': + t3 = getstring(&ptr, buff[3], talloc_array_length(buff[3]), false); + break; - fr_canonicalize_error(cs, &spaces, &text, slen, cp->value); + default: + { + const char *q = ptr; - cf_log_err_cp(cp, "Failed parsing expanded string:"); - cf_log_err_cp(cp, "%s", text); - cf_log_err_cp(cp, "%s^ %s", spaces, error); + t3 = T_BARE_WORD; + while (*q && (*q >= ' ') && (*q != ',') && + !isspace(*q)) q++; - talloc_free(spaces); - talloc_free(text); - talloc_free(value); - talloc_free(xlat); - return -1; + if ((size_t) (q - ptr) >= talloc_array_length(buff[3])) { + ERROR("%s[%d]: Parse error: value too long", filename, *lineno); + goto error; + } + + memcpy(buff[3], ptr, (q - ptr)); + buff[3][q - ptr] = '\0'; + ptr = q; + } } - talloc_free(value); - talloc_free(xlat); + if (t3 == T_INVALID) { + ERROR("%s[%d]: Parse error: %s", filename, *lineno, fr_strerror()); + goto error; + } /* - * If the "multi" flag is set, check all of them. + * Allow "foo" by itself, or "foo = bar" */ - if (multi) { - cp = cf_pair_find_next(cs, cp, cp->attr); - if (cp) goto redo; - } - continue; - - /* - * Parse the pair into a template - */ - } else if (is_tmpl) { - ssize_t slen; - - vp_tmpl_t **out = (vp_tmpl_t **)data; - vp_tmpl_t *vpt; + switch (t3) { + bool soft_fail; - slen = tmpl_afrom_str(cs, &vpt, cp->value, talloc_array_length(cp->value) - 1, - cf_pair_value_type(cp), - REQUEST_CURRENT, PAIR_LIST_REQUEST, true); - if (slen < 0) { - char *spaces, *text; + case T_BARE_WORD: + case T_DOUBLE_QUOTED_STRING: + case T_BACK_QUOTED_STRING: +#ifdef WITH_CONF_WRITE + orig_value = buff[3]; +#endif + value = cf_expand_variables(filename, lineno, this, buff[4], talloc_array_length(buff[4]), buff[3], &soft_fail); + if (!value) { + if (!soft_fail) goto error; - fr_canonicalize_error(vpt, &spaces, &text, slen, cp->value); + /* + * References an item which doesn't exist, + * or which is already marked up as being + * expanded in pass2. Wait for pass2 to + * do the expansions. + */ + pass2 = true; + value = buff[3]; + } + break; - cf_log_err_cp(cp, "%s", text); - cf_log_err_cp(cp, "%s^ %s", spaces, fr_strerror()); + case T_HASH: + case T_EOL: + value = NULL; + break; - talloc_free(spaces); - talloc_free(text); - return -1; + default: + value = buff[3]; + break; } - if (attribute && (vpt->type != TMPL_TYPE_ATTR)) { - cf_log_err(&cp->item, "Expected attr got %s", - fr_int2str(tmpl_names, vpt->type, "???")); - return -1; - } + /* + * Add this CONF_PAIR to our CONF_SECTION + */ + do_set: + cpn = cf_pair_alloc(this, buff[1], value, t2, t1, t3); + if (!cpn) goto error; + cpn->item.filename = filename; + cpn->item.lineno = *lineno; + cpn->pass2 = pass2; + cf_item_add(this, &(cpn->item)); - switch (vpt->type) { +#ifdef WITH_CONF_WRITE + if (orig_value) cpn->orig_value = talloc_typed_strdup(cpn, orig_value); + orig_value = NULL; +#endif /* - * All attributes should have been defined by this point. + * Require a comma, unless there's a comment. */ - case TMPL_TYPE_ATTR_UNDEFINED: - talloc_free(vpt); - cf_log_err(&cp->item, "Unknown attribute '%s'", vpt->tmpl_unknown_name); - return -1; + while (isspace(*ptr)) ptr++; - case TMPL_TYPE_UNPARSED: - case TMPL_TYPE_ATTR: - case TMPL_TYPE_LIST: - case TMPL_TYPE_DATA: - case TMPL_TYPE_EXEC: - case TMPL_TYPE_XLAT: - case TMPL_TYPE_XLAT_STRUCT: + if (*ptr == ',') { + ptr++; break; + } - case TMPL_TYPE_UNKNOWN: - case TMPL_TYPE_REGEX: - case TMPL_TYPE_REGEX_STRUCT: - case TMPL_TYPE_NULL: - rad_assert(0); - /* Don't add default */ + /* + * module # stuff! + * foo = bar # other stuff + */ +#ifdef WITH_CONF_WRITE + if (*ptr == '#') { + t3 = T_HASH; + ptr++; } /* - * Free the old value if we're overwriting + * Allocate a CONF_COMMENT, and add it to the list of children. */ - TALLOC_FREE(*out); - *(vp_tmpl_t **)out = vpt; - } - } /* for all variables in the configuration section */ + if ((t3 == T_HASH) && (*ptr >= ' ')) { + cf_comment_add(this, *lineno, ptr); + } +#endif - return 0; -} + if ((t3 == T_HASH) || (t3 == T_COMMA) || (t3 == T_EOL) || (*ptr == '#')) continue; -/** Parses a #CONF_PAIR into a C data type - * - * @copybrief cf_pair_value - * @see cf_pair_value - * - * @param[out] out Where to write the parsed value. - * @param[in] ctx to allocate any dynamic buffers in. - * @param[in] cs containing the cp. - * @param[in] cp to parse. - * @param[in] type to parse to. May contain flags. - * @return - * - 0 on success. - * - -1 on failure. - */ -static int cf_pair_parse_value(TALLOC_CTX *ctx, void *out, CONF_SECTION *cs, CONF_PAIR *cp, unsigned int type) -{ - int rcode = 0; - bool attribute, required, secret, file_input, cant_be_empty, tmpl, file_exists; - - fr_ipaddr_t *ipaddr; - ssize_t slen; + if (!*ptr || (*ptr == '}')) break; - if (!cs) return -1; + ERROR("%s[%d]: Syntax error: Expected comma after '%s': %s", + filename, *lineno, value, ptr); + goto error; - attribute = (type & FR_TYPE_ATTRIBUTE); - required = (type & FR_TYPE_REQUIRED); - secret = (type & FR_TYPE_SECRET); - file_input = (type == FR_TYPE_FILE_INPUT); /* check, not and */ - file_exists = (type == FR_TYPE_FILE_EXISTS); /* check, not and */ - cant_be_empty = (type & FR_TYPE_NOT_EMPTY); - tmpl = (type & FR_TYPE_TMPL); + /* + * No '=', must be a section or sub-section. + */ + case T_BARE_WORD: + case T_DOUBLE_QUOTED_STRING: + case T_SINGLE_QUOTED_STRING: + t3 = gettoken(&ptr, buff[3], talloc_array_length(buff[3]), true); + if (t3 != T_LCBRACE) { + ERROR("%s[%d]: Expecting section start brace '{' after \"%s %s\"", + filename, *lineno, buff[1], buff[2]); + goto error; + } + /* FALL-THROUGH */ - rad_assert(cp); - rad_assert(!(type & FR_TYPE_ATTRIBUTE) || tmpl); /* Attribute flag only valid for templates */ + alloc_section: + case T_LCBRACE: + css = cf_section_alloc(this, buff[1], + t2 == T_LCBRACE ? NULL : buff[2]); + if (!css) { + ERROR("%s[%d]: Failed allocating memory for section", + filename, *lineno); + goto error; + } - if (required) cant_be_empty = true; /* May want to review this in the future... */ + css->item.filename = filename; + css->item.lineno = *lineno; + cf_item_add(this, &(css->item)); - type = FR_BASE_TYPE(type); /* normal types are small */ + /* + * There may not be a name2 + */ + css->name2_quote = (t2 == T_LCBRACE) ? T_INVALID : t2; - /* - * Everything except templates must have a base type. - */ - if (!type && !tmpl) { - cf_log_err_cp(cp, "Configuration pair \"%s\" must have a data type", cf_pair_attr(cp)); - return -1; - } + /* + * The current section is now the child section. + */ + this = css; + break; - rad_assert(cp->value); + case T_INVALID: + ERROR("%s[%d]: Syntax error in '%s': %s", filename, *lineno, ptr, fr_strerror()); - /* - * Check for zero length strings - */ - if ((cp->value[0] == '\0') && cant_be_empty) { - cf_log_err_cp(cp, "Configuration pair \"%s\" must not be empty (zero length)", cf_pair_attr(cp)); - if (!required) cf_log_err_cp(cp, "Comment item to silence this message"); - rcode = -1; + goto error; - error: - return rcode; - } + default: + ERROR("%s[%d]: Parse error after \"%s\": unexpected token \"%s\"", + filename, *lineno, buff[1], fr_int2str(fr_tokens_table, t2, "")); - if (tmpl) { - vp_tmpl_t *vpt; + goto error; + } + check_for_more: /* - * This is so we produce TMPL_TYPE_ATTR_UNDEFINED template that - * the bootstrap functions can use to create an attribute. - * - * For other types of template such as xlats, we don't bother. - * There's no reason bootstrap functions need access to the raw - * xlat strings. + * Done parsing one thing. Skip to EOL if possible. */ - if (attribute) { - slen = tmpl_afrom_attr_str(cp, &vpt, cp->value, REQUEST_CURRENT, PAIR_LIST_REQUEST, - true, true); - if (slen < 0) { - char *spaces, *text; - - fr_canonicalize_error(ctx, &spaces, &text, slen, cp->value); + while (isspace(*ptr)) ptr++; - cf_log_err(&cp->item, "Failed parsing attribute reference:"); - cf_log_err(&cp->item, "%s", text); - cf_log_err(&cp->item, "%s^ %s", spaces, fr_strerror()); + if (*ptr == '#') continue; - talloc_free(spaces); - talloc_free(text); - goto error; - } - *(vp_tmpl_t **)out = vpt; + if (*ptr) { + goto get_more; } - goto finish; - } - switch (type) { - case FR_TYPE_BOOL: - /* - * Allow yes/no, true/false, and on/off - */ - if ((strcasecmp(cp->value, "yes") == 0) || - (strcasecmp(cp->value, "true") == 0) || - (strcasecmp(cp->value, "on") == 0)) { - *(bool *)out = true; - } else if ((strcasecmp(cp->value, "no") == 0) || - (strcasecmp(cp->value, "false") == 0) || - (strcasecmp(cp->value, "off") == 0)) { - *(bool *)out = false; - } else { - cf_log_err(&(cs->item), "Invalid value \"%s\" for boolean variable %s", - cp->value, cf_pair_attr(cp)); - rcode = -1; - goto error; - } - cf_log_info(cs, "%.*s\t%s = %s", cs->depth, parse_spaces, cf_pair_attr(cp), cp->value); - break; + } - case FR_TYPE_UINT32: - { - unsigned long v = strtoul(cp->value, 0, 0); + /* + * See if EOF was unexpected .. + */ + if (feof(fp) && (this != current)) { + ERROR("%s[%d]: EOF reached without closing brace for section %s starting at line %d", + filename, *lineno, cf_section_name1(this), cf_lineno(this)); + goto error; + } - /* - * Restrict integer values to 0-INT32_MAX, this means - * it will always be safe to cast them to a signed type - * for comparisons, and imposes the same range limit as - * before we switched to using an unsigned type to - * represent config item integers. - */ - if (v > INT32_MAX) { - cf_log_err(&(cs->item), "Invalid value \"%s\" for variable %s, must be between 0-%u", cp->value, - cf_pair_attr(cp), INT32_MAX); - rcode = -1; - goto error; - } + return 0; +} - *(uint32_t *)out = v; - cf_log_info(cs, "%.*s\t%s = %u", cs->depth, parse_spaces, cf_pair_attr(cp), *(uint32_t *)out); - } - break; +/* + * Include one config file in another. + */ +static int cf_file_include(CONF_SECTION *cs, char const *filename_in, +#ifndef WITH_CONF_WRITE + UNUSED +#endif + CONF_INCLUDE_TYPE file_type, char *buff[7]) +{ + FILE *fp; + int lineno = 0; + char const *filename; - case FR_TYPE_UINT8: - { - unsigned long v = strtoul(cp->value, 0, 0); + /* + * So we only need to do this once. + */ + filename = talloc_strdup(cs, filename_in); - if (v > UINT8_MAX) { - cf_log_err(&(cs->item), "Invalid value \"%s\" for variable %s, must be between 0-%u", cp->value, - cf_pair_attr(cp), UINT8_MAX); - rcode = -1; - goto error; - } - *(uint8_t *)out = (uint8_t) v; - cf_log_info(cs, "%.*s\t%s = %u", cs->depth, parse_spaces, cf_pair_attr(cp), *(uint8_t *)out); - } - break; + DEBUG2("Including configuration file \"%s\"", filename); - case FR_TYPE_UINT16: - { - unsigned long v = strtoul(cp->value, 0, 0); + fp = cf_file_open(cs, filename); + if (!fp) return -1; - if (v > UINT16_MAX) { - cf_log_err(&(cs->item), "Invalid value \"%s\" for variable %s, must be between 0-%u", cp->value, - cf_pair_attr(cp), UINT16_MAX); - rcode = -1; - goto error; - } - *(uint16_t *)out = (uint16_t) v; - cf_log_info(cs, "%.*s\t%s = %u", cs->depth, parse_spaces, cf_pair_attr(cp), *(uint16_t *)out); - } - break; + if (!cs->item.filename) cs->item.filename = filename; - case FR_TYPE_UINT64: - *(uint64_t *)out = strtoull(cp->value, NULL, 10); - cf_log_info(cs, "%.*s\t%s = %" PRIu64, cs->depth, parse_spaces, cf_pair_attr(cp), *(uint64_t *)out); - break; +#ifdef WITH_CONF_WRITE + /* + * Instruct the parser that we've started to include a + * file at this point. + */ + cf_include_add(cs, filename, file_type); +#endif - case FR_TYPE_SIZE: - { - if (fr_size_from_str((size_t *)out, cp->value) < 0) { - cf_log_err(&(cs->item), "Invalid value \"%s\" for variable %s: %s", cp->value, - cf_pair_attr(cp), fr_strerror()); - rcode = -1; - goto error; - } - cf_log_info(cs, "%.*s\t%s = %zu", cs->depth, parse_spaces, cf_pair_attr(cp), *(size_t *)out); - break; + /* + * Read the section. It's OK to have EOF without a + * matching close brace. + */ + if (cf_section_read(filename, &lineno, fp, cs, buff) < 0) { + ERROR("Failed parsing configuration file \"%s\"", filename); + fclose(fp); + return -1; } - case FR_TYPE_INT32: - *(int32_t *)out = strtol(cp->value, NULL, 10); - cf_log_info(cs, "%.*s\t%s = %d", cs->depth, parse_spaces, cf_pair_attr(cp), *(int32_t *)out); - break; +#ifdef WITH_CONF_WRITE + /* + * Instruct the parser that we've finished including a + * file at this point. + */ + cf_include_add(cs, NULL, file_type); +#endif - case FR_TYPE_STRING: - { - char **str = out; + fclose(fp); + return 0; +} - /* - * Hide secrets when using "radiusd -X". - */ - if (secret && (rad_debug_lvl < L_DBG_LVL_3)) { - cf_log_info(cs, "%.*s\t%s = <<< secret >>>", cs->depth, parse_spaces, cf_pair_attr(cp)); - } else { - cf_log_info(cs, "%.*s\t%s = \"%s\"", cs->depth, parse_spaces, cf_pair_attr(cp), cp->value); - } - - /* - * If there's out AND it's an input file, check - * that we can read it. This check allows errors - * to be caught as early as possible, during - * server startup. - */ - if (file_input && !cf_file_check(cs, cp->value, true)) { - rcode = -1; - goto error; - } - - if (file_exists && !cf_file_check(cs, cp->value, false)) { - rcode = -1; - goto error; - } - - /* - * Free any existing buffers - */ - talloc_free(*str); - *str = talloc_typed_strdup(cs, cp->value); - } - break; - - case FR_TYPE_IPV4_ADDR: - case FR_TYPE_IPV4_PREFIX: - ipaddr = out; +/* + * Bootstrap a config file. + */ +int cf_file_read(CONF_SECTION *cs, char const *filename) +{ + int i; + char *p; + CONF_PAIR *cp; + rbtree_t *tree; + char **buff; - if (fr_inet_pton4(ipaddr, cp->value, -1, true, false, true) < 0) { - cf_log_err(&(cp->item), "%s", fr_strerror()); - rcode = -1; - goto error; - } - /* Also prints the IP to the log */ - if (fr_item_validate_ipaddr(cs, cf_pair_attr(cp), type, cp->value, ipaddr) < 0) { - rcode = -1; - goto error; - } - break; + cp = cf_pair_alloc(cs, "confdir", filename, T_OP_EQ, T_BARE_WORD, T_SINGLE_QUOTED_STRING); + if (!cp) return -1; - case FR_TYPE_IPV6_ADDR: - case FR_TYPE_IPV6_PREFIX: - ipaddr = out; + p = strrchr(cp->value, FR_DIR_SEP); + if (p) *p = '\0'; - if (fr_inet_pton6(ipaddr, cp->value, -1, true, false, true) < 0) { - cf_log_err(&(cp->item), "%s", fr_strerror()); - rcode = -1; - goto error; - } - /* Also prints the IP to the log */ - if (fr_item_validate_ipaddr(cs, cf_pair_attr(cp), type, cp->value, ipaddr) < 0) { - rcode = -1; - goto error; - } - break; + cf_item_add(cs, &(cp->item)); - case FR_TYPE_COMBO_IP_ADDR: - case FR_TYPE_COMBO_IP_PREFIX: - ipaddr = out; + MEM(tree = rbtree_create(cs, _filename_cmp, NULL, 0)); - if (fr_inet_pton(ipaddr, cp->value, -1, AF_UNSPEC, true, true) < 0) { - cf_log_err(&(cp->item), "%s", fr_strerror()); - rcode = -1; - goto error; - } - /* Also prints the IP to the log */ - if (fr_item_validate_ipaddr(cs, cf_pair_attr(cp), type, cp->value, ipaddr) < 0) { - rcode = -1; - goto error; - } - break; + cf_data_add(cs, tree, "filename", false); - case FR_TYPE_TIMEVAL: - { - struct timeval tv; + /* + * Allocate temporary buffers on the heap (so we don't use *all* the stack space) + */ + buff = talloc_array(cs, char *, 7); + for (i = 0; i < 7; i++) MEM(buff[i] = talloc_array(buff, char, 8192)); - if (fr_timeval_from_str(&tv, cp->value) < 0) { - cf_log_err(&(cp->item), "%s", fr_strerror()); - rcode = -1; - goto error; - } - cf_log_info(cs, "%.*s\t%s = %d.%06d", cs->depth, parse_spaces, cf_pair_attr(cp), - (int)tv.tv_sec, (int)tv.tv_usec); - memcpy(out, &tv, sizeof(tv)); + if (cf_file_include(cs, filename, CONF_INCLUDE_FILE, buff) < 0) { + talloc_free(buff); + return -1; } - break; - default: - /* - * If we get here, it's a sanity check error. - * It's not an error parsing the configuration - * file. - */ - rad_assert(type > FR_TYPE_INVALID); - rad_assert(type < FR_TYPE_MAX); + talloc_free(buff); - cf_log_err(&(cp->item), "type '%s' (%i) is not supported in the configuration files", - fr_int2str(dict_attr_types, type, "?Unknown?"), type); - rcode = -1; - goto error; + /* + * Now that we've read the file, go back through it and + * expand the variables. + */ + if (cf_section_pass2(cs) < 0) { + cf_log_err(cs, "Parsing config items failed"); + return -1; } -finish: - cp->parsed = true; + return 0; +} - return rcode; +void cf_file_free(CONF_SECTION *cs) +{ + talloc_free(cs); } -/** Allocate a pair using the dflt value and quotation +/** Set the euid/egid used when performing file checks * - * The pair created by this function should fed to #cf_pair_parse for parsing. + * Sets the euid, and egid used when cf_file_check is called to check + * permissions on conf items of type #FR_TYPE_FILE_INPUT. * - * @param[out] out Where to write the CONF_PAIR we created with the default value. - * @param[in] cs to parent the CONF_PAIR from. - * @param[in] name of the CONF_PAIR to create. - * @param[in] type of conf item being parsed (determines default quoting). - * @param[in] dflt value to assign the CONF_PAIR. - * @param[in] dflt_quote surrounding the CONF_PAIR. - * @return - * - 0 on success. - * - -1 on failure. + * @note This is probably only useful for the freeradius daemon itself. + * + * @param uid to set, (uid_t)-1 to use current euid. + * @param gid to set, (gid_t)-1 to use current egid. */ -static int cf_pair_default(CONF_PAIR **out, CONF_SECTION *cs, char const *name, - int type, char const *dflt, FR_TOKEN dflt_quote) +void cf_file_check_user(uid_t uid, gid_t gid) { - int lineno = 0; - char const *expanded; - CONF_PAIR *cp; - char buffer[8192]; + if (uid != 0) conf_check_uid = uid; + if (gid != 0) conf_check_gid = gid; +} - rad_assert(dflt); +/* + * See if any of the files have changed. + */ +int cf_file_changed(CONF_SECTION *cs, rb_walker_t callback) +{ + CONF_SECTION *top; + cf_file_callback_t cb; + rbtree_t *tree; - type = FR_BASE_TYPE(type); + top = cf_root(cs); + tree = cf_data_value(cf_data_find(top, rbtree_t, "filename")); + if (!tree) return true; - /* - * Defaults may need their values expanding - */ - expanded = cf_expand_variables("", &lineno, cs, buffer, sizeof(buffer), dflt, NULL); - if (!expanded) { - cf_log_err(&(cs->item), "Failed expanding variable %s", name); - return -1; - } + cb.rcode = CF_FILE_NONE; + cb.callback = callback; + cb.modules = cf_section_find(cs, "modules", NULL); - /* - * If no default quote was set, determine it from the type - */ - if (dflt_quote == T_INVALID) { - switch (type) { - case FR_TYPE_STRING: - dflt_quote = T_DOUBLE_QUOTED_STRING; - break; + (void) rbtree_walk(tree, RBTREE_IN_ORDER, _file_callback, &cb); - case FR_TYPE_FILE_INPUT: - case FR_TYPE_FILE_OUTPUT: - dflt_quote = T_DOUBLE_QUOTED_STRING; - break; + return cb.rcode; +} - default: - dflt_quote = T_BARE_WORD; - break; - } - } +#ifdef WITH_CONF_WRITE +static char const parse_tabs[] = " "; - cp = cf_pair_alloc(cs, name, expanded, T_OP_EQ, T_BARE_WORD, dflt_quote); - if (!cp) return -1; +static ssize_t cf_string_write(FILE *fp, char const *string, size_t len, FR_TOKEN t) +{ + size_t outlen; + char c; + char buffer[2048]; - cp->parsed = true; + switch (t) { + default: + c = '\0'; + break; - /* - * Set the rcode to indicate we used a default value - */ - *out = cp; + case T_DOUBLE_QUOTED_STRING: + c = '"'; + break; + + case T_SINGLE_QUOTED_STRING: + c = '\''; + break; + + case T_BACK_QUOTED_STRING: + c = '`'; + break; + } + if (c) fprintf(fp, "%c", c); + + outlen = fr_snprint(buffer, sizeof(buffer), string, len, c); + fwrite(buffer, outlen, 1, fp); + + if (c) fprintf(fp, "%c", c); return 1; } -/** Parses a #CONF_PAIR into a C data type, with a default value. - * - * Takes fields from a #CONF_PARSER struct and uses them to parse the string value - * of a #CONF_PAIR into a C data type matching the type argument. - * - * The format of the types are the same as #fr_value_box_t types. - * - * @note The dflt value will only be used if no matching #CONF_PAIR is found. Empty strings will not - * result in the dflt value being used. - * - * **fr_type_t to data type mappings** - * | fr_type_t | Data type | Dynamically allocated | - * | ----------------------- | ------------------ | ---------------------- | - * | FR_TYPE_TMPL | ``vp_tmpl_t`` | Yes | - * | FR_TYPE_BOOL | ``bool`` | No | - * | FR_TYPE_UINT32 | ``uint32_t`` | No | - * | FR_TYPE_UINT16 | ``uint16_t`` | No | - * | FR_TYPE_UINT64 | ``uint64_t`` | No | - * | FR_TYPE_INT32 | ``int32_t`` | No | - * | FR_TYPE_STRING | ``char const *`` | Yes | - * | FR_TYPE_IPV4_ADDR | ``fr_ipaddr_t`` | No | - * | FR_TYPE_IPV4_PREFIX | ``fr_ipaddr_t`` | No | - * | FR_TYPE_IPV6_ADDR | ``fr_ipaddr_t`` | No | - * | FR_TYPE_IPV6_PREFIX | ``fr_ipaddr_t`` | No | - * | FR_TYPE_COMBO_IP_ADDR | ``fr_ipaddr_t`` | No | - * | FR_TYPE_COMBO_IP_PREFIX | ``fr_ipaddr_t`` | No | - * | FR_TYPE_TIMEVAL | ``struct timeval`` | No | - * - * @param[in] ctx To allocate arrays and values in. - * @param[in] cs to search for matching #CONF_PAIR in. - * @param[in] name of #CONF_PAIR to search for. - * @param[in] type Data type to parse #CONF_PAIR value as. - * Should be one of the following ``data`` types, - * and one or more of the following ``flag`` types or'd together: - * - ``data`` #FR_TYPE_TMPL - @copybrief FR_TYPE_TMPL - * Feeds the value into #tmpl_afrom_str. Value can be - * obtained when processing requests, with #tmpl_expand or #tmpl_aexpand. - * - ``data`` #FR_TYPE_BOOL - @copybrief FR_TYPE_BOOL - * - ``data`` #FR_TYPE_UINT32 - @copybrief FR_TYPE_UINT32 - * - ``data`` #FR_TYPE_UINT16 - @copybrief FR_TYPE_UINT16 - * - ``data`` #FR_TYPE_UINT64 - @copybrief FR_TYPE_UINT64 - * - ``data`` #FR_TYPE_INT32 - @copybrief FR_TYPE_INT32 - * - ``data`` #FR_TYPE_STRING - @copybrief FR_TYPE_STRING - * - ``data`` #FR_TYPE_IPV4_ADDR - @copybrief FR_TYPE_IPV4_ADDR (IPv4 address with prefix 32). - * - ``data`` #FR_TYPE_IPV4_PREFIX - @copybrief FR_TYPE_IPV4_PREFIX (IPv4 address with variable prefix). - * - ``data`` #FR_TYPE_IPV6_ADDR - @copybrief FR_TYPE_IPV6_ADDR (IPv6 address with prefix 128). - * - ``data`` #FR_TYPE_IPV6_PREFIX - @copybrief FR_TYPE_IPV6_PREFIX (IPv6 address with variable prefix). - * - ``data`` #FR_TYPE_COMBO_IP_ADDR - @copybrief FR_TYPE_COMBO_IP_ADDR (IPv4/IPv6 address with - * prefix 32/128). - * - ``data`` #FR_TYPE_COMBO_IP_PREFIX - @copybrief FR_TYPE_COMBO_IP_PREFIX (IPv4/IPv6 address with - * variable prefix). - * - ``data`` #FR_TYPE_TIMEVAL - @copybrief FR_TYPE_TIMEVAL - * - ``flag`` #FR_TYPE_DEPRECATED - @copybrief FR_TYPE_DEPRECATED - * - ``flag`` #FR_TYPE_REQUIRED - @copybrief FR_TYPE_REQUIRED - * - ``flag`` #FR_TYPE_ATTRIBUTE - @copybrief FR_TYPE_ATTRIBUTE - * - ``flag`` #FR_TYPE_SECRET - @copybrief FR_TYPE_SECRET - * - ``flag`` #FR_TYPE_FILE_INPUT - @copybrief FR_TYPE_FILE_INPUT - * - ``flag`` #FR_TYPE_NOT_EMPTY - @copybrief FR_TYPE_NOT_EMPTY - * - ``flag`` #FR_TYPE_MULTI - @copybrief FR_TYPE_MULTI - * - ``flag`` #FR_TYPE_IS_SET - @copybrief FR_TYPE_IS_SET - * @param[out] out Pointer to a global variable, or pointer to a field in the struct being populated with values. - * @param[in] dflt value to use, if no #CONF_PAIR is found. - * @param[in] dflt_quote around the dflt value. - * @return - * - 1 if default value was used, or if there was no CONF_PAIR or dflt. - * - 0 on success. - * - -1 on error. - * - -2 if deprecated. - */ -int cf_pair_parse(TALLOC_CTX *ctx, CONF_SECTION *cs, - char const *name, unsigned int type, void *out, - char const *dflt, FR_TOKEN dflt_quote) +static size_t cf_pair_write(FILE *fp, CONF_PAIR *cp) { - bool multi, required, deprecated; - size_t count = 0; - CONF_PAIR *cp, *dflt_cp = NULL; + if (!cp->value) { + fprintf(fp, "%s\n", cp->attr); + return 0; + } - rad_assert(!(type & FR_TYPE_TMPL) || !dflt || (dflt_quote != T_INVALID)); /* We ALWAYS need a quoting type for templates */ + cf_string_write(fp, cp->attr, strlen(cp->attr), cp->lhs_quote); + fprintf(fp, " %s ", fr_int2str(fr_tokens_table, cp->op, "")); + cf_string_write(fp, cp->orig_value, strlen(cp->orig_value), cp->rhs_quote); + fprintf(fp, "\n"); - multi = (type & FR_TYPE_MULTI); - required = (type & FR_TYPE_REQUIRED); - deprecated = (type & FR_TYPE_DEPRECATED); + return 1; /* FIXME */ +} + +static FILE *cf_file_write(CONF_SECTION *cs, char const *filename) +{ + FILE *fp; + char *p; + char const *q; + char buffer[8192]; + + q = filename; + if ((q[0] == '.') && (q[1] == '/')) q += 2; + + snprintf(buffer, sizeof(buffer), "%s/%s", main_config.write_dir, q); + + p = strrchr(buffer, '/'); + *p = '\0'; + if ((rad_mkdir(buffer, 0700, -1, -1) < 0) && + (errno != EEXIST)) { + cf_log_err(cs, "Failed creating directory %s: %s", + buffer, strerror(errno)); + return NULL; + } /* - * If the item is multi-valued we allocate an array - * to hold the multiple values. + * And again, because rad_mkdir() butchers the buffer. */ - if (multi) { - CONF_PAIR *first; - void **array; - size_t i; + snprintf(buffer, sizeof(buffer), "%s/%s", main_config.write_dir, q); - /* - * Easier than re-allocing - */ - for (cp = first = cf_pair_find(cs, name); - cp; - cp = cf_pair_find_next(cs, cp, name)) count++; + fp = fopen(buffer, "a"); + if (!fp) { + cf_log_err(cs, "Failed creating file %s: %s", + buffer, strerror(errno)); + return NULL; + } - /* - * Multivalued, but there's no value, create a - * default pair. - */ - if (!count) { - if (deprecated) return 0; - if (!dflt) { - if (required) { - need_value: - cf_log_err_cs(cs, "Configuration item \"%s\" must have a value", name); - return -1; - } - return 1; - } + return fp; +} - if (cf_pair_default(&dflt_cp, cs, name, type, dflt, dflt_quote) < 0) return -1; - cp = dflt_cp; - count = 1; /* Need one to hold the default */ - } else { - cp = first; /* reset */ - } +size_t cf_section_write(FILE *in_fp, CONF_SECTION *cs, int depth) +{ + bool prev = false; + CONF_ITEM *ci; + FILE *fp = NULL; + int fp_max = 0; + FILE *array[32]; - if (deprecated) { - deprecated: - cf_log_err_cp(cp, "Configuration pair \"%s\" is deprecated", cf_pair_attr(cp)); - return -2; - } + /* + * Default to writing to the FP we're given. + */ + fp = in_fp; + array[0] = fp; + fp_max = 0; + + /* + * If we have somewhere to print, then print the section + * name1, etc. + */ + if (fp) { + fwrite(parse_tabs, depth, 1, fp); + cf_string_write(fp, cs->name1, strlen(cs->name1), T_BARE_WORD); /* - * Tmpl is outside normal range - */ - if (type & FR_TYPE_TMPL) { - array = (void **)talloc_zero_array(ctx, vp_tmpl_t *, count); - /* - * Allocate an array of values. + * FIXME: check for "if" or "elsif". And if so, print + * out the parsed condition, instead of the input text * - * We don't NULL terminate. Consumer must use - * talloc_array_length(). + * cf_data_find(cs, CF_DATA_TYPE_UNLANG, "if"); */ - } else switch (FR_BASE_TYPE(type)) { - case FR_TYPE_BOOL: - array = (void **)talloc_zero_array(ctx, bool, count); - break; - case FR_TYPE_UINT32: - array = (void **)talloc_zero_array(ctx, uint32_t, count); - break; + if (cs->name2) { + fr_cond_t *c; - case FR_TYPE_UINT16: - array = (void **)talloc_zero_array(ctx, uint16_t, count); - break; + fputs(" ", fp); - case FR_TYPE_UINT64: - array = (void **)talloc_zero_array(ctx, uint64_t, count); - break; + c = cf_data_value(cf_data_find(cs, fr_cond_t, NULL)); + if (c) { + char buffer[1024]; - case FR_TYPE_INT32: - array = (void **)talloc_zero_array(ctx, int32_t, count); - break; + cond_snprint(buffer, sizeof(buffer), c); + fprintf(fp, "(%s)", buffer); - case FR_TYPE_STRING: - array = (void **)talloc_zero_array(ctx, char *, count); + } else { /* dump the string as-is */ + cf_string_write(fp, cs->name2, strlen(cs->name2), cs->name2_quote); + } + } + + fputs(" {\n", fp); + } + + /* + * Loop over the children. Either recursing, or opening + * a new file. + */ + for (ci = cs->item.child; ci; ci = ci->next) { + switch (ci->type) { + case CONF_ITEM_SECTION: + if (!fp) continue; + + cf_section_write(fp, cf_item_to_section(ci), depth + 1); break; - case FR_TYPE_IPV4_ADDR: - case FR_TYPE_IPV4_PREFIX: - case FR_TYPE_IPV6_ADDR: - case FR_TYPE_IPV6_PREFIX: - case FR_TYPE_COMBO_IP_ADDR: - case FR_TYPE_COMBO_IP_PREFIX: - array = (void **)talloc_zero_array(ctx, fr_ipaddr_t, count); + case CONF_ITEM_PAIR: + if (!fp) continue; + + /* + * Ignore internal things. + */ + if (!ci->filename || (ci->filename[0] == '<')) break; + + fwrite(parse_tabs, depth + 1, 1, fp); + cf_pair_write(fp, cf_item_to_pair(ci)); + if (!prev) fputs("\n", fp); + prev = true; break; - case FR_TYPE_TIMEVAL: - array = (void **)talloc_zero_array(ctx, struct timeval, count); + case CONF_ITEM_COMMENT: + rad_assert(fp != NULL); + + prev = false; + fwrite(parse_tabs, depth + 1, 1, fp); + fprintf(fp, "#%s", ((CONF_COMMENT *)ci)->comment); break; - default: - rad_assert(0); /* Unsupported type */ - return -1; - } + case CONF_ITEM_INCLUDE: + /* + * Filename == open the new filename and use that. + * + * NULL == close the previous filename + */ + if (((CONF_INCLUDE *) ci)->filename) { + CONF_INCLUDE *cc = (CONF_INCLUDE *) ci; - for (i = 0; i < count; i++, cp = cf_pair_find_next(cs, cp, name)) { - if (cf_pair_parse_value(array, &array[i], cs, cp, type) < 0) { - talloc_free(array); - talloc_free(dflt_cp); - return -1; - } - } + /* + * Print out + * + * $INCLUDE foo.conf + * $INCLUDE foo/ + * + * but not the files included from the last one. + */ + if (fp && (cc->file_type != CONF_INCLUDE_FROMDIR)) { + fprintf(fp, "$INCLUDE %s\n", ((CONF_INCLUDE *)ci)->filename); + } - *(void **)out = array; - /* - * Single valued config item gets written to - * the data pointer directly. - */ - } else { - CONF_PAIR *next; + /* + * If it's a file, we write the + * file. We ignore the + * directories. They're just for printing. + */ + if (cc->file_type != CONF_INCLUDE_DIR) { + fp = cf_file_write(cs, ((CONF_INCLUDE *) ci)->filename); + if (!fp) return 0; + + fp_max++; + array[fp_max] = fp; + } + } else { + /* + * We're done the current file. + */ + rad_assert(fp != NULL); + rad_assert(fp_max > 0); + fclose(fp); + + fp_max--; + fp = array[fp_max]; + } + break; + + default: + break; + } + } + + if (fp) { + fwrite(parse_tabs, depth, 1, fp); + fputs("}\n\n", fp); + } + + return 1; +} +#endif /* WITH_CONF_WRITE */ + +static char const parse_spaces[] = " "; + +/** Validation function for ipaddr conf_file types + * + */ +static inline int fr_item_validate_ipaddr(CONF_SECTION *cs, char const *name, fr_type_t type, char const *value, + fr_ipaddr_t *ipaddr) +{ + char ipbuf[128]; + + if (strcmp(value, "*") == 0) { + cf_log_info(cs, "%.*s\t%s = *", cs->depth, parse_spaces, name); + } else if (strspn(value, ".0123456789abdefABCDEF:%[]/") == strlen(value)) { + cf_log_info(cs, "%.*s\t%s = %s", cs->depth, parse_spaces, name, value); + } else { + cf_log_info(cs, "%.*s\t%s = %s IPv%s address [%s]", cs->depth, parse_spaces, name, value, + (ipaddr->af == AF_INET ? "4" : " 6"), fr_inet_ntoh(ipaddr, ipbuf, sizeof(ipbuf))); + } + + switch (type) { + case FR_TYPE_IPV4_ADDR: + case FR_TYPE_IPV6_ADDR: + case FR_TYPE_COMBO_IP_ADDR: + switch (ipaddr->af) { + case AF_INET: + if (ipaddr->prefix != 32) { + ERROR("Invalid IPv4 mask length \"/%i\". Only \"/32\" permitted for non-prefix types", + ipaddr->prefix); + + return -1; + } + break; + + case AF_INET6: + if (ipaddr->prefix != 128) { + ERROR("Invalid IPv6 mask length \"/%i\". Only \"/128\" permitted for non-prefix types", + ipaddr->prefix); + + return -1; + } + break; + + default: + return -1; + } + default: + return 0; + } +} + + + +/** Parses a #CONF_PAIR into a C data type + * + * @copybrief cf_pair_value + * @see cf_pair_value + * + * @param[out] out Where to write the parsed value. + * @param[in] ctx to allocate any dynamic buffers in. + * @param[in] cs containing the cp. + * @param[in] cp to parse. + * @param[in] type to parse to. May contain flags. + * @return + * - 0 on success. + * - -1 on failure. + */ +static int cf_pair_parse_value(TALLOC_CTX *ctx, void *out, CONF_SECTION *cs, CONF_PAIR *cp, unsigned int type) +{ + int rcode = 0; + bool attribute, required, secret, file_input, cant_be_empty, tmpl, file_exists; + + fr_ipaddr_t *ipaddr; + ssize_t slen; + + if (!cs) return -1; + + attribute = (type & FR_TYPE_ATTRIBUTE); + required = (type & FR_TYPE_REQUIRED); + secret = (type & FR_TYPE_SECRET); + file_input = (type == FR_TYPE_FILE_INPUT); /* check, not and */ + file_exists = (type == FR_TYPE_FILE_EXISTS); /* check, not and */ + cant_be_empty = (type & FR_TYPE_NOT_EMPTY); + tmpl = (type & FR_TYPE_TMPL); + + rad_assert(cp); + rad_assert(!(type & FR_TYPE_ATTRIBUTE) || tmpl); /* Attribute flag only valid for templates */ + + if (required) cant_be_empty = true; /* May want to review this in the future... */ + + type = FR_BASE_TYPE(type); /* normal types are small */ + + /* + * Everything except templates must have a base type. + */ + if (!type && !tmpl) { + cf_log_err(cp, "Configuration pair \"%s\" must have a data type", cf_pair_attr(cp)); + return -1; + } + + rad_assert(cp->value); + + /* + * Check for zero length strings + */ + if ((cp->value[0] == '\0') && cant_be_empty) { + cf_log_err(cp, "Configuration pair \"%s\" must not be empty (zero length)", cf_pair_attr(cp)); + if (!required) cf_log_err(cp, "Comment item to silence this message"); + rcode = -1; + + error: + return rcode; + } + + if (tmpl) { + vp_tmpl_t *vpt; + + /* + * This is so we produce TMPL_TYPE_ATTR_UNDEFINED template that + * the bootstrap functions can use to create an attribute. + * + * For other types of template such as xlats, we don't bother. + * There's no reason bootstrap functions need access to the raw + * xlat strings. + */ + if (attribute) { + slen = tmpl_afrom_attr_str(cp, &vpt, cp->value, REQUEST_CURRENT, PAIR_LIST_REQUEST, + true, true); + if (slen < 0) { + char *spaces, *text; + + fr_canonicalize_error(ctx, &spaces, &text, slen, cp->value); + + cf_log_err(&cp->item, "Failed parsing attribute reference:"); + cf_log_err(&cp->item, "%s", text); + cf_log_err(&cp->item, "%s^ %s", spaces, fr_strerror()); + + talloc_free(spaces); + talloc_free(text); + goto error; + } + *(vp_tmpl_t **)out = vpt; + } + goto finish; + } + + switch (type) { + case FR_TYPE_BOOL: + /* + * Allow yes/no, true/false, and on/off + */ + if ((strcasecmp(cp->value, "yes") == 0) || + (strcasecmp(cp->value, "true") == 0) || + (strcasecmp(cp->value, "on") == 0)) { + *(bool *)out = true; + } else if ((strcasecmp(cp->value, "no") == 0) || + (strcasecmp(cp->value, "false") == 0) || + (strcasecmp(cp->value, "off") == 0)) { + *(bool *)out = false; + } else { + cf_log_err(&(cs->item), "Invalid value \"%s\" for boolean variable %s", + cp->value, cf_pair_attr(cp)); + rcode = -1; + goto error; + } + cf_log_info(cs, "%.*s\t%s = %s", cs->depth, parse_spaces, cf_pair_attr(cp), cp->value); + break; + + case FR_TYPE_UINT32: + { + unsigned long v = strtoul(cp->value, 0, 0); + + /* + * Restrict integer values to 0-INT32_MAX, this means + * it will always be safe to cast them to a signed type + * for comparisons, and imposes the same range limit as + * before we switched to using an unsigned type to + * represent config item integers. + */ + if (v > INT32_MAX) { + cf_log_err(&(cs->item), "Invalid value \"%s\" for variable %s, must be between 0-%u", cp->value, + cf_pair_attr(cp), INT32_MAX); + rcode = -1; + goto error; + } + + *(uint32_t *)out = v; + cf_log_info(cs, "%.*s\t%s = %u", cs->depth, parse_spaces, cf_pair_attr(cp), *(uint32_t *)out); + } + break; + + case FR_TYPE_UINT8: + { + unsigned long v = strtoul(cp->value, 0, 0); + + if (v > UINT8_MAX) { + cf_log_err(&(cs->item), "Invalid value \"%s\" for variable %s, must be between 0-%u", cp->value, + cf_pair_attr(cp), UINT8_MAX); + rcode = -1; + goto error; + } + *(uint8_t *)out = (uint8_t) v; + cf_log_info(cs, "%.*s\t%s = %u", cs->depth, parse_spaces, cf_pair_attr(cp), *(uint8_t *)out); + } + break; + + case FR_TYPE_UINT16: + { + unsigned long v = strtoul(cp->value, 0, 0); + + if (v > UINT16_MAX) { + cf_log_err(&(cs->item), "Invalid value \"%s\" for variable %s, must be between 0-%u", cp->value, + cf_pair_attr(cp), UINT16_MAX); + rcode = -1; + goto error; + } + *(uint16_t *)out = (uint16_t) v; + cf_log_info(cs, "%.*s\t%s = %u", cs->depth, parse_spaces, cf_pair_attr(cp), *(uint16_t *)out); + } + break; + + case FR_TYPE_UINT64: + *(uint64_t *)out = strtoull(cp->value, NULL, 10); + cf_log_info(cs, "%.*s\t%s = %" PRIu64, cs->depth, parse_spaces, cf_pair_attr(cp), *(uint64_t *)out); + break; + + case FR_TYPE_SIZE: + { + if (fr_size_from_str((size_t *)out, cp->value) < 0) { + cf_log_err(&(cs->item), "Invalid value \"%s\" for variable %s: %s", cp->value, + cf_pair_attr(cp), fr_strerror()); + rcode = -1; + goto error; + } + cf_log_info(cs, "%.*s\t%s = %zu", cs->depth, parse_spaces, cf_pair_attr(cp), *(size_t *)out); + break; + } + + case FR_TYPE_INT32: + *(int32_t *)out = strtol(cp->value, NULL, 10); + cf_log_info(cs, "%.*s\t%s = %d", cs->depth, parse_spaces, cf_pair_attr(cp), *(int32_t *)out); + break; + + case FR_TYPE_STRING: + { + char **str = out; + + /* + * Hide secrets when using "radiusd -X". + */ + if (secret && (rad_debug_lvl < L_DBG_LVL_3)) { + cf_log_info(cs, "%.*s\t%s = <<< secret >>>", cs->depth, parse_spaces, cf_pair_attr(cp)); + } else { + cf_log_info(cs, "%.*s\t%s = \"%s\"", cs->depth, parse_spaces, cf_pair_attr(cp), cp->value); + } + + /* + * If there's out AND it's an input file, check + * that we can read it. This check allows errors + * to be caught as early as possible, during + * server startup. + */ + if (file_input && !cf_file_check(cs, cp->value, true)) { + rcode = -1; + goto error; + } + + if (file_exists && !cf_file_check(cs, cp->value, false)) { + rcode = -1; + goto error; + } + + /* + * Free any existing buffers + */ + talloc_free(*str); + *str = talloc_typed_strdup(cs, cp->value); + } + break; + + case FR_TYPE_IPV4_ADDR: + case FR_TYPE_IPV4_PREFIX: + ipaddr = out; + + if (fr_inet_pton4(ipaddr, cp->value, -1, true, false, true) < 0) { + cf_log_err(&(cp->item), "%s", fr_strerror()); + rcode = -1; + goto error; + } + /* Also prints the IP to the log */ + if (fr_item_validate_ipaddr(cs, cf_pair_attr(cp), type, cp->value, ipaddr) < 0) { + rcode = -1; + goto error; + } + break; + + case FR_TYPE_IPV6_ADDR: + case FR_TYPE_IPV6_PREFIX: + ipaddr = out; + + if (fr_inet_pton6(ipaddr, cp->value, -1, true, false, true) < 0) { + cf_log_err(&(cp->item), "%s", fr_strerror()); + rcode = -1; + goto error; + } + /* Also prints the IP to the log */ + if (fr_item_validate_ipaddr(cs, cf_pair_attr(cp), type, cp->value, ipaddr) < 0) { + rcode = -1; + goto error; + } + break; - cp = cf_pair_find(cs, name); - if (!cp) { - if (deprecated) return 0; - if (!dflt) { - if (required) goto need_value; - return 1; - } + case FR_TYPE_COMBO_IP_ADDR: + case FR_TYPE_COMBO_IP_PREFIX: + ipaddr = out; - if (cf_pair_default(&dflt_cp, cs, name, type, dflt, dflt_quote) < 0) return -1; - cp = dflt_cp; + if (fr_inet_pton(ipaddr, cp->value, -1, AF_UNSPEC, true, true) < 0) { + cf_log_err(&(cp->item), "%s", fr_strerror()); + rcode = -1; + goto error; } - - next = cf_pair_find_next(cs, cp, name); - if (next) { - cf_log_err(&(next->item), "Invalid duplicate configuration item '%s'", name); - return -1; + /* Also prints the IP to the log */ + if (fr_item_validate_ipaddr(cs, cf_pair_attr(cp), type, cp->value, ipaddr) < 0) { + rcode = -1; + goto error; } + break; - if (deprecated) goto deprecated; + case FR_TYPE_TIMEVAL: + { + struct timeval tv; - if (cf_pair_parse_value(ctx, out, cs, cp, type) < 0) { - talloc_free(dflt_cp); - return -1; + if (fr_timeval_from_str(&tv, cp->value) < 0) { + cf_log_err(&(cp->item), "%s", fr_strerror()); + rcode = -1; + goto error; } + cf_log_info(cs, "%.*s\t%s = %d.%06d", cs->depth, parse_spaces, cf_pair_attr(cp), + (int)tv.tv_sec, (int)tv.tv_usec); + memcpy(out, &tv, sizeof(tv)); } + break; - /* - * If we created a default cp and succeeded - * in parsing the dflt value, add the new - * cp to the enclosing section. - */ - if (dflt_cp) { - cf_item_add(cs, &(dflt_cp->item)); - return 1; + default: + /* + * If we get here, it's a sanity check error. + * It's not an error parsing the configuration + * file. + */ + rad_assert(type > FR_TYPE_INVALID); + rad_assert(type < FR_TYPE_MAX); + + cf_log_err(&(cp->item), "type '%s' (%i) is not supported in the configuration files", + fr_int2str(dict_attr_types, type, "?Unknown?"), type); + rcode = -1; + goto error; } - return 0; +finish: + cp->parsed = true; + + return rcode; } -/** Pre-allocate a config section structure to allow defaults to be set +/** Allocate a pair using the dflt value and quotation * - * @param cs The parent subsection. - * @param base pointer or variable. - * @param variables that may have defaults in this config section. + * The pair created by this function should fed to #cf_pair_parse for parsing. + * + * @param[out] out Where to write the CONF_PAIR we created with the default value. + * @param[in] cs to parent the CONF_PAIR from. + * @param[in] name of the CONF_PAIR to create. + * @param[in] type of conf item being parsed (determines default quoting). + * @param[in] dflt value to assign the CONF_PAIR. + * @param[in] dflt_quote surrounding the CONF_PAIR. + * @return + * - 0 on success. + * - -1 on failure. */ -static int cf_section_parse_init(CONF_SECTION *cs, void *base, CONF_PARSER const *variables) +static int cf_pair_default(CONF_PAIR **out, CONF_SECTION *cs, char const *name, + int type, char const *dflt, FR_TOKEN dflt_quote) { - int i; - - for (i = 0; variables[i].name != NULL; i++) { - if ((FR_BASE_TYPE(variables[i].type) == FR_TYPE_SUBSECTION)) { - CONF_SECTION *subcs; - - if (!variables[i].dflt) continue; - - subcs = cf_subsection_find(cs, variables[i].name); - if (!subcs && (variables[i].type & FR_TYPE_REQUIRED)) { - cf_log_err_cs(cs, "Missing %s {} subsection", variables[i].name); - return -1; - } - - /* - * Set the is_set field for the subsection. - */ - if (variables[i].type & FR_TYPE_IS_SET) { - bool *is_set; + int lineno = 0; + char const *expanded; + CONF_PAIR *cp; + char buffer[8192]; - is_set = variables[i].data ? variables[i].is_set_ptr : - ((uint8_t *)base) + variables[i].is_set_offset; - if (is_set) *is_set = !!subcs; - } + rad_assert(dflt); - /* - * If there's no subsection in the - * config, BUT the CONF_PARSER wants one, - * then create an empty one. This is so - * that we can track the strings, - * etc. allocated in the subsection. - */ - if (!subcs) { - subcs = cf_section_alloc(cs, variables[i].name, NULL); - if (!subcs) return -1; + type = FR_BASE_TYPE(type); - cf_item_add(cs, &(subcs->item)); - } + /* + * Defaults may need their values expanding + */ + expanded = cf_expand_variables("", &lineno, cs, buffer, sizeof(buffer), dflt, NULL); + if (!expanded) { + cf_log_err(&(cs->item), "Failed expanding variable %s", name); + return -1; + } - continue; - } + /* + * If no default quote was set, determine it from the type + */ + if (dflt_quote == T_INVALID) { + switch (type) { + case FR_TYPE_STRING: + dflt_quote = T_DOUBLE_QUOTED_STRING; + break; - if ((FR_BASE_TYPE(variables[i].type) != FR_TYPE_STRING) && - (variables[i].type != FR_TYPE_FILE_INPUT) && - (variables[i].type != FR_TYPE_FILE_OUTPUT)) { - continue; - } + case FR_TYPE_FILE_INPUT: + case FR_TYPE_FILE_OUTPUT: + dflt_quote = T_DOUBLE_QUOTED_STRING; + break; - if (variables[i].data) { - *(char **) variables[i].data = NULL; - } else if (base) { - *(char **) (((char *)base) + variables[i].offset) = NULL; - } else { - continue; + default: + dflt_quote = T_BARE_WORD; + break; } - } /* for all variables in the configuration section */ - - return 0; -} - -static void cf_section_parse_warn(CONF_SECTION *cs) -{ - CONF_ITEM *ci; + } - for (ci = cs->children; ci; ci = ci->next) { - /* - * Don't recurse on sections. We can only safely - * check conf pairs at the same level as the - * section that was just parsed. - */ - if (ci->type == CONF_ITEM_SECTION) continue; - if (ci->type == CONF_ITEM_PAIR) { - CONF_PAIR *cp; + cp = cf_pair_alloc(cs, name, expanded, T_OP_EQ, T_BARE_WORD, dflt_quote); + if (!cp) return -1; - cp = cf_item_to_pair(ci); - if (cp->parsed || (ci->lineno < 0)) continue; + cp->parsed = true; - WARN("%s[%d]: The item '%s' is defined, but is unused by the configuration", - ci->filename, ci->lineno, - cp->attr); - } + /* + * Set the rcode to indicate we used a default value + */ + *out = cp; - /* - * Skip everything else. - */ - } + return 1; } -/** Parse a subsection +/** Parses a #CONF_PAIR into a C data type, with a default value. * - * @note Turns out using nested structures (instead of pointers) for subsections, was actually - * a pretty bad design decision, and will need to be fixed at some future point. - * For now we have a horrible hack where only multi-subsections get an array of structures - * of the appropriate size. + * Takes fields from a #CONF_PARSER struct and uses them to parse the string value + * of a #CONF_PAIR into a C data type matching the type argument. * - * @param[in] ctx to allocate any additional structures under. - * @param[out] out pointer to a struct/pointer to fill with data. - * @param[in] cs to parse. - * @param[in] name of subsection to parse. - * @param[in] type flags. - * @param[in] subcs_vars CONF_PARSER definitions for the subsection. - * @param[in] subcs_size size of subsection structures to allocate. + * The format of the types are the same as #fr_value_box_t types. + * + * @note The dflt value will only be used if no matching #CONF_PAIR is found. Empty strings will not + * result in the dflt value being used. + * + * **fr_type_t to data type mappings** + * | fr_type_t | Data type | Dynamically allocated | + * | ----------------------- | ------------------ | ---------------------- | + * | FR_TYPE_TMPL | ``vp_tmpl_t`` | Yes | + * | FR_TYPE_BOOL | ``bool`` | No | + * | FR_TYPE_UINT32 | ``uint32_t`` | No | + * | FR_TYPE_UINT16 | ``uint16_t`` | No | + * | FR_TYPE_UINT64 | ``uint64_t`` | No | + * | FR_TYPE_INT32 | ``int32_t`` | No | + * | FR_TYPE_STRING | ``char const *`` | Yes | + * | FR_TYPE_IPV4_ADDR | ``fr_ipaddr_t`` | No | + * | FR_TYPE_IPV4_PREFIX | ``fr_ipaddr_t`` | No | + * | FR_TYPE_IPV6_ADDR | ``fr_ipaddr_t`` | No | + * | FR_TYPE_IPV6_PREFIX | ``fr_ipaddr_t`` | No | + * | FR_TYPE_COMBO_IP_ADDR | ``fr_ipaddr_t`` | No | + * | FR_TYPE_COMBO_IP_PREFIX | ``fr_ipaddr_t`` | No | + * | FR_TYPE_TIMEVAL | ``struct timeval`` | No | + * + * @param[in] ctx To allocate arrays and values in. + * @param[in] cs to search for matching #CONF_PAIR in. + * @param[in] name of #CONF_PAIR to search for. + * @param[in] type Data type to parse #CONF_PAIR value as. + * Should be one of the following ``data`` types, + * and one or more of the following ``flag`` types or'd together: + * - ``data`` #FR_TYPE_TMPL - @copybrief FR_TYPE_TMPL + * Feeds the value into #tmpl_afrom_str. Value can be + * obtained when processing requests, with #tmpl_expand or #tmpl_aexpand. + * - ``data`` #FR_TYPE_BOOL - @copybrief FR_TYPE_BOOL + * - ``data`` #FR_TYPE_UINT32 - @copybrief FR_TYPE_UINT32 + * - ``data`` #FR_TYPE_UINT16 - @copybrief FR_TYPE_UINT16 + * - ``data`` #FR_TYPE_UINT64 - @copybrief FR_TYPE_UINT64 + * - ``data`` #FR_TYPE_INT32 - @copybrief FR_TYPE_INT32 + * - ``data`` #FR_TYPE_STRING - @copybrief FR_TYPE_STRING + * - ``data`` #FR_TYPE_IPV4_ADDR - @copybrief FR_TYPE_IPV4_ADDR (IPv4 address with prefix 32). + * - ``data`` #FR_TYPE_IPV4_PREFIX - @copybrief FR_TYPE_IPV4_PREFIX (IPv4 address with variable prefix). + * - ``data`` #FR_TYPE_IPV6_ADDR - @copybrief FR_TYPE_IPV6_ADDR (IPv6 address with prefix 128). + * - ``data`` #FR_TYPE_IPV6_PREFIX - @copybrief FR_TYPE_IPV6_PREFIX (IPv6 address with variable prefix). + * - ``data`` #FR_TYPE_COMBO_IP_ADDR - @copybrief FR_TYPE_COMBO_IP_ADDR (IPv4/IPv6 address with + * prefix 32/128). + * - ``data`` #FR_TYPE_COMBO_IP_PREFIX - @copybrief FR_TYPE_COMBO_IP_PREFIX (IPv4/IPv6 address with + * variable prefix). + * - ``data`` #FR_TYPE_TIMEVAL - @copybrief FR_TYPE_TIMEVAL + * - ``flag`` #FR_TYPE_DEPRECATED - @copybrief FR_TYPE_DEPRECATED + * - ``flag`` #FR_TYPE_REQUIRED - @copybrief FR_TYPE_REQUIRED + * - ``flag`` #FR_TYPE_ATTRIBUTE - @copybrief FR_TYPE_ATTRIBUTE + * - ``flag`` #FR_TYPE_SECRET - @copybrief FR_TYPE_SECRET + * - ``flag`` #FR_TYPE_FILE_INPUT - @copybrief FR_TYPE_FILE_INPUT + * - ``flag`` #FR_TYPE_NOT_EMPTY - @copybrief FR_TYPE_NOT_EMPTY + * - ``flag`` #FR_TYPE_MULTI - @copybrief FR_TYPE_MULTI + * - ``flag`` #FR_TYPE_IS_SET - @copybrief FR_TYPE_IS_SET + * @param[out] out Pointer to a global variable, or pointer to a field in the struct being populated with values. + * @param[in] dflt value to use, if no #CONF_PAIR is found. + * @param[in] dflt_quote around the dflt value. * @return + * - 1 if default value was used, or if there was no CONF_PAIR or dflt. * - 0 on success. - * - -1 on general error. - * - -2 if a deprecated #CONF_ITEM was found. + * - -1 on error. + * - -2 if deprecated. */ -static int cf_subsection_parse(TALLOC_CTX *ctx, void *out, CONF_SECTION *cs, - char const *name, fr_type_t type, CONF_PARSER const *subcs_vars, size_t subcs_size) +int cf_pair_parse(TALLOC_CTX *ctx, CONF_SECTION *cs, + char const *name, unsigned int type, void *out, + char const *dflt, FR_TOKEN dflt_quote) { - CONF_SECTION *subcs; - int count, i, ret; - uint8_t **array; + bool multi, required, deprecated; + size_t count = 0; + CONF_PAIR *cp, *dflt_cp = NULL; - rad_assert(type & FR_TYPE_SUBSECTION); + rad_assert(!(type & FR_TYPE_TMPL) || !dflt || (dflt_quote != T_INVALID)); /* We ALWAYS need a quoting type for templates */ - subcs = cf_subsection_find(cs, name); - rad_assert(subcs); /* should have been pre-allocated earlier */ + multi = (type & FR_TYPE_MULTI); + required = (type & FR_TYPE_REQUIRED); + deprecated = (type & FR_TYPE_DEPRECATED); /* - * Handle the single subsection case (which is simple) + * If the item is multi-valued we allocate an array + * to hold the multiple values. */ - if (!(type & FR_TYPE_MULTI)) { - uint8_t *buff; + if (multi) { + CONF_PAIR *first; + void **array; + size_t i; /* - * FIXME: We shouldn't allow nested structures like this. - * Each subsection struct should be allocated separately so - * we have a clean talloc hierarchy. + * Easier than re-allocing */ - if (!subcs_size) return cf_section_parse(ctx, out, subcs, subcs_vars); - - MEM(buff = talloc_array(ctx, uint8_t, subcs_size)); - ret = cf_section_parse(buff, buff, subcs, subcs_vars); - if (ret < 0) { - talloc_free(buff); - return -1; - } - - *((uint8_t **)out) = buff; - } - - rad_assert(subcs_size); - - /* - * Handle the multi subsection case (which is harder) - */ - for (subcs = cf_subsection_find(cs, name), count = 0; - subcs; - subcs = cf_subsection_find_next(cs, subcs, name), count++); - - /* - * Allocate an array to hold the subsections - */ - MEM(array = talloc_array(ctx, uint8_t *, count)); + for (cp = first = cf_pair_find(cs, name); + cp; + cp = cf_pair_find_next(cs, cp, name)) count++; - /* - * Start parsing... - * - * Note, we allocate each subsection structure individually - * so that they can be used as talloc contexts and we can - * keep the talloc hierarchy clean. - */ - for (subcs = cf_subsection_find(cs, name), i = 0; - subcs; - subcs = cf_subsection_find_next(cs, subcs, name), i++) { - uint8_t *buff; + /* + * Multivalued, but there's no value, create a + * default pair. + */ + if (!count) { + if (deprecated) return 0; + if (!dflt) { + if (required) { + need_value: + cf_log_err(cs, "Configuration item \"%s\" must have a value", name); + return -1; + } + return 1; + } - MEM(buff = talloc_zero_array(array, uint8_t, subcs_size)); - array[i] = buff; + if (cf_pair_default(&dflt_cp, cs, name, type, dflt, dflt_quote) < 0) return -1; + cp = dflt_cp; + count = 1; /* Need one to hold the default */ + } else { + cp = first; /* reset */ + } - ret = cf_section_parse(buff, buff, subcs, subcs_vars); - if (ret < 0) { - talloc_free(array); - return ret; + if (deprecated) { + deprecated: + cf_log_err(cp, "Configuration pair \"%s\" is deprecated", cf_pair_attr(cp)); + return -2; } - } - *((uint8_t ***)out) = array; + /* + * Tmpl is outside normal range + */ + if (type & FR_TYPE_TMPL) { + array = (void **)talloc_zero_array(ctx, vp_tmpl_t *, count); + /* + * Allocate an array of values. + * + * We don't NULL terminate. Consumer must use + * talloc_array_length(). + */ + } else switch (FR_BASE_TYPE(type)) { + case FR_TYPE_BOOL: + array = (void **)talloc_zero_array(ctx, bool, count); + break; - return 0; -} + case FR_TYPE_UINT32: + array = (void **)talloc_zero_array(ctx, uint32_t, count); + break; -/** Parse a configuration section into user-supplied variables - * - * @param[in] ctx to allocate any strings, or additional structures in. - * Usually the same as base, unless base is a nested struct. - * @param[out] base pointer to a struct to fill with data. - * @param[in] cs to parse. - * @param[in] variables mappings between struct fields and #CONF_ITEM s. - * @return - * - 0 on success. - * - -1 on general error. - * - -2 if a deprecated #CONF_ITEM was found. - */ -int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs, CONF_PARSER const *variables) -{ - int ret = 0; - int i; - void *data; - bool *is_set = NULL; + case FR_TYPE_UINT16: + array = (void **)talloc_zero_array(ctx, uint16_t, count); + break; - /* - * Hack for partially parsed sections. - */ - if (!variables) { - cf_log_info(cs, "%.*s}", cs->depth, parse_spaces); - return 0; - } + case FR_TYPE_UINT64: + array = (void **)talloc_zero_array(ctx, uint64_t, count); + break; - cs->variables = variables; /* this doesn't hurt anything */ + case FR_TYPE_INT32: + array = (void **)talloc_zero_array(ctx, int32_t, count); + break; - if (!cs->name2) { - cf_log_info(cs, "%.*s%s {", cs->depth, parse_spaces, cs->name1); - } else { - cf_log_info(cs, "%.*s%s %s {", cs->depth, parse_spaces, cs->name1, cs->name2); - } + case FR_TYPE_STRING: + array = (void **)talloc_zero_array(ctx, char *, count); + break; - if (cf_section_parse_init(cs, base, variables) < 0) return -1; + case FR_TYPE_IPV4_ADDR: + case FR_TYPE_IPV4_PREFIX: + case FR_TYPE_IPV6_ADDR: + case FR_TYPE_IPV6_PREFIX: + case FR_TYPE_COMBO_IP_ADDR: + case FR_TYPE_COMBO_IP_PREFIX: + array = (void **)talloc_zero_array(ctx, fr_ipaddr_t, count); + break; - /* - * Handle the known configuration parameters. - */ - for (i = 0; variables[i].name != NULL; i++) { - /* - * Handle subsections specially - */ - if (FR_BASE_TYPE(variables[i].type) == FR_TYPE_SUBSECTION) { - if (cf_subsection_parse(ctx, (uint8_t *)base + variables[i].offset, cs, - variables[i].name, variables[i].type, - variables[i].subcs, variables[i].subcs_size) < 0) goto finish; - continue; - } /* else it's a CONF_PAIR */ + case FR_TYPE_TIMEVAL: + array = (void **)talloc_zero_array(ctx, struct timeval, count); + break; - if (variables[i].data) { - data = variables[i].data; /* prefer this. */ - } else if (base) { - data = ((uint8_t *)base) + variables[i].offset; - } else if (!rad_cond_assert(0)) { - ret = -1; - goto finish; + default: + rad_assert(0); /* Unsupported type */ + return -1; } - /* - * Get pointer to where we need to write out - * whether the pointer was set. - */ - if (variables[i].type & FR_TYPE_IS_SET) { - is_set = variables[i].data ? variables[i].is_set_ptr : - ((uint8_t *)base) + variables[i].is_set_offset; + for (i = 0; i < count; i++, cp = cf_pair_find_next(cs, cp, name)) { + if (cf_pair_parse_value(array, &array[i], cs, cp, type) < 0) { + talloc_free(array); + talloc_free(dflt_cp); + return -1; + } } - /* - * Parse the pair we found, or a default value. - */ - ret = cf_pair_parse(ctx, cs, variables[i].name, variables[i].type, data, - variables[i].dflt, variables[i].quote); - switch (ret) { - case 1: /* Used default (or not present) */ - if (is_set) *is_set = false; - ret = 0; - break; - - case 0: /* OK */ - if (is_set) *is_set = true; - break; - - case -1: /* Parse error */ - goto finish; + *(void **)out = array; + /* + * Single valued config item gets written to + * the data pointer directly. + */ + } else { + CONF_PAIR *next; - case -2: /* Deprecated CONF ITEM */ - if ((variables[i + 1].offset && (variables[i + 1].offset == variables[i].offset)) || - (variables[i + 1].data && (variables[i + 1].data == variables[i].data))) { - cf_log_err(&(cs->item), "Replace \"%s\" with \"%s\"", variables[i].name, - variables[i + 1].name); + cp = cf_pair_find(cs, name); + if (!cp) { + if (deprecated) return 0; + if (!dflt) { + if (required) goto need_value; + return 1; } - goto finish; + + if (cf_pair_default(&dflt_cp, cs, name, type, dflt, dflt_quote) < 0) return -1; + cp = dflt_cp; } - } /* for all variables in the configuration section */ - /* - * Ensure we have a proper terminator, type so we catch - * missing terminators reliably - */ - rad_cond_assert(variables[i].type == conf_term.type); + next = cf_pair_find_next(cs, cp, name); + if (next) { + cf_log_err(&(next->item), "Invalid duplicate configuration item '%s'", name); + return -1; + } - cs->base = base; + if (deprecated) goto deprecated; - /* - * Hack for partially parsed sections. We don't print - * out the final "}", that will be printed out when the - * caller re-calls us with 'variable=NULL'. And, we don't warn about unused - */ - if (variables[i].offset == 1) return ret; + if (cf_pair_parse_value(ctx, out, cs, cp, type) < 0) { + talloc_free(dflt_cp); + return -1; + } + } /* - * Warn about items in the configuration which weren't - * checked during parsing. + * If we created a default cp and succeeded + * in parsing the dflt value, add the new + * cp to the enclosing section. */ - if (rad_debug_lvl >= 3) cf_section_parse_warn(cs); - - cf_log_info(cs, "%.*s}", cs->depth, parse_spaces); + if (dflt_cp) { + cf_item_add(cs, &(dflt_cp->item)); + return 1; + } -finish: - return ret; + return 0; } -/* - * Merge the template so everyting else "just works". +/** Pre-allocate a config section structure to allow defaults to be set + * + * @param cs The parent subsection. + * @param base pointer or variable. + * @param variables that may have defaults in this config section. */ -static bool cf_template_merge(CONF_SECTION *cs, CONF_SECTION const *template) +static int cf_section_parse_init(CONF_SECTION *cs, void *base, CONF_PARSER const *variables) { - CONF_ITEM *ci; + int i; - if (!cs || !template) return true; + for (i = 0; variables[i].name != NULL; i++) { + if ((FR_BASE_TYPE(variables[i].type) == FR_TYPE_SUBSECTION)) { + CONF_SECTION *subcs; - cs->template = NULL; + if (!variables[i].dflt) continue; - /* - * Walk over the template, adding its' entries to the - * current section. But only if the entries don't - * already exist in the current section. - */ - for (ci = template->children; ci; ci = ci->next) { - if (ci->type == CONF_ITEM_PAIR) { - CONF_PAIR *cp1, *cp2; + subcs = cf_section_find(cs, variables[i].name, NULL); + if (!subcs && (variables[i].type & FR_TYPE_REQUIRED)) { + cf_log_err(cs, "Missing %s {} subsection", variables[i].name); + return -1; + } /* - * It exists, don't over-write it. + * Set the is_set field for the subsection. */ - cp1 = cf_item_to_pair(ci); - if (cf_pair_find(cs, cp1->attr)) { - continue; + if (variables[i].type & FR_TYPE_IS_SET) { + bool *is_set; + + is_set = variables[i].data ? variables[i].is_set_ptr : + ((uint8_t *)base) + variables[i].is_set_offset; + if (is_set) *is_set = !!subcs; } /* - * Create a new pair with all of the data - * of the old one. + * If there's no subsection in the + * config, BUT the CONF_PARSER wants one, + * then create an empty one. This is so + * that we can track the strings, + * etc. allocated in the subsection. */ - cp2 = cf_pair_dup(cs, cp1); - if (!cp2) return false; + if (!subcs) { + subcs = cf_section_alloc(cs, variables[i].name, NULL); + if (!subcs) return -1; - cp2->item.filename = cp1->item.filename; - cp2->item.lineno = cp1->item.lineno; + cf_item_add(cs, &(subcs->item)); + } - cf_item_add(cs, &(cp2->item)); continue; } - if (ci->type == CONF_ITEM_SECTION) { - CONF_SECTION *subcs1, *subcs2; - - subcs1 = cf_item_to_section(ci); - rad_assert(subcs1 != NULL); - - subcs2 = cf_subsection_find_name2(cs, subcs1->name1, subcs1->name2); - if (subcs2) { - /* - * sub-sections get merged. - */ - if (!cf_template_merge(subcs2, subcs1)) { - return false; - } - continue; - } - - /* - * Our section doesn't have a matching - * sub-section. Copy it verbatim from - * the template. - */ - subcs2 = cf_section_dup(cs, subcs1, - cf_section_name1(subcs1), cf_section_name2(subcs1), - false); - if (!subcs2) return false; - - subcs2->item.filename = subcs1->item.filename; - subcs2->item.lineno = subcs1->item.lineno; - - cf_item_add(cs, &(subcs2->item)); + if ((FR_BASE_TYPE(variables[i].type) != FR_TYPE_STRING) && + (variables[i].type != FR_TYPE_FILE_INPUT) && + (variables[i].type != FR_TYPE_FILE_OUTPUT)) { continue; } - /* ignore everything else */ - } + if (variables[i].data) { + *(char **) variables[i].data = NULL; + } else if (base) { + *(char **) (((char *)base) + variables[i].offset) = NULL; + } else { + continue; + } + } /* for all variables in the configuration section */ - return true; + return 0; } -static char const *cf_local_file(char const *base, char const *filename, - char *buffer, size_t bufsize) +static void cf_section_parse_warn(CONF_SECTION *cs) { - size_t dirsize; - char *p; + CONF_ITEM *ci; - strlcpy(buffer, base, bufsize); + for (ci = cs->item.child; ci; ci = ci->next) { + /* + * Don't recurse on sections. We can only safely + * check conf pairs at the same level as the + * section that was just parsed. + */ + if (ci->type == CONF_ITEM_SECTION) continue; + if (ci->type == CONF_ITEM_PAIR) { + CONF_PAIR *cp; - p = strrchr(buffer, FR_DIR_SEP); - if (!p) return filename; - if (p[1]) { /* ./foo */ - p[1] = '\0'; - } + cp = cf_item_to_pair(ci); + if (cp->parsed || (ci->lineno < 0)) continue; - dirsize = (p - buffer) + 1; + WARN("%s[%d]: The item '%s' is defined, but is unused by the configuration", + ci->filename, ci->lineno, + cp->attr); + } - if ((dirsize + strlen(filename)) >= bufsize) { - return NULL; + /* + * Skip everything else. + */ } - - strlcpy(p + 1, filename, bufsize - dirsize); - - return buffer; } -static bool invalid_location(CONF_SECTION *this, char const *name, char const *filename, int lineno) +/** Parse a subsection + * + * @note Turns out using nested structures (instead of pointers) for subsections, was actually + * a pretty bad design decision, and will need to be fixed at some future point. + * For now we have a horrible hack where only multi-subsections get an array of structures + * of the appropriate size. + * + * @param[in] ctx to allocate any additional structures under. + * @param[out] out pointer to a struct/pointer to fill with data. + * @param[in] cs to parse. + * @param[in] name of subsection to parse. + * @param[in] type flags. + * @param[in] subcs_vars CONF_PARSER definitions for the subsection. + * @param[in] subcs_size size of subsection structures to allocate. + * @return + * - 0 on success. + * - -1 on general error. + * - -2 if a deprecated #CONF_ITEM was found. + */ +static int cf_subsection_parse(TALLOC_CTX *ctx, void *out, CONF_SECTION *cs, + char const *name, fr_type_t type, CONF_PARSER const *subcs_vars, size_t subcs_size) { - /* - * if / elsif MUST be inside of a - * processing section, which MUST in turn - * be inside of a "server" directive. - */ - if (!this || !this->item.parent) { - invalid_location: - ERROR("%s[%d]: Invalid location for '%s'", - filename, lineno, name); - return true; - } + CONF_SECTION *subcs; + int count, i, ret; + uint8_t **array; + + rad_assert(type & FR_TYPE_SUBSECTION); + + subcs = cf_section_find(cs, name, NULL); + if (!subcs) return 0; /* - * Can only have "if" in 3 named sections. + * Handle the single subsection case (which is simple) */ - this = cf_item_to_section(this->item.parent); - while ((strcmp(this->name1, "server") != 0) && - (strcmp(this->name1, "policy") != 0) && - (strcmp(this->name1, "instantiate") != 0)) { - this = cf_item_to_section(this->item.parent); - if (!this) goto invalid_location; - } + if (!(type & FR_TYPE_MULTI)) { + uint8_t *buff; - return false; -} + /* + * FIXME: We shouldn't allow nested structures like this. + * Each subsection struct should be allocated separately so + * we have a clean talloc hierarchy. + */ + if (!subcs_size) return cf_section_parse(ctx, out, subcs, subcs_vars); -#ifdef WITH_CONF_WRITE -static void cf_comment_add(CONF_SECTION *cs, int lineno, char const *ptr) -{ - CONF_COMMENT *cc; + MEM(buff = talloc_array(ctx, uint8_t, subcs_size)); + ret = cf_section_parse(buff, buff, subcs, subcs_vars); + if (ret < 0) { + talloc_free(buff); + return -1; + } - cc = talloc_zero(cs, CONF_COMMENT); - cc->item.type = CONF_ITEM_COMMENT; - cc->item.parent = cs; - cc->item.filename = cs->item.filename; - cc->item.lineno = lineno; - cc->comment = talloc_typed_strdup(cc, ptr); + *((uint8_t **)out) = buff; + } + + rad_assert(subcs_size); + + /* + * Handle the multi subsection case (which is harder) + */ + for (subcs = cf_section_find(cs, name, NULL), count = 0; + subcs; + subcs = cf_section_find_next(cs, subcs, name, NULL), count++); + /* + * Allocate an array to hold the subsections + */ + MEM(array = talloc_array(ctx, uint8_t *, count)); - cf_item_add(cs, &(cc->item)); -} + /* + * Start parsing... + * + * Note, we allocate each subsection structure individually + * so that they can be used as talloc contexts and we can + * keep the talloc hierarchy clean. + */ + for (subcs = cf_section_find(cs, name, NULL), i = 0; + subcs; + subcs = cf_section_find_next(cs, subcs, name, NULL), i++) { + uint8_t *buff; -static void cf_include_add(CONF_SECTION *cs, char const *filename, CONF_INCLUDE_TYPE file_type) -{ - CONF_INCLUDE *cc; + MEM(buff = talloc_zero_array(array, uint8_t, subcs_size)); + array[i] = buff; - cc = talloc_zero(cs, CONF_INCLUDE); - cc->item.type = CONF_ITEM_INCLUDE; - cc->item.parent = cs; - cc->item.filename = cs->item.filename; - cc->item.lineno = 0; - cc->filename = talloc_typed_strdup(cc, filename); - cc->file_type = file_type; + ret = cf_section_parse(buff, buff, subcs, subcs_vars); + if (ret < 0) { + talloc_free(array); + return ret; + } + } - cf_item_add(cs, &(cc->item)); -} -#endif + *((uint8_t ***)out) = array; + return 0; +} -/* - * Read a part of the config file. +/** Parse a configuration section into user-supplied variables + * + * @param[in] ctx to allocate any strings, or additional structures in. + * Usually the same as base, unless base is a nested struct. + * @param[out] base pointer to a struct to fill with data. + * @param[in] cs to parse. + * @param[in] variables mappings between struct fields and #CONF_ITEM s. + * @return + * - 0 on success. + * - -1 on general error. + * - -2 if a deprecated #CONF_ITEM was found. */ -static int cf_section_read(char const *filename, int *lineno, FILE *fp, - CONF_SECTION *current, char *buff[7]) - +int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs, CONF_PARSER const *variables) { - CONF_SECTION *this, *css; - CONF_PAIR *cpn; - char const *ptr; - char const *value; -#ifdef WITH_CONF_WRITE - char const *orig_value = NULL; -#endif + int ret = 0; + int i; + void *data; + bool *is_set = NULL; - FR_TOKEN t1 = T_INVALID, t2, t3; - bool has_spaces = false; - bool pass2; - char *cbuff; - size_t len; + /* + * Hack for partially parsed sections. + */ + if (!variables) { + cf_log_info(cs, "%.*s}", cs->depth, parse_spaces); + return 0; + } - this = current; /* add items here */ + cs->variables = variables; /* this doesn't hurt anything */ - cbuff = buff[0]; + if (!cs->name2) { + cf_log_info(cs, "%.*s%s {", cs->depth, parse_spaces, cs->name1); + } else { + cf_log_info(cs, "%.*s%s %s {", cs->depth, parse_spaces, cs->name1, cs->name2); + } + + if (cf_section_parse_init(cs, base, variables) < 0) return -1; /* - * Read, checking for line continuations ('\\' at EOL) + * Handle the known configuration parameters. */ - for (;;) { - int at_eof; - css = NULL; - + for (i = 0; variables[i].name != NULL; i++) { /* - * Get data, and remember if we are at EOF. + * Handle subsections specially */ - at_eof = (fgets(cbuff, talloc_array_length(buff[0]) - (cbuff - buff[0]), fp) == NULL); - (*lineno)++; + if (FR_BASE_TYPE(variables[i].type) == FR_TYPE_SUBSECTION) { + if (cf_subsection_parse(ctx, (uint8_t *)base + variables[i].offset, cs, + variables[i].name, variables[i].type, + variables[i].subcs, variables[i].subcs_size) < 0) goto finish; + continue; + } /* else it's a CONF_PAIR */ + + if (variables[i].data) { + data = variables[i].data; /* prefer this. */ + } else if (base) { + data = ((uint8_t *)base) + variables[i].offset; + } else if (!rad_cond_assert(0)) { + ret = -1; + goto finish; + } /* - * We read the entire 8k worth of data: complain. - * Note that we don't care if the last character - * is \n: it's still forbidden. This means that - * the maximum allowed length of text is 8k-1, which - * should be plenty. + * Get pointer to where we need to write out + * whether the pointer was set. */ - len = strlen(cbuff); - if ((cbuff + len + 1) >= (buff[0] + talloc_array_length(buff[0]))) { - ERROR("%s[%d]: Line too long", filename, *lineno); - error: - return -1; + if (variables[i].type & FR_TYPE_IS_SET) { + is_set = variables[i].data ? variables[i].is_set_ptr : + ((uint8_t *)base) + variables[i].is_set_offset; } - if (has_spaces) { - ptr = cbuff; - while (isspace((int) *ptr)) ptr++; + /* + * Parse the pair we found, or a default value. + */ + ret = cf_pair_parse(ctx, cs, variables[i].name, variables[i].type, data, + variables[i].dflt, variables[i].quote); + switch (ret) { + case 1: /* Used default (or not present) */ + if (is_set) *is_set = false; + ret = 0; + break; - if (ptr > cbuff) { - memmove(cbuff, ptr, len - (ptr - cbuff)); - len -= (ptr - cbuff); + case 0: /* OK */ + if (is_set) *is_set = true; + break; + + case -1: /* Parse error */ + goto finish; + + case -2: /* Deprecated CONF ITEM */ + if ((variables[i + 1].offset && (variables[i + 1].offset == variables[i].offset)) || + (variables[i + 1].data && (variables[i + 1].data == variables[i].data))) { + cf_log_err(&(cs->item), "Replace \"%s\" with \"%s\"", variables[i].name, + variables[i + 1].name); } + goto finish; } + } /* for all variables in the configuration section */ - /* - * Not doing continuations: check for edge - * conditions. - */ - if (cbuff == buff[0]) { - if (at_eof) break; + /* + * Ensure we have a proper terminator, type so we catch + * missing terminators reliably + */ + rad_cond_assert(variables[i].type == conf_term.type); - ptr = buff[0]; - while (*ptr && isspace((int) *ptr)) ptr++; + cs->base = base; -#ifdef WITH_CONF_WRITE - /* - * This is where all of the comments are handled - */ - if (*ptr == '#') { - cf_comment_add(this, *lineno, ptr + 1); - } -#endif + /* + * Hack for partially parsed sections. We don't print + * out the final "}", that will be printed out when the + * caller re-calls us with 'variable=NULL'. And, we don't warn about unused + */ + if (variables[i].offset == 1) return ret; - if (!*ptr || (*ptr == '#')) continue; + /* + * Warn about items in the configuration which weren't + * checked during parsing. + */ + if (rad_debug_lvl >= 3) cf_section_parse_warn(cs); - } else if (at_eof || (len == 0)) { - ERROR("%s[%d]: Continuation at EOF is illegal", filename, *lineno); - goto error; - } + cf_log_info(cs, "%.*s}", cs->depth, parse_spaces); - /* - * See if there's a continuation. - */ - while ((len > 0) && - ((cbuff[len - 1] == '\n') || (cbuff[len - 1] == '\r'))) { - len--; - cbuff[len] = '\0'; - } +finish: + return ret; +} - if ((len > 0) && (cbuff[len - 1] == '\\')) { - /* - * Check for "suppress spaces" magic. - */ - if (!has_spaces && (len > 2) && (cbuff[len - 2] == '"')) { - has_spaces = true; - } +/** Fixup xlat expansions and attributes + * + * @note Despite the name, this is really the second phase of #cf_pair_parse. + * + * @param[out] base start of structure to write #vp_tmpl_t s to. + * @param[in] cs CONF_SECTION to fixup. + * @param[in] variables Array of CONF_PARSER structs to process. + * @return + * - 0 on success. + * - -1 on failure (parse errors etc...). + */ +int cf_section_parse_pass2(void *base, CONF_SECTION *cs, CONF_PARSER const variables[]) +{ - cbuff[len - 1] = '\0'; - cbuff += len - 1; - continue; - } + int i; - ptr = cbuff = buff[0]; - has_spaces = false; + /* + * Handle the known configuration parameters. + */ + for (i = 0; variables[i].name != NULL; i++) { + bool attribute, multi, is_tmpl, is_xlat; + CONF_PAIR *cp; + void *data; - get_more: - pass2 = false; + char const *name = variables[i].name; + int type = variables[i].type; + + is_tmpl = (type & FR_TYPE_TMPL); + is_xlat = (type & FR_TYPE_XLAT); + attribute = (type & FR_TYPE_ATTRIBUTE); + multi = (type & FR_TYPE_MULTI); + + type = FR_BASE_TYPE(type); /* normal types are small */ /* - * The parser is getting to be evil. + * It's a section, recurse! */ - while ((*ptr == ' ') || (*ptr == '\t')) ptr++; - - if (((ptr[0] == '%') && (ptr[1] == '{')) || - (ptr[0] == '`')) { - ssize_t slen; - - if (ptr[0] == '%') { - slen = rad_copy_variable(buff[1], ptr); - } else { - slen = rad_copy_string(buff[1], ptr); - } - if (slen <= 0) { - char *spaces, *text; - - fr_canonicalize_error(current, &spaces, &text, slen, ptr); + if (type == FR_TYPE_SUBSECTION) { + uint8_t *subcs_base; + CONF_SECTION *subcs = cf_section_find(cs, name, NULL); - ERROR("%s[%d]: %s", filename, *lineno, text); - ERROR("%s[%d]: %s^ Invalid expansion", filename, *lineno, spaces); + /* + * Select base by whether this is a nested struct, + * or a pointer to another struct. + */ + if (!base) { + subcs_base = NULL; + } else if (multi) { + size_t j, len; + uint8_t **array; - talloc_free(spaces); - talloc_free(text); + array = (uint8_t **)((uint8_t *)base) + variables[i].offset; + len = talloc_array_length(array); - goto error; + for (j = 0; j < len; j++) { + if (cf_section_parse_pass2(array[j], subcs, + (CONF_PARSER const *)variables[i].dflt) < 0) { + return -1; + } + } + continue; + } else if (variables[i].subcs_size) { + subcs_base = (*(uint8_t **)((uint8_t *)base) + variables[i].offset); + } else { + subcs_base = (uint8_t *)base + variables[i].offset; } - ptr += slen; - - t2 = gettoken(&ptr, buff[2], talloc_array_length(buff[2]), true); - switch (t2) { - case T_HASH: - case T_EOL: - goto do_bare_word; + if (cf_section_parse_pass2(subcs_base, subcs, + (CONF_PARSER const *)variables[i].dflt) < 0) return -1; - default: - ERROR("%s[%d]: Invalid expansion: %s", filename, *lineno, ptr); - goto error; - } - } else { - t1 = gettoken(&ptr, buff[1], talloc_array_length(buff[1]), true); + continue; } /* - * The caller eats "name1 name2 {", and calls us - * for the data inside of the section. So if we - * receive a closing brace, then it must mean the - * end of the section. + * Find the CONF_PAIR, may still not exist if there was + * no default set for the CONF_PARSER. */ - if (t1 == T_RCBRACE) { - if (this == current) { - ERROR("%s[%d]: Too many closing braces", filename, *lineno); - goto error; - } + cp = cf_pair_find(cs, name); + if (!cp) continue; - /* - * Merge the template into the existing - * section. This uses more memory, but - * means that templates now work with - * sub-sections, etc. - */ - if (!cf_template_merge(this, this->template)) goto error; + /* + * Figure out which data we need to fix. + */ + data = variables[i].data; /* prefer this. */ + if (!data && base) data = ((char *)base) + variables[i].offset; + if (!data) continue; - this = cf_item_to_section(this->item.parent); - goto check_for_more; - } + /* + * Non-xlat expansions shouldn't have xlat! + */ + if (!is_xlat && !is_tmpl) { + /* + * Ignore %{... in shared secrets. + * They're never dynamically expanded. + */ + if ((variables[i].type & FR_TYPE_SECRET) != 0) continue; - if (t1 != T_BARE_WORD) goto skip_keywords; + if (strstr(cp->value, "%{") != NULL) { + cf_log_err(&cp->item, "Found dynamic expansion in string which " + "will not be dynamically expanded"); + return -1; + } + continue; + } /* - * Allow for $INCLUDE files + * Parse (and throw away) the xlat string (for validation). * - * This *SHOULD* work for any level include. - * I really really really hate this file. -cparker + * FIXME: All of these should be converted from FR_TYPE_XLAT + * to FR_TYPE_TMPL. */ - if ((strcasecmp(buff[1], "$INCLUDE") == 0) || - (strcasecmp(buff[1], "$-INCLUDE") == 0)) { - bool relative = true; + if (is_xlat) { + char const *error; + ssize_t slen; + char *value; + xlat_exp_t *xlat; - t2 = getword(&ptr, buff[2], talloc_array_length(buff[2]), true); - if (t2 != T_EOL) { - ERROR("%s[%d]: Unexpected text after $INCLUDE", filename, *lineno); - goto error; - } + redo: + xlat = NULL; - if (buff[2][0] == '$') relative = false; + /* + * xlat expansions should be parseable. + */ + value = talloc_strdup(cs, cp->value); /* modified by xlat_tokenize */ + slen = xlat_tokenize(cs, value, &xlat, &error); + if (slen < 0) { + char *spaces, *text; - value = cf_expand_variables(filename, lineno, this, buff[4], talloc_array_length(buff[4]), - buff[2], NULL); - if (!value) goto error; + fr_canonicalize_error(cs, &spaces, &text, slen, cp->value); - if (!FR_DIR_IS_RELATIVE(value)) relative = false; + cf_log_err(cp, "Failed parsing expanded string:"); + cf_log_err(cp, "%s", text); + cf_log_err(cp, "%s^ %s", spaces, error); - if (relative) { - value = cf_local_file(filename, value, buff[3], talloc_array_length(buff[3])); - if (!value) { - ERROR("%s[%d]: Directories too deep", filename, *lineno); - goto error; - } + talloc_free(spaces); + talloc_free(text); + talloc_free(value); + talloc_free(xlat); + return -1; } + talloc_free(value); + talloc_free(xlat); -#ifdef HAVE_DIRENT_H /* - * $INCLUDE foo/ - * - * Include ALL non-"dot" files in the directory. - * careful! + * If the "multi" flag is set, check all of them. */ - if (value[strlen(value) - 1] == '/') { - DIR *dir; - struct dirent *dp; - struct stat stat_buf; - char *my_directory; - - my_directory = talloc_strdup(this, value); - - DEBUG2("including files in directory %s", my_directory); - -#ifdef WITH_CONF_WRITE - /* - * We print this out, but don't - * actually open a file based on - * it. - */ - cf_include_add(this, my_directory, CONF_INCLUDE_DIR); -#endif - -#ifdef S_IWOTH - /* - * Security checks. - */ - if (stat(my_directory, &stat_buf) < 0) { - ERROR("%s[%d]: Failed reading directory %s: %s", - filename, *lineno, - my_directory, fr_syserror(errno)); - talloc_free(my_directory); - goto error; - } - - if ((stat_buf.st_mode & S_IWOTH) != 0) { - ERROR("%s[%d]: Directory %s is globally writable. Refusing to start due to " - "insecure configuration", filename, *lineno, my_directory); - talloc_free(my_directory); - goto error; - } -#endif - dir = opendir(my_directory); - if (!dir) { - ERROR("%s[%d]: Error reading directory %s: %s", - filename, *lineno, value, - fr_syserror(errno)); - talloc_free(my_directory); - goto error; - } + if (multi) { + cp = cf_pair_find_next(cs, cp, cp->attr); + if (cp) goto redo; + } + continue; - /* - * Read the directory, ignoring "." files. - */ - while ((dp = readdir(dir)) != NULL) { - char const *p; + /* + * Parse the pair into a template + */ + } else if (is_tmpl) { + ssize_t slen; - if (dp->d_name[0] == '.') continue; + vp_tmpl_t **out = (vp_tmpl_t **)data; + vp_tmpl_t *vpt; - /* - * Check for valid characters - */ - for (p = dp->d_name; *p != '\0'; p++) { - if (isalpha((int)*p) || - isdigit((int)*p) || - (*p == '-') || - (*p == '_') || - (*p == '.')) continue; - break; - } - if (*p != '\0') continue; + slen = tmpl_afrom_str(cs, &vpt, cp->value, talloc_array_length(cp->value) - 1, + cf_pair_value_quote(cp), + REQUEST_CURRENT, PAIR_LIST_REQUEST, true); + if (slen < 0) { + char *spaces, *text; + fr_canonicalize_error(vpt, &spaces, &text, slen, cp->value); - snprintf(buff[2], talloc_array_length(buff[2]), "%s%s", - my_directory, dp->d_name); - if ((stat(buff[2], &stat_buf) != 0) || - S_ISDIR(stat_buf.st_mode)) continue; + cf_log_err(cp, "%s", text); + cf_log_err(cp, "%s^ %s", spaces, fr_strerror()); - /* - * Read the file into the current - * configuration section. - */ - if (cf_file_include(this, buff[2], CONF_INCLUDE_FROMDIR, buff) < 0) { - closedir(dir); - goto error; - } - } - closedir(dir); - talloc_free(my_directory); + talloc_free(spaces); + talloc_free(text); + return -1; + } - } else -#endif - { /* it was a normal file */ - if (buff[1][1] == '-') { - struct stat statbuf; + if (attribute && (vpt->type != TMPL_TYPE_ATTR)) { + cf_log_err(&cp->item, "Expected attr got %s", + fr_int2str(tmpl_names, vpt->type, "???")); + return -1; + } - if (stat(value, &statbuf) < 0) { - WARN("Not including file %s: %s", value, fr_syserror(errno)); - continue; - } - } + switch (vpt->type) { + /* + * All attributes should have been defined by this point. + */ + case TMPL_TYPE_ATTR_UNDEFINED: + talloc_free(vpt); + cf_log_err(&cp->item, "Unknown attribute '%s'", vpt->tmpl_unknown_name); + return -1; - if (cf_file_include(this, value, CONF_INCLUDE_FILE, buff) < 0) goto error; + case TMPL_TYPE_UNPARSED: + case TMPL_TYPE_ATTR: + case TMPL_TYPE_LIST: + case TMPL_TYPE_DATA: + case TMPL_TYPE_EXEC: + case TMPL_TYPE_XLAT: + case TMPL_TYPE_XLAT_STRUCT: + break; + + case TMPL_TYPE_UNKNOWN: + case TMPL_TYPE_REGEX: + case TMPL_TYPE_REGEX_STRUCT: + case TMPL_TYPE_NULL: + rad_assert(0); + /* Don't add default */ } - continue; - } /* we were in an include */ - if (strcasecmp(buff[1], "$template") == 0) { - CONF_ITEM *ci; - CONF_SECTION *parentcs, *templatecs; - t2 = getword(&ptr, buff[2], talloc_array_length(buff[2]), true); + /* + * Free the old value if we're overwriting + */ + TALLOC_FREE(*out); + *(vp_tmpl_t **)out = vpt; + } + } /* for all variables in the configuration section */ - if (t2 != T_EOL) { - ERROR("%s[%d]: Unexpected text after $TEMPLATE", filename, *lineno); - goto error; - } + return 0; +} - parentcs = cf_top_section(current); +const CONF_PARSER *cf_section_parse_table(CONF_SECTION *cs) +{ + if (!cs) return NULL; - templatecs = cf_subsection_find(parentcs, "templates"); - if (!templatecs) { - ERROR("%s[%d]: No \"templates\" section for reference \"%s\"", filename, *lineno, buff[2]); - goto error; - } + return cs->variables; +} - ci = cf_reference_item(parentcs, templatecs, buff[2]); - if (!ci || (ci->type != CONF_ITEM_SECTION)) { - ERROR("%s[%d]: Reference \"%s\" not found", filename, *lineno, buff[2]); - goto error; - } +CONF_ITEM *cf_reference_item(CONF_SECTION const *parent_cs, + CONF_SECTION const *outer_cs, + char const *ptr) +{ + CONF_PAIR *cp; + CONF_SECTION *next; + CONF_SECTION const *cs = outer_cs; + char name[8192]; + char *p; - if (!this) { - ERROR("%s[%d]: Internal sanity check error in template reference", filename, *lineno); - goto error; - } + if (!cs) goto no_such_item; - if (this->template) { - ERROR("%s[%d]: Section already has a template", filename, *lineno); - goto error; - } + strlcpy(name, ptr, sizeof(name)); - this->template = cf_item_to_section(ci); - continue; - } + p = name; + + /* + * ".foo" means "foo from the current section" + */ + if (*p == '.') { + p++; /* - * Ensure that the user can't add CONF_PAIRs - * with 'internal' names; + * Just '.' means the current section */ - if (buff[1][0] == '_') { - ERROR("%s[%d]: Illegal configuration pair name \"%s\"", filename, *lineno, buff[1]); - goto error; - } + if (*p == '\0') return cf_section_to_item(cs); /* - * Handle if/elsif specially. + * ..foo means "foo from the section + * enclosing this section" (etc.) */ - if ((strcmp(buff[1], "if") == 0) || (strcmp(buff[1], "elsif") == 0)) { - ssize_t slen; - char const *error = NULL; - char *p; - fr_cond_t *cond = NULL; - - if (invalid_location(this, buff[1], filename, *lineno)) goto error; + while (*p == '.') { + if (cs->item.parent) cs = cf_item_to_section(cs->item.parent); /* - * Skip (...) to find the { + * .. means the section + * enclosing this section */ - slen = fr_cond_tokenize(this, cf_section_to_item(this), ptr, &cond, - &error, FR_COND_TWO_PASS); - memcpy(&p, &ptr, sizeof(p)); + if (!*++p) return cf_section_to_item(cs); + } - if (slen < 0) { - if (p[-slen] != '{') goto cond_error; - slen = -slen; - } - TALLOC_FREE(cond); + /* + * "foo.bar.baz" means "from the root" + */ + } else if (strchr(p, '.') != NULL) { + if (!parent_cs) goto no_such_item; + cs = parent_cs; + } - /* - * This hack is so that the NEXT stage - * doesn't go "too far" in expanding the - * variable. We can parse the conditions - * without expanding the ${...} stuff. - * BUT we don't want to expand all of the - * stuff AFTER the condition. So we do - * two passes. - * - * The first pass is to discover the end - * of the condition. We then expand THAT - * string, and do a second pass parsing - * the expanded condition. - */ - p += slen; - *p = '\0'; + while (*p) { + char *q, *r; + + r = strchr(p, '['); + q = strchr(p, '.'); + if (!r && !q) break; + + if (r && q > r) q = NULL; + if (q && q < r) r = NULL; + + /* + * Split off name2. + */ + if (r) { + q = strchr(r + 1, ']'); + if (!q) return NULL; /* parse error */ /* - * Nuke trailing spaces. This hack - * really belongs in the parser. + * Points to foo[bar]xx: parse error, + * it should be foo[bar] or foo[bar].baz */ - while ((p > ptr) && (isspace((int) p[-1]))) { - p--; - *p = '\0'; - } + if (q[1] && q[1] != '.') goto no_such_item; + + *r = '\0'; + *q = '\0'; + next = cf_section_find(cs, p, r + 1); + *r = '['; + *q = ']'; /* - * If there's a ${...}. If so, expand it. + * Points to a named instance of a section. */ - if (strchr(ptr, '$') != NULL) { - ptr = cf_expand_variables(filename, lineno, - this, - buff[3], talloc_array_length(buff[3]), - ptr, NULL); - if (!ptr) { - ERROR("%s[%d]: Parse error expanding ${...} in condition", - filename, *lineno); - goto error; - } - } /* else leave it alone */ - - css = cf_section_alloc(this, buff[1], ptr); - if (!css) { - ERROR("%s[%d]: Failed allocating memory for section", filename, *lineno); - goto error; + if (!q[1]) { + if (!next) goto no_such_item; + return &(next->item); } - css->item.filename = filename; - css->item.lineno = *lineno; - slen = fr_cond_tokenize(css, cf_section_to_item(css), ptr, &cond, - &error, FR_COND_TWO_PASS); - *p = '{'; /* put it back */ + q++; /* ensure we skip the ']' and '.' */ - cond_error: - if (slen < 0) { - char *spaces, *text; + } else { + *q = '\0'; + next = cf_section_find(cs, p, NULL); + *q = '.'; + } - fr_canonicalize_error(this, &spaces, &text, slen, ptr); + if (!next) break; /* it MAY be a pair in this section! */ - ERROR("%s[%d]: Parse error in condition", - filename, *lineno); - ERROR("%s[%d]: %s", filename, *lineno, text); - ERROR("%s[%d]: %s^ %s", filename, *lineno, spaces, error); + cs = next; + p = q + 1; + } - talloc_free(spaces); - talloc_free(text); - talloc_free(css); - goto error; - } + if (!*p) goto no_such_item; - if ((size_t) slen >= (talloc_array_length(buff[2]) - 1)) { - talloc_free(css); - ERROR("%s[%d]: Condition is too large after \"%s\"", filename, *lineno, buff[1]); - goto error; - } + retry: + /* + * Find it in the current referenced + * section. + */ + cp = cf_pair_find(cs, p); + if (cp) { + cp->parsed = true; /* conf pairs which are referenced count as parsed */ + return &(cp->item); + } - /* - * Copy the expanded and parsed condition - * into buff[2]. Then, parse the text after - * the condition, which now MUST be a '{. - * - * If it wasn't '{' it would have been - * caught in the first pass of - * conditional parsing, above. - */ - memcpy(buff[2], ptr, slen); - buff[2][slen] = '\0'; - ptr = p; + next = cf_section_find(cs, p, NULL); + if (next) return &(next->item); + + /* + * "foo" is "in the current section, OR in main". + */ + if ((p == name) && (parent_cs != NULL) && (cs != parent_cs)) { + cs = parent_cs; + goto retry; + } - if ((t3 = gettoken(&ptr, buff[3], talloc_array_length(buff[3]), true)) != T_LCBRACE) { - talloc_free(css); - ERROR("%s[%d]: Expected '{' %d", filename, *lineno, t3); - goto error; - } +no_such_item: + return NULL; +} - /* - * Swap the condition with trailing stuff for - * the final condition. - */ - memcpy(&p, &css->name2, sizeof(css->name2)); - talloc_free(p); - css->name2 = talloc_typed_strdup(css, buff[2]); +/** Return the next child that's of the specified type + * + * @param[in] parent to return children from. + * @param[in] prev child to start searching from. + * @param[in] type to search for. + * @return + * - The next #CONF_ITEM that's a child of ci matching type. + * - NULL if no #CONF_ITEM matches that criteria. + */ +static CONF_ITEM *cf_next(CONF_ITEM const *parent, CONF_ITEM const *prev, CONF_ITEM_TYPE type) +{ + CONF_ITEM *ci; - cf_data_add(css, cond, NULL, false); + for (ci = prev ? prev->next : parent->child; + ci; + ci = ci->next) { + if (ci->type == type) return ci; + } - add_section: - cf_item_add(this, &(css->item)); + return NULL; +} - /* - * The current section is now the child section. - */ - this = css; - css = NULL; - goto check_for_more; - } +/** Return the next child that's of the specified type with the specified identifiers + * + * @param[in] parent The section we're searching in. + * @param[in] type of #CONF_ITEM we're searching for. + * @param[in] ident1 The first identifier. + * @param[in] ident2 The second identifier. Special value CF_IDENT_ANY + * can be used to match any ident2 value. + * @return + * - The first matching item. + * - NULL if no items matched. + */ +static CONF_ITEM *cf_find(CONF_ITEM const *parent, CONF_ITEM_TYPE type, char const *ident1, char const *ident2) +{ + CONF_SECTION cs_find; + CONF_PAIR cp_find; + CONF_DATA cd_find; + CONF_ITEM *find; - /* - * "map" sections have three arguments! - */ - if (strcmp(buff[1], "map") == 0) { - char const *mod; - char const *exp = NULL; - char const *p; + if (!parent) return NULL; + if (!parent->child) return NULL; /* No children */ - t2 = gettoken(&ptr, buff[2], talloc_array_length(buff[2]), false); + if (!ident1) return cf_next(parent, NULL, type); - if (invalid_location(this, buff[1], filename, *lineno)) { - if (t2 != T_LCBRACE) { - ERROR("%s[%d]: Invalid syntax for 'map'", filename, *lineno); - goto error; - } + switch (type) { + case CONF_ITEM_SECTION: + memset(&cs_find, 0, sizeof(cs_find)); + cs_find.item.type = CONF_ITEM_SECTION; + cs_find.name1 = ident1; + if (ident2 != CF_IDENT_ANY) cs_find.name2 = ident2; - goto alloc_section; - } + find = (CONF_ITEM *)&cs_find; + break; - if (t2 != T_BARE_WORD) { - ERROR("%s[%d]: Expected module name after 'map'", filename, *lineno); - goto error; - } + case CONF_ITEM_PAIR: + rad_assert((ident2 == NULL) || (ident2 == CF_IDENT_ANY)); - mod = cf_expand_variables(filename, lineno, - this, - buff[3], talloc_array_length(buff[3]), - buff[2], NULL); - if (!mod) { - ERROR("%s[%d]: Parse error expanding ${...} in map module name", - filename, *lineno); - goto error; - } + memset(&cp_find, 0, sizeof(cp_find)); + cp_find.item.type = CONF_ITEM_PAIR; + cp_find.attr = ident1; - p = ptr; - t3 = gettoken(&p, buff[4], talloc_array_length(buff[4]), false); - if (fr_str_tok[t3]) { - ptr = p; + find = (CONF_ITEM *)&cp_find; + break; - exp = cf_expand_variables(filename, lineno, - this, - buff[5], talloc_array_length(buff[5]), - buff[4], NULL); - if (!exp) { - ERROR("%s[%d]: Parse error expanding ${...} in map module name", - filename, *lineno); - goto error; - } - } + case CONF_ITEM_DATA: + memset(&cd_find, 0, sizeof(cd_find)); + cd_find.item.type = CONF_ITEM_DATA; + cd_find.type = ident1; + if (ident2 != CF_IDENT_ANY) cd_find.name = ident2; - if (gettoken(&ptr, buff[6], talloc_array_length(buff[6]), false) != T_LCBRACE) { - ERROR("%s[%d]: Expecting section start brace '{' in 'map' definition", - filename, *lineno); - goto error; - } + find = (CONF_ITEM *)&cd_find; + break; - /* - * Allocate the section - */ - css = cf_section_alloc(this, buff[1], mod); - if (!css) { - ERROR("%s[%d]: Failed allocating memory for section", filename, *lineno); - goto error; - } - css->item.filename = filename; - css->item.lineno = *lineno; - css->name2_type = T_BARE_WORD; + default: + rad_assert(0); + } - css->argc = 0; - if (exp) { - css->argv = talloc_array(css, char const *, 1); - css->argv[0] = talloc_typed_strdup(css->argv, exp); - css->argv_type = talloc_array(css, FR_TOKEN, 1); - css->argv_type[0] = t3; - css->argc++; - } + /* + * No ident1, iterate over the child list + */ + if (ident1 == CF_IDENT_ANY) { + CONF_ITEM *ci; - goto add_section; - } + for (ci = parent->child; + ci && (cf_ident2_cmp(find, ci) != 0); + ci = ci->next); - skip_keywords: - /* - * Grab the next token. - */ - t2 = gettoken(&ptr, buff[2], talloc_array_length(buff[2]), false); - switch (t2) { - case T_HASH: - case T_EOL: - case T_COMMA: - do_bare_word: - t3 = t2; - t2 = T_OP_EQ; - value = NULL; - goto do_set; + return ci; + } - case T_OP_INCRM: - case T_OP_ADD: - case T_OP_SUB: - case T_OP_NE: - case T_OP_GE: - case T_OP_GT: - case T_OP_LE: - case T_OP_LT: - case T_OP_CMP_EQ: - case T_OP_CMP_FALSE: - if (!this || ((strcmp(this->name1, "update") != 0) && (strcmp(this->name1, "map") != 0))) { - ERROR("%s[%d]: Invalid operator in assignment", - filename, *lineno); - goto error; - } - /* FALL-THROUGH */ + /* + * No ident2, use the ident1 tree. + */ + if (ident2 == CF_IDENT_ANY) return rbtree_finddata(parent->ident1, find); - case T_OP_EQ: - case T_OP_SET: - while (isspace((int) *ptr)) ptr++; + /* + * Both ident1 and ident2 use the ident2 tree. + */ + return rbtree_finddata(parent->ident2, find); +} - /* - * New parser: non-quoted strings are - * bare words, and we parse everything - * until the next newline, or the next - * comma. If they have { or } in a bare - * word, well... too bad. - */ - switch (*ptr) { - case '"': - case '\'': - case '`': - case '/': - t3 = getstring(&ptr, buff[3], talloc_array_length(buff[3]), false); - break; +/** Return the next child that's of the specified type with the specified identifiers + * + * @param[in] parent The section we're searching in. + * @param[in] type of #CONF_ITEM we're searching for. + * @param[in] ident1 The first identifier. + * @param[in] ident2 The second identifier. Special value CF_IDENT_ANY + * can be used to match any ident2 value. + * @return + * - The first matching item. + * - NULL if no items matched. + */ +static CONF_ITEM *cf_find_next(CONF_ITEM const *parent, CONF_ITEM const *prev, + CONF_ITEM_TYPE type, char const *ident1, char const *ident2) +{ + CONF_SECTION cs_find; + CONF_PAIR cp_find; + CONF_DATA cd_find; + CONF_ITEM *find; + CONF_ITEM *ci; - default: - { - const char *q = ptr; + if (!parent) return NULL; - t3 = T_BARE_WORD; - while (*q && (*q >= ' ') && (*q != ',') && - !isspace(*q)) q++; + if (!prev) { + if (!ident1) return cf_next(parent, NULL, type); + return cf_find(parent, type, ident1, ident2); + } + if (!ident1) return cf_next(parent, prev, type); - if ((size_t) (q - ptr) >= talloc_array_length(buff[3])) { - ERROR("%s[%d]: Parse error: value too long", filename, *lineno); - goto error; - } + switch (type) { + case CONF_ITEM_SECTION: + memset(&cs_find, 0, sizeof(cs_find)); + cs_find.item.type = CONF_ITEM_SECTION; + cs_find.name1 = ident1; + if (ident2 != CF_IDENT_ANY) cs_find.name2 = ident2; - memcpy(buff[3], ptr, (q - ptr)); - buff[3][q - ptr] = '\0'; - ptr = q; - } - } + find = (CONF_ITEM *)&cs_find; + break; - if (t3 == T_INVALID) { - ERROR("%s[%d]: Parse error: %s", filename, *lineno, fr_strerror()); - goto error; - } + case CONF_ITEM_PAIR: + rad_assert((ident2 == NULL) || (ident2 == CF_IDENT_ANY)); - /* - * Allow "foo" by itself, or "foo = bar" - */ - switch (t3) { - bool soft_fail; + memset(&cp_find, 0, sizeof(cp_find)); + cp_find.item.type = CONF_ITEM_PAIR; + cp_find.attr = ident1; - case T_BARE_WORD: - case T_DOUBLE_QUOTED_STRING: - case T_BACK_QUOTED_STRING: -#ifdef WITH_CONF_WRITE - orig_value = buff[3]; -#endif - value = cf_expand_variables(filename, lineno, this, buff[4], talloc_array_length(buff[4]), buff[3], &soft_fail); - if (!value) { - if (!soft_fail) goto error; + find = (CONF_ITEM *)&cp_find; + break; - /* - * References an item which doesn't exist, - * or which is already marked up as being - * expanded in pass2. Wait for pass2 to - * do the expansions. - */ - pass2 = true; - value = buff[3]; - } - break; + case CONF_ITEM_DATA: + memset(&cd_find, 0, sizeof(cd_find)); + cd_find.item.type = CONF_ITEM_DATA; + cd_find.type = ident1; + if (ident2 != CF_IDENT_ANY) cd_find.name = ident2; - case T_HASH: - case T_EOL: - value = NULL; - break; + find = (CONF_ITEM *)&cd_find; + break; - default: - value = buff[3]; - break; - } + default: + rad_assert(0); + } - /* - * Add this CONF_PAIR to our CONF_SECTION - */ - do_set: - cpn = cf_pair_alloc(this, buff[1], value, t2, t1, t3); - if (!cpn) goto error; - cpn->item.filename = filename; - cpn->item.lineno = *lineno; - cpn->pass2 = pass2; - cf_item_add(this, &(cpn->item)); + if (ident1 == CF_IDENT_ANY) { + for (ci = prev->next; + ci && (cf_ident2_cmp(ci, find) != 0); + ci = ci->next); -#ifdef WITH_CONF_WRITE - if (orig_value) cpn->orig_value = talloc_typed_strdup(cpn, orig_value); - orig_value = NULL; -#endif - /* - * Require a comma, unless there's a comment. - */ - while (isspace(*ptr)) ptr++; + return ci; + } - if (*ptr == ',') { - ptr++; - break; - } + if (ident2 == CF_IDENT_ANY) { + for (ci = prev->next; + ci && (_cf_ident1_cmp(ci, find) != 0); + ci = ci->next); + + return ci; + } + + for (ci = prev->next; + ci && (_cf_ident2_cmp(ci, find) != 0); + ci = ci->next); + + return ci; +} - /* - * module # stuff! - * foo = bar # other stuff - */ -#ifdef WITH_CONF_WRITE - if (*ptr == '#') { - t3 = T_HASH; - ptr++; - } +/** Compare the first identifier of a child + * + * For CONF_ITEM_PAIR this is 'attr'. + * For CONF_ITEM_SECTION this is 'name1'. + * For CONF_ITEM_DATA this is 'type'. + * + * @param[in] a First CONF_ITEM to compare. + * @param[in] b Second CONF_ITEM to compare. + * @return + * - >0 if a > b. + * - <0 if a < b. + * - 0 if a == b. + */ +static inline int _cf_ident1_cmp(void const *a, void const *b) +{ + CONF_ITEM_TYPE type; - /* - * Allocate a CONF_COMMENT, and add it to the list of children. - */ - if ((t3 == T_HASH) && (*ptr >= ' ')) { - cf_comment_add(this, *lineno, ptr); - } -#endif + { + CONF_ITEM const *one = a; + CONF_ITEM const *two = b; - if ((t3 == T_HASH) || (t3 == T_COMMA) || (t3 == T_EOL) || (*ptr == '#')) continue; + if (one->type > two->type) return +1; + if (one->type < two->type) return -1; - if (!*ptr || (*ptr == '}')) break; + type = one->type; + } - ERROR("%s[%d]: Syntax error: Expected comma after '%s': %s", - filename, *lineno, value, ptr); - goto error; + switch (type) { + case CONF_ITEM_PAIR: + { + CONF_PAIR const *one = a; + CONF_PAIR const *two = b; - /* - * No '=', must be a section or sub-section. - */ - case T_BARE_WORD: - case T_DOUBLE_QUOTED_STRING: - case T_SINGLE_QUOTED_STRING: - t3 = gettoken(&ptr, buff[3], talloc_array_length(buff[3]), true); - if (t3 != T_LCBRACE) { - ERROR("%s[%d]: Expecting section start brace '{' after \"%s %s\"", - filename, *lineno, buff[1], buff[2]); - goto error; - } - /* FALL-THROUGH */ + return strcmp(one->attr, two->attr); + } - alloc_section: - case T_LCBRACE: - css = cf_section_alloc(this, buff[1], - t2 == T_LCBRACE ? NULL : buff[2]); - if (!css) { - ERROR("%s[%d]: Failed allocating memory for section", - filename, *lineno); - goto error; - } + case CONF_ITEM_SECTION: + { + CONF_SECTION const *one = a; + CONF_SECTION const *two = b; - css->item.filename = filename; - css->item.lineno = *lineno; - cf_item_add(this, &(css->item)); + return strcmp(one->name1, two->name1); + } - /* - * There may not be a name2 - */ - css->name2_type = (t2 == T_LCBRACE) ? T_INVALID : t2; + case CONF_ITEM_DATA: + { + CONF_DATA const *one = a; + CONF_DATA const *two = b; - /* - * The current section is now the child section. - */ - this = css; - break; + return strcmp(one->type, two->type); + } - case T_INVALID: - ERROR("%s[%d]: Syntax error in '%s': %s", filename, *lineno, ptr, fr_strerror()); + default: + rad_assert(0); + } +} - goto error; +/** Compare only the second identifier of a child + * + * For CONF_ITEM_SECTION this is 'name2'. + * For CONF_ITEM_DATA this is 'name'. + * + * @param[in] a First CONF_ITEM to compare. + * @param[in] b Second CONF_ITEM to compare. + * @return + * - >0 if a > b. + * - <0 if a < b. + * - 0 if a == b. + */ +static inline int cf_ident2_cmp(void const *a, void const *b) +{ + CONF_ITEM const *ci = a; - default: - ERROR("%s[%d]: Parse error after \"%s\": unexpected token \"%s\"", - filename, *lineno, buff[1], fr_int2str(fr_tokens_table, t2, "")); + switch (ci->type) { + case CONF_ITEM_PAIR: + return 0; - goto error; - } + case CONF_ITEM_SECTION: + { + CONF_SECTION const *one = a; + CONF_SECTION const *two = b; - check_for_more: - /* - * Done parsing one thing. Skip to EOL if possible. - */ - while (isspace(*ptr)) ptr++; + if (!two->name2 && one->name2) return +1; + if (two->name2 && !one->name2) return -1; + if (!two->name2 && !one->name2) return 0; - if (*ptr == '#') continue; + return strcmp(one->name2, two->name2); + } - if (*ptr) { - goto get_more; - } + case CONF_ITEM_DATA: + { + CONF_DATA const *one = a; + CONF_DATA const *two = b; + + if (!two->name && one->name) return +1; + if (two->name && !one->name) return -1; + if (!two->name && !one->name) return 0; + return strcmp(one->name, two->name); } - /* - * See if EOF was unexpected .. - */ - if (feof(fp) && (this != current)) { - ERROR("%s[%d]: EOF reached without closing brace for section %s starting at line %d", - filename, *lineno, cf_section_name1(this), cf_section_lineno(this)); - goto error; + default: + rad_assert(0); } +} - return 0; +/** Compare the first and second identifiers of a child + * + * For CONF_ITEM_SECTION this is 'name2'. + * For CONF_ITEM_DATA this is 'name'. + * + * @param[in] a First CONF_ITEM to compare. + * @param[in] b Second CONF_ITEM to compare. + * @return + * - >0 if a > b. + * - <0 if a < b. + * - 0 if a == b. + */ +static int _cf_ident2_cmp(void const *a, void const *b) +{ + int ret; + + ret = _cf_ident1_cmp(a, b); + if (ret != 0) return ret; + + return cf_ident2_cmp(a, b); } -/* - * Include one config file in another. +/** Add a child + * */ -static int cf_file_include(CONF_SECTION *cs, char const *filename_in, -#ifndef WITH_CONF_WRITE - UNUSED -#endif - CONF_INCLUDE_TYPE file_type, char *buff[7]) +void _cf_item_add(CONF_ITEM *parent, CONF_ITEM *child) { - FILE *fp; - int lineno = 0; - char const *filename; + fr_cursor_t to_merge; + CONF_ITEM *ci; + + rad_assert(parent != child); + + if (!parent || !child) return; /* - * So we only need to do this once. + * New child, add child trees. */ - filename = talloc_strdup(cs, filename_in); + if (!parent->ident1) parent->ident1 = rbtree_create(parent, _cf_ident1_cmp, NULL, RBTREE_FLAG_NONE); + if (!parent->ident2) parent->ident2 = rbtree_create(parent, _cf_ident2_cmp, NULL, RBTREE_FLAG_NONE); - DEBUG2("including configuration file %s", filename); + fr_cursor_init(&to_merge, &child); - fp = cf_file_open(cs, filename); - if (!fp) return -1; + for (ci = fr_cursor_head(&to_merge); + ci; + ci = fr_cursor_next(&to_merge)) { + rbtree_insert(parent->ident1, ci); + rbtree_insert(parent->ident2, ci); /* NULL ident2 is still a value */ + fr_cursor_append(&parent->cursor, ci); /* Append to the list of children */ + } +} - if (!cs->item.filename) cs->item.filename = filename; +/** Remove item from parent and fixup trees + * + * @param[in] parent to remove child from. + * @param[in] child to remove. + * @return + * - The item removed. + * - NULL if the item wasn't set. + */ +static CONF_ITEM *cf_remove(CONF_ITEM *parent, CONF_ITEM *child) +{ + CONF_ITEM *found; + bool in_ident1, in_ident2; -#ifdef WITH_CONF_WRITE - /* - * Instruct the parser that we've started to include a - * file at this point. - */ - cf_include_add(cs, filename, file_type); -#endif + if (!parent || !parent->child) return NULL; + if (parent != child->parent) return NULL; + + for (found = fr_cursor_head(&parent->cursor); + found && (child != found); + found = fr_cursor_next(&parent->cursor)); + + if (!found) return NULL; /* - * Read the section. It's OK to have EOF without a - * matching close brace. + * Fixup the linked list */ - if (cf_section_read(filename, &lineno, fp, cs, buff) < 0) { - fclose(fp); - return -1; + found = fr_cursor_remove(&parent->cursor); + rad_assert(found == child); + + in_ident1 = (rbtree_finddata(parent->ident1, child) == child); + if (in_ident1 && (!rbtree_deletebydata(parent->ident1, child))) { + rad_assert(0); + return NULL; + } + + in_ident2 = (rbtree_finddata(parent->ident2, child) == child); + if (in_ident2 && (!rbtree_deletebydata(parent->ident2, child))) { + rad_assert(0); + return NULL; } -#ifdef WITH_CONF_WRITE /* - * Instruct the parser that we've finished including a - * file at this point. + * Look for twins */ - cf_include_add(cs, NULL, file_type); -#endif + for (found = fr_cursor_head(&parent->cursor); + found && (in_ident1 || in_ident2); + found = fr_cursor_next(&parent->cursor)) { + if (in_ident1 && (_cf_ident1_cmp(found, child) == 0)) { + rbtree_insert(parent->ident1, child); + in_ident1 = false; + } - fclose(fp); - return 0; + if (in_ident2 && (_cf_ident2_cmp(found, child) == 0)) { + rbtree_insert(parent->ident2, child); + in_ident2 = false; + } + } + + return child; +} + +/** Return the next child of cs + * + * @param[in] ci to return children from. + * @param[in] prev child to start searching from. + * @return + * - The next #CONF_ITEM that's a child of cs. + * - NULL if no more #CONF_ITEM. + */ +CONF_ITEM *_cf_item_next(CONF_ITEM const *ci, CONF_ITEM const *prev) +{ + return prev ? prev->next : ci->child; +} + +CONF_SECTION *_cf_root(CONF_ITEM const *ci) +{ + CONF_ITEM const *ci_p; + + if (!ci) return NULL; + + for (ci_p = ci; ci_p->parent; ci_p = ci_p->parent); + + return cf_item_to_section(ci_p); +} + +CONF_ITEM *_cf_parent(CONF_ITEM const *ci) +{ + if (!ci) return NULL; + + return ci->parent; +} + +int _cf_lineno(CONF_ITEM const *ci) +{ + return ci->lineno; +} + +char const *_cf_filename(CONF_ITEM const *ci) +{ + return ci->filename; +} + +bool cf_item_is_section(CONF_ITEM const *ci) +{ + return ci->type == CONF_ITEM_SECTION; +} + +bool cf_item_is_pair(CONF_ITEM const *ci) +{ + return ci->type == CONF_ITEM_PAIR; +} + +bool cf_item_is_data(CONF_ITEM const *ci) +{ + return ci->type == CONF_ITEM_DATA; +} + +/** Cast a CONF_ITEM to a CONF_PAIR + * + */ +CONF_PAIR *cf_item_to_pair(CONF_ITEM const *ci) +{ + CONF_PAIR *out; + + if (ci == NULL) return NULL; + + rad_assert(ci->type == CONF_ITEM_PAIR); + + memcpy(&out, &ci, sizeof(out)); + return out; +} + +/** Cast a CONF_ITEM to a CONF_SECTION + * + */ +CONF_SECTION *cf_item_to_section(CONF_ITEM const *ci) +{ + CONF_SECTION *out; + + if (ci == NULL) return NULL; + + rad_assert(ci->type == CONF_ITEM_SECTION); + + memcpy(&out, &ci, sizeof(out)); + return out; +} + +CONF_DATA *cf_item_to_data(CONF_ITEM const *ci) +{ + CONF_DATA *out; + + if (ci == NULL) return NULL; + + rad_assert(ci->type == CONF_ITEM_DATA); + + memcpy(&out, &ci, sizeof(out)); + return out; } +/** Cast a CONF_PAIR to a CONF_ITEM + * + */ +CONF_ITEM *cf_pair_to_item(CONF_PAIR const *cp) +{ + CONF_ITEM *out; + + if (cp == NULL) return NULL; + + memcpy(&out, &cp, sizeof(out)); + return out; +} -/* - * Do variable expansion in pass2. +/** Cast a CONF_SECTION to a CONF_ITEM * - * This is a breadth-first expansion. "deep */ -static int cf_section_pass2(CONF_SECTION *cs) +CONF_ITEM *cf_section_to_item(CONF_SECTION const *cs) { - CONF_ITEM *ci; - - for (ci = cs->children; ci; ci = ci->next) { - char const *value; - CONF_PAIR *cp; - char buffer[8192]; - - if (ci->type != CONF_ITEM_PAIR) continue; + CONF_ITEM *out; - cp = cf_item_to_pair(ci); - if (!cp->value || !cp->pass2) continue; + if (cs == NULL) return NULL; - rad_assert((cp->rhs_type == T_BARE_WORD) || - (cp->rhs_type == T_DOUBLE_QUOTED_STRING) || - (cp->rhs_type == T_BACK_QUOTED_STRING)); + memcpy(&out, &cs, sizeof(out)); + return out; +} - value = cf_expand_variables(ci->filename, &ci->lineno, cs, buffer, sizeof(buffer), cp->value, NULL); - if (!value) return -1; +/** Cast CONF_DATA to a CONF_ITEM + * + */ +CONF_ITEM *cf_data_to_item(CONF_DATA const *cd) +{ + CONF_ITEM *out; - talloc_const_free(cp->value); - cp->value = talloc_typed_strdup(cp, value); - } + if (cd == NULL) return NULL; - for (ci = cs->children; ci; ci = ci->next) { - if (ci->type != CONF_ITEM_SECTION) continue; + memcpy(&out, &cd, sizeof(out)); + return out; +} - if (cf_section_pass2(cf_item_to_section(ci)) < 0) return -1; - } +static int _cf_section_free(CONF_SECTION *cs) +{ + if (cs->item.ident1) TALLOC_FREE(cs->item.ident1); + if (cs->item.ident2) TALLOC_FREE(cs->item.ident2); return 0; } - -/* - * Bootstrap a config file. +/** Allocate a #CONF_SECTION + * + * @param parent #CONF_SECTION to hang this #CONF_SECTION off of. + * @param name1 Primary name. + * @param name2 Secondary name. + * @return + * - NULL on error. + * - A new #CONF_SECTION parented by parent. */ -int cf_file_read(CONF_SECTION *cs, char const *filename) +CONF_SECTION *cf_section_alloc(CONF_SECTION *parent, char const *name1, char const *name2) { - int i; - char *p; - CONF_PAIR *cp; - rbtree_t *tree; - char **buff; - - cp = cf_pair_alloc(cs, "confdir", filename, T_OP_EQ, T_BARE_WORD, T_SINGLE_QUOTED_STRING); - if (!cp) return -1; + CONF_SECTION *cs; - p = strrchr(cp->value, FR_DIR_SEP); - if (p) *p = '\0'; + if (!name1) return NULL; - cf_item_add(cs, &(cp->item)); + if (name2 && parent) { + char buffer[1024]; - tree = rbtree_create(cs, filename_cmp, NULL, 0); - if (!tree) return -1; + if (strchr(name2, '$')) { + name2 = cf_expand_variables(parent->item.filename, + &parent->item.lineno, + parent, + buffer, sizeof(buffer), name2, NULL); + if (!name2) { + ERROR("Failed expanding section name"); + return NULL; + } + } + } - cf_data_add(cs, tree, "filename", false); + cs = talloc_zero(parent, CONF_SECTION); + if (!cs) return NULL; - /* - * Allocate temporary buffers on the heap (so we don't use *all* the stack space) - */ - buff = talloc_array(cs, char *, 7); - for (i = 0; i < 7; i++) { - buff[i] = talloc_array(buff, char, 8192); - } + cs->item.type = CONF_ITEM_SECTION; + cs->item.parent = cf_section_to_item(parent); + fr_cursor_init(&cs->item.cursor, &cs->item.child); - if (cf_file_include(cs, filename, CONF_INCLUDE_FILE, buff) < 0) { - talloc_free(buff); - return -1; + MEM(cs->name1 = talloc_typed_strdup(cs, name1)); + if (name2) { + MEM(cs->name2 = talloc_typed_strdup(cs, name2)); + cs->name2_quote = T_BARE_WORD; } + talloc_set_destructor(cs, _cf_section_free); - talloc_free(buff); - - /* - * Now that we've read the file, go back through it and - * expand the variables. - */ - if (cf_section_pass2(cs) < 0) return -1; + if (parent) cs->depth = parent->depth + 1; - return 0; + return cs; } - -void cf_file_free(CONF_SECTION *cs) +/** Duplicate a configuration section + * + * @note recursively duplicates any child sections. + * @note does not duplicate any data associated with a section, or its child sections. + * + * @param[in] parent section (may be NULL). + * @param[in] cs to duplicate. + * @param[in] name1 of new section. + * @param[in] name2 of new section. + * @param[in] copy_meta Copy additional meta data for a section + * (like template, base, depth and variables). + * @return + * - A duplicate of the existing section. + * - NULL on error. + */ +CONF_SECTION *cf_section_dup(CONF_SECTION *parent, CONF_SECTION const *cs, + char const *name1, char const *name2, bool copy_meta) { - talloc_free(cs); -} + CONF_SECTION *new, *subcs; + CONF_PAIR *cp; + CONF_ITEM *ci; + fr_cursor_t cursor; + new = cf_section_alloc(parent, name1, name2); -/* - * Return a CONF_PAIR within a CONF_SECTION. - */ -CONF_PAIR *cf_pair_find(CONF_SECTION const *cs, char const *name) -{ - CONF_PAIR *cp, mycp; + if (copy_meta) { + new->template = cs->template; + new->base = cs->base; + new->depth = cs->depth; + new->variables = cs->variables; + } + + new->item.lineno = cs->item.lineno; + new->item.filename = cs->item.filename; + + fr_cursor_copy(&cursor, &cs->item.cursor); /* Mutable cursor */ + for (ci = fr_cursor_head(&cursor); + ci; + ci = fr_cursor_next(&cursor)) { + switch (ci->type) { + case CONF_ITEM_SECTION: + subcs = cf_item_to_section(ci); + subcs = cf_section_dup(new, subcs, + cf_section_name1(subcs), cf_section_name2(subcs), + copy_meta); + if (!subcs) { + talloc_free(new); + return NULL; + } + cf_section_add(new, subcs); + break; - if (!cs || !name) return NULL; + case CONF_ITEM_PAIR: + cp = cf_pair_dup(new, cf_item_to_pair(ci)); + if (!cp) { + talloc_free(new); + return NULL; + } + cf_pair_add(new, cp); + break; - mycp.attr = name; - cp = rbtree_finddata(cs->pair_tree, &mycp); - if (cp) return cp; + case CONF_ITEM_DATA: /* Skip data */ +#ifdef WITH_CONF_WRITE + case CONF_ITEM_COMMENT: + case CONF_ITEM_INCLUDE: +#endif + break; - if (!cs->template) return NULL; + case CONF_ITEM_INVALID: + rad_assert(0); + } + } - return rbtree_finddata(cs->template->pair_tree, &mycp); + return new; } -/* - * Return the attr of a CONF_PAIR +/** Add a section as a child of another section + * + * @param[in] parent section we're adding to. + * @param[in] cs we're adding. */ - -char const *cf_pair_attr(CONF_PAIR const *pair) +void cf_section_add(CONF_SECTION *parent, CONF_SECTION *cs) { - return (pair ? pair->attr : NULL); + cf_item_add(parent, &(cs->item)); } -/* - * Return the value of a CONF_PAIR +/** Return the next child that's a #CONF_SECTION + * + * @param[in] cs to return children from. + * @param[in] prev child to start searching from. + * @return + * - The next #CONF_ITEM that's a child of cs and a CONF_SECTION. + * - NULL if no #CONF_ITEM matches that criteria. */ - -char const *cf_pair_value(CONF_PAIR const *pair) +CONF_SECTION *cf_section_next(CONF_SECTION const *cs, CONF_SECTION const *prev) { - return (pair ? pair->value : NULL); + return cf_item_to_section(cf_next(cf_section_to_item(cs), cf_section_to_item(prev), CONF_ITEM_SECTION)); } -FR_TOKEN cf_pair_operator(CONF_PAIR const *pair) +/** Find a CONF_SECTION with name1 and optionally name2. + * + * @param[in] cs The section we're searching in. + * @param[in] name1 The first section identifier. + * @param[in] name2 The second section identifier. Special value CF_IDENT_ANY + * can be used to match any name2 value. + * @return + * - The first matching subsection. + * - NULL if no subsections match. + */ +CONF_SECTION *cf_section_find(CONF_SECTION const *cs, + char const *name1, char const *name2) { - return (pair ? pair->op : T_INVALID); + return cf_item_to_section(cf_find(cf_section_to_item(cs), CONF_ITEM_SECTION, name1, name2)); } -/** Return the value (lhs) type +/** Return the next matching section * - * @param pair to extract value type from. + * @param[in] cs The section we're searching in. + * @param[in] prev section we found. May be NULL in which case + * we just return the next section after prev. + * @param[in] name1 of the section we're searching for. + * @param[in] name2 of the section we're searching for. Special value CF_IDENT_ANY + * can be used to match any name2 value. * @return - * - #T_BARE_WORD. - * - #T_SINGLE_QUOTED_STRING. - * - #T_BACK_QUOTED_STRING. - * - #T_DOUBLE_QUOTED_STRING. - * - #T_INVALID if the pair is NULL. + * - The next CONF_SECTION. + * - NULL if there are no more CONF_SECTIONs */ -FR_TOKEN cf_pair_attr_type(CONF_PAIR const *pair) +CONF_SECTION *cf_section_find_next(CONF_SECTION const *cs, CONF_SECTION const *prev, + char const *name1, char const *name2) { - return (pair ? pair->lhs_type : T_INVALID); + return cf_item_to_section(cf_find_next(cf_section_to_item(cs), cf_section_to_item(prev), + CONF_ITEM_SECTION, name1, name2)); } -/** Return the value (rhs) type +/** Find a value in a CONF_SECTION * - * @param pair to extract value type from. - * @return - * - #T_BARE_WORD. - * - #T_SINGLE_QUOTED_STRING. - * - #T_BACK_QUOTED_STRING. - * - #T_DOUBLE_QUOTED_STRING. - * - #T_INVALID if the pair is NULL. */ -FR_TOKEN cf_pair_value_type(CONF_PAIR const *pair) +char const *cf_section_value_find(CONF_SECTION const *cs, char const *attr) { - return (pair ? pair->rhs_type : T_INVALID); + CONF_PAIR *cp; + + cp = cf_pair_find(cs, attr); + + return (cp ? cp->value : NULL); } -/* - * Return the first label of a CONF_SECTION +/** Return the first label of a CONF_SECTION + * */ - char const *cf_section_name1(CONF_SECTION const *cs) { return (cs ? cs->name1 : NULL); } -/* - * Return the second label of a CONF_SECTION +/** Return the second label of a CONF_SECTION + * */ - char const *cf_section_name2(CONF_SECTION const *cs) { return (cs ? cs->name2 : NULL); @@ -3836,260 +4183,200 @@ char const *cf_section_name(CONF_SECTION const *cs) return cf_section_name1(cs); } -char const *cf_section_argv(CONF_SECTION const *cs, int argc) -{ - if (!cs || !cs->argv || (argc < 0) || (argc > cs->argc)) return NULL; - - return cs->argv[argc]; -} - -/* - * Find a value in a CONF_SECTION - */ -char const *cf_section_value_find(CONF_SECTION const *cs, char const *attr) -{ - CONF_PAIR *cp; - - cp = cf_pair_find(cs, attr); - - return (cp ? cp->value : NULL); -} - - -CONF_SECTION *cf_section_find_name2(CONF_SECTION const *cs, - char const *name1, char const *name2) -{ - char const *their2; - CONF_ITEM const *ci; - - if (!cs || !name1) return NULL; - - for (ci = &(cs->item); ci; ci = ci->next) { - if (ci->type != CONF_ITEM_SECTION) - continue; - - if (strcmp(cf_item_to_section(ci)->name1, name1) != 0) { - continue; - } - - their2 = cf_item_to_section(ci)->name2; - - if ((!name2 && !their2) || - (name2 && their2 && (strcmp(name2, their2) == 0))) { - return cf_item_to_section(ci); - } - } - - return NULL; -} - -/** Find a pair with a name matching attr, after specified pair. - * - * @param cs to search in. - * @param pair to search from (may be NULL). - * @param attr to find (may be NULL in which case any attribute matches). - * @return the next matching #CONF_PAIR or NULL if none matched. - */ -CONF_PAIR *cf_pair_find_next(CONF_SECTION const *cs, - CONF_PAIR const *pair, char const *attr) -{ - CONF_ITEM *ci; - - if (!cs) return NULL; - - /* - * If pair is NULL and we're trying to find a specific - * attribute this must be a first time run. - * - * Find the pair with correct name. - */ - if (!pair && attr) return cf_pair_find(cs, attr); - - /* - * Start searching from the next child, or from the head - * of the list of children (if no pair was provided). - */ - for (ci = pair ? pair->item.next : cs->children; - ci; - ci = ci->next) { - if (ci->type != CONF_ITEM_PAIR) continue; - - if (!attr || strcmp(cf_item_to_pair(ci)->attr, attr) == 0) break; - } +char const *cf_section_argv(CONF_SECTION const *cs, int argc) +{ + if (!cs || !cs->argv || (argc < 0) || (argc > cs->argc)) return NULL; - return cf_item_to_pair(ci); + return cs->argv[argc]; } -/** Find a sub-section in a section - * - * This finds ANY section having the same first name. - * The second name is ignored. +/* + * For "switch" and "case" statements. */ -CONF_SECTION *cf_subsection_find(CONF_SECTION const *cs, char const *name) +FR_TOKEN cf_section_name2_quote(CONF_SECTION const *cs) { - CONF_SECTION mycs; + if (!cs) return T_INVALID; - if (!cs || !name) return NULL; /* can't find an un-named section */ + return cs->name2_quote; +} - /* - * No sub-sections have been defined, so none exist. - */ - if (!cs->section_tree) return NULL; +FR_TOKEN cf_section_argv_quote(CONF_SECTION const *cs, int argc) +{ + if (!cs || !cs->argv_quote || (argc < 0) || (argc > cs->argc)) return T_INVALID; - mycs.name1 = name; - mycs.name2 = NULL; - return rbtree_finddata(cs->section_tree, &mycs); + return cs->argv_quote[argc]; } - -/** Find a CONF_SECTION with both names. +/** Allocate a #CONF_PAIR * + * @param[in] parent #CONF_SECTION to hang this #CONF_PAIR off of. + * @param[in] attr name. + * @param[in] value of #CONF_PAIR. + * @param[in] op #T_OP_EQ, #T_OP_SET etc. + * @param[in] lhs_quote #T_BARE_WORD, #T_DOUBLE_QUOTED_STRING, #T_BACK_QUOTED_STRING. + * @param[in] rhs_quote #T_BARE_WORD, #T_DOUBLE_QUOTED_STRING, #T_BACK_QUOTED_STRING. + * @return + * - NULL on error. + * - A new #CONF_SECTION parented by parent. */ -CONF_SECTION *cf_subsection_find_name2(CONF_SECTION const *cs, - char const *name1, char const *name2) +CONF_PAIR *cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value, + FR_TOKEN op, FR_TOKEN lhs_quote, FR_TOKEN rhs_quote) { - CONF_ITEM *ci; - - if (!cs) return NULL; - - if (name1) { - CONF_SECTION mycs, *master_cs; - - if (!cs->section_tree) return NULL; + CONF_PAIR *cp; - mycs.name1 = name1; - mycs.name2 = name2; + rad_assert(fr_equality_op[op] || fr_assignment_op[op]); + if (!attr) return NULL; - master_cs = rbtree_finddata(cs->section_tree, &mycs); - if (!master_cs) return NULL; + cp = talloc_zero(parent, CONF_PAIR); + if (!cp) return NULL; - /* - * Look it up in the name2 tree. If it's there, - * return it. - */ - if (master_cs->name2_tree) { - CONF_SECTION *subcs; + cp->item.type = CONF_ITEM_PAIR; + cp->item.parent = cf_section_to_item(parent); + cp->lhs_quote = lhs_quote; + cp->rhs_quote = rhs_quote; + cp->op = op; + cp->item.filename = ""; /* will be over-written if necessary */ + fr_cursor_init(&cp->item.cursor, &cp->item.child); - subcs = rbtree_finddata(master_cs->name2_tree, &mycs); - if (subcs) return subcs; - } + cp->attr = talloc_typed_strdup(cp, attr); + if (!cp->attr) { + error: + talloc_free(cp); + return NULL; + } - /* - * We don't insert ourselves into the name2 tree. - * So if there's nothing in the name2 tree, maybe - * *we* are the answer. - */ - if (!master_cs->name2 && name2) return NULL; - if (master_cs->name2 && !name2) return NULL; - if (!master_cs->name2 && !name2) return master_cs; + if (value) { +#ifdef WITH_CONF_WRITE + cp->orig_value = talloc_typed_strdup(cp, value); +#endif + cp->value = talloc_typed_strdup(cp, value); + if (!cp->value) goto error; + } - if (strcmp(master_cs->name2, name2) == 0) { - return master_cs; - } + return cp; +} - return NULL; - } +/** Duplicate a #CONF_PAIR + * + * @param parent to allocate new pair in. + * @param cp to duplicate. + * @return + * - NULL on error. + * - A duplicate of the input pair. + */ +CONF_PAIR *cf_pair_dup(CONF_SECTION *parent, CONF_PAIR *cp) +{ + CONF_PAIR *new; - /* - * Else do it the old-fashioned way. - */ - for (ci = cs->children; ci; ci = ci->next) { - CONF_SECTION *subcs; + rad_assert(parent); + rad_assert(cp); - if (ci->type != CONF_ITEM_SECTION) - continue; + new = cf_pair_alloc(parent, cp->attr, cf_pair_value(cp), + cp->op, cp->lhs_quote, cp->rhs_quote); + if (!new) return NULL; - subcs = cf_item_to_section(ci); - if (!subcs->name2) { - if (strcmp(subcs->name1, name2) == 0) break; - } else { - if (strcmp(subcs->name2, name2) == 0) break; - } - } + new->parsed = cp->parsed; + new->item.lineno = cp->item.lineno; + new->item.filename = cp->item.filename; - return cf_item_to_section(ci); + return new; } -/* - * Return the next subsection after a CONF_SECTION - * with a certain name1 (char *name1). If the requested - * name1 is NULL, any name1 matches. +/** Replace pair in a given section with a new pair, of the given value. + * + * @param[in] cs to replace pair in. + * @param[in] cp to replace. + * @param[in] value New value to assign to cp. + * @return + * - 0 on success. + * - -1 on failure. */ - -CONF_SECTION *cf_subsection_find_next(CONF_SECTION const *section, - CONF_SECTION const *subsection, - char const *name1) +int cf_pair_replace(CONF_SECTION *cs, CONF_PAIR *cp, char const *value) { - CONF_ITEM *ci; + CONF_PAIR *new_cp; + CONF_ITEM *ci; + + if (!cs || !cp || !value) return -1; - if (!section) return NULL; + MEM(new_cp = cf_pair_alloc(cs, cp->attr, value, cp->op, cp->lhs_quote, cp->rhs_quote)); /* - * If subsection is NULL this must be a first time run - * Find the subsection with correct name + * Remove the old CONF_PAIR */ + ci = cf_remove(cf_section_to_item(cs), cf_pair_to_item(cp)); + rad_assert(!ci || (ci == cf_pair_to_item(cp))); - if (!subsection) { - ci = section->children; - } else { - ci = subsection->item.next; - } + /* + * Add the new CONF_PAIR + */ + cf_item_add(cf_section_to_item(cs), cf_pair_to_item(new_cp)); - for (; ci; ci = ci->next) { - if (ci->type != CONF_ITEM_SECTION) - continue; - if ((name1 == NULL) || - (strcmp(cf_item_to_section(ci)->name1, name1) == 0)) - break; - } + cp = cf_pair_find(cs, cp->attr); + rad_assert(cp == new_cp); - return cf_item_to_section(ci); -} + talloc_free(ci); + return 0; +} -/* - * Return the next section after a CONF_SECTION - * with a certain name1 (char *name1). If the requested - * name1 is NULL, any name1 matches. +/** Add a configuration pair to a section + * + * @param[in] parent section to add pair to. + * @param[in] cp to add. */ - -CONF_SECTION *cf_section_find_next(CONF_SECTION const *section, - CONF_SECTION const *subsection, - char const *name1) +void cf_pair_add(CONF_SECTION *parent, CONF_PAIR *cp) { - if (!section) return NULL; - - if (!section->item.parent) return NULL; + cf_item_add(parent, cf_pair_to_item(cp)); +} - return cf_subsection_find_next(cf_item_to_section(section->item.parent), subsection, name1); +/** Return the next child that's a #CONF_PAIR + * + * @param[in] cs to return children from. + * @param[in] prev child to start searching from. + * @return + * - The next #CONF_ITEM that's a child of cs and a CONF_PAIR. + * - NULL if no #CONF_ITEM matches that criteria. + */ +CONF_PAIR *cf_pair_next(CONF_SECTION const *cs, CONF_PAIR const *prev) +{ + return cf_item_to_pair(cf_next(cf_section_to_item(cs), cf_pair_to_item(prev), CONF_ITEM_PAIR)); } -/** Return the next item after a CONF_ITEM. +/** Search for a #CONF_PAIR with a specific name * + * @param[in] cs to search in. + * @param[in] attr to find. + * @return + * - The next matching #CONF_PAIR. + * - NULL if none matched. */ -CONF_ITEM *cf_item_find_next(CONF_SECTION const *section, CONF_ITEM const *item) +CONF_PAIR *cf_pair_find(CONF_SECTION const *cs, char const *attr) { - if (!section) return NULL; + return cf_item_to_pair(cf_find(cf_section_to_item(cs), CONF_ITEM_PAIR, attr, NULL)); +} - /* - * If item is NULL this must be a first time run - * Return the first item - */ - if (item == NULL) { - return section->children; - } else { - return item->next; - } +/** Find a pair with a name matching attr, after specified pair. + * + * @param[in] cs to search in. + * @param[in] prev Pair to search from (may be NULL). + * @param[in] attr to find (may be NULL in which case any attribute matches). + * @return + * - The next matching #CONF_PAIR + * - NULL if none matched. + */ +CONF_PAIR *cf_pair_find_next(CONF_SECTION const *cs, CONF_PAIR const *prev, char const *attr) +{ + return cf_item_to_pair(cf_find_next(cf_section_to_item(cs), cf_pair_to_item(prev), CONF_ITEM_PAIR, attr, NULL)); } +/** Callback to determine the number of pairs in a section + * + */ static void _pair_count(int *count, CONF_SECTION const *cs) { - CONF_ITEM const *ci; - - for (ci = cf_item_find_next(cs, NULL); - ci != NULL; - ci = cf_item_find_next(cs, ci)) { + CONF_ITEM const *ci = NULL; + while ((ci = cf_item_next(cs, ci))) { if (cf_item_is_section(ci)) { _pair_count(count, cf_item_to_section(ci)); continue; @@ -4102,7 +4389,7 @@ static void _pair_count(int *count, CONF_SECTION const *cs) /** Count the number of conf pairs beneath a section * * @param[in] cs to search for items in. - * @return number of pairs nested within section. + * @return The number of pairs nested within section. */ int cf_pair_count(CONF_SECTION const *cs) { @@ -4113,66 +4400,55 @@ int cf_pair_count(CONF_SECTION const *cs) return count; } -CONF_ITEM *cf_item_parent(CONF_ITEM const *ci) -{ - if (!ci) return NULL; - - return ci->parent; -} - -CONF_SECTION *cf_section_parent(CONF_SECTION const *cs) -{ - if (!cs) return NULL; - - return cf_item_to_section(cs->item.parent); -} - -CONF_SECTION *cf_pair_parent(CONF_PAIR const *cp) -{ - if (!cp) return NULL; - - return cf_item_to_section(cp->item.parent); -} - -CONF_SECTION *cf_item_root(CONF_ITEM const *ci) -{ - CONF_ITEM *ci_p; - - if (!ci) return NULL; - - for (ci_p = ci->parent; ci_p->parent; ci_p = ci_p->parent); - - return cf_item_to_section(ci_p); -} - -int cf_section_lineno(CONF_SECTION const *section) -{ - return section->item.lineno; -} - -char const *cf_pair_filename(CONF_PAIR const *pair) +/** Return the attr of a CONF_PAIR + * + */ +char const *cf_pair_attr(CONF_PAIR const *pair) { - return pair->item.filename; + return (pair ? pair->attr : NULL); } -char const *cf_section_filename(CONF_SECTION const *section) +/** Return the value of a CONF_PAIR + * + */ +char const *cf_pair_value(CONF_PAIR const *pair) { - return section->item.filename; + return (pair ? pair->value : NULL); } -int cf_pair_lineno(CONF_PAIR const *pair) +FR_TOKEN cf_pair_operator(CONF_PAIR const *pair) { - return pair->item.lineno; + return (pair ? pair->op : T_INVALID); } -bool cf_item_is_section(CONF_ITEM const *item) +/** Return the value (lhs) type + * + * @param pair to extract value type from. + * @return + * - #T_BARE_WORD. + * - #T_SINGLE_QUOTED_STRING. + * - #T_BACK_QUOTED_STRING. + * - #T_DOUBLE_QUOTED_STRING. + * - #T_INVALID if the pair is NULL. + */ +FR_TOKEN cf_pair_attr_quote(CONF_PAIR const *pair) { - return item->type == CONF_ITEM_SECTION; + return (pair ? pair->lhs_quote : T_INVALID); } -bool cf_item_is_pair(CONF_ITEM const *item) +/** Return the value (rhs) type + * + * @param pair to extract value type from. + * @return + * - #T_BARE_WORD. + * - #T_SINGLE_QUOTED_STRING. + * - #T_BACK_QUOTED_STRING. + * - #T_DOUBLE_QUOTED_STRING. + * - #T_INVALID if the pair is NULL. + */ +FR_TOKEN cf_pair_value_quote(CONF_PAIR const *pair) { - return item->type == CONF_ITEM_PAIR; + return (pair ? pair->rhs_quote : T_INVALID); } /** Allocate a new user data container @@ -4194,6 +4470,7 @@ static CONF_DATA *cf_data_alloc(CONF_ITEM *parent, void const *data, char const cd->item.type = CONF_ITEM_DATA; cd->item.parent = parent; + fr_cursor_init(&cd->item.cursor, &cd->item.child); /* * strdup so if the data is freed, we can @@ -4216,130 +4493,110 @@ static CONF_DATA *cf_data_alloc(CONF_ITEM *parent, void const *data, char const /** Find user data in a config section * - * @param[in] cs to add data to. + * @param[in] ci to add data to. * @param[in] type of user data. Used for name spacing and walking over a specific * type of user data. - * @param[in] name String identifier of the user data. + * @param[in] name String identifier of the user data. Special value CF_IDENT_ANY + * may be used to match on type only. * @return * - The user data. * - NULL if no user data exists. */ -void *_cf_data_find(CONF_SECTION const *cs, char const *type, char const *name) +CONF_DATA const *_cf_data_find(CONF_ITEM const *ci, char const *type, char const *name) { - if (!cs || (!type && !name)) { - cf_log_err_cs(cs, "Invalid arguments"); - return NULL; - } + return cf_item_to_data(cf_find(ci, CONF_ITEM_DATA, type, name)); +} - /* - * Find the name in the tree, for speed. - */ - if (cs->data_tree) { - CONF_DATA mycd, *cd; +/** Return the next matching section + * + * @param[in] ci The section we're searching in. + * @param[in] prev section we found. May be NULL in which case + * we just return the next section after prev. + * @param[in] type of user data. Used for name spacing and walking over a specific + * type of user data. + * @param[in] name String identifier of the user data. Special value CF_IDENT_ANY + * can be used to match any name2 value. + * @return + * - The next CONF_SECTION. + * - NULL if there are no more CONF_SECTIONs + */ +CONF_DATA const *_cf_data_find_next(CONF_ITEM const *ci, CONF_ITEM const *prev, char const *type, char const *name) +{ + return cf_item_to_data(cf_find_next(ci, prev, CONF_ITEM_DATA, type, name)); +} - mycd.type = type; - mycd.name = name; - cd = rbtree_finddata(cs->data_tree, &mycd); - if (cd) { - void *to_return; - memcpy(&to_return, &cd->data, sizeof(to_return)); +/** Return the user assigned value of #CONF_DATA + * + */ +void *cf_data_value(CONF_DATA const *cd) +{ + void *to_return; - return to_return; - } - } + if (!cd) return NULL; - return NULL; + memcpy(&to_return, &cd->data, sizeof(to_return)); + + return to_return; } /** Add user data to a config section * - * @param[in] cs to add data to. + * @param[in] ci to add data to. * @param[in] data to add. * @param[in] name String identifier of the user data. * @param[in] do_free Function to free user data when the CONF_SECTION is freed. * @return - * - 0 on success. - * - -1 on error. + * - #CONF_DATA - opaque handle to the stored data - on success. + * - NULL error. */ -int _cf_data_add(CONF_SECTION *cs, void const *data, char const *name, bool do_free) +CONF_DATA const *_cf_data_add(CONF_ITEM *ci, void const *data, char const *name, bool do_free) { CONF_DATA *cd; char const *type = NULL; - if (!cs || (!data && !name)) { - cf_log_err_cs(cs, "Invalid arguments"); - return -1; - } + if (!ci) return NULL; if (data) type = talloc_get_name(data); /* * Already exists. Can't add it. */ - if (_cf_data_find(cs, type, name)) { - cf_log_err_cs(cs, "Data of type %s with name %s already exists", type, name); - return -1; + if (_cf_data_find(ci, type, name)) { + cf_log_err(ci, "Data of type %s with name %s already exists", type, name); + return NULL; } - cd = cf_data_alloc(cf_section_to_item(cs), data, name, do_free); + cd = cf_data_alloc(ci, data, name, do_free); if (!cd) { - cf_log_err_cs(cs, "Failed allocating data"); - return -1; + cf_log_err(ci, "Failed allocating data"); + return NULL; } - cf_item_add(cs, cf_data_to_item(cd)); + cf_item_add(ci, cf_data_to_item(cd)); - return 0; + return cd; } /** Remove named data from a configuration section * - * @param[in] cs to remove data from. - * @param[in] type of user data. Used for name spacing and walking over a specific - * type of user data. - * @param[in] name String identifier of the user data. + * @param[in] parent to remove data from. + * @param[in] cd opaque handle of the stored data. * @return - * - The user data. - * - NULL if no matching data is found. + * - The value stored within the data (if cd is valid and was found and removed). + * - NULL if not found. */ -void *_cf_data_remove(CONF_SECTION *cs, char const *type, char const *name) +void *_cf_data_remove(CONF_ITEM *parent, CONF_DATA const *cd) { - CONF_DATA mycd; - CONF_DATA *cd; - CONF_ITEM *ci, *it; void *data; + CONF_ITEM *ci; - if (!cs || !name) return NULL; - if (!cs->data_tree) return NULL; - - /* - * Find the name in the tree, for speed. - */ - mycd.type = type; - mycd.name = name; - - cd = rbtree_finddata(cs->data_tree, &mycd); - if (!cd) return NULL; - - ci = cf_data_to_item(cd); - if (cs->children == ci) { - cs->children = ci->next; - if (cs->tail == ci) cs->tail = NULL; - } else { - for (it = cs->children; it; it = it->next) { - if (it->next == ci) { - it->next = ci->next; - if (cs->tail == ci) cs->tail = it; - break; - } - } - } + ci = cf_remove(parent, cf_data_to_item(cd)); + rad_assert(!ci || (ci == cf_data_to_item(cd))); + if (!ci) return NULL; talloc_set_destructor(cd, NULL); /* Disarm the destructor */ - rbtree_deletebydata(cs->data_tree, &mycd); - memcpy(&data, &cd->data, sizeof(data)); - talloc_free(cd); + talloc_const_free(cd); return data; } @@ -4362,9 +4619,15 @@ static int _cf_data_walk_cb(void *ctx, void *data) { cf_data_walk_ctx_t *cd_ctx = ctx; CONF_DATA *cd = data; + CONF_ITEM *ci = data; void *mutable; int ret; + /* + * We're walking ident2, not all of the items will be data + */ + if (ci->type != CONF_ITEM_DATA) return 0; + if ((cd->type != cd_ctx->type) && (strcmp(cd->type, cd_ctx->type) != 0)) return 0; memcpy(&mutable, &cd->data, sizeof(data)); @@ -4375,7 +4638,7 @@ static int _cf_data_walk_cb(void *ctx, void *data) /** Walk over a specific type of CONF_DATA * - * @param[in] cs containing the CONF_DATA to walk over. + * @param[in] ci containing the CONF_DATA to walk over. * @param[in] type of CONF_DATA to walk over. * @param[in] cb to call when we find CONF_DATA of the specified type. * @param[in] ctx to pass to cb. @@ -4383,7 +4646,7 @@ static int _cf_data_walk_cb(void *ctx, void *data) * - 0 on success. * - -1 on failure. */ -int _cf_data_walk(CONF_SECTION *cs, char const *type, cf_walker_t cb, void *ctx) +int _cf_data_walk(CONF_ITEM *ci, char const *type, cf_walker_t cb, void *ctx) { cf_data_walk_ctx_t cd_ctx = { .type = type, @@ -4391,420 +4654,281 @@ int _cf_data_walk(CONF_SECTION *cs, char const *type, cf_walker_t cb, void *ctx) .ctx = ctx }; - if (!cs->data_tree) return 0; - - return rbtree_walk(cs->data_tree, RBTREE_IN_ORDER, _cf_data_walk_cb, &cd_ctx); -} - -/* - * This is here to make the rest of the code easier to read. It - * ties conf_file.c to log.c, but it means we don't have to - * pollute every other function with the knowledge of the - * configuration internals. - */ -void cf_log_err(CONF_ITEM const *ci, char const *fmt, ...) -{ - va_list ap; - char buffer[256]; - - va_start(ap, fmt); - vsnprintf(buffer, sizeof(buffer), fmt, ap); - va_end(ap); - - if (ci) { - ERROR("%s[%d]: %s", - ci->filename, ci->lineno, - buffer); - } else { - ERROR("[*]: %s", buffer); - } -} - -void cf_log_err_cs(CONF_SECTION const *cs, char const *fmt, ...) -{ - va_list ap; - char buffer[256]; - - va_start(ap, fmt); - vsnprintf(buffer, sizeof(buffer), fmt, ap); - va_end(ap); - - rad_assert(cs != NULL); + if (!ci->ident2) return 0; - ERROR("%s[%d]: %s", - cs->item.filename, cs->item.lineno, - buffer); + return rbtree_walk(ci->ident2, RBTREE_IN_ORDER, _cf_data_walk_cb, &cd_ctx); } -void cf_log_perr_cs(CONF_SECTION const *cs, char const *fmt, ...) +/** Log an error message relating to a #CONF_ITEM + * + * @param[in] ci #CONF_ITEM to print file/lineno for. + * @param[in] fmt Msg format string. + * @param[in] ... Format args. + */ +void _cf_log_err(CONF_ITEM const *ci, char const *fmt, ...) { - va_list ap; - char buffer[256]; + va_list ap; + char *msg; va_start(ap, fmt); - vsnprintf(buffer, sizeof(buffer), fmt, ap); + msg = talloc_vasprintf(NULL, fmt, ap); va_end(ap); - rad_assert(cs != NULL); + if (!ci || !ci->filename) { + ERROR("%s", msg); + } else { + ERROR("%s[%d]: %s", ci->filename, ci->lineno, msg); + } - PERROR("%s[%d]: %s", cs->item.filename, cs->item.lineno, buffer); + talloc_free(msg); } -void cf_log_err_cp(CONF_PAIR const *cp, char const *fmt, ...) +/** Log an error message relating to a #CONF_ITEM + * + * Drains the fr_strerror() stack emitting one or more error messages. + * + * @param[in] ci #CONF_ITEM to print file/lineno for. + * @param[in] fmt Msg format string. + * @param[in] ... Format args. + */ +void _cf_log_perr(CONF_ITEM const *ci, char const *fmt, ...) { - va_list ap; - char buffer[256]; + va_list ap; + char *msg; va_start(ap, fmt); - vsnprintf(buffer, sizeof(buffer), fmt, ap); + msg = talloc_vasprintf(NULL, fmt, ap); va_end(ap); - rad_assert(cp != NULL); + if (!ci || !ci->filename) { + PERROR("%s", msg); + } else { + PERROR("%s[%d]: %s", ci->filename, ci->lineno, msg); + } - ERROR("%s[%d]: %s", cp->item.filename, cp->item.lineno, buffer); + talloc_free(msg); } -void cf_log_perr_cp(CONF_PAIR const *cp, char const *fmt, ...) +/** Log a warning message relating to a #CONF_ITEM + * + * @param[in] ci #CONF_ITEM to print file/lineno for. + * @param[in] fmt Msg format string. + * @param[in] ... Format args. + */ +void _cf_log_warn(CONF_ITEM const *ci, char const *fmt, ...) { - va_list ap; - char buffer[256]; + va_list ap; + char *msg; va_start(ap, fmt); - vsnprintf(buffer, sizeof(buffer), fmt, ap); + msg = talloc_vasprintf(NULL, fmt, ap); va_end(ap); - rad_assert(cp != NULL); + if (!ci || !ci->filename) { + WARN("%s", msg); + } else { + WARN("%s[%d]: %s", ci->filename, ci->lineno, msg); + } - PERROR("%s[%d]: %s", cp->item.filename, cp->item.lineno, buffer); + talloc_free(msg); } -void cf_log_err_by_name(CONF_SECTION const *parent, char const *name, char const *fmt, ...) +/** Log a info message relating to a #CONF_ITEM + * + * @param[in] ci #CONF_ITEM to print file/lineno for. + * @param[in] fmt Msg format string. + * @param[in] ... Format args. + */ +void _cf_log_info(CONF_ITEM const *ci, char const *fmt, ...) { - va_list ap; - CONF_PAIR const *cp; - char buffer[256]; + va_list ap; + char *msg; va_start(ap, fmt); - vsnprintf(buffer, sizeof(buffer), fmt, ap); + msg = talloc_vasprintf(NULL, fmt, ap); va_end(ap); - cp = cf_pair_find(parent, name); - if (cp) { - ERROR("%s[%d]: %s", - cp->item.filename, cp->item.lineno, - buffer); + if (!ci || !ci->filename || !DEBUG_ENABLED3) { + INFO("%s", msg); } else { - ERROR("%s[%d]: %s", - parent->item.filename, parent->item.lineno, - buffer); + INFO("%s[%d]: %s", ci->filename, ci->lineno, msg); } + talloc_free(msg); } -void cf_log_warn_cp(CONF_PAIR const *cp, char const *fmt, ...) +/** Log a debug message relating to a #CONF_ITEM + * + * @param[in] ci #CONF_ITEM to print file/lineno for. + * @param[in] fmt Msg format string. + * @param[in] ... Format args. + */ +void _cf_log_debug(CONF_ITEM const *ci, char const *fmt, ...) { - va_list ap; - char buffer[256]; - - va_start(ap, fmt); - vsnprintf(buffer, sizeof(buffer), fmt, ap); - va_end(ap); - - rad_assert(cp != NULL); + va_list ap; + char *msg; - WARN("%s[%d]: %s", - cp->item.filename, cp->item.lineno, - buffer); -} - -void cf_log_warn(CONF_SECTION const *cs, char const *fmt, ...) -{ - va_list ap; + if (rad_debug_lvl < 1) return; va_start(ap, fmt); - if (cs) fr_vlog(&default_log, L_WARN, fmt, ap); + msg = talloc_vasprintf(NULL, fmt, ap); va_end(ap); -} -void cf_log_info(CONF_SECTION const *cs, char const *fmt, ...) -{ - va_list ap; + if (!ci || !ci->filename || !DEBUG_ENABLED4) { + DEBUG("%s", msg); + } else { + DEBUG("%s[%d]: %s", ci->filename, ci->lineno, msg); + } - va_start(ap, fmt); - if ((rad_debug_lvl > 1) && cs) fr_vlog(&default_log, L_DBG, fmt, ap); - va_end(ap); + talloc_free(msg); } -/* - * Wrapper to simplify the code. - */ -void cf_log_module(CONF_SECTION const *cs, char const *fmt, ...) +void cf_log_err_by_name(CONF_SECTION const *parent, char const *name, char const *fmt, ...) { - va_list ap; - char buffer[256]; + va_list ap; + char *msg; + CONF_PAIR const *cp; va_start(ap, fmt); - if (rad_debug_lvl > 1 && cs) { - vsnprintf(buffer, sizeof(buffer), fmt, ap); - - DEBUG("%.*s# %s", cs->depth, parse_spaces, buffer); - } + msg = talloc_vasprintf(NULL, fmt, ap); va_end(ap); -} -const CONF_PARSER *cf_section_parse_table(CONF_SECTION *cs) -{ - if (!cs) return NULL; + cp = cf_pair_find(parent, name); + if (cp) { + ERROR("%s[%d]: %s", cp->item.filename, cp->item.lineno, msg); + } else { + CONF_ITEM const *ci; - return cs->variables; + ci = cf_section_to_item(parent); + ERROR("%s[%d]: %s", ci->filename, ci->lineno, msg); + } + talloc_free(msg); } -/* - * For "switch" and "case" statements. +/** Print out debugging information about a CONFIG_ITEM + * + * @param[in] ci being debugged. */ -FR_TOKEN cf_section_name2_type(CONF_SECTION const *cs) -{ - if (!cs) return T_INVALID; - - return cs->name2_type; -} - -FR_TOKEN cf_section_argv_type(CONF_SECTION const *cs, int argc) -{ - if (!cs || !cs->argv_type || (argc < 0) || (argc > cs->argc)) return T_INVALID; - - return cs->argv_type[argc]; -} - -#ifdef WITH_CONF_WRITE -static char const parse_tabs[] = " "; - -static ssize_t cf_string_write(FILE *fp, char const *string, size_t len, FR_TOKEN t) +void _cf_debug(CONF_ITEM const *ci) { - size_t outlen; - char c; - char buffer[2048]; - - switch (t) { - default: - c = '\0'; - break; - - case T_DOUBLE_QUOTED_STRING: - c = '"'; - break; + fr_cursor_t cursor; + CONF_ITEM const *child; - case T_SINGLE_QUOTED_STRING: - c = '\''; - break; - - case T_BACK_QUOTED_STRING: - c = '`'; - break; + /* + * Print summary of the item + */ + switch (ci->type) { + case CONF_ITEM_SECTION: + { + CONF_SECTION const *cs = cf_item_to_section(ci); + int i; + + DEBUG("SECTION - %p", cs); + DEBUG(" name1 : %s", cs->name1); + DEBUG(" name2 : %s", cs->name2 ? cs->name2 : ""); + DEBUG(" name2_quote : %s", fr_int2str(fr_token_quotes_table, cs->name2_quote, "")); + DEBUG(" argc : %u", cs->argc); + + for (i = 0; i < cs->argc; i++) { + char const *quote = fr_int2str(fr_token_quotes_table, cs->argv_quote[i], ""); + DEBUG(" argv[%i] : %s%s%s", i, quote, cs->argv[i], quote); + } } + break; - if (c) fprintf(fp, "%c", c); - - outlen = fr_snprint(buffer, sizeof(buffer), string, len, c); - fwrite(buffer, outlen, 1, fp); - - if (c) fprintf(fp, "%c", c); - return 1; -} - - -static size_t cf_pair_write(FILE *fp, CONF_PAIR *cp) -{ - if (!cp->value) { - fprintf(fp, "%s\n", cp->attr); - return 0; + case CONF_ITEM_PAIR: + { + CONF_PAIR const *cp = cf_item_to_pair(ci); + + DEBUG("PAIR - %p", cp); + DEBUG(" attr : %s", cp->attr); + DEBUG(" value : %s", cp->value); + DEBUG(" operator : %s", fr_int2str(fr_tokens_table, cp->op, "")); + DEBUG(" lhs_quote : %s", fr_int2str(fr_token_quotes_table, cp->lhs_quote, "")); + DEBUG(" rhs_quote : %s", fr_int2str(fr_token_quotes_table, cp->rhs_quote, "")); + DEBUG(" pass2 : %s", cp->pass2 ? "yes" : "no"); + DEBUG(" parsed : %s", cp->parsed ? "yes" : "no"); } + break; - cf_string_write(fp, cp->attr, strlen(cp->attr), cp->lhs_type); - fprintf(fp, " %s ", fr_int2str(fr_tokens_table, cp->op, "")); - cf_string_write(fp, cp->orig_value, strlen(cp->orig_value), cp->rhs_type); - fprintf(fp, "\n"); - - return 1; /* FIXME */ -} - - -static FILE *cf_file_write(CONF_SECTION *cs, char const *filename) -{ - FILE *fp; - char *p; - char const *q; - char buffer[8192]; - - q = filename; - if ((q[0] == '.') && (q[1] == '/')) q += 2; - - snprintf(buffer, sizeof(buffer), "%s/%s", main_config.write_dir, q); + case CONF_ITEM_DATA: + { + CONF_DATA const *cd = cf_item_to_data(ci); - p = strrchr(buffer, '/'); - *p = '\0'; - if ((rad_mkdir(buffer, 0700, -1, -1) < 0) && - (errno != EEXIST)) { - cf_log_err_cs(cs, "Failed creating directory %s: %s", - buffer, strerror(errno)); - return NULL; + DEBUG("DATA - %p", cd); + DEBUG(" type : %s", cd->type); + DEBUG(" name : %s", cd->name); + DEBUG(" data : %p", cd->data); + DEBUG(" free wth prnt : %s", cd->free ? "yes" : "no"); } + break; - /* - * And again, because rad_mkdir() butchers the buffer. - */ - snprintf(buffer, sizeof(buffer), "%s/%s", main_config.write_dir, q); - - fp = fopen(buffer, "a"); - if (!fp) { - cf_log_err_cs(cs, "Failed creating file %s: %s", - buffer, strerror(errno)); - return NULL; + default: + DEBUG("INVALID - %p", ci); + return; } - return fp; -} - -size_t cf_section_write(FILE *in_fp, CONF_SECTION *cs, int depth) -{ - bool prev = false; - CONF_ITEM *ci; - FILE *fp = NULL; - int fp_max = 0; - FILE *array[32]; + DEBUG(" filename : %s", ci->filename); + DEBUG(" line : %i", ci->lineno); + DEBUG(" next : %p", ci->next); + DEBUG(" parent : %p", ci->parent); + DEBUG(" children : %s", ci->child ? "yes" : "no"); + DEBUG(" ident1 tree : %p (%u entries)", ci->ident1, ci->ident1 ? rbtree_num_elements(ci->ident1) : 0); + DEBUG(" ident2 tree : %p (%u entries)", ci->ident2, ci->ident2 ? rbtree_num_elements(ci->ident2) : 0); - /* - * Default to writing to the FP we're given. - */ - fp = in_fp; - array[0] = fp; - fp_max = 0; + if (!ci->child) return; /* - * If we have somewhere to print, then print the section - * name1, etc. + * Print summary of the item's children */ - if (fp) { - fwrite(parse_tabs, depth, 1, fp); - cf_string_write(fp, cs->name1, strlen(cs->name1), T_BARE_WORD); - - /* - * FIXME: check for "if" or "elsif". And if so, print - * out the parsed condition, instead of the input text - * - * cf_data_find(cs, CF_DATA_TYPE_UNLANG, "if"); - */ - - if (cs->name2) { - fr_cond_t *c; - - fputs(" ", fp); - - c = cf_data_find(cs, fr_cond_t, NULL); - if (c) { - char buffer[1024]; - - cond_snprint(buffer, sizeof(buffer), c); - fprintf(fp, "(%s)", buffer); + DEBUG("CHILDREN"); + fr_cursor_copy(&cursor, &ci->cursor); - } else { /* dump the string as-is */ - cf_string_write(fp, cs->name2, strlen(cs->name2), cs->name2_type); - } - } + for (child = fr_cursor_head(&cursor); + child; + child = fr_cursor_next(&cursor)) { + char const *in_ident1, *in_ident2; - fputs(" {\n", fp); - } + in_ident1 = rbtree_finddata(ci->ident1, child) == child? "in ident1 " : ""; + in_ident2 = rbtree_finddata(ci->ident2, child) == child? "in ident2 " : ""; - /* - * Loop over the children. Either recursing, or opening - * a new file. - */ - for (ci = cs->children; ci; ci = ci->next) { - switch (ci->type) { + switch (child->type) { case CONF_ITEM_SECTION: - if (!fp) continue; + { + CONF_SECTION const *cs = cf_item_to_section(child); - cf_section_write(fp, cf_item_to_section(ci), depth + 1); + DEBUG(" SECTION %p (%s %s) %s%s", child, cs->name1, cs->name2 ? cs->name2 : "", + in_ident1, in_ident2); + } break; case CONF_ITEM_PAIR: - if (!fp) continue; - - /* - * Ignore internal things. - */ - if (!ci->filename || (ci->filename[0] == '<')) break; - - fwrite(parse_tabs, depth + 1, 1, fp); - cf_pair_write(fp, cf_item_to_pair(ci)); - if (!prev) fputs("\n", fp); - prev = true; - break; - - case CONF_ITEM_COMMENT: - rad_assert(fp != NULL); - - prev = false; - fwrite(parse_tabs, depth + 1, 1, fp); - fprintf(fp, "#%s", ((CONF_COMMENT *)ci)->comment); + { + CONF_PAIR const *cp = cf_item_to_pair(child); + char const *lhs_quote = fr_int2str(fr_token_quotes_table, cp->lhs_quote, ""); + char const *rhs_quote = fr_int2str(fr_token_quotes_table, cp->rhs_quote, ""); + + DEBUG(" PAIR %p (%s%s%s %s %s%s%s) %s%s", child, + lhs_quote, cp->attr, lhs_quote, + fr_int2str(fr_tokens_table, cp->op, ""), + rhs_quote, cp->value, rhs_quote, + in_ident1, in_ident2); + } break; - case CONF_ITEM_INCLUDE: - /* - * Filename == open the new filename and use that. - * - * NULL == close the previous filename - */ - if (((CONF_INCLUDE *) ci)->filename) { - CONF_INCLUDE *cc = (CONF_INCLUDE *) ci; - - /* - * Print out - * - * $INCLUDE foo.conf - * $INCLUDE foo/ - * - * but not the files included from the last one. - */ - if (fp && (cc->file_type != CONF_INCLUDE_FROMDIR)) { - fprintf(fp, "$INCLUDE %s\n", ((CONF_INCLUDE *)ci)->filename); - } - - /* - * If it's a file, we write the - * file. We ignore the - * directories. They're just for printing. - */ - if (cc->file_type != CONF_INCLUDE_DIR) { - fp = cf_file_write(cs, ((CONF_INCLUDE *) ci)->filename); - if (!fp) return 0; - - fp_max++; - array[fp_max] = fp; - } - } else { - /* - * We're done the current file. - */ - rad_assert(fp != NULL); - rad_assert(fp_max > 0); - fclose(fp); + case CONF_ITEM_DATA: + { + CONF_DATA const *cd = cf_item_to_data(child); - fp_max--; - fp = array[fp_max]; - } + DEBUG(" DATA %p (%s *)%s = %p %s%s", child, + cd->type, cd->name ? cd->name : "", cd->data, + in_ident1, in_ident2); break; + } default: + DEBUG(" INVALID - %p", child); break; } } - - if (fp) { - fwrite(parse_tabs, depth, 1, fp); - fputs("}\n\n", fp); - } - - return 1; } -#endif /* WITH_CONF_WRITE */ diff --git a/src/main/dl.c b/src/main/dl.c index f76d8a12050..e9dbef72a7c 100644 --- a/src/main/dl.c +++ b/src/main/dl.c @@ -224,9 +224,9 @@ static int dl_magic_verify(CONF_SECTION const *cs, dl_common_t const *module) if (MAGIC_PREFIX(module->magic) != MAGIC_PREFIX(RADIUSD_MAGIC_NUMBER)) { #ifdef HAVE_DLADDR - cf_log_err_cs(cs, "Failed loading module rlm_%s from file %s", module->name, dl_info.dli_fname); + cf_log_err(cs, "Failed loading module rlm_%s from file %s", module->name, dl_info.dli_fname); #endif - cf_log_err_cs(cs, "Application and rlm_%s magic number (prefix) mismatch." + cf_log_err(cs, "Application and rlm_%s magic number (prefix) mismatch." " application: %x module: %x", module->name, MAGIC_PREFIX(RADIUSD_MAGIC_NUMBER), MAGIC_PREFIX(module->magic)); @@ -235,9 +235,9 @@ static int dl_magic_verify(CONF_SECTION const *cs, dl_common_t const *module) if (MAGIC_VERSION(module->magic) != MAGIC_VERSION(RADIUSD_MAGIC_NUMBER)) { #ifdef HAVE_DLADDR - cf_log_err_cs(cs, "Failed loading module rlm_%s from file %s", module->name, dl_info.dli_fname); + cf_log_err(cs, "Failed loading module rlm_%s from file %s", module->name, dl_info.dli_fname); #endif - cf_log_err_cs(cs, "Application and rlm_%s magic number (version) mismatch." + cf_log_err(cs, "Application and rlm_%s magic number (version) mismatch." " application: %lx module: %lx", module->name, (unsigned long) MAGIC_VERSION(RADIUSD_MAGIC_NUMBER), (unsigned long) MAGIC_VERSION(module->magic)); @@ -246,9 +246,9 @@ static int dl_magic_verify(CONF_SECTION const *cs, dl_common_t const *module) if (MAGIC_COMMIT(module->magic) != MAGIC_COMMIT(RADIUSD_MAGIC_NUMBER)) { #ifdef HAVE_DLADDR - cf_log_err_cs(cs, "Failed loading module rlm_%s from file %s", module->name, dl_info.dli_fname); + cf_log_err(cs, "Failed loading module rlm_%s from file %s", module->name, dl_info.dli_fname); #endif - cf_log_err_cs(cs, "Application and rlm_%s magic number (commit) mismatch." + cf_log_err(cs, "Application and rlm_%s magic number (commit) mismatch." " application: %lx module: %lx", module->name, (unsigned long) MAGIC_COMMIT(RADIUSD_MAGIC_NUMBER), (unsigned long) MAGIC_COMMIT(module->magic)); @@ -416,7 +416,7 @@ int dl_instance_data_alloc(void **data, TALLOC_CTX *ctx, dl_t const *module, CON talloc_set_name(*data, "%s", module->common->inst_type); } if (module->common->config && (cf_section_parse(*data, *data, cs, module->common->config) < 0)) { - cf_log_err_cs(cs, "Invalid configuration for module \"%s\"", module->name); + cf_log_err(cs, "Invalid configuration for module \"%s\"", module->name); talloc_free(*data); return -1; } @@ -707,8 +707,8 @@ dl_t const *dl_module(CONF_SECTION *conf, dl_t const *parent, char const *name, */ handle = dl_by_name(module_name); if (!handle) { - cf_log_err_cs(conf, "Failed to link to module \"%s\": %s", module_name, fr_strerror()); - cf_log_err_cs(conf, "Make sure it (and all its dependent libraries!) are in the search path" + cf_log_err(conf, "Failed to link to module \"%s\": %s", module_name, fr_strerror()); + cf_log_err(conf, "Make sure it (and all its dependent libraries!) are in the search path" " of your system's ld"); error: talloc_free(module_name); @@ -721,7 +721,7 @@ dl_t const *dl_module(CONF_SECTION *conf, dl_t const *parent, char const *name, module = dlsym(handle, module_name); if (!module) { - cf_log_err_cs(conf, "Failed linking to \"%s\" structure: %s", module_name, dlerror()); + cf_log_err(conf, "Failed linking to \"%s\" structure: %s", module_name, dlerror()); goto error; } @@ -744,17 +744,17 @@ dl_t const *dl_module(CONF_SECTION *conf, dl_t const *parent, char const *name, * Call initialisation functions */ if (dl_symbol_init_walk(dl_module) < 0) { - cf_log_err_cs(conf, "Module initialisation failed \"%s\"", module_name); + cf_log_err(conf, "Module initialisation failed \"%s\"", module_name); goto error; } - cf_log_module(conf, "Loaded module \"%s\"", module_name); + cf_log_debug(conf, "Loaded module \"%s\"", module_name); /* * Add the module to the dlhandle cache */ if (!rbtree_insert(dl->tree, dl_module) || !rbtree_insert(dl->sym_tree, dl_module)) { - cf_log_err_cs(conf, "Failed to cache module \"%s\"", module_name); + cf_log_err(conf, "Failed to cache module \"%s\"", module_name); goto error; } diff --git a/src/main/listen.c b/src/main/listen.c index 1a428616f5e..45b2e1bce41 100644 --- a/src/main/listen.c +++ b/src/main/listen.c @@ -100,14 +100,14 @@ int listen_compile(CONF_SECTION *server, CONF_SECTION *cs) rad_protocol_t const *proto; dl_t *module; - module = cf_data_find(cs, dl_t, "proto"); + module = cf_data_value(cf_data_find(cs, dl_t, "proto")); if (!module) return 0; proto = (rad_protocol_t const *)module->common; if (!proto->compile) return 0; if (proto->compile(server, cs) < 0) { - cf_log_err_cs(server, "Failed compiling unlang policies for listen type '%s'", proto->name); + cf_log_err(server, "Failed compiling unlang policies for listen type '%s'", proto->name); return -1; } @@ -137,13 +137,13 @@ int listen_bootstrap(CONF_SECTION *server, CONF_SECTION *cs, char const *server_ cp = cf_pair_find(cs, "type"); if (!cp) { - cf_log_err_cs(cs, "No 'type' specified in listen section"); + cf_log_err(cs, "No 'type' specified in listen section"); return -1; } type = cf_pair_value(cp); if (!type) { - cf_log_err_cs(cs, "Invalid 'type' specified in listen section"); + cf_log_err(cs, "Invalid 'type' specified in listen section"); return -1; } @@ -154,14 +154,14 @@ int listen_bootstrap(CONF_SECTION *server, CONF_SECTION *cs, char const *server_ if (!server_name) { if ((strcmp(type, "control") != 0) && (strcmp(type, "proxy") != 0)) { - cf_log_err_cs(cs, "Listeners of type '%s' MUST be defined in a server", type); + cf_log_err(cs, "Listeners of type '%s' MUST be defined in a server", type); return -1; } } else { if ((strcmp(type, "control") == 0) || (strcmp(type, "proxy") == 0)) { - cf_log_err_cs(cs, "Listeners of type '%s' MUST NOT be defined in a server", type); + cf_log_err(cs, "Listeners of type '%s' MUST NOT be defined in a server", type); return -1; } } @@ -199,7 +199,7 @@ int listen_bootstrap(CONF_SECTION *server, CONF_SECTION *cs, char const *server_ } if (fr_dict_enum_add_alias(da, type, fr_box_uint32(max_listener), true, false) < 0) { - cf_log_err_cs(cs, + cf_log_err(cs, "Failed adding dictionary entry for protocol %s: %s", type, fr_strerror()); talloc_const_free(module); @@ -213,13 +213,13 @@ int listen_bootstrap(CONF_SECTION *server, CONF_SECTION *cs, char const *server_ * the protocol-specific processing sections. */ if (proto->bootstrap && (proto->bootstrap(server, cs) < 0)) { - cf_log_err_cs(cs, "Failed loading protocol %s", type); + cf_log_err(cs, "Failed loading protocol %s", type); talloc_const_free(module); return -1; } if (cf_data_find(cs, dl_t, "proto") != NULL) { - cf_log_err_cs(cs, "Virtual server cannot have two protocols"); + cf_log_err(cs, "Virtual server cannot have two protocols"); talloc_const_free(module); return -1; } @@ -232,7 +232,7 @@ int listen_bootstrap(CONF_SECTION *server, CONF_SECTION *cs, char const *server_ */ dv = fr_dict_enum_by_alias(NULL, fr_dict_attr_by_num(NULL, 0, FR_LISTEN_SOCKET_TYPE), type); if (!dv) { - cf_log_err_cs(cs, "Failed finding dictionary entry for protocol %s", type); + cf_log_err(cs, "Failed finding dictionary entry for protocol %s", type); talloc_const_free(module); return -1; } @@ -254,7 +254,7 @@ int listen_bootstrap(CONF_SECTION *server, CONF_SECTION *cs, char const *server_ } else { type = cf_pair_value(cp); if (!type) { - cf_log_err_cs(cs, "No value for 'proto'"); + cf_log_err(cs, "No value for 'proto'"); return -1; } @@ -265,7 +265,7 @@ int listen_bootstrap(CONF_SECTION *server, CONF_SECTION *cs, char const *server_ transports = TRANSPORT_TCP; } else { - cf_log_err_cs(cs, "Unknown transport protocol 'proto = %s'", type); + cf_log_err(cs, "Unknown transport protocol 'proto = %s'", type); return -1; } } @@ -274,7 +274,7 @@ int listen_bootstrap(CONF_SECTION *server, CONF_SECTION *cs, char const *server_ * Asked for UDP and required TCP, or require UDP and asked for TCP. */ if ((transports & proto->transports) == 0) { - cf_log_err_cs(cs, "Invalid transport 'proto = %s' for listeners of 'type = %s'", + cf_log_err(cs, "Invalid transport 'proto = %s' for listeners of 'type = %s'", type, proto->name); return -1; } @@ -287,7 +287,7 @@ int listen_bootstrap(CONF_SECTION *server, CONF_SECTION *cs, char const *server_ * address unless we know the destination. */ if ((strcmp(proto->name, "proxy") == 0) && (transports == TRANSPORT_TCP)) { - cf_log_err_cs(cs, "Invalid transport 'proto = %s' for listeners of 'type = %s'", + cf_log_err(cs, "Invalid transport 'proto = %s' for listeners of 'type = %s'", type, proto->name); return -1; } @@ -300,23 +300,23 @@ int listen_bootstrap(CONF_SECTION *server, CONF_SECTION *cs, char const *server_ * * If there's no "tls" section, that's fine, too. */ - tls = cf_subsection_find(cs, "tls"); + tls = cf_section_find(cs, "tls", NULL); #ifndef WITH_TCP if (tls) { - cf_log_err_cs(cs, "TLS transport is not available in this executable"); + cf_log_err(cs, "TLS transport is not available in this executable"); return -1; } #else if (tls) { if (!proto->tls) { - cf_log_err_cs(cs, "TLS transport is not available for listeners with 'type = %s", + cf_log_err(cs, "TLS transport is not available for listeners with 'type = %s", proto->name); return -1; } if (transports == TRANSPORT_UDP) { - cf_log_err_cs(cs, "TLS transport is not available for listeners with 'proto = udp'"); + cf_log_err(cs, "TLS transport is not available for listeners with 'proto = udp'"); return -1; } } @@ -457,7 +457,7 @@ RADCLIENT *client_listener_find(rad_listen_t *listener, * We don't need to re-load the same information. */ if (client->cs && - (filename = cf_section_filename(client->cs)) != NULL) { + (filename = cf_filename(client->cs)) != NULL) { struct stat buf; if ((stat(filename, &buf) >= 0) && @@ -1328,7 +1328,7 @@ int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this) if (cf_pair_find(cs, "proto")) { #ifndef WITH_TCP - cf_log_err_cs(cs, "System does not support the TCP protocol. " + cf_log_err(cs, "System does not support the TCP protocol. " "Delete this line from the configuration file"); return -1; #else @@ -1354,18 +1354,18 @@ int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this) */ if ((this->type == RAD_LISTEN_PROXY) && (sock->my_port != 0)) { - cf_log_err_cs(this->cs, "You must not specify a source port for proxy sockets over TCP"); + cf_log_err(this->cs, "You must not specify a source port for proxy sockets over TCP"); return -1; } #endif } else { - cf_log_err_cs(cs, "Unknown proto name \"%s\"", proto); + cf_log_err(cs, "Unknown proto name \"%s\"", proto); return -1; } # ifdef WITH_TLS - tls = cf_subsection_find(cs, "tls"); + tls = cf_section_find(cs, "tls", NULL); if (tls) { /* * If unset, set to default. @@ -1393,19 +1393,19 @@ int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this) /* * Magical tuning methods! */ - subcs = cf_subsection_find(cs, "performance"); + subcs = cf_section_find(cs, "performance", NULL); if (subcs) { rcode = cf_section_parse(this, this, subcs, performance_config); if (rcode < 0) return -1; } - subcs = cf_subsection_find(cs, "limit"); + subcs = cf_section_find(cs, "limit", NULL); if (subcs) { rcode = cf_section_parse(sock, sock, subcs, limit_config); if (rcode < 0) return -1; if (sock->max_rate && ((sock->max_rate < 10) || (sock->max_rate > 1000000))) { - cf_log_err_cs(cs, + cf_log_err(cs, "Invalid value for \"max_pps\""); return -1; } @@ -1472,7 +1472,7 @@ int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this) if (cp) { char const *value = cf_pair_value(cp); if (!value) { - cf_log_err_cs(cs, + cf_log_err(cs, "No interface name given"); return -1; } @@ -1491,19 +1491,19 @@ int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this) * (i.e. if SO_BINDTODEVICE is available). */ # if defined(SO_BINDTODEVICE) && !defined(SO_BROADCAST) - cf_log_err_cs(cs, + cf_log_err(cs, "System does not support broadcast sockets. Delete this line from the configuration file"); return -1; # else if (this->type != RAD_LISTEN_DHCP) { - cf_log_err_cp(cp, + cf_log_err(cp, "Broadcast can only be set for DHCP listeners. Delete this line from the configuration file"); return -1; } char const *value = cf_pair_value(cp); if (!value) { - cf_log_err_cs(cs, + cf_log_err(cs, "No broadcast value given"); return -1; } @@ -1528,17 +1528,17 @@ int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this) * generic ones. */ clients_cs = NULL; - parent_cs = cf_top_section(cs); + parent_cs = cf_root(cs); rcode = cf_pair_parse(NULL, cs, "clients", FR_ITEM_POINTER(FR_TYPE_STRING, §ion_name), NULL, T_INVALID); if (rcode < 0) return -1; /* bad string */ if (rcode == 0) { /* * Explicit list given: use it. */ - clients_cs = cf_subsection_find_name2(parent_cs, "clients", section_name); - if (!clients_cs) clients_cs = cf_subsection_find(main_config.config, section_name); + clients_cs = cf_section_find(parent_cs, "clients", section_name); + if (!clients_cs) clients_cs = cf_section_find(main_config.config, section_name, NULL); if (!clients_cs) { - cf_log_err_cs(cs, "Failed to find clients %s {...}", section_name); + cf_log_err(cs, "Failed to find clients %s {...}", section_name); return -1; } } /* else there was no "clients = " entry. */ @@ -1547,9 +1547,9 @@ int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this) /* * Always cache the CONF_SECTION of the server. */ - this->server_cs = cf_subsection_find_name2(parent_cs, "server", this->server); + this->server_cs = cf_section_find(parent_cs, "server", this->server); if (!this->server_cs) { - cf_log_err_cs(cs, "Failed to find virtual server '%s'", this->server); + cf_log_err(cs, "Failed to find virtual server '%s'", this->server); return -1; } @@ -1560,7 +1560,7 @@ int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this) * choose the global list of clients. */ if (!clients_cs) { - if (cf_subsection_find(this->server_cs, "client") != NULL) { + if (cf_section_find(this->server_cs, "client", NULL) != NULL) { clients_cs = this->server_cs; } else { clients_cs = parent_cs; @@ -1573,7 +1573,7 @@ int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this) sock->clients = client_list_parse_section(clients_cs, false); #endif if (!sock->clients) { - cf_log_err_cs(cs, + cf_log_err(cs, "Failed to load clients for this listen section"); return -1; } @@ -1588,7 +1588,7 @@ int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this) this->children = rbtree_create(this, listener_cmp, NULL, 0); if (!this->children) { - cf_log_err_cs(cs, "Failed to create child list for TCP socket."); + cf_log_err(cs, "Failed to create child list for TCP socket."); return -1; } } @@ -1609,7 +1609,7 @@ int common_socket_open(CONF_SECTION *cs, rad_listen_t *this) /* Only use libpcap if pcap_type has a value. Otherwise, use socket with SO_BINDTODEVICE */ if (sock->interface && sock->pcap_type) { if (init_pcap(this) < 0) { - cf_log_err_cs(cs, + cf_log_err(cs, "Error initializing pcap."); return -1; } @@ -1623,7 +1623,7 @@ int common_socket_open(CONF_SECTION *cs, rad_listen_t *this) */ if (listen_bind(this) < 0) { char buffer[128]; - cf_log_err_cs(cs, + cf_log_err(cs, "Error binding to port for %s port %d", fr_inet_ntoh(&sock->my_ipaddr, buffer, sizeof(buffer)), sock->my_port); @@ -3211,8 +3211,8 @@ int listen_init(rad_listen_t **head, for (this = *head; this != NULL; this = this->next) { #ifdef WITH_TLS if (!spawn_workers && this->tls) { - cf_log_err_cs(this->cs, "Threading must be enabled for TLS sockets to function properly"); - cf_log_err_cs(this->cs, "You probably need to do '%s -fxx -l stdout' for debugging", + cf_log_err(this->cs, "Threading must be enabled for TLS sockets to function properly"); + cf_log_err(this->cs, "You probably need to do '%s -fxx -l stdout' for debugging", main_config.name); return -1; } diff --git a/src/main/mainconfig.c b/src/main/mainconfig.c index 64b4c5cca26..472e8d3de6a 100644 --- a/src/main/mainconfig.c +++ b/src/main/mainconfig.c @@ -729,7 +729,7 @@ int main_config_init(void) * Read the distribution dictionaries first, then * the ones in raddb. */ - DEBUG2("including dictionary file %s/%s", main_config.dictionary_dir, FR_DICTIONARY_FILE); + 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) { ERROR("Errors reading dictionary: %s", fr_strerror()); @@ -743,7 +743,7 @@ do {\ ERROR("Error reading %s/%s: %s", _d, _n, fr_strerror());\ return -1;\ case 0:\ - DEBUG2("including dictionary file %s/%s", _d,_n);\ + DEBUG2("Including dictionary file \"%s/%s\"", _d,_n);\ break;\ default:\ break;\ @@ -765,7 +765,7 @@ do {\ * to manually override the ones set by modules * or the server. */ - subcs = cf_subsection_find(cs, "feature"); + subcs = cf_section_find(cs, "feature", NULL); if (!subcs) { subcs = cf_section_alloc(cs, "feature", NULL); if (!subcs) return -1; @@ -779,7 +779,7 @@ do {\ * We check if it's defined first, this is for * backwards compatibility. */ - subcs = cf_subsection_find(cs, "version"); + subcs = cf_section_find(cs, "version", NULL); if (!subcs) { subcs = cf_section_alloc(cs, "version", NULL); if (!subcs) return -1; diff --git a/src/main/map.c b/src/main/map.c index 7193c44c696..59abc862ba8 100644 --- a/src/main/map.c +++ b/src/main/map.c @@ -209,7 +209,7 @@ int map_afrom_cp(TALLOC_CTX *ctx, vp_map_t **out, CONF_PAIR *cp, attr = cf_pair_attr(cp); value = cf_pair_value(cp); if (!value) { - cf_log_err_cp(cp, "Missing attribute value"); + cf_log_err(cp, "Missing attribute value"); goto error; } @@ -217,7 +217,7 @@ int map_afrom_cp(TALLOC_CTX *ctx, vp_map_t **out, CONF_PAIR *cp, * LHS may be an expansion (that expands to an attribute reference) * or an attribute reference. Quoting determines which it is. */ - type = cf_pair_attr_type(cp); + type = cf_pair_attr_quote(cp); switch (type) { case T_DOUBLE_QUOTED_STRING: case T_BACK_QUOTED_STRING: @@ -228,8 +228,8 @@ int map_afrom_cp(TALLOC_CTX *ctx, vp_map_t **out, CONF_PAIR *cp, marker: fr_canonicalize_error(ctx, &spaces, &text, slen, attr); - cf_log_err_cp(cp, "%s", text); - cf_log_err_cp(cp, "%s^ %s", spaces, fr_strerror()); + cf_log_err(cp, "%s", text); + cf_log_err(cp, "%s^ %s", spaces, fr_strerror()); talloc_free(spaces); talloc_free(text); @@ -240,13 +240,13 @@ int map_afrom_cp(TALLOC_CTX *ctx, vp_map_t **out, CONF_PAIR *cp, default: slen = tmpl_afrom_attr_str(ctx, &map->lhs, attr, dst_request_def, dst_list_def, true, true); if (slen <= 0) { - cf_log_err_cp(cp, "Failed parsing attribute reference"); + cf_log_err(cp, "Failed parsing attribute reference"); goto marker; } if (tmpl_define_unknown_attr(map->lhs) < 0) { - cf_log_err_cp(cp, "Failed creating attribute %s: %s", + cf_log_err(cp, "Failed creating attribute %s: %s", map->lhs->name, fr_strerror()); goto error; } @@ -257,7 +257,7 @@ int map_afrom_cp(TALLOC_CTX *ctx, vp_map_t **out, CONF_PAIR *cp, /* * RHS might be an attribute reference. */ - type = cf_pair_value_type(cp); + type = cf_pair_value_quote(cp); if ((type == T_BARE_WORD) && (value[0] == '0') && (tolower((int)value[1]) == 'x') && (map->lhs->type == TMPL_TYPE_ATTR) && @@ -267,12 +267,12 @@ int map_afrom_cp(TALLOC_CTX *ctx, vp_map_t **out, CONF_PAIR *cp, slen = tmpl_afrom_str(map, &map->rhs, value, strlen(value), type, src_request_def, src_list_def, true); if (slen < 0) goto marker; if (tmpl_define_unknown_attr(map->rhs) < 0) { - cf_log_err_cp(cp, "Failed creating attribute %s: %s", map->rhs->name, fr_strerror()); + cf_log_err(cp, "Failed creating attribute %s: %s", map->rhs->name, fr_strerror()); goto error; } } if (!map->rhs) { - cf_log_err_cp(cp, "%s", fr_strerror()); + cf_log_err(cp, "%s", fr_strerror()); goto error; } @@ -282,7 +282,7 @@ int map_afrom_cp(TALLOC_CTX *ctx, vp_map_t **out, CONF_PAIR *cp, */ if ((map->rhs->type == TMPL_TYPE_ATTR) && (map->rhs->tmpl_num == NUM_COUNT)) { - cf_log_err_cp(cp, "Cannot assign from a count"); + cf_log_err(cp, "Cannot assign from a count"); goto error; } @@ -360,9 +360,9 @@ int map_afrom_cs(vp_map_t **out, CONF_SECTION *cs, } } - for (ci = cf_item_find_next(cs, NULL); + for (ci = cf_item_next(cs, NULL); ci != NULL; - ci = cf_item_find_next(cs, ci)) { + ci = cf_item_next(cs, ci)) { if (total++ == max) { cf_log_err(ci, "Map size exceeded"); error: diff --git a/src/main/modules.c b/src/main/modules.c index 6042bdd5b6a..52166de30b7 100644 --- a/src/main/modules.c +++ b/src/main/modules.c @@ -41,18 +41,18 @@ static TALLOC_CTX *instance_ctx = NULL; * Ordered by component */ const section_type_value_t section_type_value[MOD_COUNT] = { - { "authenticate", "Auth-Type", FR_AUTH_TYPE }, - { "authorize", "Autz-Type", FR_AUTZ_TYPE }, - { "preacct", "Pre-Acct-Type", FR_PRE_ACCT_TYPE }, - { "accounting", "Acct-Type", FR_ACCT_TYPE }, - { "session", "Session-Type", FR_SESSION_TYPE }, - { "pre-proxy", "Pre-Proxy-Type", FR_PRE_PROXY_TYPE }, - { "post-proxy", "Post-Proxy-Type", FR_POST_PROXY_TYPE }, - { "post-auth", "Post-Auth-Type", FR_POST_AUTH_TYPE } + { "authenticate", "Auth-Type", FR_AUTH_TYPE }, + { "authorize", "Autz-Type", FR_AUTZ_TYPE }, + { "preacct", "Pre-Acct-Type", FR_PRE_ACCT_TYPE }, + { "accounting", "Acct-Type", FR_ACCT_TYPE }, + { "session", "Session-Type", FR_SESSION_TYPE }, + { "pre-proxy", "Pre-Proxy-Type", FR_PRE_PROXY_TYPE }, + { "post-proxy", "Post-Proxy-Type", FR_POST_PROXY_TYPE }, + { "post-auth", "Post-Auth-Type", FR_POST_AUTH_TYPE } #ifdef WITH_COA , - { "recv-coa", "Recv-CoA-Type", FR_RECV_COA_TYPE }, - { "send-coa", "Send-CoA-Type", FR_SEND_COA_TYPE } + { "recv-coa", "Recv-CoA-Type", FR_RECV_COA_TYPE }, + { "send-coa", "Send-CoA-Type", FR_SEND_COA_TYPE } #endif }; @@ -105,7 +105,7 @@ exfile_t *module_exfile_init(TALLOC_CTX *ctx, handle = exfile_init(ctx, max_entries, max_idle, locking); if (!handle) return NULL; - exfile_enable_triggers(handle, cf_subsection_find(module, "file"), trigger_prefix, trigger_args); + exfile_enable_triggers(handle, cf_section_find(module, "file", NULL), trigger_prefix, trigger_args); return handle; } @@ -142,6 +142,7 @@ int module_sibling_section_find(CONF_SECTION **out, CONF_SECTION *module, char c { CONF_PAIR *cp; CONF_SECTION *cs; + CONF_DATA const *cd; module_instance_t *inst; @@ -154,7 +155,7 @@ int module_sibling_section_find(CONF_SECTION **out, CONF_SECTION *module, char c /* * Is a real section (not referencing sibling module). */ - cs = cf_subsection_find(module, name); + cs = cf_section_find(module, name, NULL); if (cs) { *out = cs; @@ -168,11 +169,11 @@ int module_sibling_section_find(CONF_SECTION **out, CONF_SECTION *module, char c if (!cp) return 0; if (cf_data_find(module, CONF_SECTION, FIND_SIBLING_CF_KEY)) { - cf_log_err_cp(cp, "Module reference loop found"); + cf_log_err(cp, "Module reference loop found"); return -1; } - cf_data_add(module, module, FIND_SIBLING_CF_KEY, false); + cd = cf_data_add(module, module, FIND_SIBLING_CF_KEY, false); /* * Item found, resolve it to a module instance. @@ -180,9 +181,9 @@ int module_sibling_section_find(CONF_SECTION **out, CONF_SECTION *module, char c * instantiation order issues. */ inst_name = cf_pair_value(cp); - inst = module_find(cf_section_parent(module), inst_name); + inst = module_find(cf_item_to_section(cf_parent(module)), inst_name); if (!inst) { - cf_log_err_cp(cp, "Unknown module instance \"%s\"", inst_name); + cf_log_err(cp, "Unknown module instance \"%s\"", inst_name); return -1; } @@ -196,7 +197,7 @@ int module_sibling_section_find(CONF_SECTION **out, CONF_SECTION *module, char c do { CONF_SECTION *tmp; - tmp = cf_section_parent(parent); + tmp = cf_item_to_section(cf_parent(parent)); if (!tmp) break; parent = tmp; @@ -209,19 +210,19 @@ int module_sibling_section_find(CONF_SECTION **out, CONF_SECTION *module, char c * Remove the config data we added for loop * detection. */ - cf_data_remove(module, CONF_SECTION, FIND_SIBLING_CF_KEY); + cf_data_remove(module, cd); /* * Check the module instances are of the same type. */ if (strcmp(cf_section_name1(inst->cs), cf_section_name1(module)) != 0) { - cf_log_err_cp(cp, "Referenced module is a rlm_%s instance, must be a rlm_%s instance", + cf_log_err(cp, "Referenced module is a rlm_%s instance, must be a rlm_%s instance", cf_section_name1(inst->cs), cf_section_name1(module)); return -1; } - *out = cf_subsection_find(inst->cs, name); + *out = cf_section_find(inst->cs, name, NULL); return 1; } @@ -242,12 +243,12 @@ int module_sibling_section_find(CONF_SECTION **out, CONF_SECTION *module, char c * - NULL on error. */ fr_pool_t *module_connection_pool_init(CONF_SECTION *module, - void *opaque, - fr_pool_connection_create_t c, - fr_pool_connection_alive_t a, - char const *log_prefix, - char const *trigger_prefix, - VALUE_PAIR *trigger_args) + void *opaque, + fr_pool_connection_create_t c, + fr_pool_connection_alive_t a, + char const *log_prefix, + char const *trigger_prefix, + VALUE_PAIR *trigger_args) { CONF_SECTION *cs, *mycs; char log_prefix_buff[128]; @@ -258,7 +259,7 @@ fr_pool_t *module_connection_pool_init(CONF_SECTION *module, int ret; -#define parent_name(_x) cf_section_name(cf_section_parent(_x)) +#define parent_name(_x) cf_section_name(cf_item_to_section(cf_parent(_x))) cs_name1 = cf_section_name1(module); cs_name2 = cf_section_name2(module); @@ -294,7 +295,7 @@ fr_pool_t *module_connection_pool_init(CONF_SECTION *module, /* * Get our pool config section */ - mycs = cf_subsection_find(module, "pool"); + mycs = cf_section_find(module, "pool", NULL); if (!mycs) { DEBUG4("%s: Adding pool section to config item \"%s\" to store pool references", log_prefix, cf_section_name(module)); @@ -320,7 +321,7 @@ fr_pool_t *module_connection_pool_init(CONF_SECTION *module, * This allows modules to pass in the config sections * they would like to use the connection pool from. */ - pool = cf_data_find(cs, fr_pool_t, NULL); + pool = cf_data_value(cf_data_find(cs, fr_pool_t, NULL)); if (!pool) { DEBUG4("%s: No pool reference found for config item \"%s.pool\"", log_prefix, parent_name(cs)); pool = fr_pool_init(cs, cs, opaque, c, a, log_prefix); @@ -396,7 +397,7 @@ module_instance_t *module_find(CONF_SECTION *modules, char const *asked_name) instance_name = asked_name; if (instance_name[0] == '-') instance_name++; - inst = cf_data_find(modules, module_instance_t, instance_name); + inst = cf_data_value(cf_data_find(modules, module_instance_t, instance_name)); if (!inst) return NULL; return talloc_get_type_abort(inst, module_instance_t); @@ -466,7 +467,7 @@ module_instance_t *module_find_with_method(rlm_components_t *method, CONF_SECTIO * the specified method. */ if (!inst->module->methods[i]) { - cf_log_module(modules, "%s does not implement method \"%s\"", inst->name, p + 1); + cf_log_debug(modules, "%s does not implement method \"%s\"", inst->name, p + 1); return NULL; } if (method) *method = i; @@ -611,7 +612,7 @@ int modules_thread_instantiate(CONF_SECTION *root, fr_event_list_t *el) rbtree_t *thread_inst_tree; _thread_intantiate_ctx_t ctx; - modules = cf_subsection_find(root, "modules"); + modules = cf_section_find(root, "modules", NULL); if (!modules) return 0; thread_inst_tree = module_thread_inst_tree; @@ -661,14 +662,14 @@ static int _module_instantiate(void *instance, UNUSED void *ctx) * Call the instantiate method, if any. */ if (inst->module->instantiate) { - cf_log_module(inst->cs, "Instantiating module \"%s\" from file %s", inst->name, - cf_section_filename(inst->cs)); + cf_log_debug(inst->cs, "Instantiating module \"%s\" from file %s", inst->name, + cf_filename(inst->cs)); /* * Call the module's instantiation routine. */ if ((inst->module->instantiate)(inst->cs, inst->data) < 0) { - cf_log_err_cs(inst->cs, "Instantiation failed for module \"%s\"", inst->name); + cf_log_err(inst->cs, "Instantiation failed for module \"%s\"", inst->name); return -1; } @@ -718,10 +719,10 @@ static int module_instantiate(CONF_SECTION *root, char const *name) module_instance_t *inst; CONF_SECTION *modules; - modules = cf_subsection_find(root, "modules"); + modules = cf_section_find(root, "modules", NULL); if (!modules) return 0; - inst = cf_data_find(modules, module_instance_t, name); + inst = cf_data_value(cf_data_find(modules, module_instance_t, name)); if (!inst) return -1; return _module_instantiate(inst, NULL); @@ -741,7 +742,7 @@ int modules_instantiate(CONF_SECTION *root) { CONF_SECTION *modules; - modules = cf_subsection_find(root, "modules"); + modules = cf_section_find(root, "modules", NULL); if (!modules) return 0; if (cf_data_walk(modules, module_instance_t, _module_instantiate, NULL) < 0) return -1; @@ -831,7 +832,7 @@ static module_instance_t *module_bootstrap(CONF_SECTION *modules, CONF_SECTION * int i; char const *name1, *instance_name; module_instance_t *instance; - dl_t const *module; + dl_t const *module; /* * Figure out which module we want to load. @@ -858,10 +859,10 @@ static module_instance_t *module_bootstrap(CONF_SECTION *modules, CONF_SECTION * if (instance) { ERROR("Duplicate module \"%s\", in file %s:%d and file %s:%d", instance_name, - cf_section_filename(cs), - cf_section_lineno(cs), - cf_section_filename(instance->cs), - cf_section_lineno(instance->cs)); + cf_filename(cs), + cf_lineno(cs), + cf_filename(instance->cs), + cf_lineno(instance->cs)); return NULL; } @@ -887,8 +888,8 @@ static module_instance_t *module_bootstrap(CONF_SECTION *modules, CONF_SECTION * return NULL; } - cf_log_module(cs, "Loading module \"%s\" from file %s", instance->name, - cf_section_filename(cs)); + cf_log_debug(cs, "Loading module \"%s\" from file %s", instance->name, + cf_filename(cs)); /* * Parse the modules configuration. @@ -903,7 +904,7 @@ static module_instance_t *module_bootstrap(CONF_SECTION *modules, CONF_SECTION * */ if (instance->module->bootstrap && ((instance->module->bootstrap)(cs, instance->data) < 0)) { - cf_log_err_cs(cs, "Instantiation failed for module \"%s\"", instance->name); + cf_log_err(cs, "Instantiation failed for module \"%s\"", instance->name); talloc_free(instance); return NULL; } @@ -929,7 +930,7 @@ static int virtual_module_bootstrap(CONF_SECTION *modules, CONF_SECTION *vm_cs) char const *name; bool all_same = true; rad_module_t const *last = NULL; - CONF_ITEM *sub_ci; + CONF_ITEM *sub_ci = NULL; CONF_PAIR *cp; module_instance_t *instance; @@ -944,13 +945,13 @@ static int virtual_module_bootstrap(CONF_SECTION *modules, CONF_SECTION *vm_cs) (strcmp(name, "load-balance") == 0)) { name = cf_section_name2(vm_cs); if (!name) { - cf_log_err_cs(vm_cs, "Subsection must have a name"); + cf_log_err(vm_cs, "Subsection must have a name"); return -1; } if (is_reserved_word(name)) { is_reserved: - cf_log_err_cs(vm_cs, "Virtual modules cannot overload unlang keywords"); + cf_log_err(vm_cs, "Virtual modules cannot overload unlang keywords"); return -1; } } else { @@ -960,9 +961,7 @@ static int virtual_module_bootstrap(CONF_SECTION *modules, CONF_SECTION *vm_cs) /* * Ensure that the modules we reference here exist. */ - for (sub_ci = cf_item_find_next(vm_cs, NULL); - sub_ci != NULL; - sub_ci = cf_item_find_next(vm_cs, sub_ci)) { + while ((sub_ci = cf_item_next(vm_cs, sub_ci))) { if (cf_item_is_pair(sub_ci)) { cp = cf_item_to_pair(sub_ci); if (cf_pair_value(cp)) { @@ -1000,13 +999,7 @@ static int virtual_module_bootstrap(CONF_SECTION *modules, CONF_SECTION *vm_cs) /* * Register a redundant xlat */ - if (all_same) { - if (!xlat_register_redundant(vm_cs)) { - WARN("%s[%d] Not registering expansions for %s", - cf_section_filename(vm_cs), cf_section_lineno(vm_cs), - cf_section_name2(vm_cs)); - } - } + if (all_same && (xlat_register_redundant(vm_cs) < 0)) return -1; return 0; } @@ -1030,8 +1023,11 @@ int modules_bootstrap(CONF_SECTION *root) /* * Remember where the modules were stored. */ - modules = cf_subsection_find(root, "modules"); - if (!modules) WARN("Cannot find a \"modules\" section in the rooturation file!"); + modules = cf_section_find(root, "modules", NULL); + if (!modules) { + WARN("Cannot find a \"modules\" section in the configuration file!"); + return 0; + } DEBUG2("%s: #### Loading modules ####", main_config.name); @@ -1043,14 +1039,14 @@ int modules_bootstrap(CONF_SECTION *root) * This is O(N^2) in the number of modules, but most * systems should have less than 100 modules. */ - for (ci = cf_item_find_next(modules, NULL); + for (ci = cf_item_next(modules, NULL); ci != NULL; ci = next) { char const *name1; CONF_SECTION *subcs; module_instance_t *instance; - next = cf_item_find_next(modules, ci); + next = cf_item_next(modules, ci); if (!cf_item_is_section(ci)) continue; @@ -1064,7 +1060,7 @@ int modules_bootstrap(CONF_SECTION *root) name1 = cf_section_name1(subcs); if (is_reserved_word(name1)) { - cf_log_err_cs(subcs, "Modules cannot overload unlang keywords"); + cf_log_err(subcs, "Modules cannot overload unlang keywords"); return -1; } } @@ -1075,34 +1071,43 @@ int modules_bootstrap(CONF_SECTION *root) * us to load modules with no authorize/authenticate/etc. * sections. */ - cs = cf_subsection_find(root, "instantiate"); + cs = cf_section_find(root, "instantiate", NULL); if (cs) { cf_log_info(cs, " instantiate {"); + ci = NULL; /* * Loop over the items in the 'instantiate' section. */ - for (ci = cf_item_find_next(cs, NULL); - ci != NULL; - ci = cf_item_find_next(cs, ci)) { + while ((ci = cf_item_next(cs, ci))) { + CONF_SECTION *vm_cs; + /* * Skip sections and "other" stuff. * Sections will be handled later, if * they're referenced at all... */ if (cf_item_is_pair(ci)) { - cf_log_warn_cp(cf_item_to_pair(ci), "Only virtual modules can be instantiated " - "with the instantiate section"); + cf_log_warn(ci, "Only virtual modules can be instantiated " + "with the instantiate section"); continue; } + /* + * Skip section + */ + if (!cf_item_is_section(ci)) continue; + + vm_cs = cf_item_to_section(ci); + cf_log_debug(ci, "Instantiating virtual module \"%s %s\"", + cf_section_name1(vm_cs), cf_section_name2(vm_cs)); + /* * Can only be "redundant" or * "load-balance" or * "redundant-load-balance" */ - if (cf_item_is_section(ci) && - (virtual_module_bootstrap(modules, cf_item_to_section(ci)) < 0)) return -1; + if (virtual_module_bootstrap(modules, cf_item_to_section(ci)) < 0) return -1; } cf_log_info(cs, " }"); diff --git a/src/main/pool.c b/src/main/pool.c index a955b948a44..103d740255b 100644 --- a/src/main/pool.c +++ b/src/main/pool.c @@ -1054,7 +1054,7 @@ fr_pool_t *fr_pool_init(TALLOC_CTX *ctx, * Some simple limits */ if (pool->max == 0) { - cf_log_err_cs(cs, "Cannot set 'max' to zero"); + cf_log_err(cs, "Cannot set 'max' to zero"); goto error; } @@ -1062,7 +1062,7 @@ fr_pool_t *fr_pool_init(TALLOC_CTX *ctx, pool->pending_window = (pool->max_pending > 0) ? pool->max_pending : pool->max; if (pool->min > pool->max) { - cf_log_err_cs(cs, "Cannot set 'min' to more than 'max'"); + cf_log_err(cs, "Cannot set 'min' to more than 'max'"); goto error; } diff --git a/src/main/radmin.c b/src/main/radmin.c index bf6333a5b45..126b823bd93 100644 --- a/src/main/radmin.c +++ b/src/main/radmin.c @@ -556,7 +556,7 @@ int main(int argc, char **argv) gid = getgid(); subcs = NULL; - while ((subcs = cf_subsection_find_next(cs, subcs, "listen")) != NULL) { + while ((subcs = cf_section_find_next(cs, subcs, "listen", NULL)) != NULL) { char const *value; CONF_PAIR *cp = cf_pair_find(subcs, "type"); @@ -637,7 +637,7 @@ int main(int argc, char **argv) * Log the commands we've run. */ if (!radmin_log.file) { - subcs = cf_subsection_find(cs, "log"); + subcs = cf_section_find(cs, "log", NULL); if (subcs) { CONF_PAIR *cp = cf_pair_find(subcs, "radmin"); if (cp) { diff --git a/src/main/radwho.c b/src/main/radwho.c index 4ffb9598586..c35fe3cb3fc 100644 --- a/src/main/radwho.c +++ b/src/main/radwho.c @@ -333,13 +333,13 @@ int main(int argc, char **argv) exit(1); } - cs = cf_subsection_find(maincs, "modules"); + cs = cf_section_find(maincs, "modules", NULL); if (!cs) { fprintf(stderr, "%s: No modules section found in radiusd.conf\n", argv[0]); exit(1); } /* Read the radutmp section of radiusd.conf */ - cs = cf_subsection_find_name2(cs, "radutmp", NULL); + cs = cf_section_find(cs, "radutmp", NULL); if (!cs) { fprintf(stderr, "%s: No configuration information in radutmp section of radiusd.conf\n", argv[0]); exit(1); diff --git a/src/main/realms.c b/src/main/realms.c index ce360c62755..7d4cb792c72 100644 --- a/src/main/realms.c +++ b/src/main/realms.c @@ -470,7 +470,7 @@ void realm_home_server_sanitize(home_server_t *home, CONF_SECTION *cs) home->src_ipaddr.af = home->ipaddr.af; } - parent = cf_section_parent(cs); + parent = cf_item_to_section(cf_parent(cs)); if (parent && strcmp(cf_section_name1(parent), "server") == 0) { home->parent_server = cf_section_name2(parent); } @@ -487,13 +487,13 @@ void realm_home_server_sanitize(home_server_t *home, CONF_SECTION *cs) static bool home_server_insert(home_server_t *home, CONF_SECTION *cs) { if (home->name && !rbtree_insert(home_servers_byname, home)) { - cf_log_err_cs(cs, "Internal error %d adding home server %s", __LINE__, home->log_name); + cf_log_err(cs, "Internal error %d adding home server %s", __LINE__, home->log_name); return false; } if (!home->server && !rbtree_insert(home_servers_byaddr, home)) { rbtree_deletebydata(home_servers_byname, home); - cf_log_err_cs(cs, "Internal error %d adding home server %s", __LINE__, home->log_name); + cf_log_err(cs, "Internal error %d adding home server %s", __LINE__, home->log_name); return false; } @@ -504,7 +504,7 @@ static bool home_server_insert(home_server_t *home, CONF_SECTION *cs) if (home->ipaddr.af != AF_UNSPEC) { rbtree_deletebydata(home_servers_byname, home); } - cf_log_err_cs(cs, "Internal error %d adding home server %s", __LINE__, home->log_name); + cf_log_err(cs, "Internal error %d adding home server %s", __LINE__, home->log_name); return false; } #endif @@ -531,7 +531,7 @@ bool realm_home_server_add(home_server_t *home) } if (home->name && (rbtree_finddata(home_servers_byname, home) != NULL)) { - cf_log_err_cs(home->cs, "Duplicate home server name %s", home->name); + cf_log_err(home->cs, "Duplicate home server name %s", home->name); return false; } @@ -540,7 +540,7 @@ bool realm_home_server_add(home_server_t *home) inet_ntop(home->ipaddr.af, &home->ipaddr.addr, buffer, sizeof(buffer)); - cf_log_err_cs(home->cs, "Duplicate home server address%s%s%s: %s:%s%s/%i", + cf_log_err(home->cs, "Duplicate home server address%s%s%s: %s:%s%s/%i", home->name ? " (already in use by " : "", home->name ? home->name : "", home->name ? ")" : "", @@ -630,7 +630,7 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE */ if (cf_pair_find(cs, "ipaddr") || cf_pair_find(cs, "ipv4addr") || cf_pair_find(cs, "ipv6addr")) { if (fr_ipaddr_is_inaddr_any(&home->ipaddr) == 1) { - cf_log_err_cs(cs, "Wildcard '*' addresses are not permitted for home servers"); + cf_log_err(cs, "Wildcard '*' addresses are not permitted for home servers"); goto error; } @@ -649,7 +649,7 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE home->ipaddr.af = AF_UNSPEC; /* mark ipaddr as unused */ if (!home->server) { - cf_log_err_cs(cs, "Invalid value for virtual_server"); + cf_log_err(cs, "Invalid value for virtual_server"); goto error; } @@ -658,8 +658,8 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE * the config with a name that matches the * virtual_server. */ - if (!cf_subsection_find_name2(rc->cs, "server", home->server)) { - cf_log_err_cs(cs, "No such server %s", home->server); + if (!cf_section_find(rc->cs, "server", home->server)) { + cf_log_err(cs, "No such server %s", home->server); goto error; } @@ -670,7 +670,7 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE * raise an error. */ } else { - cf_log_err_cs(cs, "No ipaddr, ipv4addr, ipv6addr, or virtual_server defined " + cf_log_err(cs, "No ipaddr, ipv4addr, ipv6addr, or virtual_server defined " "for home server"); error: talloc_free(home); @@ -680,15 +680,15 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE /* * Check the TLS configuration. */ - tls = cf_subsection_find(cs, "tls"); + tls = cf_section_find(cs, "tls", NULL); if (tls && home->ipaddr.af == AF_UNSPEC) { - cf_log_err_cs(cs, "TLS transport cannot be used for home servers with 'virtual_server' set"); + cf_log_err(cs, "TLS transport cannot be used for home servers with 'virtual_server' set"); goto error; } #ifndef WITH_TLS if (tls) { - cf_log_err_cs(cs, "TLS transport is not available in this executable"); + cf_log_err(cs, "TLS transport is not available in this executable"); goto error; } #endif @@ -710,20 +710,20 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE case HOME_PING_CHECK_REQUEST: if (!home->ping_user_name) { - cf_log_err_cs(cs, "You must supply a 'username' to enable status_check=request"); + cf_log_err(cs, "You must supply a 'username' to enable status_check=request"); goto error; } if (((home->type == HOME_TYPE_AUTH) || (home->type == HOME_TYPE_AUTH_ACCT)) && !home->ping_user_password) { - cf_log_err_cs(cs, "You must supply a 'password' to enable status_check=request"); + cf_log_err(cs, "You must supply a 'password' to enable status_check=request"); goto error; } break; case HOME_PING_CHECK_INVALID: - cf_log_err_cs(cs, "Invalid status_check \"%s\" for home server %s", + cf_log_err(cs, "Invalid status_check \"%s\" for home server %s", home->ping_check_str, home->log_name); goto error; } @@ -733,7 +733,7 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE if (home->ipaddr.af == AF_UNSPEC) { if (home->proto_str) { - cf_log_err_cs(cs, "The 'proto' configuration cannot be used for home servers with " + cf_log_err(cs, "The 'proto' configuration cannot be used for home servers with " "'virtual_server' set"); goto error; } @@ -750,18 +750,18 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE case IPPROTO_TCP: #ifndef WITH_TCP - cf_log_err_cs(cs, "Server not built with support for RADIUS over TCP"); + cf_log_err(cs, "Server not built with support for RADIUS over TCP"); goto error; #endif if (home->ping_check != HOME_PING_CHECK_NONE) { - cf_log_err_cs(cs, "Only 'status_check = none' is allowed for home " + cf_log_err(cs, "Only 'status_check = none' is allowed for home " "servers with 'proto = tcp'"); goto error; } break; default: - cf_log_err_cs(cs, "Unknown proto \"%s\"", home->proto_str); + cf_log_err(cs, "Unknown proto \"%s\"", home->proto_str); goto error; } @@ -790,20 +790,20 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE #ifdef WITH_COA case HOME_TYPE_COA: if (home->server != NULL) { - cf_log_err_cs(cs, "Home servers of type \"coa\" cannot point to a virtual server"); + cf_log_err(cs, "Home servers of type \"coa\" cannot point to a virtual server"); goto error; } break; #endif case HOME_TYPE_INVALID: - cf_log_err_cs(cs, "Invalid type \"%s\" for home server %s", home->type_str, home->log_name); + cf_log_err(cs, "Invalid type \"%s\" for home server %s", home->type_str, home->log_name); goto error; } } if (!home->server && rbtree_finddata(home_servers_byaddr, home)) { - cf_log_err_cs(cs, "Duplicate home server"); + cf_log_err(cs, "Duplicate home server"); goto error; } @@ -818,7 +818,7 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE } else #endif { - cf_log_err_cs(cs, "No shared secret defined for home server %s", home->log_name); + cf_log_err(cs, "No shared secret defined for home server %s", home->log_name); goto error; } } @@ -828,7 +828,7 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE */ if (home->server) { if (tls) { - cf_log_err_cs(cs, "Virtual home_servers cannot have a \"tls\" subsection"); + cf_log_err(cs, "Virtual home_servers cannot have a \"tls\" subsection"); goto error; } } else { @@ -840,7 +840,7 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE #ifdef WITH_TLS if (tls && (home->proto != IPPROTO_TCP)) { - cf_log_err_cs(cs, "TLS transport is not available for UDP sockets"); + cf_log_err(cs, "TLS transport is not available for UDP sockets"); goto error; } #endif @@ -897,7 +897,7 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE */ if (home->src_ipaddr_str) { if (fr_inet_hton(&home->src_ipaddr, home->ipaddr.af, home->src_ipaddr_str, false) < 0) { - cf_log_err_cs(cs, "Failed parsing src_ipaddr"); + cf_log_err(cs, "Failed parsing src_ipaddr"); goto error; } /* @@ -963,7 +963,7 @@ CONF_SECTION *home_server_cs_afrom_client(CONF_SECTION *client) * Duplicate the server section, so we don't mangle * the client CONF_SECTION we were passed. */ - cs = cf_subsection_find(client, "coa_server"); + cs = cf_section_find(client, "coa_server", CF_IDENT_ANY); if (cs) { server = cf_section_dup(client, cs, "home_server", NULL, true); } else { @@ -993,7 +993,7 @@ CONF_SECTION *home_server_cs_afrom_client(CONF_SECTION *client) if (cp) cf_pair_add(server, cf_pair_dup(server, cp)); } else if (strcmp(cf_pair_value(cp), "coa") != 0) { talloc_free(server); - cf_log_err_cs(server, "server.type must be \"coa\""); + cf_log_err(server, "server.type must be \"coa\""); return NULL; } @@ -1035,7 +1035,7 @@ static int pool_check_home_server(UNUSED realm_config_t *rc, CONF_PAIR *cp, home_server_t myhome, *home; if (!name) { - cf_log_err_cp(cp, + cf_log_err(cp, "No value given for home_server"); return 0; } @@ -1063,7 +1063,7 @@ static int pool_check_home_server(UNUSED realm_config_t *rc, CONF_PAIR *cp, break; } - cf_log_err_cp(cp, "Unknown home_server \"%s\".", name); + cf_log_err(cp, "Unknown home_server \"%s\".", name); return 0; } @@ -1191,14 +1191,14 @@ static int server_pool_add(realm_config_t *rc, name2 = cf_section_name1(cs); if (!name2 || ((strcasecmp(name2, "server_pool") != 0) && (strcasecmp(name2, "home_server_pool") != 0))) { - cf_log_err_cs(cs, + cf_log_err(cs, "Section is not a home_server_pool"); return 0; } name2 = cf_section_name2(cs); if (!name2) { - cf_log_err_cs(cs, + cf_log_err(cs, "Server pool section is missing a name"); return 0; } @@ -1219,7 +1219,7 @@ static int server_pool_add(realm_config_t *rc, } if (num_home_servers == 0) { - cf_log_err_cs(cs, + cf_log_err(cs, "No home servers defined in pool %s", name2); goto error; @@ -1238,7 +1238,7 @@ static int server_pool_add(realm_config_t *rc, if (cp) { #ifdef WITH_COA if (server_type == HOME_TYPE_COA) { - cf_log_err_cs(cs, "Home server pools of type \"coa\" cannot have a fallback virtual server"); + cf_log_err(cs, "Home server pools of type \"coa\" cannot have a fallback virtual server"); goto error; } #endif @@ -1248,7 +1248,7 @@ static int server_pool_add(realm_config_t *rc, } if (!pool->fallback->server) { - cf_log_err_cs(cs, "Fallback home_server %s does NOT contain a virtual_server directive", + cf_log_err(cs, "Fallback home_server %s does NOT contain a virtual_server directive", pool->fallback->log_name); goto error; } @@ -1275,14 +1275,14 @@ static int server_pool_add(realm_config_t *rc, value = cf_pair_value(cp); if (!value) { - cf_log_err_cp(cp, + cf_log_err(cp, "No value given for type"); goto error; } pool->type = fr_str2int(pool_types, value, 0); if (!pool->type) { - cf_log_err_cp(cp, + cf_log_err(cp, "Unknown type \"%s\".", value); goto error; @@ -1295,7 +1295,7 @@ static int server_pool_add(realm_config_t *rc, if (cp) { pool->virtual_server = cf_pair_value(cp); if (!pool->virtual_server) { - cf_log_err_cp(cp, "No value given for virtual_server"); + cf_log_err(cp, "No value given for virtual_server"); goto error; } @@ -1303,8 +1303,8 @@ static int server_pool_add(realm_config_t *rc, cf_log_info(cs, "\tvirtual_server = %s", pool->virtual_server); } - if (!cf_subsection_find_name2(rc->cs, "server", pool->virtual_server)) { - cf_log_err_cp(cp, "No such server %s", pool->virtual_server); + if (!cf_section_find(rc->cs, "server", pool->virtual_server)) { + cf_log_err(cp, "No such server %s", pool->virtual_server); goto error; } @@ -1377,7 +1377,7 @@ static int old_server_add(realm_config_t *rc, CONF_SECTION *cs, int i, insert_point, num_home_servers; home_server_t myhome, *home; home_pool_t mypool, *pool; - CONF_SECTION *subcs; + CONF_SECTION *subcs = NULL; #else (void) rc; /* -Wunused */ (void) realm; @@ -1392,7 +1392,7 @@ static int old_server_add(realm_config_t *rc, CONF_SECTION *cs, */ if (strcmp(name, "LOCAL") == 0) { if (*pool_p) { - cf_log_err_cs(cs, "Realm \"%s\" cannot be both LOCAL and remote", name); + cf_log_err(cs, "Realm \"%s\" cannot be both LOCAL and remote", name); return 0; } return 1; @@ -1407,12 +1407,12 @@ static int old_server_add(realm_config_t *rc, CONF_SECTION *cs, pool = rbtree_finddata(home_pools_byname, &mypool); if (pool) { if (pool->type != ldflag) { - cf_log_err_cs(cs, "Inconsistent ldflag for server pool \"%s\"", name); + cf_log_err(cs, "Inconsistent ldflag for server pool \"%s\"", name); return 0; } if (pool->server_type != type) { - cf_log_err_cs(cs, "Inconsistent home server type for server pool \"%s\"", name); + cf_log_err(cs, "Inconsistent home server type for server pool \"%s\"", name); return 0; } } @@ -1422,12 +1422,12 @@ static int old_server_add(realm_config_t *rc, CONF_SECTION *cs, home = rbtree_finddata(home_servers_byname, &myhome); if (home) { if (secret && (strcmp(home->secret, secret) != 0)) { - cf_log_err_cs(cs, "Inconsistent shared secret for home server \"%s\"", name); + cf_log_err(cs, "Inconsistent shared secret for home server \"%s\"", name); return 0; } if (home->type != type) { - cf_log_err_cs(cs, "Inconsistent type for home server \"%s\"", name); + cf_log_err(cs, "Inconsistent type for home server \"%s\"", name); return 0; } @@ -1436,9 +1436,7 @@ static int old_server_add(realm_config_t *rc, CONF_SECTION *cs, * in the pool. If so, do nothing else. */ if (pool) for (i = 0; i < pool->num_home_servers; i++) { - if (pool->servers[i] == home) { - return 1; - } + if (pool->servers[i] == home) return 1; } } @@ -1462,7 +1460,7 @@ static int old_server_add(realm_config_t *rc, CONF_SECTION *cs, } if (insert_point < 0) { - cf_log_err_cs(cs, "No room in pool to add home server \"%s\". Please update the realm configuration to use the new-style home servers and server pools.", name); + cf_log_err(cs, "No room in pool to add home server \"%s\". Please update the realm configuration to use the new-style home servers and server pools.", name); return 0; } } @@ -1494,14 +1492,14 @@ static int old_server_add(realm_config_t *rc, CONF_SECTION *cs, q = NULL; } else if (p == name) { - cf_log_err_cs(cs, "Invalid hostname %s", name); + cf_log_err(cs, "Invalid hostname %s", name); talloc_free(home); return 0; } else { unsigned long port = strtoul(p + 1, NULL, 0); if ((port == 0) || (port > 65535)) { - cf_log_err_cs(cs, "Invalid port %s", p + 1); + cf_log_err(cs, "Invalid port %s", p + 1); talloc_free(home); return 0; } @@ -1515,7 +1513,7 @@ static int old_server_add(realm_config_t *rc, CONF_SECTION *cs, if (!server) { if (fr_inet_hton(&home->ipaddr, AF_UNSPEC, p, false) < 0) { - cf_log_err_cs(cs, + cf_log_err(cs, "Failed looking up hostname %s.", p); talloc_free(home); @@ -1542,20 +1540,20 @@ static int old_server_add(realm_config_t *rc, CONF_SECTION *cs, home->revive_interval = rc->dead_time; if (rbtree_finddata(home_servers_byaddr, home)) { - cf_log_err_cs(cs, "Home server %s has the same IP address and/or port as another home server.", name); + cf_log_err(cs, "Home server %s has the same IP address and/or port as another home server.", name); talloc_free(home); return 0; } if (!rbtree_insert(home_servers_byname, home)) { - cf_log_err_cs(cs, "Internal error %d adding home server %s.", __LINE__, name); + cf_log_err(cs, "Internal error %d adding home server %s.", __LINE__, name); talloc_free(home); return 0; } if (!rbtree_insert(home_servers_byaddr, home)) { rbtree_deletebydata(home_servers_byname, home); - cf_log_err_cs(cs, "Internal error %d adding home server %s.", __LINE__, name); + cf_log_err(cs, "Internal error %d adding home server %s.", __LINE__, name); talloc_free(home); return 0; } @@ -1567,7 +1565,7 @@ static int old_server_add(realm_config_t *rc, CONF_SECTION *cs, if (home->ipaddr.af != AF_UNSPEC) { rbtree_deletebydata(home_servers_byname, home); } - cf_log_err_cs(cs, + cf_log_err(cs, "Internal error %d adding home server %s.", __LINE__, name); talloc_free(home); @@ -1593,9 +1591,7 @@ static int old_server_add(realm_config_t *rc, CONF_SECTION *cs, * Count the old-style realms of this name. */ num_home_servers = 0; - for (subcs = cf_section_find_next(cs, NULL, "realm"); - subcs != NULL; - subcs = cf_section_find_next(cs, subcs, "realm")) { + while ((subcs = cf_section_find_next(cs, subcs, "realm", CF_IDENT_ANY))) { char const *this = cf_section_name2(subcs); if (!this || (strcmp(this, realm) != 0)) continue; @@ -1603,14 +1599,14 @@ static int old_server_add(realm_config_t *rc, CONF_SECTION *cs, } if (num_home_servers == 0) { - cf_log_err_cs(cs, "Internal error counting pools for home server %s.", name); + cf_log_err(cs, "Internal error counting pools for home server %s.", name); talloc_free(home); return 0; } pool = server_pool_alloc(rc, realm, ldflag, type, num_home_servers); if (!pool) { - cf_log_err_cs(cs, "Out of memory"); + cf_log_err(cs, "Out of memory"); return 0; } @@ -1641,7 +1637,7 @@ static int old_realm_config(realm_config_t *rc, CONF_SECTION *cs, REALM *r) if (cp) { host = cf_pair_value(cp); if (!host) { - cf_log_err_cp(cp, "No value specified for ldflag"); + cf_log_err(cp, "No value specified for ldflag"); return 0; } @@ -1653,7 +1649,7 @@ static int old_realm_config(realm_config_t *rc, CONF_SECTION *cs, REALM *r) cf_log_info(cs, "\tldflag = round_robin"); } else { - cf_log_err_cs(cs, "Unknown value \"%s\" for ldflag", host); + cf_log_err(cs, "Unknown value \"%s\" for ldflag", host); return 0; } } /* else don't print it. */ @@ -1666,20 +1662,20 @@ static int old_realm_config(realm_config_t *rc, CONF_SECTION *cs, REALM *r) if (cp) { host = cf_pair_value(cp); if (!host) { - cf_log_err_cp(cp, "No value specified for authhost"); + cf_log_err(cp, "No value specified for authhost"); return 0; } if (strcmp(host, "LOCAL") != 0) { cp = cf_pair_find(cs, "secret"); if (!cp) { - cf_log_err_cs(cs, "No shared secret supplied for realm: %s", r->name); + cf_log_err(cs, "No shared secret supplied for realm: %s", r->name); return 0; } secret = cf_pair_value(cp); if (!secret) { - cf_log_err_cp(cp, "No value specified for secret"); + cf_log_err(cp, "No value specified for secret"); return 0; } } @@ -1696,7 +1692,7 @@ static int old_realm_config(realm_config_t *rc, CONF_SECTION *cs, REALM *r) if (cp) { host = cf_pair_value(cp); if (!host) { - cf_log_err_cp(cp, "No value specified for accthost"); + cf_log_err(cp, "No value specified for accthost"); return 0; } @@ -1707,13 +1703,13 @@ static int old_realm_config(realm_config_t *rc, CONF_SECTION *cs, REALM *r) if ((strcmp(host, "LOCAL") != 0) && !secret) { cp = cf_pair_find(cs, "secret"); if (!cp) { - cf_log_err_cs(cs, "No shared secret supplied for realm: %s", r->name); + cf_log_err(cs, "No shared secret supplied for realm: %s", r->name); return 0; } secret = cf_pair_value(cp); if (!secret) { - cf_log_err_cp(cp, "No value specified for secret"); + cf_log_err(cp, "No value specified for secret"); return 0; } } @@ -1730,7 +1726,7 @@ static int old_realm_config(realm_config_t *rc, CONF_SECTION *cs, REALM *r) if (cp) { host = cf_pair_value(cp); if (!host) { - cf_log_err_cp(cp, "No value specified for virtual_server"); + cf_log_err(cp, "No value specified for virtual_server"); return 0; } @@ -1773,16 +1769,10 @@ static int add_pool_to_realm(realm_config_t *rc, CONF_SECTION *cs, if (!pool) { CONF_SECTION *pool_cs; - pool_cs = cf_subsection_find_name2(rc->cs, - "home_server_pool", - name); - if (!pool_cs) { - pool_cs = cf_subsection_find_name2(rc->cs, - "server_pool", - name); - } + pool_cs = cf_section_find(rc->cs, "home_server_pool", name); + if (!pool_cs) pool_cs = cf_section_find(rc->cs, "server_pool", name); if (!pool_cs) { - cf_log_err_cs(cs, "Failed to find home_server_pool \"%s\"", name); + cf_log_err(cs, "Failed to find home_server_pool \"%s\"", name); return 0; } @@ -1798,7 +1788,7 @@ static int add_pool_to_realm(realm_config_t *rc, CONF_SECTION *cs, } if (pool->server_type != server_type) { - cf_log_err_cs(cs, "Incompatible home_server_pool \"%s\" (mixed auth_pool / acct_pool)", name); + cf_log_err(cs, "Incompatible home_server_pool \"%s\" (mixed auth_pool / acct_pool)", name); return 0; } @@ -1825,13 +1815,13 @@ static int realm_add(realm_config_t *rc, CONF_SECTION *cs) name2 = cf_section_name1(cs); if (!name2 || (strcasecmp(name2, "realm") != 0)) { - cf_log_err_cs(cs, "Section is not a realm"); + cf_log_err(cs, "Section is not a realm"); return 0; } name2 = cf_section_name2(cs); if (!name2) { - cf_log_err_cs(cs, "Realm section is missing the realm name"); + cf_log_err(cs, "Realm section is missing the realm name"); return 0; } @@ -1867,7 +1857,7 @@ static int realm_add(realm_config_t *rc, CONF_SECTION *cs) if (cp) auth_pool_name = cf_pair_value(cp); if (cp && auth_pool_name) { if (auth_pool) { - cf_log_err_cs(cs, "Cannot use \"pool\" and \"auth_pool\" at the same time"); + cf_log_err(cs, "Cannot use \"pool\" and \"auth_pool\" at the same time"); return 0; } if (!add_pool_to_realm(rc, cs, @@ -1883,7 +1873,7 @@ static int realm_add(realm_config_t *rc, CONF_SECTION *cs) bool do_print = true; if (acct_pool) { - cf_log_err_cs(cs, "Cannot use \"pool\" and \"acct_pool\" at the same time"); + cf_log_err(cs, "Cannot use \"pool\" and \"acct_pool\" at the same time"); return 0; } @@ -1926,7 +1916,7 @@ static int realm_add(realm_config_t *rc, CONF_SECTION *cs) if (r && (strcmp(r->name, name2) == 0)) { if (cf_pair_find(cs, "auth_pool") || cf_pair_find(cs, "acct_pool")) { - cf_log_err_cs(cs, "Duplicate realm \"%s\"", name2); + cf_log_err(cs, "Duplicate realm \"%s\"", name2); goto error; } @@ -1991,9 +1981,7 @@ static int realm_add(realm_config_t *rc, CONF_SECTION *cs) goto error; } - if (!realm_realm_add(r, cs)) { - goto error; - } + if (!realm_realm_add(r, cs)) goto error; cf_log_info(cs, " }"); @@ -2039,9 +2027,9 @@ int realm_realm_add(REALM *r, UNUSED CONF_SECTION *cs) fr_canonicalize_error(r, &spaces, &text, slen, r->name + 1); - cf_log_err_cs(cs, "Invalid regular expression:"); - cf_log_err_cs(cs, "%s", text); - cf_log_err_cs(cs, "%s^ %s", spaces, fr_strerror()); + cf_log_err(cs, "Invalid regular expression:"); + cf_log_err(cs, "%s", text); + cf_log_err(cs, "%s^ %s", spaces, fr_strerror()); talloc_free(spaces); talloc_free(text); @@ -2080,37 +2068,37 @@ static int pool_peek_type(CONF_SECTION *config, CONF_SECTION *cs) cp = cf_pair_find(cs, "home_server"); if (!cp) { - cf_log_err_cs(cs, "Pool does not contain a \"home_server\" entry"); + cf_log_err(cs, "Pool does not contain a \"home_server\" entry"); return HOME_TYPE_INVALID; } name = cf_pair_value(cp); if (!name) { - cf_log_err_cp(cp, "home_server entry does not reference a home server"); + cf_log_err(cp, "home_server entry does not reference a home server"); return HOME_TYPE_INVALID; } - server_cs = cf_subsection_find_name2(config, "home_server", name); + server_cs = cf_section_find(config, "home_server", name); if (!server_cs) { - cf_log_err_cp(cp, "home_server \"%s\" does not exist", name); + cf_log_err(cp, "home_server \"%s\" does not exist", name); return HOME_TYPE_INVALID; } cp = cf_pair_find(server_cs, "type"); if (!cp) { - cf_log_err_cs(server_cs, "home_server %s does not contain a \"type\" entry", name); + cf_log_err(server_cs, "home_server %s does not contain a \"type\" entry", name); return HOME_TYPE_INVALID; } type = cf_pair_value(cp); if (!type) { - cf_log_err_cs(server_cs, "home_server %s contains an empty \"type\" entry", name); + cf_log_err(server_cs, "home_server %s contains an empty \"type\" entry", name); return HOME_TYPE_INVALID; } home = fr_str2int(home_server_types, type, HOME_TYPE_INVALID); if (home == HOME_TYPE_INVALID) { - cf_log_err_cs(server_cs, "home_server %s contains an invalid \"type\" entry of value \"%s\"", name, type); + cf_log_err(server_cs, "home_server %s contains an invalid \"type\" entry of value \"%s\"", name, type); return HOME_TYPE_INVALID; } @@ -2123,7 +2111,7 @@ int realms_init(CONF_SECTION *config) CONF_SECTION *cs; int flags = 0; #ifdef WITH_PROXY - CONF_SECTION *server_cs; + CONF_SECTION *server_cs = NULL; #endif realm_config_t *rc; @@ -2133,7 +2121,7 @@ int realms_init(CONF_SECTION *config) rc->cs = config; #ifdef WITH_PROXY - cs = cf_subsection_find_next(config, NULL, "proxy"); + cs = cf_section_find(config, "proxy", NULL); if (cs) { if (cf_section_parse(rc, rc, cs, proxy_config) < 0) { ERROR("Failed parsing proxy section"); @@ -2166,9 +2154,8 @@ int realms_init(CONF_SECTION *config) home_pools_byname = rbtree_create(NULL, home_pool_name_cmp, NULL, flags); if (!home_pools_byname) goto error; - for (cs = cf_subsection_find_next(config, NULL, "home_server"); - cs != NULL; - cs = cf_subsection_find_next(config, cs, "home_server")) { + cs = NULL; + while ((cs = cf_section_find_next(config, cs, "home_server", CF_IDENT_ANY))) { home_server_t *home; home = home_server_afrom_cs(rc, rc, cs); @@ -2180,12 +2167,9 @@ int realms_init(CONF_SECTION *config) * Loop over virtual servers to find home servers which * are defined in them. */ - for (server_cs = cf_subsection_find_next(config, NULL, "server"); - server_cs != NULL; - server_cs = cf_subsection_find_next(config, server_cs, "server")) { - for (cs = cf_subsection_find_next(server_cs, NULL, "home_server"); - cs != NULL; - cs = cf_subsection_find_next(server_cs, cs, "home_server")) { + while ((server_cs = cf_section_find_next(config, server_cs, "server", CF_IDENT_ANY))) { + cs = NULL; + while ((cs = cf_section_find_next(server_cs, cs, "home_server", CF_IDENT_ANY))) { home_server_t *home; home = home_server_afrom_cs(rc, rc, cs); @@ -2202,9 +2186,8 @@ int realms_init(CONF_SECTION *config) realms_byname = rbtree_create(NULL, realm_name_cmp, NULL, flags); if (!realms_byname) goto error; - for (cs = cf_subsection_find_next(config, NULL, "realm"); - cs != NULL; - cs = cf_subsection_find_next(config, cs, "realm")) { + cs = NULL; + while ((cs = cf_section_find_next(config, cs, "realm", CF_IDENT_ANY))) { if (!realm_add(rc, cs)) { error: realms_free(); @@ -2221,9 +2204,8 @@ int realms_init(CONF_SECTION *config) /* * CoA pools aren't necessarily tied to realms. */ - for (cs = cf_subsection_find_next(config, NULL, "home_server_pool"); - cs != NULL; - cs = cf_subsection_find_next(config, cs, "home_server_pool")) { + cs = NULL; + while ((cs = cf_section_find_next(config, cs, "home_server_pool", CF_IDENT_ANY))) { int type; /* diff --git a/src/main/threads.c b/src/main/threads.c index 00a71701d67..e542d020397 100644 --- a/src/main/threads.c +++ b/src/main/threads.c @@ -762,7 +762,7 @@ int thread_pool_bootstrap(CONF_SECTION *cs, bool *spawn_workers) memset(&thread_pool, 0, sizeof(THREAD_POOL)); thread_pool.spawn_workers = *spawn_workers; - pool_cf = cf_subsection_find_next(cs, NULL, "thread"); + pool_cf = cf_section_find(cs, "thread", NULL); #ifdef WITH_GCD if (pool_cf) { WARN("Built with Grand Central Dispatch. Ignoring 'thread' subsection"); diff --git a/src/main/tls/conf.c b/src/main/tls/conf.c index add17fe55ab..7ed2649317c 100644 --- a/src/main/tls/conf.c +++ b/src/main/tls/conf.c @@ -311,7 +311,7 @@ fr_tls_conf_t *tls_conf_parse_server(CONF_SECTION *cs) * If cs has already been parsed there should be a cached copy * of conf already stored, so just return that. */ - conf = cf_data_find(cs, fr_tls_conf_t, NULL); + conf = cf_data_value(cf_data_find(cs, fr_tls_conf_t, NULL)); if (conf) { DEBUG("Using cached TLS configuration from previous invocation"); return conf; @@ -387,19 +387,19 @@ fr_tls_conf_t *tls_conf_parse_server(CONF_SECTION *cs) } if (conf->session_cache_server && - !cf_subsection_find_name2(main_config.config, "server", conf->session_cache_server)) { + !cf_section_find(main_config.config, "server", conf->session_cache_server)) { ERROR("No such virtual server '%s'", conf->session_cache_server); goto error; } if (conf->ocsp.cache_server && - !cf_subsection_find_name2(main_config.config, "server", conf->ocsp.cache_server)) { + !cf_section_find(main_config.config, "server", conf->ocsp.cache_server)) { ERROR("No such virtual server '%s'", conf->ocsp.cache_server); goto error; } if (conf->staple.cache_server && - !cf_subsection_find_name2(main_config.config, "server", conf->staple.cache_server)) { + !cf_section_find(main_config.config, "server", conf->staple.cache_server)) { ERROR("No such virtual server '%s'", conf->staple.cache_server); goto error; } @@ -428,7 +428,7 @@ fr_tls_conf_t *tls_conf_parse_client(CONF_SECTION *cs) fr_tls_conf_t *conf; uint32_t i; - conf = cf_data_find(cs, fr_tls_conf_t, NULL); + conf = cf_data_value(cf_data_find(cs, fr_tls_conf_t, NULL)); if (conf) { DEBUG2("Using cached TLS configuration from previous invocation"); return conf; diff --git a/src/main/trigger.c b/src/main/trigger.c index 5ccd8d44c6f..7b4918f3393 100644 --- a/src/main/trigger.c +++ b/src/main/trigger.c @@ -123,7 +123,7 @@ static int _trigger_last_fired_cmp(void const *a, void const *b) void trigger_exec_init(CONF_SECTION const *cs) { trigger_exec_main = cs; - trigger_exec_subcs = cf_subsection_find(cs, "trigger"); + trigger_exec_subcs = cf_section_find(cs, "trigger", NULL); MEM(trigger_last_fired_tree = rbtree_create(talloc_null_ctx(), _trigger_last_fired_cmp, _trigger_last_fired_free, 0)); @@ -196,7 +196,7 @@ int trigger_exec(REQUEST *request, CONF_SECTION const *cs, char const *name, boo * try using the global "trigger" section, and reset the * reference to the full path, rather than the sub-path. */ - subcs = cf_subsection_find(cs, "trigger"); + subcs = cf_section_find(cs, "trigger", NULL); if (!subcs && trigger_exec_main && (cs != trigger_exec_main)) { subcs = trigger_exec_subcs; attr = name; diff --git a/src/main/unit_test_map.c b/src/main/unit_test_map.c index bd405ab19e8..cdebcfe5d11 100644 --- a/src/main/unit_test_map.c +++ b/src/main/unit_test_map.c @@ -91,7 +91,7 @@ static int process_file(char const *filename) /* * Always has to be an "update" section. */ - cs = cf_subsection_find(main_config.config, "update"); + cs = cf_section_find(main_config.config, "update", CF_IDENT_ANY); if (!cs) { talloc_free(main_config.config); return -1; @@ -103,7 +103,7 @@ static int process_file(char const *filename) rcode = map_afrom_cs(&head, cs, PAIR_LIST_REQUEST, PAIR_LIST_REQUEST, unlang_fixup_update, NULL, 128); if (rcode < 0) return -1; /* message already printed */ if (!head) { - cf_log_err_cs(cs, "'update' sections cannot be empty"); + cf_log_err(cs, "'update' sections cannot be empty"); return -1; } diff --git a/src/main/unit_test_module.c b/src/main/unit_test_module.c index 4416110c7f6..5bd98d7f44a 100644 --- a/src/main/unit_test_module.c +++ b/src/main/unit_test_module.c @@ -444,15 +444,15 @@ static ssize_t xlat_poke(TALLOC_CTX *ctx, char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, REQUEST *request, char const *fmt) { - int i; - void *data, *base; - char *p, *q; - module_instance_t *instance; - char *buffer; - CONF_SECTION *modules; - CONF_PAIR *cp; - CONF_PARSER const *variables; - size_t len; + int i; + void *data, *base; + char *p, *q; + module_instance_t *instance; + char *buffer; + CONF_SECTION *modules; + CONF_PAIR *cp; + CONF_PARSER const *variables; + size_t len; rad_assert(outlen > 1); rad_assert(request != NULL); @@ -460,7 +460,7 @@ static ssize_t xlat_poke(TALLOC_CTX *ctx, char **out, size_t outlen, rad_assert(out != NULL); rad_assert(*out); - modules = cf_subsection_find(request->root->config, "modules"); + modules = cf_section_find(request->root->config, "modules", NULL); if (!modules) return 0; buffer = talloc_strdup(request, fmt); @@ -516,7 +516,8 @@ static ssize_t xlat_poke(TALLOC_CTX *ctx, char **out, size_t outlen, * Handle the known configuration parameters. */ for (i = 0; variables[i].name != NULL; i++) { - int ret; + int ret; + char const *quote; if (FR_BASE_TYPE(variables[i].type) == FR_TYPE_SUBSECTION) continue; /* else it's a CONF_PAIR */ @@ -544,6 +545,11 @@ static ssize_t xlat_poke(TALLOC_CTX *ctx, char **out, size_t outlen, DEBUG2("Failed inserting new value into module instance data"); goto fail; } + + quote = fr_int2str(fr_token_quotes_table, variables[i].quote, ""); + + DEBUG2("Setting config item to %s = %s%s%s", variables[i].name, quote, q, quote); + break; /* we found it, don't do any more */ } @@ -664,7 +670,7 @@ static int map_proc_verify(CONF_SECTION *cs, UNUSED void *mod_inst, UNUSED void vp_tmpl_t const *src, UNUSED vp_map_t const *maps) { if (!src) { - cf_log_err_cs(cs, "Missing source"); + cf_log_err(cs, "Missing source"); return -1; } diff --git a/src/main/unlang_compile.c b/src/main/unlang_compile.c index eeb4fcc299e..7944de240fc 100644 --- a/src/main/unlang_compile.c +++ b/src/main/unlang_compile.c @@ -498,13 +498,13 @@ static bool pass2_fixup_xlat(CONF_ITEM const *ci, vp_tmpl_t **pvpt, bool convert CONF_PAIR *cp = cf_item_to_pair(ci); WARN("%s[%d]: Please change \"%%{%s}\" to &%s", - cf_pair_filename(cp), cf_pair_lineno(cp), + cf_filename(cp), cf_lineno(cp), attr->name, attr->name); } else { CONF_SECTION *cs = cf_item_to_section(ci); WARN("%s[%d]: Please change \"%%{%s}\" to &%s", - cf_section_filename(cs), cf_section_lineno(cs), + cf_filename(cs), cf_lineno(cs), attr->name, attr->name); } TALLOC_FREE(*pvpt); @@ -747,8 +747,8 @@ static bool pass2_cond_callback(void *ctx, fr_cond_t *c) c->negate = !c->negate; WARN("%s[%d]: Please change (\"%%{%s}\" %s '') to %c&%s", - cf_section_filename(cf_item_to_section(c->ci)), - cf_section_lineno(cf_item_to_section(c->ci)), + cf_filename(cf_item_to_section(c->ci)), + cf_lineno(cf_item_to_section(c->ci)), vpt->name, c->negate ? "==" : "!=", c->negate ? '!' : ' ', vpt->name); @@ -1068,13 +1068,13 @@ static int modcall_fixup_map(vp_map_t *map, UNUSED void *ctx) if (DEBUG_ENABLED3) { if ((map->lhs->type == TMPL_TYPE_ATTR) && (map->lhs->name[0] != '&')) { WARN("%s[%d]: Please change attribute reference to '&%s %s ...'", - cf_pair_filename(cp), cf_pair_lineno(cp), + cf_filename(cp), cf_lineno(cp), map->lhs->name, fr_int2str(fr_tokens_table, map->op, "")); } if ((map->rhs->type == TMPL_TYPE_ATTR) && (map->rhs->name[0] != '&')) { WARN("%s[%d]: Please change attribute reference to '... %s &%s'", - cf_pair_filename(cp), cf_pair_lineno(cp), + cf_filename(cp), cf_lineno(cp), fr_int2str(fr_tokens_table, map->op, ""), map->rhs->name); } } @@ -1134,13 +1134,13 @@ int unlang_fixup_update(vp_map_t *map, UNUSED void *ctx) if (DEBUG_ENABLED3) { if ((map->lhs->type == TMPL_TYPE_ATTR) && (map->lhs->name[0] != '&')) { WARN("%s[%d]: Please change attribute reference to '&%s %s ...'", - cf_pair_filename(cp), cf_pair_lineno(cp), + cf_filename(cp), cf_lineno(cp), map->lhs->name, fr_int2str(fr_tokens_table, map->op, "")); } if ((map->rhs->type == TMPL_TYPE_ATTR) && (map->rhs->name[0] != '&')) { WARN("%s[%d]: Please change attribute reference to '... %s &%s'", - cf_pair_filename(cp), cf_pair_lineno(cp), + cf_filename(cp), cf_lineno(cp), fr_int2str(fr_tokens_table, map->op, ""), map->rhs->name); } } @@ -1153,7 +1153,7 @@ int unlang_fixup_update(vp_map_t *map, UNUSED void *ctx) if (map->op == T_OP_CMP_FALSE) { if ((map->rhs->type != TMPL_TYPE_UNPARSED) || (strcmp(map->rhs->name, "ANY") != 0)) { WARN("%s[%d] Wildcard deletion MUST use '!* ANY'", - cf_pair_filename(cp), cf_pair_lineno(cp)); + cf_filename(cp), cf_lineno(cp)); } TALLOC_FREE(map->rhs); @@ -1222,7 +1222,7 @@ int unlang_fixup_update(vp_map_t *map, UNUSED void *ctx) case T_OP_SET: if (map->rhs->type == TMPL_TYPE_EXEC) { WARN("%s[%d]: Please change ':=' to '=' for list assignment", - cf_pair_filename(cp), cf_pair_lineno(cp)); + cf_filename(cp), cf_lineno(cp)); } if (map->rhs->type != TMPL_TYPE_LIST) { @@ -1349,7 +1349,7 @@ static int compile_map_name(unlang_group_t *g) size_t quoted_len; char *quoted_str; - switch (cf_section_argv_type(g->cs, 0)) { + switch (cf_section_argv_quote(g->cs, 0)) { case T_DOUBLE_QUOTED_STRING: quote = '"'; break; @@ -1403,15 +1403,15 @@ static unlang_t *compile_map(unlang_t *parent, unlang_compile_t *unlang_ctx, char const *name2 = cf_section_name2(cs); - modules = cf_subsection_find(main_config.config, "modules"); + modules = cf_section_find(main_config.config, "modules", NULL); if (!modules) { - cf_log_err_cs(cs, "'map' sections require a 'modules' section"); + cf_log_err(cs, "'map' sections require a 'modules' section"); return NULL; } proc = map_proc_find(name2); if (!proc) { - cf_log_err_cs(cs, "Failed to find map processor '%s'", name2); + cf_log_err(cs, "Failed to find map processor '%s'", name2); return NULL; } @@ -1424,7 +1424,7 @@ static unlang_t *compile_map(unlang_t *parent, unlang_compile_t *unlang_ctx, if (tmpl_str) { FR_TOKEN type; - type = cf_section_argv_type(cs, 0); + type = cf_section_argv_quote(cs, 0); /* * Try to parse the template. @@ -1432,7 +1432,7 @@ static unlang_t *compile_map(unlang_t *parent, unlang_compile_t *unlang_ctx, slen = tmpl_afrom_str(cs, &vpt, tmpl_str, talloc_array_length(tmpl_str) - 1, type, REQUEST_CURRENT, PAIR_LIST_REQUEST, true); if (slen < 0) { - cf_log_err_cs(cs, "Failed parsing map: %s", fr_strerror()); + cf_log_err(cs, "Failed parsing map: %s", fr_strerror()); return NULL; } @@ -1449,7 +1449,7 @@ static unlang_t *compile_map(unlang_t *parent, unlang_compile_t *unlang_ctx, default: talloc_free(vpt); - cf_log_err_cs(cs, "Invalid third argument for map"); + cf_log_err(cs, "Invalid third argument for map"); return NULL; } } @@ -1460,7 +1460,7 @@ static unlang_t *compile_map(unlang_t *parent, unlang_compile_t *unlang_ctx, rcode = map_afrom_cs(&head, cs, PAIR_LIST_REQUEST, PAIR_LIST_REQUEST, modcall_fixup_map, NULL, 256); if (rcode < 0) return NULL; /* message already printed */ if (!head) { - cf_log_err_cs(cs, "'map' sections cannot be empty"); + cf_log_err(cs, "'map' sections cannot be empty"); return NULL; } @@ -1474,7 +1474,7 @@ static unlang_t *compile_map(unlang_t *parent, unlang_compile_t *unlang_ctx, proc_inst = map_proc_instantiate(g, proc, cs, vpt, head); if (!proc_inst) { talloc_free(g); - cf_log_err_cs(cs, "Failed instantiating map function '%s'", name2); + cf_log_err(cs, "Failed instantiating map function '%s'", name2); return NULL; } c = unlang_group_to_generic(g); @@ -1519,7 +1519,7 @@ static unlang_t *compile_update(unlang_t *parent, unlang_compile_t *unlang_ctx, rcode = map_afrom_cs(&head, cs, PAIR_LIST_REQUEST, PAIR_LIST_REQUEST, unlang_fixup_update, NULL, 128); if (rcode < 0) return NULL; /* message already printed */ if (!head) { - cf_log_err_cs(cs, "'update' sections cannot be empty"); + cf_log_err(cs, "'update' sections cannot be empty"); return NULL; } @@ -1577,12 +1577,12 @@ static int compile_action_pair(unlang_t *c, CONF_PAIR *cp) action = atoi(value); if (!action || (action > MOD_PRIORITY_MAX)) { - cf_log_err_cp(cp, "Priorities MUST be between 1 and 64."); + cf_log_err(cp, "Priorities MUST be between 1 and 64."); return 0; } } else { - cf_log_err_cp(cp, "Unknown action '%s'.\n", + cf_log_err(cp, "Unknown action '%s'.\n", value); return 0; } @@ -1592,7 +1592,7 @@ static int compile_action_pair(unlang_t *c, CONF_PAIR *cp) rcode = fr_str2int(mod_rcode_table, attr, -1); if (rcode < 0) { - cf_log_err_cp(cp, + cf_log_err(cp, "Unknown module rcode '%s'.", attr); return 0; @@ -1621,9 +1621,9 @@ static bool compile_action_section(unlang_t *c, CONF_ITEM *ci) * Over-ride the default return codes of the module. */ cs = cf_item_to_section(ci); - for (csi=cf_item_find_next(cs, NULL); + for (csi=cf_item_next(cs, NULL); csi != NULL; - csi=cf_item_find_next(cs, csi)) { + csi=cf_item_next(cs, csi)) { if (cf_item_is_section(csi)) { cf_log_err(csi, "Invalid subsection. Expected 'action = value'"); @@ -1709,7 +1709,7 @@ static bool compile_action_subsection(unlang_t *c, CONF_SECTION *cs, CONF_SECTIO ci = cf_section_to_item(subcs); - next = cf_item_find_next(cs, ci); + next = cf_item_next(cs, ci); if (next && (cf_item_is_pair(next) || cf_item_is_section(next))) { cf_log_err(ci, "'actions' MUST be the last block in a section"); return false; @@ -1735,9 +1735,9 @@ static bool compile_action_subsection(unlang_t *c, CONF_SECTION *cs, CONF_SECTIO static unlang_t *compile_children(unlang_group_t *g, UNUSED unlang_t *parent, unlang_compile_t *unlang_ctx, - unlang_group_type_t group_type, unlang_group_type_t parentgroup_type) + unlang_group_type_t group_type, unlang_group_type_t parentgroup_type) { - CONF_ITEM *ci; + CONF_ITEM *ci = NULL; unlang_t *c; c = unlang_group_to_generic(g); @@ -1745,10 +1745,7 @@ static unlang_t *compile_children(unlang_group_t *g, UNUSED unlang_t *parent, un /* * Loop over the children of this group. */ - for (ci = cf_item_find_next(g->cs, NULL); - ci != NULL; - ci = cf_item_find_next(g->cs, ci)) { - + while ((ci = cf_item_next(g->cs, ci))) { /* * Sections are references to other groups, or * to modules with updated return codes. @@ -1782,17 +1779,12 @@ static unlang_t *compile_children(unlang_group_t *g, UNUSED unlang_t *parent, un */ single = compile_item(c, unlang_ctx, ci, group_type, &name1); if (!single) { - cf_log_err(ci, "Failed to parse \"%s\" subsection.", - cf_section_name1(subcs)); + cf_log_err(ci, "Failed to parse \"%s\" subsection", cf_section_name1(subcs)); talloc_free(c); return NULL; } add_child(g, single); - - } else if (!cf_item_is_pair(ci)) { /* CONF_DATA */ - continue; - - } else { + } else if (cf_item_is_pair(ci)) { char const *attr, *value; CONF_PAIR *cp = cf_item_to_pair(ci); @@ -1816,7 +1808,7 @@ static unlang_t *compile_children(unlang_group_t *g, UNUSED unlang_t *parent, un name = cf_pair_attr(cp); if (name[0] == '-') { WARN("%s[%d]: Ignoring \"%s\" (see raddb/mods-available/README.rst)", - cf_pair_filename(cp), cf_pair_lineno(cp), name + 1); + cf_filename(cp), cf_lineno(cp), name + 1); continue; } @@ -1835,6 +1827,10 @@ static unlang_t *compile_children(unlang_group_t *g, UNUSED unlang_t *parent, un talloc_free(c); return NULL; } /* else it worked */ + } else if (cf_item_is_data(ci)) { + continue; + } else { + rad_assert(0); } } @@ -1881,7 +1877,7 @@ static unlang_t *compile_switch(unlang_t *parent, unlang_compile_t *unlang_ctx, name2 = cf_section_name2(cs); if (!name2) { - cf_log_err_cs(cs, "You must specify a variable to switch over for 'switch'"); + cf_log_err(cs, "You must specify a variable to switch over for 'switch'"); return NULL; } @@ -1892,16 +1888,16 @@ static unlang_t *compile_switch(unlang_t *parent, unlang_compile_t *unlang_ctx, * Create the template. All attributes and xlats are * defined by now. */ - type = cf_section_name2_type(cs); + type = cf_section_name2_quote(cs); slen = tmpl_afrom_str(g, &g->vpt, name2, strlen(name2), type, REQUEST_CURRENT, PAIR_LIST_REQUEST, true); if (slen < 0) { char *spaces, *text; fr_canonicalize_error(cs, &spaces, &text, slen, fr_strerror()); - cf_log_err_cs(cs, "Syntax error"); - cf_log_err_cs(cs, "%s", name2); - cf_log_err_cs(cs, "%s^ %s", spaces, text); + cf_log_err(cs, "Syntax error"); + cf_log_err(cs, "%s", name2); + cf_log_err(cs, "%s^ %s", spaces, text); talloc_free(g); talloc_free(spaces); @@ -1914,9 +1910,9 @@ static unlang_t *compile_switch(unlang_t *parent, unlang_compile_t *unlang_ctx, * Walk through the children of the switch section, * ensuring that they're all 'case' statements */ - for (ci = cf_item_find_next(cs, NULL); + for (ci = cf_item_next(cs, NULL); ci != NULL; - ci = cf_item_find_next(cs, ci)) { + ci = cf_item_next(cs, ci)) { CONF_SECTION *subcs; char const *name1; @@ -1977,7 +1973,7 @@ static unlang_t *compile_case(unlang_t *parent, unlang_compile_t *unlang_ctx, CO vp_tmpl_t *vpt = NULL; if (!parent || (parent->type != UNLANG_TYPE_SWITCH)) { - cf_log_err_cs(cs, "\"case\" statements may only appear within a \"switch\" section"); + cf_log_err(cs, "\"case\" statements may only appear within a \"switch\" section"); return NULL; } @@ -1991,7 +1987,7 @@ static unlang_t *compile_case(unlang_t *parent, unlang_compile_t *unlang_ctx, CO FR_TOKEN type; unlang_group_t *f; - type = cf_section_name2_type(cs); + type = cf_section_name2_quote(cs); slen = tmpl_afrom_str(cs, &vpt, name2, strlen(name2), type, REQUEST_CURRENT, PAIR_LIST_REQUEST, true); if (slen < 0) { @@ -1999,9 +1995,9 @@ static unlang_t *compile_case(unlang_t *parent, unlang_compile_t *unlang_ctx, CO fr_canonicalize_error(cs, &spaces, &text, slen, fr_strerror()); - cf_log_err_cs(cs, "Syntax error"); - cf_log_err_cs(cs, "%s", name2); - cf_log_err_cs(cs, "%s^ %s", spaces, text); + cf_log_err(cs, "Syntax error"); + cf_log_err(cs, "%s", name2); + cf_log_err(cs, "%s^ %s", spaces, text); talloc_free(spaces); talloc_free(text); @@ -2033,7 +2029,7 @@ static unlang_t *compile_case(unlang_t *parent, unlang_compile_t *unlang_ctx, CO rad_assert(f->vpt->tmpl_da != NULL); if (tmpl_cast_in_place(vpt, f->vpt->tmpl_da->type, f->vpt->tmpl_da) < 0) { - cf_log_err_cs(cs, "Invalid argument for case statement: %s", + cf_log_err(cs, "Invalid argument for case statement: %s", fr_strerror()); talloc_free(vpt); return NULL; @@ -2105,7 +2101,7 @@ static unlang_t *compile_foreach(unlang_t *parent, unlang_compile_t *unlang_ctx, name2 = cf_section_name2(cs); if (!name2) { - cf_log_err_cs(cs, + cf_log_err(cs, "You must specify an attribute to loop over in 'foreach'"); return NULL; } @@ -2116,16 +2112,16 @@ static unlang_t *compile_foreach(unlang_t *parent, unlang_compile_t *unlang_ctx, * module. Allow it for now. The pass2 checks below * will fix it up. */ - type = cf_section_name2_type(cs); + type = cf_section_name2_quote(cs); slen = tmpl_afrom_str(cs, &vpt, name2, strlen(name2), type, REQUEST_CURRENT, PAIR_LIST_REQUEST, true); if ((slen < 0) && ((type != T_BARE_WORD) || (name2[0] != '&'))) { char *spaces, *text; fr_canonicalize_error(cs, &spaces, &text, slen, fr_strerror()); - cf_log_err_cs(cs, "Syntax error"); - cf_log_err_cs(cs, "%s", name2); - cf_log_err_cs(cs, "%s^ %s", spaces, text); + cf_log_err(cs, "Syntax error"); + cf_log_err(cs, "%s", name2); + cf_log_err(cs, "%s^ %s", spaces, text); talloc_free(spaces); talloc_free(text); @@ -2140,13 +2136,13 @@ static unlang_t *compile_foreach(unlang_t *parent, unlang_compile_t *unlang_ctx, rad_assert(vpt); if ((vpt->type != TMPL_TYPE_ATTR) && (vpt->type != TMPL_TYPE_LIST)) { - cf_log_err_cs(cs, "MUST use attribute or list reference in 'foreach'"); + cf_log_err(cs, "MUST use attribute or list reference in 'foreach'"); talloc_free(vpt); return NULL; } if ((vpt->tmpl_num != NUM_ALL) && (vpt->tmpl_num != NUM_ANY)) { - cf_log_err_cs(cs, "MUST NOT use instance selectors in 'foreach'"); + cf_log_err(cs, "MUST NOT use instance selectors in 'foreach'"); talloc_free(vpt); return NULL; } @@ -2231,17 +2227,17 @@ static unlang_t *compile_if(unlang_t *parent, unlang_compile_t *unlang_ctx, CONF fr_cond_t *cond; if (!cf_section_name2(cs)) { - cf_log_err_cs(cs, "'%s' without condition", unlang_ops[mod_type].name); + cf_log_err(cs, "'%s' without condition", unlang_ops[mod_type].name); return NULL; } - cond = cf_data_find(cs, fr_cond_t, NULL); + cond = cf_data_value(cf_data_find(cs, fr_cond_t, NULL)); rad_assert(cond != NULL); if (cond->type == COND_TYPE_FALSE) { INFO(" # Skipping contents of '%s' as it is always 'false' -- %s:%d", unlang_ops[mod_type].name, - cf_section_filename(cs), cf_section_lineno(cs)); + cf_filename(cs), cf_lineno(cs)); return compile_empty(parent, unlang_ctx, cs, group_type, parentgroup_type, mod_type, COND_TYPE_FALSE); } @@ -2277,7 +2273,7 @@ static int previous_if(CONF_SECTION *cs, unlang_t *parent, unlang_type_t mod_typ f = unlang_generic_to_group(p->tail); if ((f->self.type != UNLANG_TYPE_IF) && (f->self.type != UNLANG_TYPE_ELSIF)) { else_fail: - cf_log_err_cs(cs, "Invalid location for '%s'. There is no preceding 'if' or 'elsif' statement", + cf_log_err(cs, "Invalid location for '%s'. There is no preceding 'if' or 'elsif' statement", unlang_ops[mod_type].name); return -1; } @@ -2286,7 +2282,7 @@ static int previous_if(CONF_SECTION *cs, unlang_t *parent, unlang_type_t mod_typ INFO(" # Skipping contents of '%s' as previous '%s' is always 'true' -- %s:%d", unlang_ops[mod_type].name, unlang_ops[f->self.type].name, - cf_section_filename(cs), cf_section_lineno(cs)); + cf_filename(cs), cf_lineno(cs)); return 0; } @@ -2302,7 +2298,7 @@ static unlang_t *compile_elsif(unlang_t *parent, unlang_compile_t *unlang_ctx, C * This is always a syntax error. */ if (!cf_section_name2(cs)) { - cf_log_err_cs(cs, "'%s' without condition", unlang_ops[mod_type].name); + cf_log_err(cs, "'%s' without condition", unlang_ops[mod_type].name); return NULL; } @@ -2322,7 +2318,7 @@ static unlang_t *compile_else(unlang_t *parent, unlang_t *c; if (cf_section_name2(cs)) { - cf_log_err_cs(cs, "'%s' cannot have a condition", unlang_ops[mod_type].name); + cf_log_err(cs, "'%s' cannot have a condition", unlang_ops[mod_type].name); return NULL; } @@ -2350,9 +2346,9 @@ static int all_children_are_modules(CONF_SECTION *cs, char const *name) { CONF_ITEM *ci; - for (ci=cf_item_find_next(cs, NULL); + for (ci=cf_item_next(cs, NULL); ci != NULL; - ci=cf_item_find_next(cs, ci)) { + ci=cf_item_next(cs, ci)) { /* * If we're a redundant, etc. group, then the * intention is to call modules, rather than @@ -2400,8 +2396,8 @@ static unlang_t *compile_redundant(unlang_t *parent, unlang_compile_t *unlang_ct /* * No children? Die! */ - if (!cf_item_find_next(cs, NULL)) { - cf_log_err_cs(cs, "%s sections cannot be empty", unlang_ops[mod_type].name); + if (!cf_item_next(cs, NULL)) { + cf_log_err(cs, "%s sections cannot be empty", unlang_ops[mod_type].name); return NULL; } @@ -2425,8 +2421,8 @@ static unlang_t *compile_redundant(unlang_t *parent, unlang_compile_t *unlang_ct * For backwards compatibility. */ if (name2 && - (strcmp(cf_section_name1(cf_section_parent(cs)), "instantiate") != 0)) { - cf_log_err_cs(cs, "%s sections cannot have a name", unlang_ops[mod_type].name); + (strcmp(cf_section_name1(cf_item_to_section(cf_parent(cs))), "instantiate") != 0)) { + cf_log_err(cs, "%s sections cannot have a name", unlang_ops[mod_type].name); return NULL; } @@ -2446,8 +2442,8 @@ static unlang_t *compile_load_balance(unlang_t *parent, unlang_compile_t *unlang /* * No children? Die! */ - if (!cf_item_find_next(cs, NULL)) { - cf_log_err_cs(cs, "%s sections cannot be empty", unlang_ops[mod_type].name); + if (!cf_item_next(cs, NULL)) { + cf_log_err(cs, "%s sections cannot be empty", unlang_ops[mod_type].name); return NULL; } @@ -2469,7 +2465,7 @@ static unlang_t *compile_load_balance(unlang_t *parent, unlang_compile_t *unlang * Inside of the "instantiate" section, the name is a name, not a key. */ if (name2) { - if (strcmp(cf_section_name1(cf_section_parent(cs)), "instantiate") == 0) name2 = NULL; + if (strcmp(cf_section_name1(cf_item_to_section(cf_parent(cs))), "instantiate") == 0) name2 = NULL; } if (name2) { @@ -2480,16 +2476,16 @@ static unlang_t *compile_load_balance(unlang_t *parent, unlang_compile_t *unlang * Create the template. All attributes and xlats are * defined by now. */ - type = cf_section_name2_type(cs); + type = cf_section_name2_quote(cs); slen = tmpl_afrom_str(g, &g->vpt, name2, strlen(name2), type, REQUEST_CURRENT, PAIR_LIST_REQUEST, true); if (slen < 0) { char *spaces, *text; fr_canonicalize_error(cs, &spaces, &text, slen, fr_strerror()); - cf_log_err_cs(cs, "Syntax error"); - cf_log_err_cs(cs, "%s", name2); - cf_log_err_cs(cs, "%s^ %s", spaces, text); + cf_log_err(cs, "Syntax error"); + cf_log_err(cs, "%s", name2); + cf_log_err(cs, "%s^ %s", spaces, text); talloc_free(g); talloc_free(spaces); @@ -2511,7 +2507,7 @@ static unlang_t *compile_load_balance(unlang_t *parent, unlang_compile_t *unlang switch (g->vpt->type) { default: - cf_log_err_cs(cs, "Invalid type in '%s': data will not result in a load-balance key", name2); + cf_log_err(cs, "Invalid type in '%s': data will not result in a load-balance key", name2); talloc_free(g); return NULL; @@ -2541,13 +2537,13 @@ static unlang_t *compile_parallel(unlang_t *parent, unlang_compile_t *unlang_ctx /* * No children? Die! */ - if (!cf_item_find_next(cs, NULL)) { - cf_log_err_cs(cs, "%s sections cannot be empty", unlang_ops[mod_type].name); + if (!cf_item_next(cs, NULL)) { + cf_log_err(cs, "%s sections cannot be empty", unlang_ops[mod_type].name); return NULL; } if (cf_section_name2(cs) != NULL) { - cf_log_err_cs(cs, "%s sections cannot have an argument", unlang_ops[mod_type].name); + cf_log_err(cs, "%s sections cannot have an argument", unlang_ops[mod_type].name); return NULL; } @@ -2603,12 +2599,12 @@ static CONF_SECTION *virtual_module_find_cs(rlm_components_t *pcomponent, * * Return it to the caller, with the updated method. */ - cs = cf_subsection_find(main_config.config, "instantiate"); + cs = cf_section_find(main_config.config, "instantiate", NULL); if (cs) { /* * Found "foo". Load it as "foo", or "foo.method". */ - subcs = cf_subsection_find_name2(cs, NULL, virtual_name); + subcs = cf_section_find(cs, CF_IDENT_ANY, virtual_name); if (subcs) { *pcomponent = method; return subcs; @@ -2620,7 +2616,7 @@ static CONF_SECTION *virtual_module_find_cs(rlm_components_t *pcomponent, * * If there's no policy section, we can't do anything else. */ - cs = cf_subsection_find(main_config.config, "policy"); + cs = cf_section_find(main_config.config, "policy", NULL); if (!cs) return NULL; /* @@ -2629,7 +2625,7 @@ static CONF_SECTION *virtual_module_find_cs(rlm_components_t *pcomponent, * And bail out if there's no policy "foo". */ if (method_name) { - subcs = cf_subsection_find_name2(cs, NULL, virtual_name); + subcs = cf_section_find(cs, virtual_name, NULL); if (subcs) *pcomponent = method; return subcs; @@ -2641,12 +2637,11 @@ static CONF_SECTION *virtual_module_find_cs(rlm_components_t *pcomponent, * a policy "foo". * */ - snprintf(buffer, sizeof(buffer), "%s.%s", - virtual_name, comp2str[method]); - subcs = cf_subsection_find_name2(cs, NULL, buffer); + snprintf(buffer, sizeof(buffer), "%s.%s", virtual_name, comp2str[method]); + subcs = cf_section_find(cs, buffer, NULL); if (subcs) return subcs; - return cf_subsection_find_name2(cs, NULL, virtual_name); + return cf_section_find(cs, virtual_name, NULL); } @@ -2737,16 +2732,16 @@ static modcall_compile_t compile_table[] = { * Compile one entry of a module call. */ static unlang_t *compile_item(unlang_t *parent, unlang_compile_t *unlang_ctx, CONF_ITEM *ci, - unlang_group_type_t parent_group_type, char const **modname) + unlang_group_type_t parent_group_type, char const **modname) { - char const *modrefname, *p; - unlang_t *c; - module_instance_t *this; - CONF_SECTION *cs, *subcs, *modules; - CONF_ITEM *loop; - char const *realname; - rlm_components_t component = unlang_ctx->component; - unlang_compile_t unlang_ctx2; + char const *modrefname, *p; + unlang_t *c; + module_instance_t *this; + CONF_SECTION *cs, *subcs, *modules; + CONF_ITEM *loop; + char const *realname; + rlm_components_t component = unlang_ctx->component; + unlang_compile_t unlang_ctx2; if (cf_item_is_section(ci)) { int i; @@ -2765,7 +2760,7 @@ static unlang_t *compile_item(unlang_t *parent, unlang_compile_t *unlang_ctx, CO * Some blocks can be empty. The rest need * to have contents. */ - if (!cf_item_find_next(cs, NULL) && + if (!cf_item_next(cs, NULL) && !((compile_table[i].mod_type == UNLANG_TYPE_CASE) || (compile_table[i].mod_type == UNLANG_TYPE_IF) || (compile_table[i].mod_type == UNLANG_TYPE_ELSIF))) { @@ -2892,9 +2887,9 @@ static unlang_t *compile_item(unlang_t *parent, unlang_compile_t *unlang_ctx, CO * of an "sql" policy. If so, we allow the * second "sql" to refer to the module. */ - for (loop = cf_item_parent(ci); + for (loop = cf_parent(ci); loop && subcs; - loop = cf_item_parent(loop)) { + loop = cf_parent(loop)) { if (loop == cf_section_to_item(subcs)) { subcs = NULL; } @@ -2963,7 +2958,7 @@ static unlang_t *compile_item(unlang_t *parent, unlang_compile_t *unlang_ctx, CO /* * Not a virtual module. It must be a real module. */ - modules = cf_subsection_find(main_config.config, "modules"); + modules = cf_section_find(main_config.config, "modules", NULL); if (!modules) goto fail; this = NULL; diff --git a/src/main/unlang_interpret.c b/src/main/unlang_interpret.c index a8a437e47a6..aa4a76b5ddf 100644 --- a/src/main/unlang_interpret.c +++ b/src/main/unlang_interpret.c @@ -1412,7 +1412,7 @@ void unlang_push_section(REQUEST *request, CONF_SECTION *cs, rlm_rcode_t action) * associated with sections. */ if (cs) { - instruction = (unlang_t *)cf_data_find(cs, unlang_group_t, NULL); + instruction = (unlang_t *)cf_data_value(cf_data_find(cs, unlang_group_t, NULL)); if (!instruction) { RPEDEBUG("Failed to find pre-compiled unlang for section %s %s { ... }", cf_section_name1(cs), cf_section_name2(cs)); diff --git a/src/main/version.c b/src/main/version.c index c42b2686c17..f8ea703cdb1 100644 --- a/src/main/version.c +++ b/src/main/version.c @@ -530,16 +530,16 @@ void version_print(void) DEBUG2("Server was built with: "); - for (ci = cf_item_find_next(features, NULL); + for (ci = cf_item_next(features, NULL); ci; - ci = cf_item_find_next(features, ci)) { + ci = cf_item_next(features, ci)) { len = talloc_array_length(cf_pair_attr(cf_item_to_pair(ci))); if (max < len) max = len; } - for (ci = cf_item_find_next(versions, NULL); + for (ci = cf_item_next(versions, NULL); ci; - ci = cf_item_find_next(versions, ci)) { + ci = cf_item_next(versions, ci)) { len = talloc_array_length(cf_pair_attr(cf_item_to_pair(ci))); if (max < len) max = len; } @@ -553,9 +553,9 @@ void version_print(void) } #endif - for (ci = cf_item_find_next(features, NULL); + for (ci = cf_item_next(features, NULL); ci; - ci = cf_item_find_next(features, ci)) { + ci = cf_item_next(features, ci)) { char const *attr; cp = cf_item_to_pair(ci); @@ -569,9 +569,9 @@ void version_print(void) DEBUG2("Server core libs:"); - for (ci = cf_item_find_next(versions, NULL); + for (ci = cf_item_next(versions, NULL); ci; - ci = cf_item_find_next(versions, ci)) { + ci = cf_item_next(versions, ci)) { char const *attr; cp = cf_item_to_pair(ci); diff --git a/src/main/virtual_servers.c b/src/main/virtual_servers.c index c7e7614afa4..fda4a27b11d 100644 --- a/src/main/virtual_servers.c +++ b/src/main/virtual_servers.c @@ -44,7 +44,7 @@ static int default_component_results[MOD_COUNT] = { RLM_MODULE_NOOP /* POST_AUTH */ #ifdef WITH_COA , - RLM_MODULE_NOOP, /* RECV_COA_TYPE */ + RLM_MODULE_NOOP, /* RECV_COA_TYPE */ RLM_MODULE_NOOP /* SEND_COA_TYPE */ #endif }; @@ -71,10 +71,10 @@ static rlm_rcode_t module_method_call(rlm_components_t comp, int idx, REQUEST *r */ server_cs = request->server_cs; if (!server_cs || (strcmp(request->server, cf_section_name2(server_cs)) != 0)) { - request->server_cs = cf_subsection_find_name2(main_config.config, "server", request->server); + request->server_cs = cf_section_find(main_config.config, "server", request->server); } - cs = cf_subsection_find(request->server_cs, section_type_value[comp].section); + cs = cf_section_find(request->server_cs, section_type_value[comp].section, NULL); if (!cs) { RDEBUG2("Empty %s section in virtual server \"%s\". Using default return value %s.", section_type_value[comp].section, request->server, @@ -87,7 +87,7 @@ static rlm_rcode_t module_method_call(rlm_components_t comp, int idx, REQUEST *r */ if (!idx) { RDEBUG("Running section %s from file %s", - section_type_value[comp].section, cf_section_filename(cs)); + section_type_value[comp].section, cf_filename(cs)); } else { fr_dict_attr_t const *da; @@ -100,7 +100,7 @@ static rlm_rcode_t module_method_call(rlm_components_t comp, int idx, REQUEST *r dv = fr_dict_enum_by_value(NULL, da, fr_box_uint32((uint32_t)idx)); if (!dv) return RLM_MODULE_FAIL; - subcs = cf_subsection_find_name2(cs, da->name, dv->alias); + subcs = cf_section_find(cs, da->name, dv->alias); if (!subcs) { RDEBUG2("%s %s sub-section not found. Using default return values.", da->name, dv->alias); @@ -108,7 +108,7 @@ static rlm_rcode_t module_method_call(rlm_components_t comp, int idx, REQUEST *r } RDEBUG("Running %s %s from file %s", - da->name, dv->alias, cf_section_filename(subcs)); + da->name, dv->alias, cf_filename(subcs)); cs = subcs; } @@ -236,7 +236,7 @@ rlm_rcode_t process_send_coa(int send_coa_type, REQUEST *request) } #endif -static bool define_type(CONF_SECTION *cs, fr_dict_attr_t const *da, char const *name) +static int define_type(CONF_SECTION *cs, fr_dict_attr_t const *da, char const *name) { fr_value_box_t value = { .type = FR_TYPE_UINT32 }; fr_dict_enum_t *dval; @@ -248,11 +248,10 @@ static bool define_type(CONF_SECTION *cs, fr_dict_attr_t const *da, char const * dval = fr_dict_enum_by_alias(NULL, da, name); if (dval) { if (dval->value == 0) { - ERROR("The dictionaries must not define VALUE %s %s 0", - da->name, name); - return false; + ERROR("The dictionaries must not define VALUE %s %s 0", da->name, name); + return -1; } - return true; + return 0; } /* @@ -266,13 +265,13 @@ static bool define_type(CONF_SECTION *cs, fr_dict_attr_t const *da, char const * value.vb_uint32 = (fr_rand() & 0x00ffffff) + 1; } while (fr_dict_enum_by_value(NULL, da, &value)); - cf_log_module(cs, "Creating %s = %s", da->name, name); + cf_log_debug(cs, "Creating %s = %s", da->name, name); if (fr_dict_enum_add_alias(da, name, &value, true, false) < 0) { ERROR("%s", fr_strerror()); - return false; + return -1; } - return true; + return 0; } /* @@ -298,25 +297,23 @@ static bool load_subcomponent_section(CONF_SECTION *cs, */ dval = fr_dict_enum_by_alias(NULL, da, name2); if (!dval) { - cf_log_err_cs(cs, - "The %s attribute has no VALUE defined for %s", - section_type_value[comp].typename, name2); + cf_log_err(cs, + "The %s attribute has no VALUE defined for %s", + section_type_value[comp].typename, name2); return false; } /* * Compile the group. */ - if (unlang_compile(cs, comp) < 0) { - return false; - } + if (unlang_compile(cs, comp) < 0) return false; return true; } static int load_component_section(CONF_SECTION *cs, rlm_components_t comp) { - CONF_SECTION *subcs; + CONF_SECTION *subcs = NULL; fr_dict_attr_t const *da; /* @@ -324,9 +321,9 @@ static int load_component_section(CONF_SECTION *cs, rlm_components_t comp) */ da = fr_dict_attr_by_num(NULL, 0, section_type_value[comp].attr); if (!da) { - cf_log_err_cs(cs, - "No such attribute %s", - section_type_value[comp].typename); + cf_log_err(cs, + "No such attribute %s", + section_type_value[comp].typename); return -1; } @@ -336,9 +333,7 @@ static int load_component_section(CONF_SECTION *cs, rlm_components_t comp) * The results will be cached, so that the next * compilation will skip these sections. */ - for (subcs = cf_subsection_find_next(cs, NULL, section_type_value[comp].typename); - subcs != NULL; - subcs = cf_subsection_find_next(cs, subcs, section_type_value[comp].typename)) { + while ((subcs = cf_section_find_next(cs, subcs, section_type_value[comp].typename, CF_IDENT_ANY))) { if (!load_subcomponent_section(subcs, da, comp)) { return -1; /* FIXME: memleak? */ } @@ -348,7 +343,7 @@ static int load_component_section(CONF_SECTION *cs, rlm_components_t comp) * Compile the section. */ if (unlang_compile(cs, comp) < 0) { - cf_log_err_cs(cs, "Errors parsing %s section.\n", + cf_log_err(cs, "Errors parsing %s section.\n", cf_section_name1(cs)); return -1; } @@ -364,7 +359,7 @@ static int virtual_servers_compile(CONF_SECTION *cs) CONF_PAIR *cp; cf_log_info(cs, "server %s { # from file %s", - name, cf_section_filename(cs)); + name, cf_filename(cs)); cp = cf_pair_find(cs, "namespace"); if (cp) { @@ -380,8 +375,7 @@ static int virtual_servers_compile(CONF_SECTION *cs) for (comp = 0; comp < MOD_COUNT; ++comp) { CONF_SECTION *subcs; - subcs = cf_subsection_find(cs, - section_type_value[comp].section); + subcs = cf_section_find(cs, section_type_value[comp].section, NULL); if (!subcs) continue; if (cp) { @@ -390,7 +384,7 @@ static int virtual_servers_compile(CONF_SECTION *cs) return -1; } - if (cf_item_find_next(subcs, NULL) == NULL) continue; + if (cf_item_next(subcs, NULL) == NULL) continue; /* * Skip pre/post-proxy sections if we're not @@ -429,14 +423,12 @@ static int virtual_servers_compile(CONF_SECTION *cs) */ if (!found) do { - CONF_SECTION *subcs; + CONF_SECTION *subcs = NULL; /* * Compile the listeners. */ - for (subcs = cf_subsection_find_next(cs, NULL, "listen"); - subcs != NULL; - subcs = cf_subsection_find_next(cs, subcs, "listen")) { + while ((subcs = cf_section_find_next(cs, subcs, "listen", NULL))) { if (listen_compile(cs, subcs) < 0) return -1; } @@ -462,9 +454,9 @@ static bool virtual_server_define_types(CONF_SECTION *cs, rlm_components_t comp) */ da = fr_dict_attr_by_num(NULL, 0, section_type_value[comp].attr); if (!da) { - cf_log_err_cs(cs, - "No such attribute %s", - section_type_value[comp].typename); + cf_log_err(cs, + "No such attribute %s", + section_type_value[comp].typename); return false; } @@ -473,9 +465,9 @@ static bool virtual_server_define_types(CONF_SECTION *cs, rlm_components_t comp) * bare words in them. Fix those up to be sections. */ if (comp == MOD_AUTHENTICATE) { - for (ci = cf_item_find_next(cs, NULL); + for (ci = cf_item_next(cs, NULL); ci != NULL; - ci = cf_item_find_next(cs, ci)) { + ci = cf_item_next(cs, ci)) { CONF_PAIR *cp; if (!cf_item_is_pair(ci)) continue; @@ -492,23 +484,20 @@ static bool virtual_server_define_types(CONF_SECTION *cs, rlm_components_t comp) /* * Define the Autz-Type, etc. based on the subsections. */ - for (subcs = cf_subsection_find_next(cs, NULL, section_type_value[comp].typename); - subcs != NULL; - subcs = cf_subsection_find_next(cs, subcs, section_type_value[comp].typename)) { + subcs = NULL; + while ((subcs = cf_section_find_next(cs, subcs, section_type_value[comp].typename, CF_IDENT_ANY))) { char const *name2; CONF_SECTION *cs2; name2 = cf_section_name2(subcs); - cs2 = cf_subsection_find_name2(cs, section_type_value[comp].typename, name2); + cs2 = cf_section_find(cs, section_type_value[comp].typename, name2); if (cs2 != subcs) { - cf_log_err_cs(cs2, "Duplicate configuration section %s %s", - section_type_value[comp].typename, name2); + cf_log_err(cs2, "Duplicate configuration section %s %s", + section_type_value[comp].typename, name2); return false; } - if (!define_type(cs, da, name2)) { - return false; - } + if (define_type(cs, da, name2) < 0) return false; } return true; @@ -520,10 +509,10 @@ static bool virtual_server_define_types(CONF_SECTION *cs, rlm_components_t comp) */ int virtual_servers_bootstrap(CONF_SECTION *config) { - CONF_SECTION *cs; + CONF_SECTION *cs = NULL; char const *server_name; - if (!cf_subsection_find_next(config, NULL, "server")) { + if (!cf_section_find(config, "server", CF_IDENT_ANY)) { ERROR("No virtual servers found"); return -1; } @@ -531,9 +520,7 @@ int virtual_servers_bootstrap(CONF_SECTION *config) /* * Bootstrap global listeners. */ - for (cs = cf_subsection_find_next(config, NULL, "listen"); - cs != NULL; - cs = cf_subsection_find_next(config, cs, "listen")) { + while ((cs = cf_section_find_next(config, cs, "listen", NULL))) { if (cf_pair_find(cs, "namespace") != NULL) { main_config.namespace = true; continue; @@ -542,30 +529,29 @@ int virtual_servers_bootstrap(CONF_SECTION *config) if (listen_bootstrap(config, cs, NULL) < 0) return -1; } - for (cs = cf_subsection_find_next(config, NULL, "server"); - cs != NULL; - cs = cf_subsection_find_next(config, cs, "server")) { + cs = NULL; + while ((cs = cf_section_find_next(config, cs, "server", CF_IDENT_ANY))) { CONF_ITEM *ci; CONF_SECTION *subcs; CONF_PAIR *cp; server_name = cf_section_name2(cs); if (!server_name) { - cf_log_err_cs(cs, "server sections must have a name"); + cf_log_err(cs, "server sections must have a name"); return -1; } /* * Check for duplicates. */ - subcs = cf_subsection_find_name2(config, "server", server_name); + subcs = cf_section_find(config, "server", server_name); if (subcs && (subcs != cs)) { ERROR("Duplicate virtual server \"%s\", in file %s:%d and file %s:%d", server_name, - cf_section_filename(cs), - cf_section_lineno(cs), - cf_section_filename(subcs), - cf_section_lineno(subcs)); + cf_filename(cs), + cf_lineno(cs), + cf_filename(subcs), + cf_lineno(subcs)); return -1; } @@ -580,30 +566,30 @@ int virtual_servers_bootstrap(CONF_SECTION *config) value = cf_pair_value(cp); if (!value) { - cf_log_err_cs(cs, "Cannot have empty namespace"); + cf_log_err(cs, "Cannot have empty namespace"); return -1; } if (strcmp(value, "radius") != 0) { - cf_log_err_cs(cs, "Unknown namespace '%s'", value); + cf_log_err(cs, "Unknown namespace '%s'", value); return -1; } module = dl_module(cs, NULL, value, DL_TYPE_PROTO); if (!module) { - cf_log_err_cs(cs, "Failed to find library for 'namespace = %s'", value); + cf_log_err(cs, "Failed to find library for 'namespace = %s'", value); return -1; } app = (fr_app_t const *) module->common; if (app->bootstrap && (app->bootstrap(cs) < 0)) { - cf_log_err_cs(cs, "Failed to bootstrap library for 'namespace = %s'", value); + cf_log_err(cs, "Failed to bootstrap library for 'namespace = %s'", value); return -1; } if (!app->instantiate) { - cf_log_err_cs(cs, "Failed to find initialization function for 'transport = %s'", + cf_log_err(cs, "Failed to find initialization function for 'transport = %s'", value); return -1; } @@ -612,9 +598,9 @@ int virtual_servers_bootstrap(CONF_SECTION *config) continue; } - for (ci = cf_item_find_next(cs, NULL); + for (ci = cf_item_next(cs, NULL); ci != NULL; - ci = cf_item_find_next(cs, ci)) { + ci = cf_item_next(cs, ci)) { rlm_components_t comp; char const *name1; @@ -652,16 +638,14 @@ int virtual_servers_bootstrap(CONF_SECTION *config) */ int virtual_servers_init(fr_schedule_t *sc, CONF_SECTION *config) { - CONF_SECTION *cs; + CONF_SECTION *cs = NULL; DEBUG2("%s: #### Loading Virtual Servers ####", main_config.name); /* * Load all of the virtual servers. */ - for (cs = cf_subsection_find_next(config, NULL, "server"); - cs != NULL; - cs = cf_subsection_find_next(config, cs, "server")) { + while ((cs = cf_section_find_next(config, cs, "server", CF_IDENT_ANY))) { char const *name2; name2 = cf_section_name2(cs); @@ -675,7 +659,7 @@ int virtual_servers_init(fr_schedule_t *sc, CONF_SECTION *config) if (!sc) continue; - module = cf_data_find(cs, dl_t, "app"); + module = cf_data_value(cf_data_find(cs, dl_t, "app")); if (!module) continue; app = (fr_app_t const *) module->common; @@ -685,11 +669,11 @@ int virtual_servers_init(fr_schedule_t *sc, CONF_SECTION *config) */ cf_log_info(cs, "server %s { # from file %s", - name2, cf_section_filename(cs)); + name2, cf_filename(cs)); cf_log_info(cs, " namespace = %s", app->name); if (app->instantiate(sc, cs, check_config) < 0) { - cf_log_err_cs(cs, "Failed loading virtual server %s", name2); + cf_log_err(cs, "Failed loading virtual server %s", name2); return -1; } diff --git a/src/main/xlat_func.c b/src/main/xlat_func.c index 69f1a63d569..11dad2ebcf1 100644 --- a/src/main/xlat_func.c +++ b/src/main/xlat_func.c @@ -693,7 +693,7 @@ int xlat_register(void *mod_inst, char const *name, rbnode_t *node; if (!name || !*name) { - DEBUG("xlat_register: Invalid xlat name"); + ERROR("%s: Invalid xlat name", __FUNCTION__); return -1; } @@ -710,7 +710,7 @@ int xlat_register(void *mod_inst, char const *name, xlat_root = rbtree_create(NULL, xlat_cmp, NULL, RBTREE_FLAG_REPLACE); if (!xlat_root) { - DEBUG("xlat_register: Failed to create tree"); + ERROR("%s: Failed to create tree", __FUNCTION__); return -1; } @@ -760,7 +760,7 @@ int xlat_register(void *mod_inst, char const *name, c = rbtree_finddata(xlat_root, &my_xlat); if (c) { if (c->internal) { - DEBUG("xlat_register: Cannot re-define internal xlat"); + ERROR("%s: Cannot re-define internal xlat", __FUNCTION__); return -1; } @@ -786,13 +786,9 @@ int xlat_register(void *mod_inst, char const *name, c->instantiate = instantiate; c->inst_size = inst_size; - DEBUG3("xlat_register: %s", c->name); + DEBUG3("%s: %s", c->name, __FUNCTION__); - node = rbtree_insert_node(xlat_root, c); - if (!node) { - talloc_free(c); - return -1; - } + MEM(node = rbtree_insert_node(xlat_root, c)); return 0; } @@ -872,9 +868,9 @@ static ssize_t xlat_redundant(TALLOC_CTX *ctx, char **out, NDEBUG_UNUSED size_t /* * Pick the first xlat which succeeds */ - for (ci = cf_item_find_next(xr->cs, NULL); + for (ci = cf_item_next(xr->cs, NULL); ci != NULL; - ci = cf_item_find_next(xr->cs, ci)) { + ci = cf_item_next(xr->cs, ci)) { ssize_t rcode; if (!cf_item_is_pair(ci)) continue; @@ -924,9 +920,9 @@ static ssize_t xlat_load_balance(TALLOC_CTX *ctx, char **out, NDEBUG_UNUSED size /* * Choose a child at random. */ - for (ci = cf_item_find_next(xr->cs, NULL); + for (ci = cf_item_next(xr->cs, NULL); ci != NULL; - ci = cf_item_find_next(xr->cs, ci)) { + ci = cf_item_next(xr->cs, ci)) { if (!cf_item_is_pair(ci)) continue; count++; @@ -991,15 +987,24 @@ static ssize_t xlat_load_balance(TALLOC_CTX *ctx, char **out, NDEBUG_UNUSED size /* * Go to the next one, wrapping around at the end. */ - ci = cf_item_find_next(xr->cs, ci); - if (!ci) ci = cf_item_find_next(xr->cs, NULL); + ci = cf_item_next(xr->cs, ci); + if (!ci) ci = cf_item_next(xr->cs, NULL); } while (ci != found); return -1; } - -bool xlat_register_redundant(CONF_SECTION *cs) +/** Registers a redundant xlat + * + * These xlats wrap the xlat methods of the modules in a redundant section, + * emulating the behaviour of a redundant section, but over xlats. + * + * @return + * - 0 on success. + * - -1 on error. + * - 1 if the modules in the section do not have an xlat method. + */ +int xlat_register_redundant(CONF_SECTION *cs) { char const *name1, *name2; xlat_redundant_t *xr; @@ -1008,24 +1013,20 @@ bool xlat_register_redundant(CONF_SECTION *cs) name2 = cf_section_name2(cs); if (xlat_find(name2)) { - cf_log_err_cs(cs, "An expansion is already registered for this name"); - return false; + cf_log_err(cs, "An expansion is already registered for this name"); + return -1; } - xr = talloc_zero(cs, xlat_redundant_t); - if (!xr) return false; + MEM(xr = talloc_zero(cs, xlat_redundant_t)); if (strcmp(name1, "redundant") == 0) { xr->type = XLAT_REDUNDANT; - } else if (strcmp(name1, "redundant-load-balance") == 0) { xr->type = XLAT_REDUNDANT_LOAD_BALANCE; - } else if (strcmp(name1, "load-balance") == 0) { xr->type = XLAT_LOAD_BALANCE; - } else { - return false; + rad_assert(0); } xr->cs = cs; @@ -1035,33 +1036,41 @@ bool xlat_register_redundant(CONF_SECTION *cs) */ if (xr->type == XLAT_REDUNDANT) { if (xlat_register(xr, name2, xlat_redundant, NULL, NULL, 0, 0) < 0) { + ERROR("Registering xlat for redundant section failed"); talloc_free(xr); - return false; + return -1; } } else { - CONF_ITEM *ci; + CONF_ITEM *ci = NULL; + + while ((ci = cf_item_next(cs, ci))) { + char const *attr; - for (ci = cf_item_find_next(cs, NULL); - ci != NULL; - ci = cf_item_find_next(cs, ci)) { if (!cf_item_is_pair(ci)) continue; - if (!xlat_find(cf_pair_attr(cf_item_to_pair(ci)))) { + attr = cf_pair_attr(cf_item_to_pair(ci)); + + /* + * This is ok, it just means the module + * doesn't have an xlat method. + */ + if (!xlat_find(attr)) { talloc_free(xr); - return false; + return 1; } xr->count++; } if (xlat_register(xr, name2, xlat_load_balance, NULL, NULL, 0, 0) < 0) { + ERROR("Registering xlat for load-balance section failed"); talloc_free(xr); - return false; + return -1; } } - return true; + return 0; } diff --git a/src/modules/proto_arp/proto_arp.c b/src/modules/proto_arp/proto_arp.c index 09aa46ef7cf..aa6663c1838 100644 --- a/src/modules/proto_arp/proto_arp.c +++ b/src/modules/proto_arp/proto_arp.c @@ -55,7 +55,7 @@ static rlm_rcode_t arp_process(REQUEST *request) request->server = request->listener->server; request->server_cs = request->listener->server_cs; - unlang = cf_subsection_find(request->server_cs, "arp"); + unlang = cf_section_find(request->server_cs, "arp", NULL); request->component = "arp"; @@ -236,7 +236,7 @@ static int arp_socket_parse(CONF_SECTION *cs, rad_listen_t *this) if (rcode != 0) return rcode; if (!sock->lsock.interface) { - cf_log_err_cs(cs, "'interface' is required for arp"); + cf_log_err(cs, "'interface' is required for arp"); return -1; } @@ -272,9 +272,9 @@ static int arp_socket_bootstrap(CONF_SECTION *server_cs, UNUSED CONF_SECTION *li { CONF_SECTION *cs; - cs = cf_subsection_find(server_cs, "arp"); + cs = cf_section_find(server_cs, "arp", NULL); if (!cs) { - cf_log_err_cs(server_cs, "No 'arp' sub-section found"); + cf_log_err(server_cs, "No 'arp' sub-section found"); return -1; } @@ -288,16 +288,16 @@ static int arp_socket_compile(CONF_SECTION *server_cs, UNUSED CONF_SECTION *list { CONF_SECTION *cs; - cs = cf_subsection_find(server_cs, "arp"); + cs = cf_section_find(server_cs, "arp", NULL); if (!cs) { - cf_log_err_cs(server_cs, "No 'arp' sub-section found"); + cf_log_err(server_cs, "No 'arp' sub-section found"); return -1; } - cf_log_module(cs, "Loading arp {...}"); + cf_log_debug(cs, "Loading arp {...}"); if (unlang_compile(cs, MOD_POST_AUTH) < 0) { - cf_log_err_cs(cs, "Failed compiling 'arp' section"); + cf_log_err(cs, "Failed compiling 'arp' section"); return -1; } diff --git a/src/modules/proto_bfd/proto_bfd.c b/src/modules/proto_bfd/proto_bfd.c index 1a82ca158eb..b56b0b06253 100644 --- a/src/modules/proto_bfd/proto_bfd.c +++ b/src/modules/proto_bfd/proto_bfd.c @@ -1581,9 +1581,9 @@ static int bfd_init_sessions(CONF_SECTION *cs, bfd_socket_t *sock, int sockfd) uint16_t port; fr_ipaddr_t ipaddr; - for (ci=cf_item_find_next(cs, NULL); + for (ci=cf_item_next(cs, NULL); ci != NULL; - ci=cf_item_find_next(cs, ci)) { + ci=cf_item_next(cs, ci)) { bfd_state_t *session, my_session; if (!cf_item_is_section(ci)) continue; @@ -1733,8 +1733,8 @@ static int bfd_socket_parse(CONF_SECTION *cs, rad_listen_t *this) /* * Find the sibling "bfd" section of the "listen" section. */ - server = cf_section_parent(cs); - sock->unlang = cf_subsection_find(server, "bfd"); + server = cf_item_to_section(cf_parent(cs)); + sock->unlang = cf_section_find(server, "bfd", NULL); return 0; } @@ -1815,9 +1815,9 @@ static int bfd_socket_bootstrap(CONF_SECTION *server_cs, UNUSED CONF_SECTION *li { CONF_SECTION *cs; - cs = cf_subsection_find(server_cs, "bfd"); + cs = cf_section_find(server_cs, "bfd", NULL); if (!cs) { - cf_log_err_cs(server_cs, "No 'bfd' sub-section found"); + cf_log_err(server_cs, "No 'bfd' sub-section found"); return -1; } @@ -1831,16 +1831,16 @@ static int bfd_socket_compile(CONF_SECTION *server_cs, UNUSED CONF_SECTION *list { CONF_SECTION *cs; - cs = cf_subsection_find(server_cs, "bfd"); + cs = cf_section_find(server_cs, "bfd", NULL); if (!cs) { - cf_log_err_cs(server_cs, "No 'bfd' sub-section found"); + cf_log_err(server_cs, "No 'bfd' sub-section found"); return -1; } - cf_log_module(cs, "Loading bfd {...}"); + cf_log_debug(cs, "Loading bfd {...}"); if (unlang_compile(cs, MOD_AUTHORIZE) < 0) { - cf_log_err_cs(cs, "Failed compiling 'bfd' section"); + cf_log_err(cs, "Failed compiling 'bfd' section"); return -1; } diff --git a/src/modules/proto_detail/proto_detail.c b/src/modules/proto_detail/proto_detail.c index 08b58f75f57..d4b18bf1b35 100644 --- a/src/modules/proto_detail/proto_detail.c +++ b/src/modules/proto_detail/proto_detail.c @@ -1039,7 +1039,7 @@ static int detail_parse(CONF_SECTION *cs, rad_listen_t *this) rcode = cf_section_parse(data, data, cs, detail_config); if (rcode < 0) { - cf_log_err_cs(cs, "Failed parsing listen section"); + cf_log_err(cs, "Failed parsing listen section"); return -1; } @@ -1052,7 +1052,7 @@ static int detail_parse(CONF_SECTION *cs, rad_listen_t *this) this->nodup = true; if (!data->filename) { - cf_log_err_cs(cs, "No detail file specified in listen section"); + cf_log_err(cs, "No detail file specified in listen section"); return -1; } @@ -1095,7 +1095,7 @@ static int detail_parse(CONF_SECTION *cs, rad_listen_t *this) */ if ((strchr(buffer, '*') != NULL) || (strchr(buffer, '[') != NULL)) { - cf_log_err_cs(cs, "Wildcard directories are not supported"); + cf_log_err(cs, "Wildcard directories are not supported"); return -1; } @@ -1128,7 +1128,7 @@ static int detail_parse(CONF_SECTION *cs, rad_listen_t *this) client->secret = client->shortname; client->nas_type = talloc_strdup(data, "none"); /* Part of 'data' not dynamically allocated */ - this->server_cs = cf_section_parent(this->cs); + this->server_cs = cf_item_to_section(cf_parent(this->cs)); client->server_cs = this->server_cs; return 0; diff --git a/src/modules/proto_dhcp/proto_dhcp.c b/src/modules/proto_dhcp/proto_dhcp.c index a7c5d8a5b1d..dc5a5ba54b0 100644 --- a/src/modules/proto_dhcp/proto_dhcp.c +++ b/src/modules/proto_dhcp/proto_dhcp.c @@ -322,9 +322,9 @@ static rlm_rcode_t dhcp_process(REQUEST *request) RDEBUG("Trying sub-section dhcp %s {...}", dv->alias); - server = cf_section_parent(request->listener->cs); + server = cf_item_to_section(cf_parent(request->listener->cs)); - unlang = cf_subsection_find_name2(server, "dhcp", dv->alias); + unlang = cf_section_find(server, "dhcp", dv->alias); rcode = unlang_interpret(request, unlang, RLM_MODULE_NOOP); } else { REDEBUG("Unknown DHCP-Message-Type %d", vp->vp_uint8); @@ -1006,37 +1006,35 @@ static int dhcp_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request) */ static int dhcp_listen_compile(CONF_SECTION *server_cs, CONF_SECTION *listen_cs) { - CONF_SECTION *cs; + CONF_SECTION *subcs = NULL; fr_dict_attr_t const *da; fr_dict_enum_t const *dv; da = fr_dict_attr_by_name(NULL, "DHCP-Message-Type"); if (!da) { - cf_log_err_cs(listen_cs, "No DHCP-Message-Type attribute found"); + cf_log_err(listen_cs, "No DHCP-Message-Type attribute found"); return -1; } - for (cs = cf_subsection_find_next(server_cs, NULL, "dhcp"); - cs != NULL; - cs = cf_subsection_find_next(server_cs, cs, "dhcp")) { - char const *name2 = cf_section_name2(cs); + while ((subcs = cf_section_find_next(server_cs, subcs, "dhcp", NULL))) { + char const *name2 = cf_section_name2(subcs); if (name2) { - cf_log_module(cs, "Loading dhcp %s {...}", name2); + cf_log_debug(subcs, "Loading dhcp %s {...}", name2); } else { - cf_log_module(cs, "Loading dhcp {...}"); + cf_log_debug(subcs, "Loading dhcp {...}"); } dv = fr_dict_enum_by_alias(NULL, da, name2); if (!dv) { - cf_log_err_cs(cs, "Server contains 'dhcp %s {...}, but there is no such value for DHCP-Message-Type", - name2); + cf_log_err(subcs, "Server contains 'dhcp %s {...}, but there is no such value for " + "DHCP-Message-Type", name2); return -1; } - if (unlang_compile(cs, MOD_POST_AUTH) < 0) { - cf_log_err_cs(cs, "Failed compiling 'dhcp %s' section", name2); + if (unlang_compile(subcs, MOD_POST_AUTH) < 0) { + cf_log_err(subcs, "Failed compiling 'dhcp %s' section", name2); return -1; } } diff --git a/src/modules/proto_ldap_sync/proto_ldap_sync.c b/src/modules/proto_ldap_sync/proto_ldap_sync.c index 3684ff29a3f..12d7e98193d 100644 --- a/src/modules/proto_ldap_sync/proto_ldap_sync.c +++ b/src/modules/proto_ldap_sync/proto_ldap_sync.c @@ -363,8 +363,8 @@ static void request_running(REQUEST *request, fr_state_action_t action) rad_assert(0); return; } - unlang = cf_subsection_find_name2(request->server_cs, verb, state); - if (!unlang) unlang = cf_subsection_find_name2(request->server_cs, "recv", "*"); + unlang = cf_section_find(request->server_cs, verb, state); + if (!unlang) unlang = cf_section_find(request->server_cs, "recv", "*"); if (!unlang) { RDEBUG2("Ignoring %s operation. Add \"%s %s {}\" to virtual-server \"%s\"" " to handle", fr_int2str(ldap_sync_code_table, request->packet->code, ""), @@ -374,7 +374,7 @@ static void request_running(REQUEST *request, fr_state_action_t action) } RDEBUG("Running '%s %s' from file %s", cf_section_name1(unlang), - cf_section_name2(unlang), cf_section_filename(unlang)); + cf_section_name2(unlang), cf_filename(unlang)); unlang_push_section(request, unlang, RLM_MODULE_NOOP); request->request_state = REQUEST_RECV; @@ -607,7 +607,7 @@ static int _proto_ldap_present(fr_ldap_conn_t *conn, sync_config_t const *config { rad_listen_t *listen = talloc_get_type_abort(user_ctx, rad_listen_t); - if (!cf_subsection_find_name2(listen->server_cs, "recv", "Present")) { + if (!cf_section_find(listen->server_cs, "recv", "Present")) { DEBUG2("Present phase is not supported, reinitialising sync"); return _proto_ldap_refresh_required(conn, config, sync_id, phase, user_ctx); @@ -784,7 +784,7 @@ static int proto_ldap_cookie_load(TALLOC_CTX *ctx, uint8_t **cookie, rad_listen_ proto_ldap_attributes_add(request, config); request->packet->code = LDAP_SYNC_CODE_COOKIE_STORE; - unlang = cf_subsection_find_name2(request->server_cs, "load", "Cookie"); + unlang = cf_section_find(request->server_cs, "load", "Cookie"); if (!unlang) { RDEBUG2("Ignoring %s operation. Add \"load Cookie {}\" to virtual-server \"%s\"" " to handle", fr_int2str(ldap_sync_code_table, request->packet->code, ""), @@ -1053,10 +1053,10 @@ static int proto_ldap_socket_parse(CONF_SECTION *cs, rad_listen_t *listen) /* * Always cache the CONF_SECTION of the server. */ - parent_cs = cf_top_section(cs); - listen->server_cs = cf_subsection_find_name2(parent_cs, "server", listen->server); + parent_cs = cf_root(cs); + listen->server_cs = cf_section_find(parent_cs, "server", listen->server); if (!listen->server_cs) { - cf_log_err_cs(cs, "Failed to find virtual server '%s'", listen->server); + cf_log_err(cs, "Failed to find virtual server '%s'", listen->server); return -1; } @@ -1073,9 +1073,9 @@ static int proto_ldap_socket_parse(CONF_SECTION *cs, rad_listen_t *listen) /* * Convert scope strings to enumerated constants */ - for (sync_cs = cf_subsection_find(cs, "sync"), i = 0; + for (sync_cs = cf_section_find(cs, "sync", NULL), i = 0; sync_cs; - sync_cs = cf_subsection_find_next(cs, sync_cs, "sync"), i++) { + sync_cs = cf_section_find_next(cs, sync_cs, "sync", NULL), i++) { int scope; void **tmp; CONF_SECTION *map_cs; @@ -1084,7 +1084,7 @@ static int proto_ldap_socket_parse(CONF_SECTION *cs, rad_listen_t *listen) scope = fr_str2int(fr_ldap_scope, inst->sync_config[i]->scope_str, -1); if (scope < 0) { - cf_log_err_cs(cs, "Invalid 'user.scope' value \"%s\", expected 'sub', 'one'" + cf_log_err(cs, "Invalid 'user.scope' value \"%s\", expected 'sub', 'one'" #ifdef LDAP_SCOPE_CHILDREN ", 'base' or 'children'" #else @@ -1114,7 +1114,7 @@ static int proto_ldap_socket_parse(CONF_SECTION *cs, rad_listen_t *listen) /* * Parse and validate any maps */ - map_cs = cf_subsection_find(sync_cs, "update"); + map_cs = cf_section_find(sync_cs, "update", NULL); if (map_cs && map_afrom_cs(&inst->sync_config[i]->entry_map, map_cs, PAIR_LIST_REQUEST, PAIR_LIST_REQUEST, fr_ldap_map_verify, NULL, LDAP_MAX_ATTRMAP) < 0) { @@ -1145,13 +1145,13 @@ static int ldap_compile_section(CONF_SECTION *server_cs, char const *name1, char { CONF_SECTION *cs; - cs = cf_subsection_find_name2(server_cs, name1, name2); + cs = cf_section_find(server_cs, name1, name2); if (!cs) return 0; - cf_log_module(cs, "Loading %s %s {...}", name1, name2); + cf_log_debug(cs, "Loading %s %s {...}", name1, name2); if (unlang_compile(cs, component) < 0) { - cf_log_err_cs(cs, "Failed compiling '%s %s { ... }' section", name1, name2); + cf_log_err(cs, "Failed compiling '%s %s { ... }' section", name1, name2); return -1; } @@ -1193,7 +1193,7 @@ static int proto_ldap_listen_compile(CONF_SECTION *server_cs, UNUSED CONF_SECTIO if (rcode > 0) found++; if (found == 0) { - cf_log_err_cs(server_cs, "At least one of 'recv [Present|Add|Delete|Modify] { ... }' " + cf_log_err(server_cs, "At least one of 'recv [Present|Add|Delete|Modify] { ... }' " "sections must be present in virtual server %s", cf_section_name2(server_cs)); return -1; diff --git a/src/modules/proto_radius/proto_radius.c b/src/modules/proto_radius/proto_radius.c index fc64e62ea2b..247d7fe7cca 100644 --- a/src/modules/proto_radius/proto_radius.c +++ b/src/modules/proto_radius/proto_radius.c @@ -114,7 +114,7 @@ static int compile_type(proto_radius_ctx_t *ctx, CONF_SECTION *server, CONF_SECT fr_app_subtype_t const *app; if (!value || !*value) { - cf_log_err_cs(cs, "Must specify a value for 'type'"); + cf_log_err(cs, "Must specify a value for 'type'"); return -1; } @@ -127,12 +127,12 @@ static int compile_type(proto_radius_ctx_t *ctx, CONF_SECTION *server, CONF_SECT } if (!code) { - cf_log_err_cs(cs, "Unknown 'type = %s'", value); + cf_log_err(cs, "Unknown 'type = %s'", value); return -1; } if (ctx->process[i]) { - cf_log_err_cs(cs, "Duplicate 'type = %s'", value); + cf_log_err(cs, "Duplicate 'type = %s'", value); return -1; } @@ -155,7 +155,7 @@ static int compile_type(proto_radius_ctx_t *ctx, CONF_SECTION *server, CONF_SECT } if (!lib) { - cf_log_err_cs(cs, "Unknown 'type = %s'", value); + cf_log_err(cs, "Unknown 'type = %s'", value); return -1; } @@ -170,7 +170,7 @@ static int compile_type(proto_radius_ctx_t *ctx, CONF_SECTION *server, CONF_SECT cp = cf_pair_alloc(cs, "port_name", port_name, T_OP_SET, T_BARE_WORD, T_BARE_WORD); if (!cp) { - cf_log_err_cs(cs, "Out of memory"); + cf_log_err(cs, "Out of memory"); return -1; } @@ -184,7 +184,7 @@ static int compile_type(proto_radius_ctx_t *ctx, CONF_SECTION *server, CONF_SECT */ module = dl_module(server, NULL, lib, DL_TYPE_PROTO); if (!module) { - cf_log_err_cs(cs, "Failed finding submodule library for 'type = %s'", value); + cf_log_err(cs, "Failed finding submodule library for 'type = %s'", value); return -1; } @@ -212,7 +212,7 @@ static int open_transport(proto_radius_ctx_t *ctx, fr_schedule_t *handle, char buffer[256]; if (!value || !*value) { - cf_log_err_cs(cs, "Must specify a value for 'transport'"); + cf_log_err(cs, "Must specify a value for 'transport'"); return -1; } @@ -220,21 +220,21 @@ static int open_transport(proto_radius_ctx_t *ctx, fr_schedule_t *handle, module = dl_module(server, NULL, buffer, DL_TYPE_PROTO); if (!module) { - cf_log_err_cs(cs, "Failed finding submodule library for 'transport = %s'", value); + cf_log_err(cs, "Failed finding submodule library for 'transport = %s'", value); return -1; } /* * Lookup io section. */ - io_cs = cf_subsection_find(cs, value); + io_cs = cf_section_find(cs, value, NULL); if (!io_cs) { - cf_log_err_cs(cs, "Must contain a '%s' section", value); + cf_log_err(cs, "Must contain a '%s' section", value); return -1; } if (dl_instance_data_alloc(&io_ctx, NULL, module, io_cs) < 0) { - cf_log_perr_cs(cs, "Failed io_ctx data"); + cf_log_perr(cs, "Failed io_ctx data"); return -1; } @@ -243,7 +243,7 @@ static int open_transport(proto_radius_ctx_t *ctx, fr_schedule_t *handle, cp = cf_pair_alloc(io_cs, "port_name", cf_pair_value(cp), T_OP_SET, T_BARE_WORD, T_BARE_WORD); if (!cp) { - cf_log_err_cs(cs, "Out of memory"); + cf_log_err(cs, "Out of memory"); return -1; } @@ -252,7 +252,7 @@ static int open_transport(proto_radius_ctx_t *ctx, fr_schedule_t *handle, app_io = (fr_app_io_t const *) module->common; if (app_io->instantiate(io_cs, io_ctx) < 0) { - cf_log_err_cs(cs, "Failed instantiating 'transport = %s'", value); + cf_log_err(cs, "Failed instantiating 'transport = %s'", value); talloc_free(io_ctx); return -1; } @@ -260,7 +260,7 @@ static int open_transport(proto_radius_ctx_t *ctx, fr_schedule_t *handle, if (verify_config) return 0; if (app_io->op.open(io_ctx) < 0) { - cf_log_err_cs(cs, "Failed opening I/O interface '%s'", value); + cf_log_err(cs, "Failed opening I/O interface '%s'", value); return -1; } @@ -303,23 +303,23 @@ static int open_listen(fr_schedule_t *handle, CONF_SECTION *server, CONF_SECTION if ((cf_section_parse(cs, &config, cs, mod_config) < 0) || (cf_section_parse_pass2(&config, cs, mod_config) < 0)) { - cf_log_err_cs(cs, "Failed parsing listen { ...}"); + cf_log_err(cs, "Failed parsing listen { ...}"); return -1; } if (!config.types) { - cf_log_err_cs(cs, "type MUST be specified"); + cf_log_err(cs, "type MUST be specified"); return -1; } if (!config.transport) { - cf_log_err_cs(cs, "transport MUST be specified"); + cf_log_err(cs, "transport MUST be specified"); return -1; } ctx = talloc_zero(NULL, proto_radius_ctx_t); if (!ctx) { - cf_log_err_cs(cs, "Failed allocating memory"); + cf_log_err(cs, "Failed allocating memory"); return -1; } @@ -328,7 +328,7 @@ static int open_listen(fr_schedule_t *handle, CONF_SECTION *server, CONF_SECTION */ for (i = 0; i < talloc_array_length(config.types); i++) { if (compile_type(ctx, server, cs, config.types[i]) < 0) { - cf_log_err_cs(server, "Failed compiling unlang for 'type = %s'", + cf_log_err(server, "Failed compiling unlang for 'type = %s'", config.types[i]); return -1; } @@ -338,7 +338,7 @@ static int open_listen(fr_schedule_t *handle, CONF_SECTION *server, CONF_SECTION * Call transport-specific library to open the socket. */ if (open_transport(ctx, handle, server, cs, config.transport, verify_config) < 0) { - cf_log_err_cs(server, "Failed opening connection for 'transport = %s'", + cf_log_err(server, "Failed opening connection for 'transport = %s'", config.transport); return -1; } @@ -357,28 +357,26 @@ static int open_listen(fr_schedule_t *handle, CONF_SECTION *server, CONF_SECTION */ static int mod_parse(fr_schedule_t *handle, CONF_SECTION *cs, bool verify_config) { - CONF_SECTION *subcs; + CONF_SECTION *subcs = NULL; /* * Load all of the listen sections. They do all of the * dirty work. */ - for (subcs = cf_subsection_find_next(cs, NULL, "listen"); - subcs != NULL; - subcs = cf_subsection_find_next(cs, cs, "listen")) { + while ((subcs = cf_section_find_next(cs, subcs, "listen", NULL))) { if (open_listen(handle, cs, subcs, verify_config) < 0) { return -1; } } + subcs = NULL; + /* * Compile the sub-sections AFTER parsing all of the * listen sections. This is mainly for nice debugging * output. It's inefficient as heck, but it's pretty. */ - for (subcs = cf_subsection_find_next(cs, NULL, "listen"); - subcs != NULL; - subcs = cf_subsection_find_next(cs, cs, "listen")) { + while ((subcs = cf_section_find_next(cs, subcs, "listen", NULL))) { CONF_PAIR *cp; for (cp = cf_pair_find(subcs, "type"); @@ -390,16 +388,16 @@ static int mod_parse(fr_schedule_t *handle, CONF_SECTION *cs, bool verify_config value = cf_pair_value(cp); - module = cf_data_find(cs, dl_t, value); + module = cf_data_value(cf_data_find(cs, dl_t, value)); if (!module) { - cf_log_err_cs(cs, "Section missing module data"); + cf_log_err(cs, "Section missing module data"); return -1; } if (cf_data_find(cs, char const *, value)) continue; app = (fr_app_subtype_t const *) module->common; if (app->instantiate(cs) < 0) { - cf_log_err_cs(cs, "Failed compiling unlang for 'type = %s'", value); + cf_log_err(cs, "Failed compiling unlang for 'type = %s'", value); return -1; } diff --git a/src/modules/proto_radius/proto_radius_acct.c b/src/modules/proto_radius/proto_radius_acct.c index 2e832aa2c7f..22b7cec980d 100644 --- a/src/modules/proto_radius/proto_radius_acct.c +++ b/src/modules/proto_radius/proto_radius_acct.c @@ -65,14 +65,14 @@ static fr_io_final_t acct_process(REQUEST *request) return FR_IO_FAIL; } - unlang = cf_subsection_find_name2(request->server_cs, "recv", dv->alias); - if (!unlang) unlang = cf_subsection_find_name2(request->server_cs, "recv", "*"); + unlang = cf_section_find(request->server_cs, "recv", dv->alias); + if (!unlang) unlang = cf_section_find(request->server_cs, "recv", "*"); if (!unlang) { REDEBUG("Failed to find 'recv' section"); return FR_IO_FAIL; } - RDEBUG("Running 'recv %s' from file %s", cf_section_name2(unlang), cf_section_filename(unlang)); + RDEBUG("Running 'recv %s' from file %s", cf_section_name2(unlang), cf_filename(unlang)); unlang_push_section(request, unlang, RLM_MODULE_NOOP); request->request_state = REQUEST_RECV; @@ -131,12 +131,12 @@ static fr_io_final_t acct_process(REQUEST *request) dv = fr_dict_enum_by_value(NULL, da, fr_box_uint32(request->reply->code)); unlang = NULL; if (dv) { - unlang = cf_subsection_find_name2(request->server_cs, "send", dv->alias); + unlang = cf_section_find(request->server_cs, "send", dv->alias); } - if (!unlang) unlang = cf_subsection_find_name2(request->server_cs, "send", "*"); + if (!unlang) unlang = cf_section_find(request->server_cs, "send", "*"); if (!unlang) goto send_reply; - RDEBUG("Running 'send %s' from file %s", cf_section_name2(unlang), cf_section_filename(unlang)); + RDEBUG("Running 'send %s' from file %s", cf_section_name2(unlang), cf_filename(unlang)); unlang_push_section(request, unlang, RLM_MODULE_NOOP); request->request_state = REQUEST_SEND; @@ -361,13 +361,13 @@ static int acct_compile_section(CONF_SECTION *server_cs, char const *name1, char { CONF_SECTION *cs; - cs = cf_subsection_find_name2(server_cs, name1, name2); + cs = cf_section_find(server_cs, name1, name2); if (!cs) return 0; - cf_log_module(cs, "Loading %s %s {...}", name1, name2); + cf_log_debug(cs, "Loading %s %s {...}", name1, name2); if (unlang_compile(cs, component) < 0) { - cf_log_err_cs(cs, "Failed compiling '%s %s { ... }' section", name1, name2); + cf_log_err(cs, "Failed compiling '%s %s { ... }' section", name1, name2); return -1; } @@ -391,7 +391,7 @@ static int acct_listen_compile(CONF_SECTION *server_cs, UNUSED CONF_SECTION *lis } if (rcode == 0) { - cf_log_err_cs(server_cs, "Failed finding 'recv Accounting-Request { ... }' section of virtual server %s", + cf_log_err(server_cs, "Failed finding 'recv Accounting-Request { ... }' section of virtual server %s", cf_section_name2(server_cs)); return -1; } diff --git a/src/modules/proto_radius/proto_radius_auth.c b/src/modules/proto_radius/proto_radius_auth.c index 1b5fb45feed..1e67086df12 100644 --- a/src/modules/proto_radius/proto_radius_auth.c +++ b/src/modules/proto_radius/proto_radius_auth.c @@ -314,8 +314,8 @@ static fr_io_final_t auth_process(REQUEST *request) goto setup_send; } - unlang = cf_subsection_find_name2(request->server_cs, "recv", dv->alias); - if (!unlang) unlang = cf_subsection_find_name2(request->server_cs, "recv", "*"); + unlang = cf_section_find(request->server_cs, "recv", dv->alias); + if (!unlang) unlang = cf_section_find(request->server_cs, "recv", "*"); if (!unlang) { REDEBUG("Failed to find 'recv' section"); request->reply->code = FR_CODE_ACCESS_REJECT; @@ -336,7 +336,7 @@ static fr_io_final_t auth_process(REQUEST *request) /* * Push the conf section into the unlang stack. */ - RDEBUG("Running 'recv %s' from file %s", cf_section_name2(unlang), cf_section_filename(unlang)); + RDEBUG("Running 'recv %s' from file %s", cf_section_name2(unlang), cf_filename(unlang)); unlang_push_section(request, unlang, RLM_MODULE_REJECT); request->request_state = REQUEST_RECV; @@ -430,14 +430,14 @@ static fr_io_final_t auth_process(REQUEST *request) goto setup_send; } - unlang = cf_subsection_find_name2(request->server_cs, "process", dv->alias); + unlang = cf_section_find(request->server_cs, "process", dv->alias); if (!unlang) { REDEBUG2("No 'process %s' section found: rejecting the user", dv->alias); request->reply->code = FR_CODE_ACCESS_REJECT; goto setup_send; } - RDEBUG("Running 'process %s' from file %s", cf_section_name2(unlang), cf_section_filename(unlang)); + RDEBUG("Running 'process %s' from file %s", cf_section_name2(unlang), cf_filename(unlang)); unlang_push_section(request, unlang, RLM_MODULE_NOTFOUND); request->request_state = REQUEST_PROCESS; @@ -544,14 +544,14 @@ static fr_io_final_t auth_process(REQUEST *request) dv = fr_dict_enum_by_value(NULL, da, fr_box_uint32(request->reply->code)); unlang = NULL; if (dv) { - unlang = cf_subsection_find_name2(request->server_cs, "send", dv->alias); + unlang = cf_section_find(request->server_cs, "send", dv->alias); } - if (!unlang) unlang = cf_subsection_find_name2(request->server_cs, "send", "*"); + if (!unlang) unlang = cf_section_find(request->server_cs, "send", "*"); if (!unlang) goto send_reply; rerun_nak: - RDEBUG("Running 'send %s' from file %s", cf_section_name2(unlang), cf_section_filename(unlang)); + RDEBUG("Running 'send %s' from file %s", cf_section_name2(unlang), cf_filename(unlang)); unlang_push_section(request, unlang, RLM_MODULE_NOOP); request->request_state = REQUEST_SEND; @@ -595,7 +595,7 @@ static fr_io_final_t auth_process(REQUEST *request) unlang = NULL; if (!dv) goto send_reply; - unlang = cf_subsection_find_name2(request->server_cs, "send", dv->alias); + unlang = cf_section_find(request->server_cs, "send", dv->alias); if (unlang) goto rerun_nak; RWDEBUG("Not running 'send %s' section as it does not exist", dv->alias); @@ -952,13 +952,13 @@ static int auth_compile_section(CONF_SECTION *server_cs, char const *name1, char { CONF_SECTION *cs; - cs = cf_subsection_find_name2(server_cs, name1, name2); + cs = cf_section_find(server_cs, name1, name2); if (!cs) return 0; - cf_log_module(cs, "Loading %s %s {...}", name1, name2); + cf_log_debug(cs, "Loading %s %s {...}", name1, name2); if (unlang_compile(cs, component) < 0) { - cf_log_err_cs(cs, "Failed compiling '%s %s { ... }' section", name1, name2); + cf_log_err(cs, "Failed compiling '%s %s { ... }' section", name1, name2); return -1; } @@ -972,13 +972,13 @@ static int auth_compile_section(CONF_SECTION *server_cs, char const *name1, char static int auth_listen_compile(CONF_SECTION *server_cs, UNUSED CONF_SECTION *listen_cs) { int rcode; - CONF_SECTION *subcs; + CONF_SECTION *subcs = NULL; rcode = auth_compile_section(server_cs, "recv", "Access-Request", MOD_AUTHORIZE); if (rcode < 0) return rcode; if (rcode == 0) { - cf_log_err_cs(server_cs, "Failed finding 'recv Access-Request { ... }' section of virtual server %s", + cf_log_err(server_cs, "Failed finding 'recv Access-Request { ... }' section of virtual server %s", cf_section_name2(server_cs)); return -1; } @@ -986,7 +986,7 @@ static int auth_listen_compile(CONF_SECTION *server_cs, UNUSED CONF_SECTION *lis rcode = auth_compile_section(server_cs, "send", "Access-Accept", MOD_POST_AUTH); if (rcode < 0) return rcode; if (rcode == 0) { - cf_log_err_cs(server_cs, "Failed finding 'send Access-Accept { ... }' section of virtual server %s", + cf_log_err(server_cs, "Failed finding 'send Access-Accept { ... }' section of virtual server %s", cf_section_name2(server_cs)); return -1; } @@ -994,7 +994,7 @@ static int auth_listen_compile(CONF_SECTION *server_cs, UNUSED CONF_SECTION *lis rcode = auth_compile_section(server_cs, "send", "Access-Reject", MOD_POST_AUTH); if (rcode < 0) return rcode; if (rcode == 0) { - cf_log_err_cs(server_cs, "Failed finding 'send Access-Reject { ... }' section of virtual server %s", + cf_log_err(server_cs, "Failed finding 'send Access-Reject { ... }' section of virtual server %s", cf_section_name2(server_cs)); return -1; } @@ -1005,21 +1005,19 @@ static int auth_listen_compile(CONF_SECTION *server_cs, UNUSED CONF_SECTION *lis rcode = auth_compile_section(server_cs, "send", "Access-Challenge", MOD_POST_AUTH); if (rcode < 0) return rcode; - for (subcs = cf_subsection_find_next(server_cs, NULL, "process"); - subcs != NULL; - subcs = cf_subsection_find_next(server_cs, subcs, "process")) { + while ((subcs = cf_section_find_next(server_cs, subcs, "process", NULL))) { char const *name2; name2 = cf_section_name2(subcs); if (!name2) { - cf_log_err_cs(subcs, "Cannot compile 'process { ... }' section"); + cf_log_err(subcs, "Cannot compile 'process { ... }' section"); return -1; } - cf_log_module(subcs, "Loading process %s {...}", name2); + cf_log_debug(subcs, "Loading process %s {...}", name2); if (unlang_compile(subcs, MOD_AUTHENTICATE) < 0) { - cf_log_err_cs(subcs, "Failed compiling 'process %s { ... }' section", name2); + cf_log_err(subcs, "Failed compiling 'process %s { ... }' section", name2); return -1; } } @@ -1029,25 +1027,23 @@ static int auth_listen_compile(CONF_SECTION *server_cs, UNUSED CONF_SECTION *lis static int auth_listen_bootstrap(CONF_SECTION *server_cs, UNUSED CONF_SECTION *listen_cs) { - CONF_SECTION *subcs; - fr_dict_attr_t const *da; + CONF_SECTION *subcs = NULL;; + fr_dict_attr_t const *da; da = fr_dict_attr_by_num(NULL, 0, FR_AUTH_TYPE); if (!da) { - cf_log_err_cs(server_cs, "Failed finding dictionary definition for Auth-Type"); + cf_log_err(server_cs, "Failed finding dictionary definition for Auth-Type"); return -1; } - for (subcs = cf_subsection_find_next(server_cs, NULL, "process"); - subcs != NULL; - subcs = cf_subsection_find_next(server_cs, subcs, "process")) { + while ((subcs = cf_section_find_next(server_cs, subcs, "process", NULL))) { char const *name2; fr_value_box_t value = { .type = FR_TYPE_UINT32 }; fr_dict_enum_t *dv; name2 = cf_section_name2(subcs); if (!name2) { - cf_log_err_cs(subcs, "Invalid 'process { ... }' section, it must have a name"); + cf_log_err(subcs, "Invalid 'process { ... }' section, it must have a name"); return -1; } @@ -1068,7 +1064,7 @@ static int auth_listen_bootstrap(CONF_SECTION *server_cs, UNUSED CONF_SECTION *l value.vb_uint32 = (fr_rand() & 0x00ffffff) + 1; } while (fr_dict_enum_by_value(NULL, da, &value)); - cf_log_module(subcs, "Creating %s = %s", da->name, name2); + cf_log_debug(subcs, "Creating %s = %s", da->name, name2); if (fr_dict_enum_add_alias(da, name2, &value, true, false) < 0) { ERROR("%s", fr_strerror()); return -1; diff --git a/src/modules/proto_radius/proto_radius_coa.c b/src/modules/proto_radius/proto_radius_coa.c index 187fba7ee4b..b72fdd6ce2f 100644 --- a/src/modules/proto_radius/proto_radius_coa.c +++ b/src/modules/proto_radius/proto_radius_coa.c @@ -66,14 +66,14 @@ static fr_io_final_t coa_process(REQUEST *request) return FR_IO_FAIL; } - unlang = cf_subsection_find_name2(request->server_cs, "recv", dv->alias); - if (!unlang) unlang = cf_subsection_find_name2(request->server_cs, "recv", "*"); + unlang = cf_section_find(request->server_cs, "recv", dv->alias); + if (!unlang) unlang = cf_section_find(request->server_cs, "recv", "*"); if (!unlang) { REDEBUG("Failed to find 'recv' section"); return FR_IO_FAIL; } - RDEBUG("Running 'recv %s' from file %s", cf_section_name2(unlang), cf_section_filename(unlang)); + RDEBUG("Running 'recv %s' from file %s", cf_section_name2(unlang), cf_filename(unlang)); unlang_push_section(request, unlang, RLM_MODULE_NOOP); request->request_state = REQUEST_RECV; @@ -127,9 +127,9 @@ static fr_io_final_t coa_process(REQUEST *request) dv = fr_dict_enum_by_value(NULL, da, fr_box_uint32(request->reply->code)); unlang = NULL; if (dv) { - unlang = cf_subsection_find_name2(request->server_cs, "send", dv->alias); + unlang = cf_section_find(request->server_cs, "send", dv->alias); } - if (!unlang) unlang = cf_subsection_find_name2(request->server_cs, "send", "*"); + if (!unlang) unlang = cf_section_find(request->server_cs, "send", "*"); if (!unlang) goto send_reply; @@ -140,7 +140,7 @@ static fr_io_final_t coa_process(REQUEST *request) * server as quickly as possible. */ rerun_nak: - RDEBUG("Running 'send %s' from file %s", cf_section_name2(unlang), cf_section_filename(unlang)); + RDEBUG("Running 'send %s' from file %s", cf_section_name2(unlang), cf_filename(unlang)); unlang_push_section(request, unlang, RLM_MODULE_NOOP); request->log.unlang_indent = 0; @@ -185,7 +185,7 @@ static fr_io_final_t coa_process(REQUEST *request) unlang = NULL; if (!dv) goto send_reply; - unlang = cf_subsection_find_name2(request->server_cs, "send", dv->alias); + unlang = cf_section_find(request->server_cs, "send", dv->alias); if (unlang) goto rerun_nak; RWDEBUG("Not running 'send %s' section as it does not exist", dv->alias); @@ -403,13 +403,13 @@ static int coa_compile_section(CONF_SECTION *server_cs, char const *name1, char { CONF_SECTION *cs; - cs = cf_subsection_find_name2(server_cs, name1, name2); + cs = cf_section_find(server_cs, name1, name2); if (!cs) return 0; - cf_log_module(cs, "Loading %s %s {...}", name1, name2); + cf_log_debug(cs, "Loading %s %s {...}", name1, name2); if (unlang_compile(cs, component) < 0) { - cf_log_err_cs(cs, "Failed compiling '%s %s { ... }' section", name1, name2); + cf_log_err(cs, "Failed compiling '%s %s { ... }' section", name1, name2); return -1; } @@ -443,12 +443,12 @@ static int coa_listen_compile(CONF_SECTION *server_cs, UNUSED CONF_SECTION *list if (rcode == 0) { if (!coa_found) { - cf_log_err_cs(server_cs, "Failed finding 'recv CoA-Request { ... }' section of virtual server %s", + cf_log_err(server_cs, "Failed finding 'recv CoA-Request { ... }' section of virtual server %s", cf_section_name2(server_cs)); return -1; } - cf_log_err_cs(server_cs, "Failed finding 'recv Disconnect-Request { ... }' section of virtual server %s", + cf_log_err(server_cs, "Failed finding 'recv Disconnect-Request { ... }' section of virtual server %s", cf_section_name2(server_cs)); return -1; } diff --git a/src/modules/proto_radius/proto_radius_status.c b/src/modules/proto_radius/proto_radius_status.c index 0062e2360cc..eef289bee6b 100644 --- a/src/modules/proto_radius/proto_radius_status.c +++ b/src/modules/proto_radius/proto_radius_status.c @@ -55,14 +55,14 @@ static fr_io_final_t mod_process(REQUEST *request, UNUSED fr_io_action_t action) return FR_IO_FAIL; } - unlang = cf_subsection_find_name2(request->server_cs, "recv", dv->alias); + unlang = cf_section_find(request->server_cs, "recv", dv->alias); if (!unlang) { RWDEBUG("Failed to find 'recv' section"); request->reply->code = FR_CODE_ACCESS_REJECT; goto send_reply; } - RDEBUG("Running 'recv %s' from file %s", cf_section_name2(unlang), cf_section_filename(unlang)); + RDEBUG("Running 'recv %s' from file %s", cf_section_name2(unlang), cf_filename(unlang)); unlang_push_section(request, unlang, RLM_MODULE_NOOP); request->request_state = REQUEST_RECV; @@ -100,13 +100,13 @@ static fr_io_final_t mod_process(REQUEST *request, UNUSED fr_io_action_t action) dv = fr_dict_enum_by_value(NULL, da, fr_box_uint32(request->reply->code)); unlang = NULL; if (dv) { - unlang = cf_subsection_find_name2(request->server_cs, "send", dv->alias); + unlang = cf_section_find(request->server_cs, "send", dv->alias); } - if (!unlang) unlang = cf_subsection_find_name2(request->server_cs, "send", "*"); + if (!unlang) unlang = cf_section_find(request->server_cs, "send", "*"); if (!unlang) goto send_reply; rerun_nak: - RDEBUG("Running 'send %s' from file %s", cf_section_name2(unlang), cf_section_filename(unlang)); + RDEBUG("Running 'send %s' from file %s", cf_section_name2(unlang), cf_filename(unlang)); unlang_push_section(request, unlang, RLM_MODULE_NOOP); request->request_state = REQUEST_SEND; @@ -147,7 +147,7 @@ static fr_io_final_t mod_process(REQUEST *request, UNUSED fr_io_action_t action) unlang = NULL; if (!dv) goto send_reply; - unlang = cf_subsection_find_name2(request->server_cs, "send", dv->alias); + unlang = cf_section_find(request->server_cs, "send", dv->alias); if (unlang) goto rerun_nak; RWDEBUG("Not running 'send %s' section as it does not exist", dv->alias); @@ -201,10 +201,10 @@ static int mod_compile_section(CONF_SECTION *server_cs, char const *name1, char { CONF_SECTION *cs; - cs = cf_subsection_find_name2(server_cs, name1, name2); + cs = cf_section_find(server_cs, name1, name2); if (!cs) return 0; - cf_log_module(cs, "Compiling policies - %s %s {...}", name1, name2); + cf_log_debug(cs, "Compiling policies - %s %s {...}", name1, name2); /* * FIXME: check if it's already compiled? @@ -216,7 +216,7 @@ static int mod_compile_section(CONF_SECTION *server_cs, char const *name1, char */ if (unlang_compile(cs, component) < 0) { - cf_log_err_cs(cs, "Failed compiling '%s %s { ... }' section", name1, name2); + cf_log_err(cs, "Failed compiling '%s %s { ... }' section", name1, name2); return -1; } @@ -234,7 +234,7 @@ static int mod_compile(CONF_SECTION *server_cs) rcode = mod_compile_section(server_cs, "recv", "Status-Server", MOD_AUTHORIZE); if (rcode < 0) return rcode; if (rcode == 0) { - cf_log_err_cs(server_cs, "Failed finding 'recv Status-Server { ... }' section of virtual server %s", + cf_log_err(server_cs, "Failed finding 'recv Status-Server { ... }' section of virtual server %s", cf_section_name2(server_cs)); return -1; } @@ -242,7 +242,7 @@ static int mod_compile(CONF_SECTION *server_cs) rcode = mod_compile_section(server_cs, "send", "Access-Accept", MOD_POST_AUTH); if (rcode < 0) return rcode; if (rcode == 0) { - cf_log_err_cs(server_cs, "Failed finding 'send Access-Accept { ... }' section of virtual server %s", + cf_log_err(server_cs, "Failed finding 'send Access-Accept { ... }' section of virtual server %s", cf_section_name2(server_cs)); return -1; } @@ -250,7 +250,7 @@ static int mod_compile(CONF_SECTION *server_cs) rcode = mod_compile_section(server_cs, "send", "Access-Reject", MOD_POST_AUTH); if (rcode < 0) return rcode; if (rcode == 0) { - cf_log_err_cs(server_cs, "Failed finding 'send Access-Reject { ... }' section of virtual server %s", + cf_log_err(server_cs, "Failed finding 'send Access-Reject { ... }' section of virtual server %s", cf_section_name2(server_cs)); return -1; } diff --git a/src/modules/proto_radius/proto_radius_udp.c b/src/modules/proto_radius/proto_radius_udp.c index a3c1c32878c..7794dc37659 100644 --- a/src/modules/proto_radius/proto_radius_udp.c +++ b/src/modules/proto_radius/proto_radius_udp.c @@ -149,13 +149,13 @@ static int mod_instantiate(CONF_SECTION *cs, void *instance) struct servent *s; if (!inst->port_name) { - cf_log_err_cs(cs, "No 'port' specified in 'udp' section"); + cf_log_err(cs, "No 'port' specified in 'udp' section"); return -1; } s = getservbyname(inst->port_name, "udp"); if (!s) { - cf_log_err_cs(cs, "Unknown value for 'port_name = %s", inst->port_name); + cf_log_err(cs, "Unknown value for 'port_name = %s", inst->port_name); return -1; } diff --git a/src/modules/proto_tacacs/proto_tacacs.c b/src/modules/proto_tacacs/proto_tacacs.c index eee0c5f95fd..063ded499cd 100644 --- a/src/modules/proto_tacacs/proto_tacacs.c +++ b/src/modules/proto_tacacs/proto_tacacs.c @@ -183,8 +183,8 @@ static void tacacs_running(REQUEST *request, fr_state_action_t action) request->server_cs = request->listener->server_cs; request->component = "tacacs"; - unlang = cf_subsection_find_name2(request->server_cs, "recv", tacacs_lookup_packet_code(request->packet)); - if (!unlang) unlang = cf_subsection_find_name2(request->server_cs, "recv", "*"); + unlang = cf_section_find(request->server_cs, "recv", tacacs_lookup_packet_code(request->packet)); + if (!unlang) unlang = cf_section_find(request->server_cs, "recv", "*"); if (!unlang) { REDEBUG("Failed to find 'recv' section"); goto setup_send; @@ -196,7 +196,7 @@ static void tacacs_running(REQUEST *request, fr_state_action_t action) fr_state_to_request(global_state, request, request->packet); } - RDEBUG("Running 'recv %s' from file %s", cf_section_name2(unlang), cf_section_filename(unlang)); + RDEBUG("Running 'recv %s' from file %s", cf_section_name2(unlang), cf_filename(unlang)); unlang_push_section(request, unlang, RLM_MODULE_REJECT); request->request_state = REQUEST_RECV; @@ -285,14 +285,14 @@ stop_processing: goto setup_send; } - unlang = cf_subsection_find_name2(request->server_cs, "process", dv->alias); + unlang = cf_section_find(request->server_cs, "process", dv->alias); if (!unlang) { REDEBUG2("No 'process %s' section found: rejecting the user.", dv->alias); tacacs_status(request, RLM_MODULE_FAIL); goto setup_send; } - RDEBUG("Running 'process %s' from file %s", cf_section_name2(unlang), cf_section_filename(unlang)); + RDEBUG("Running 'process %s' from file %s", cf_section_name2(unlang), cf_filename(unlang)); unlang_push_section(request, unlang, RLM_MODULE_NOTFOUND); request->request_state = REQUEST_PROCESS; @@ -337,12 +337,12 @@ stop_processing: setup_send: unlang = NULL; if (dv) { - unlang = cf_subsection_find_name2(request->server_cs, "send", tacacs_lookup_packet_code(request->packet)); + unlang = cf_section_find(request->server_cs, "send", tacacs_lookup_packet_code(request->packet)); } - if (!unlang) unlang = cf_subsection_find_name2(request->server_cs, "send", "*"); + if (!unlang) unlang = cf_section_find(request->server_cs, "send", "*"); if (!unlang) goto send_reply; - RDEBUG("Running 'send %s' from file %s", cf_section_name2(unlang), cf_section_filename(unlang)); + RDEBUG("Running 'send %s' from file %s", cf_section_name2(unlang), cf_filename(unlang)); unlang_push_section(request, unlang, RLM_MODULE_NOOP); request->request_state = REQUEST_SEND; @@ -529,18 +529,18 @@ static int tacacs_compile_section(CONF_SECTION *server_cs, char const *name1, ch CONF_SECTION *cs; int ret; - cs = cf_subsection_find_name2(server_cs, name1, name2); + cs = cf_section_find(server_cs, name1, name2); if (!cs) { - cf_log_err_cs(server_cs, "Failed finding '%s %s { ... }' section of virtual server %s", + cf_log_err(server_cs, "Failed finding '%s %s { ... }' section of virtual server %s", name1, name2, cf_section_name2(server_cs)); return -1; } - cf_log_module(cs, "Loading %s %s {...}", name1, name2); + cf_log_debug(cs, "Loading %s %s {...}", name1, name2); ret = unlang_compile(cs, component); if (ret < 0) { - cf_log_err_cs(cs, "Failed compiling '%s %s { ... }' section", name1, name2); + cf_log_err(cs, "Failed compiling '%s %s { ... }' section", name1, name2); return -1; } @@ -550,7 +550,7 @@ static int tacacs_compile_section(CONF_SECTION *server_cs, char const *name1, ch static int tacacs_listen_compile(CONF_SECTION *server_cs, UNUSED CONF_SECTION *listen_cs) { int rcode; - CONF_SECTION *subcs; + CONF_SECTION *subcs = NULL; rcode = tacacs_compile_section(server_cs, "recv", "Authentication", MOD_AUTHORIZE); if (rcode < 0) return rcode; @@ -570,9 +570,7 @@ static int tacacs_listen_compile(CONF_SECTION *server_cs, UNUSED CONF_SECTION *l rcode = tacacs_compile_section(server_cs, "send", "Accounting", MOD_ACCOUNTING); if (rcode < 0) return rcode; - for (subcs = cf_subsection_find_next(server_cs, NULL, "process"); - subcs != NULL; - subcs = cf_subsection_find_next(server_cs, subcs, "process")) { + while ((subcs = cf_section_find_next(server_cs, subcs, "process", NULL))) { char const *name2; name2 = cf_section_name2(subcs); diff --git a/src/modules/proto_vmps/proto_vmps.c b/src/modules/proto_vmps/proto_vmps.c index 3ddbe67fd81..edfb156903b 100644 --- a/src/modules/proto_vmps/proto_vmps.c +++ b/src/modules/proto_vmps/proto_vmps.c @@ -67,14 +67,14 @@ static void vmps_running(REQUEST *request, fr_state_action_t action) goto done; } - unlang = cf_subsection_find_name2(request->server_cs, "recv", dv->alias); - if (!unlang) unlang = cf_subsection_find_name2(request->server_cs, "recv", "*"); + unlang = cf_section_find(request->server_cs, "recv", dv->alias); + if (!unlang) unlang = cf_section_find(request->server_cs, "recv", "*"); if (!unlang) { RPEDEBUG("Failed to find 'recv' section"); goto done; } - RDEBUG("Running recv %s from file %s", cf_section_name2(unlang), cf_section_filename(unlang)); + RDEBUG("Running recv %s from file %s", cf_section_name2(unlang), cf_filename(unlang)); rcode = unlang_interpret(request, unlang, RLM_MODULE_NOOP); if (request->master_state == REQUEST_STOP_PROCESSING) goto done; @@ -104,12 +104,12 @@ static void vmps_running(REQUEST *request, fr_state_action_t action) dv = fr_dict_enum_by_value(NULL, da, fr_box_uint32(request->reply->code)); unlang = NULL; if (dv) { - unlang = cf_subsection_find_name2(request->server_cs, "send", dv->alias); + unlang = cf_section_find(request->server_cs, "send", dv->alias); } - if (!unlang) unlang = cf_subsection_find_name2(request->server_cs, "send", "*"); + if (!unlang) unlang = cf_section_find(request->server_cs, "send", "*"); if (unlang) { - RDEBUG("Running send %s from file %s", cf_section_name2(unlang), cf_section_filename(unlang)); + RDEBUG("Running send %s from file %s", cf_section_name2(unlang), cf_filename(unlang)); (void) unlang_interpret(request, unlang, RLM_MODULE_NOOP); if (request->master_state == REQUEST_STOP_PROCESSING) goto done; @@ -243,13 +243,13 @@ static int vqp_compile_section(CONF_SECTION *server_cs, char const *name1, char { CONF_SECTION *cs; - cs = cf_subsection_find_name2(server_cs, name1, name2); + cs = cf_section_find(server_cs, name1, name2); if (!cs) return 0; - cf_log_module(cs, "Loading %s %s {...}", name1, name2); + cf_log_debug(cs, "Loading %s %s {...}", name1, name2); if (unlang_compile(cs, MOD_POST_AUTH) < 0) { - cf_log_err_cs(cs, "Failed compiling '%s %s { ... }' section", name1, name2); + cf_log_err(cs, "Failed compiling '%s %s { ... }' section", name1, name2); return -1; } @@ -273,7 +273,7 @@ static int vqp_listen_compile(CONF_SECTION *server_cs, UNUSED CONF_SECTION *list } if (rcode == 0) { - cf_log_err_cs(server_cs, "Failed finding 'recv VMPS-Join-Request { ... }' section of virtual server %s", + cf_log_err(server_cs, "Failed finding 'recv VMPS-Join-Request { ... }' section of virtual server %s", cf_section_name2(server_cs)); return -1; } diff --git a/src/modules/rlm_always/rlm_always.c b/src/modules/rlm_always/rlm_always.c index 22a7e6cef51..91291932097 100644 --- a/src/modules/rlm_always/rlm_always.c +++ b/src/modules/rlm_always/rlm_always.c @@ -65,7 +65,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) */ inst->rcode = fr_str2int(mod_rcode_table, inst->rcode_str, RLM_MODULE_UNKNOWN); if (inst->rcode == RLM_MODULE_UNKNOWN) { - cf_log_err_cs(conf, "rcode value \"%s\" is invalid", inst->rcode_str); + cf_log_err(conf, "rcode value \"%s\" is invalid", inst->rcode_str); return -1; } inst->rcode_old = NULL; /* Hack - forces the compiler not to optimise away rcode_old */ diff --git a/src/modules/rlm_cache/rlm_cache.c b/src/modules/rlm_cache/rlm_cache.c index 0fa4be47eff..6b1b9003c95 100644 --- a/src/modules/rlm_cache/rlm_cache.c +++ b/src/modules/rlm_cache/rlm_cache.c @@ -921,7 +921,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) * Sanity check for crazy people. */ if (strncmp(inst->config.driver_name, "rlm_cache_", 8) != 0) { - cf_log_err_cs(conf, "\"%s\" is NOT an Cache driver!", inst->config.driver_name); + cf_log_err(conf, "\"%s\" is NOT an Cache driver!", inst->config.driver_name); return -1; } @@ -932,7 +932,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) name++; } - driver_cs = cf_subsection_find(conf, name); + driver_cs = cf_section_find(conf, name, NULL); if (!driver_cs) { driver_cs = cf_section_alloc(conf, name, NULL); if (!driver_cs) return -1; @@ -964,18 +964,18 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) #endif if (inst->config.ttl == 0) { - cf_log_err_cs(conf, "Must set 'ttl' to non-zero"); + cf_log_err(conf, "Must set 'ttl' to non-zero"); return -1; } if (inst->config.epoch != 0) { - cf_log_err_cs(conf, "Must not set 'epoch' in the configuration files"); + cf_log_err(conf, "Must not set 'epoch' in the configuration files"); return -1; } - update = cf_subsection_find(inst->cs, "update"); + update = cf_section_find(inst->cs, "update", CF_IDENT_ANY); if (!update) { - cf_log_err_cs(conf, "Must have an 'update' section in order to cache anything"); + cf_log_err(conf, "Must have an 'update' section in order to cache anything"); return -1; } @@ -988,7 +988,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) } if (!inst->maps) { - cf_log_err_cs(inst->cs, "Cache config must contain an update section, and " + cf_log_err(inst->cs, "Cache config must contain an update section, and " "that section must not be empty"); return -1; } diff --git a/src/modules/rlm_client/rlm_client.c b/src/modules/rlm_client/rlm_client.c index 9100688e8f8..43ebbf2b10f 100644 --- a/src/modules/rlm_client/rlm_client.c +++ b/src/modules/rlm_client/rlm_client.c @@ -140,6 +140,22 @@ static rlm_rcode_t map_proc_client(UNUSED void *mod_inst, UNUSED void *proc_inst RDEBUG("No client found with IP \"%s\"", client_str); return 0; } + + if (client->cs) { + char const *filename; + int line; + + filename = cf_filename(client->cs); + line = cf_lineno(client->cs); + + if (filename) { + RDEBUG2("Found client matching \"%s\". Defined in \"%s\" line %i", + client_str, filename, line); + } else { + RDEBUG2("Found client matching \"%s\"", client_str); + } + } + talloc_free(client_str); } else { client = request->client; diff --git a/src/modules/rlm_couchbase/mod.c b/src/modules/rlm_couchbase/mod.c index 56010f93c9c..52f92d98b97 100644 --- a/src/modules/rlm_couchbase/mod.c +++ b/src/modules/rlm_couchbase/mod.c @@ -157,11 +157,11 @@ int mod_build_attribute_element_map(CONF_SECTION *conf, void *instance) const char *attribute, *element; /* attribute and element names */ /* find update section */ - cs = cf_subsection_find(conf, "update"); + cs = cf_section_find(conf, "update", NULL); /* backwards compatibility */ if (!cs) { - cs = cf_subsection_find(conf, "map"); + cs = cf_section_find(conf, "map", NULL); WARN("found deprecated 'map' section - please change to 'update'"); } @@ -176,7 +176,7 @@ int mod_build_attribute_element_map(CONF_SECTION *conf, void *instance) inst->map = json_object_new_object(); /* parse update section */ - for (ci = cf_item_find_next(cs, NULL); ci != NULL; ci = cf_item_find_next(cs, ci)) { + for (ci = cf_item_next(cs, NULL); ci != NULL; ci = cf_item_next(cs, ci)) { /* validate item */ if (!cf_item_is_pair(ci)) { ERROR("failed to parse invalid item in 'update' section"); diff --git a/src/modules/rlm_couchbase/rlm_couchbase.c b/src/modules/rlm_couchbase/rlm_couchbase.c index de4f1eb16e5..c72aaa65460 100644 --- a/src/modules/rlm_couchbase/rlm_couchbase.c +++ b/src/modules/rlm_couchbase/rlm_couchbase.c @@ -823,7 +823,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) CONF_SECTION *cs, *map, *tmpl; /* conf section */ /* attempt to find client section */ - cs = cf_subsection_find(conf, "client"); + cs = cf_section_find(conf, "client", NULL); if (!cs) { ERROR("failed to find client section while loading clients"); /* fail */ @@ -831,14 +831,14 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) } /* attempt to find attribute subsection */ - map = cf_subsection_find(cs, "attribute"); + map = cf_section_find(cs, "attribute", NULL); if (!map) { ERROR("failed to find attribute subsection while loading clients"); /* fail */ return -1; } - tmpl = cf_subsection_find(cs, "template"); + tmpl = cf_section_find(cs, "template", NULL); /* debugging */ DEBUG("preparing to load client documents"); diff --git a/src/modules/rlm_csv/rlm_csv.c b/src/modules/rlm_csv/rlm_csv.c index 8bc72e42a59..9601418b430 100644 --- a/src/modules/rlm_csv/rlm_csv.c +++ b/src/modules/rlm_csv/rlm_csv.c @@ -166,14 +166,14 @@ static rlm_csv_entry_t *file2csv(CONF_SECTION *conf, rlm_csv_t *inst, int lineno for (p = buffer, i = 0; p != NULL; p = q, i++) { if (!buf2entry(inst, p, &q)) { - cf_log_err_cs(conf, "Malformed entry in file %s line %d", inst->filename, lineno); + cf_log_err(conf, "Malformed entry in file %s line %d", inst->filename, lineno); return NULL; } if (q) *(q++) = '\0'; if (i >= inst->num_fields) { - cf_log_err_cs(conf, "Too many fields at file %s line %d", inst->filename, lineno); + cf_log_err(conf, "Too many fields at file %s line %d", inst->filename, lineno); return NULL; } @@ -194,7 +194,7 @@ static rlm_csv_entry_t *file2csv(CONF_SECTION *conf, rlm_csv_t *inst, int lineno } if (i < inst->num_fields) { - cf_log_err_cs(conf, "Too few fields at file %s line %d (%d < %d)", inst->filename, lineno, i, inst->num_fields); + cf_log_err(conf, "Too few fields at file %s line %d (%d < %d)", inst->filename, lineno, i, inst->num_fields); return NULL; } @@ -202,7 +202,7 @@ static rlm_csv_entry_t *file2csv(CONF_SECTION *conf, rlm_csv_t *inst, int lineno * FIXME: Allow duplicate keys later. */ if (!rbtree_insert(inst->tree, e)) { - cf_log_err_cs(conf, "Failed inserting entry for filename %s line %d: duplicate entry", + cf_log_err(conf, "Failed inserting entry for filename %s line %d: duplicate entry", inst->filename, lineno); return NULL; } @@ -240,7 +240,7 @@ static int csv_map_verify(CONF_SECTION *cs, void *mod_inst, UNUSED void *proc_in vp_map_t const *map; if (!src) { - cf_log_err_cs(cs, "Missing file name"); + cf_log_err(cs, "Missing file name"); return -1; } @@ -284,7 +284,7 @@ static int mod_bootstrap(CONF_SECTION *conf, void *instance) if (!inst->name) inst->name = cf_section_name1(conf); if (inst->delimiter[1]) { - cf_log_err_cs(conf, "'delimiter' must be one character long"); + cf_log_err(conf, "'delimiter' must be one character long"); return -1; } @@ -293,14 +293,14 @@ static int mod_bootstrap(CONF_SECTION *conf, void *instance) } if (inst->num_fields < 2) { - cf_log_err_cs(conf, "Must have at least a key field and data field"); + cf_log_err(conf, "Must have at least a key field and data field"); return -1; } inst->field_names = talloc_array(inst, const char *, inst->num_fields); if (!inst->field_names) { oom: - cf_log_err_cs(conf, "Out of memory"); + cf_log_err(conf, "Out of memory"); return -1; } @@ -361,7 +361,7 @@ static int mod_bootstrap(CONF_SECTION *conf, void *instance) } if (inst->key_field < 0) { - cf_log_err_cs(conf, "Key field '%s' does not appear in header", inst->key); + cf_log_err(conf, "Key field '%s' does not appear in header", inst->key); return -1; } @@ -373,7 +373,7 @@ static int mod_bootstrap(CONF_SECTION *conf, void *instance) */ fp = fopen(inst->filename, "r"); if (!fp) { - cf_log_err_cs(conf, "Error opening filename %s: %s", inst->filename, strerror(errno)); + cf_log_err(conf, "Error opening filename %s: %s", inst->filename, strerror(errno)); return -1; } diff --git a/src/modules/rlm_detail/rlm_detail.c b/src/modules/rlm_detail/rlm_detail.c index cff5b15c250..5ea71e00ada 100644 --- a/src/modules/rlm_detail/rlm_detail.c +++ b/src/modules/rlm_detail/rlm_detail.c @@ -134,22 +134,22 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) inst->ef = module_exfile_init(inst, conf, 256, 30, inst->locking, NULL, NULL); if (!inst->ef) { - cf_log_err_cs(conf, "Failed creating log file context"); + cf_log_err(conf, "Failed creating log file context"); return -1; } /* * Suppress certain attributes. */ - cs = cf_subsection_find(conf, "suppress"); + cs = cf_section_find(conf, "suppress", NULL); if (cs) { CONF_ITEM *ci; inst->ht = fr_hash_table_create(NULL, detail_hash, detail_cmp, NULL); - for (ci = cf_item_find_next(cs, NULL); + for (ci = cf_item_next(cs, NULL); ci != NULL; - ci = cf_item_find_next(cs, ci)) { + ci = cf_item_next(cs, ci)) { char const *attr; fr_dict_attr_t const *da; @@ -160,7 +160,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) da = fr_dict_attr_by_name(NULL, attr); if (!da) { - cf_log_err_cs(conf, "No such attribute '%s'", attr); + cf_log_err(conf, "No such attribute '%s'", attr); return -1; } diff --git a/src/modules/rlm_eap/lib/base/eap_tls.c b/src/modules/rlm_eap/lib/base/eap_tls.c index 7ad6f832d41..87513ed3c5c 100644 --- a/src/modules/rlm_eap/lib/base/eap_tls.c +++ b/src/modules/rlm_eap/lib/base/eap_tls.c @@ -1097,13 +1097,13 @@ fr_tls_conf_t *eap_tls_conf_parse(CONF_SECTION *cs, char const *attr) CONF_SECTION *tls_cs; fr_tls_conf_t *tls_conf; - parent = cf_section_parent(cs); + parent = cf_item_to_section(cf_parent(cs)); cp = cf_pair_find(cs, attr); if (cp) { tls_conf_name = cf_pair_value(cp); - tls_cs = cf_subsection_find_name2(parent, TLS_CONFIG_SECTION, tls_conf_name); + tls_cs = cf_section_find(parent, TLS_CONFIG_SECTION, tls_conf_name); if (!tls_cs) { ERROR("Cannot find tls config \"%s\"", tls_conf_name); return NULL; @@ -1118,7 +1118,7 @@ fr_tls_conf_t *eap_tls_conf_parse(CONF_SECTION *cs, char const *attr) * find the section - that is just a config error. */ INFO("TLS section \"%s\" missing, trying to use legacy configuration", attr); - tls_cs = cf_subsection_find(parent, "tls"); + tls_cs = cf_section_find(parent, "tls", NULL); } if (!tls_cs) return NULL; diff --git a/src/modules/rlm_eap/rlm_eap.c b/src/modules/rlm_eap/rlm_eap.c index 83a781fe2f6..cdc6a3158f0 100644 --- a/src/modules/rlm_eap/rlm_eap.c +++ b/src/modules/rlm_eap/rlm_eap.c @@ -133,7 +133,7 @@ static int mod_bootstrap(CONF_SECTION *cs, void *instance) int i, ret; eap_type_t method; int num_methods; - CONF_SECTION *scs; + CONF_SECTION *scs = NULL; rlm_eap_t *inst = instance; /* @@ -148,10 +148,7 @@ static int mod_bootstrap(CONF_SECTION *cs, void *instance) /* Load all the configured EAP-Types */ num_methods = 0; - for (scs = cf_subsection_find_next(cs, NULL, NULL); - scs != NULL; - scs = cf_subsection_find_next(cs, scs, NULL)) { - + while ((scs = cf_section_next(cs, scs))) { char const *name; name = cf_section_name1(scs); @@ -161,12 +158,12 @@ static int mod_bootstrap(CONF_SECTION *cs, void *instance) method = eap_name2type(name); if (method == FR_EAP_INVALID) { - cf_log_err_cs(cs, "Unknown EAP type %s", name); + cf_log_err(cs, "Unknown EAP type %s", name); return -1; } if ((method < FR_EAP_MD5) || (method >= FR_EAP_MAX_TYPES)) { - cf_log_err_cs(cs, "Invalid EAP method %s (unsupported)", name); + cf_log_err(cs, "Invalid EAP method %s (unsupported)", name); return -1; } @@ -207,7 +204,7 @@ static int mod_bootstrap(CONF_SECTION *cs, void *instance) } if (num_methods == 0) { - cf_log_err_cs(cs, "No EAP method configured, module cannot do anything"); + cf_log_err(cs, "No EAP method configured, module cannot do anything"); return -1; } @@ -222,7 +219,7 @@ static int mod_bootstrap(CONF_SECTION *cs, void *instance) } if (!inst->methods[method]) { - cf_log_err_cs(cs, "No such sub-type for default EAP method %s", + cf_log_err(cs, "No such sub-type for default EAP method %s", inst->config.default_method_name); return -1; } diff --git a/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c b/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c index c7bea5b6089..a2905d558c0 100644 --- a/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c +++ b/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c @@ -78,7 +78,7 @@ static int mod_instantiate(UNUSED rlm_eap_config_t const *config, void *instance { rlm_eap_fast_t *inst = talloc_get_type_abort(instance, rlm_eap_fast_t); - if (!cf_subsection_find_name2(main_config.config, "server", inst->virtual_server)) { + if (!cf_section_find(main_config.config, "server", inst->virtual_server)) { cf_log_err_by_name(cs, "virtual_server", "Unknown virtual server '%s'", inst->virtual_server); return -1; } diff --git a/src/modules/rlm_eap/types/rlm_eap_gtc/rlm_eap_gtc.c b/src/modules/rlm_eap/types/rlm_eap_gtc/rlm_eap_gtc.c index 48bb208fa34..1ad58730f6f 100644 --- a/src/modules/rlm_eap/types/rlm_eap_gtc/rlm_eap_gtc.c +++ b/src/modules/rlm_eap/types/rlm_eap_gtc/rlm_eap_gtc.c @@ -126,7 +126,7 @@ static rlm_rcode_t mod_process(void *instance, eap_session_t *eap_session) */ request->password = vp; - unlang = cf_subsection_find_name2(request->server_cs, "process", inst->auth_type_name); + unlang = cf_section_find(request->server_cs, "process", inst->auth_type_name); if (!unlang) { /* * Call the authenticate section of the *current* virtual server. diff --git a/src/modules/rlm_eap/types/rlm_eap_mschapv2/rlm_eap_mschapv2.c b/src/modules/rlm_eap/types/rlm_eap_mschapv2/rlm_eap_mschapv2.c index 6da908908f3..c606d28f119 100644 --- a/src/modules/rlm_eap/types/rlm_eap_mschapv2/rlm_eap_mschapv2.c +++ b/src/modules/rlm_eap/types/rlm_eap_mschapv2/rlm_eap_mschapv2.c @@ -748,7 +748,7 @@ static int mod_instantiate(UNUSED rlm_eap_config_t const *config, void *instance fr_dict_enum_t const *dv; if (inst->identity && (strlen(inst->identity) > 255)) { - cf_log_err_cs(cs, "identity is too long"); + cf_log_err(cs, "identity is too long"); return -1; } @@ -757,7 +757,7 @@ static int mod_instantiate(UNUSED rlm_eap_config_t const *config, void *instance dv = fr_dict_enum_by_alias(NULL, fr_dict_attr_by_num(NULL, 0, FR_AUTH_TYPE), "MS-CHAP"); if (!dv) dv = fr_dict_enum_by_alias(NULL, fr_dict_attr_by_num(NULL, 0, FR_AUTH_TYPE), "MSCHAP"); if (!dv) { - cf_log_err_cs(cs, "Failed to find 'Auth-Type MS-CHAP' section. Cannot authenticate users."); + cf_log_err(cs, "Failed to find 'Auth-Type MS-CHAP' section. Cannot authenticate users."); return -1; } inst->auth_type_mschap = dv->value->vb_uint32; diff --git a/src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c b/src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c index 8b3edc787b1..183e12cac1d 100644 --- a/src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c +++ b/src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c @@ -286,13 +286,13 @@ static int mod_instantiate(UNUSED rlm_eap_config_t const *config, void *instance rlm_eap_peap_t *inst = talloc_get_type_abort(instance, rlm_eap_peap_t); fr_dict_enum_t *dv; - if (!cf_subsection_find_name2(main_config.config, "server", inst->virtual_server)) { + if (!cf_section_find(main_config.config, "server", inst->virtual_server)) { cf_log_err_by_name(cs, "virtual_server", "Unknown virtual server '%s'", inst->virtual_server); return -1; } if (inst->soh_virtual_server) { - if (!cf_subsection_find_name2(main_config.config, "server", inst->soh_virtual_server)) { + if (!cf_section_find(main_config.config, "server", inst->soh_virtual_server)) { cf_log_err_by_name(cs, "soh_virtual_server", "Unknown virtual server '%s'", inst->virtual_server); return -1; } diff --git a/src/modules/rlm_eap/types/rlm_eap_pwd/rlm_eap_pwd.c b/src/modules/rlm_eap/types/rlm_eap_pwd/rlm_eap_pwd.c index 41b53f81603..639f55d0299 100644 --- a/src/modules/rlm_eap/types/rlm_eap_pwd/rlm_eap_pwd.c +++ b/src/modules/rlm_eap/types/rlm_eap_pwd/rlm_eap_pwd.c @@ -512,7 +512,7 @@ static int mod_instantiate(UNUSED rlm_eap_config_t const *config, void *instance rlm_eap_pwd_t *inst = talloc_get_type_abort(instance, rlm_eap_pwd_t); if (inst->fragment_size < 100) { - cf_log_err_cs(cs, "Fragment size is too small"); + cf_log_err(cs, "Fragment size is too small"); return -1; } diff --git a/src/modules/rlm_eap/types/rlm_eap_sim/rlm_eap_sim.c b/src/modules/rlm_eap/types/rlm_eap_sim/rlm_eap_sim.c index bbda33fa787..6297eea5c78 100644 --- a/src/modules/rlm_eap/types/rlm_eap_sim/rlm_eap_sim.c +++ b/src/modules/rlm_eap/types/rlm_eap_sim/rlm_eap_sim.c @@ -548,36 +548,34 @@ static rlm_rcode_t mod_session_init(UNUSED void *instance, eap_session_t *eap_se static int mod_instantiate(UNUSED rlm_eap_config_t const *config, UNUSED void *instance, CONF_SECTION *cs) { fr_dict_attr_t const *da; - CONF_SECTION *subcs; + CONF_SECTION *subcs = NULL; da = fr_dict_attr_child_by_num(dict_sim_root, FR_EAP_SIM_SUBTYPE); if (!da) { - cf_log_err_cs(cs, "Failed to find EAP-Sim-Subtype attribute"); + cf_log_err(cs, "Failed to find EAP-Sim-Subtype attribute"); return -1; } - for (subcs = cf_subsection_find_next(cs, NULL, "process"); - subcs != NULL; - subcs = cf_subsection_find_next(cs, subcs, "process")) { + while ((subcs = cf_section_find_next(cs, subcs, "process", NULL))) { char const *name2; fr_dict_enum_t *dv; name2 = cf_section_name2(subcs); if (!name2) { - cf_log_err_cs(subcs, "Cannot compile 'process { ... }' section"); + cf_log_err(subcs, "Cannot compile 'process { ... }' section"); return -1; } dv = fr_dict_enum_by_alias(NULL, da, name2); if (!dv) { - cf_log_err_cs(subcs, "Unknown EAP-SIM-Subtype %s", name2); + cf_log_err(subcs, "Unknown EAP-SIM-Subtype %s", name2); return -1; } - cf_log_module(subcs, "Loading process %s {...}", name2); + cf_log_debug(subcs, "Loading process %s {...}", name2); if (unlang_compile(subcs, MOD_AUTHORIZE) < 0) { - cf_log_err_cs(subcs, "Failed compiling 'process %s { ... }' section", name2); + cf_log_err(subcs, "Failed compiling 'process %s { ... }' section", name2); return -1; } } diff --git a/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c b/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c index 1de9b860c01..b853822df0b 100644 --- a/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c +++ b/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c @@ -267,7 +267,7 @@ static int mod_instantiate(UNUSED rlm_eap_config_t const *config, void *instance { rlm_eap_ttls_t *inst = talloc_get_type_abort(instance, rlm_eap_ttls_t); - if (!cf_subsection_find_name2(main_config.config, "server", inst->virtual_server)) { + if (!cf_section_find(main_config.config, "server", inst->virtual_server)) { cf_log_err_by_name(cs, "virtual_server", "Unknown virtual server '%s'", inst->virtual_server); return -1; } diff --git a/src/modules/rlm_example/rlm_example.c b/src/modules/rlm_example/rlm_example.c index 5acbecb64b8..8e3ef5fb630 100644 --- a/src/modules/rlm_example/rlm_example.c +++ b/src/modules/rlm_example/rlm_example.c @@ -78,7 +78,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) * Do more work here */ if (!inst->boolean) { - cf_log_err_cs(conf, "Boolean is false: forcing error!"); + cf_log_err(conf, "Boolean is false: forcing error!"); return -1; } diff --git a/src/modules/rlm_exec/rlm_exec.c b/src/modules/rlm_exec/rlm_exec.c index 2880f749ae5..1d6914cc475 100644 --- a/src/modules/rlm_exec/rlm_exec.c +++ b/src/modules/rlm_exec/rlm_exec.c @@ -211,7 +211,7 @@ static int mod_bootstrap(CONF_SECTION *conf, void *instance) p = inst->input; p += radius_list_name(&inst->input_list, p, PAIR_LIST_UNKNOWN); if ((inst->input_list == PAIR_LIST_UNKNOWN) || (*p != '\0')) { - cf_log_err_cs(conf, "Invalid input list '%s'", inst->input); + cf_log_err(conf, "Invalid input list '%s'", inst->input); return -1; } } @@ -220,7 +220,7 @@ static int mod_bootstrap(CONF_SECTION *conf, void *instance) p = inst->output; p += radius_list_name(&inst->output_list, p, PAIR_LIST_UNKNOWN); if ((inst->output_list == PAIR_LIST_UNKNOWN) || (*p != '\0')) { - cf_log_err_cs(conf, "Invalid output list '%s'", inst->output); + cf_log_err(conf, "Invalid output list '%s'", inst->output); return -1; } } @@ -230,7 +230,7 @@ static int mod_bootstrap(CONF_SECTION *conf, void *instance) * then the output pairs must not be defined. */ if (!inst->wait && (inst->output != NULL)) { - cf_log_err_cs(conf, "Cannot read output pairs if wait = no"); + cf_log_err(conf, "Cannot read output pairs if wait = no"); return -1; } @@ -244,7 +244,7 @@ static int mod_bootstrap(CONF_SECTION *conf, void *instance) dval = fr_dict_enum_by_alias(NULL, fr_dict_attr_by_num(NULL, 0, FR_PACKET_TYPE), inst->packet_type); if (!dval) { - cf_log_err_cs(conf, "Unknown packet type %s: See list of VALUEs for Packet-Type in " + cf_log_err(conf, "Unknown packet type %s: See list of VALUEs for Packet-Type in " "share/dictionary", inst->packet_type); return -1; } @@ -258,14 +258,14 @@ static int mod_bootstrap(CONF_SECTION *conf, void *instance) inst->timeout = EXEC_TIMEOUT; } if (inst->timeout < 1) { - cf_log_err_cs(conf, "Timeout '%d' is too small (minimum: 1)", inst->timeout); + cf_log_err(conf, "Timeout '%d' is too small (minimum: 1)", inst->timeout); return -1; } /* * Blocking a request longer than max_request_time isn't going to help anyone. */ if (inst->timeout > main_config.max_request_time) { - cf_log_err_cs(conf, "Timeout '%d' is too large (maximum: %d)", inst->timeout, main_config.max_request_time); + cf_log_err(conf, "Timeout '%d' is too large (maximum: %d)", inst->timeout, main_config.max_request_time); return -1; } diff --git a/src/modules/rlm_json/rlm_json.c b/src/modules/rlm_json/rlm_json.c index 3f7c481ed27..d56ab51f1f1 100644 --- a/src/modules/rlm_json/rlm_json.c +++ b/src/modules/rlm_json/rlm_json.c @@ -125,7 +125,7 @@ static int mod_map_proc_instantiate(CONF_SECTION *cs, UNUSED void *mod_inst, voi rlm_json_jpath_cache_t *cache = cache_inst, **tail = &cache->next; if (!src) { - cf_log_err_cs(cs, "Missing JSON source"); + cf_log_err(cs, "Missing JSON source"); return -1; } @@ -136,7 +136,7 @@ static int mod_map_proc_instantiate(CONF_SECTION *cs, UNUSED void *mod_inst, voi #ifndef HAVE_JSON_OBJECT_GET_INT64 if ((map->lhs->type == TMPL_TYPE_ATTR) && (map->lhs->tmpl_da->type == FR_TYPE_UINT64)) { - cf_log_err_cp(cp, "64bit integers are not supported by linked json-c. " + cf_log_err(cp, "64bit integers are not supported by linked json-c. " "Upgrade to json-c >= 0.10 to use this feature"); return -1; } @@ -152,9 +152,9 @@ static int mod_map_proc_instantiate(CONF_SECTION *cs, UNUSED void *mod_inst, voi error: fr_canonicalize_error(cache, &spaces, &text, slen, fr_strerror()); - cf_log_err_cp(cp, "Syntax error"); - cf_log_err_cp(cp, "%s", p); - cf_log_err_cp(cp, "%s^ %s", spaces, text); + cf_log_err(cp, "Syntax error"); + cf_log_err(cp, "%s", p); + cf_log_err(cp, "%s^ %s", spaces, text); talloc_free(spaces); talloc_free(text); @@ -164,7 +164,7 @@ static int mod_map_proc_instantiate(CONF_SECTION *cs, UNUSED void *mod_inst, voi case TMPL_TYPE_DATA: if (map->rhs->tmpl_value_type != FR_TYPE_STRING) { - cf_log_err_cp(cp, "Right side of map must be a string"); + cf_log_err(cp, "Right side of map must be a string"); return -1; } p = map->rhs->tmpl_value.vb_strvalue; diff --git a/src/modules/rlm_ldap/clients.c b/src/modules/rlm_ldap/clients.c index a581c22ef4f..3a6c5e101a2 100644 --- a/src/modules/rlm_ldap/clients.c +++ b/src/modules/rlm_ldap/clients.c @@ -49,9 +49,9 @@ static int rlm_ldap_client_get_attrs(char const **values, int *idx, CONF_SECTION { CONF_ITEM const *ci; - for (ci = cf_item_find_next(cs, NULL); + for (ci = cf_item_next(cs, NULL); ci != NULL; - ci = cf_item_find_next(cs, ci)) { + ci = cf_item_next(cs, ci)) { char const *value; if (cf_item_is_section(ci)) { diff --git a/src/modules/rlm_ldap/rlm_ldap.c b/src/modules/rlm_ldap/rlm_ldap.c index bac20162596..6c76f97b404 100644 --- a/src/modules/rlm_ldap/rlm_ldap.c +++ b/src/modules/rlm_ldap/rlm_ldap.c @@ -358,7 +358,7 @@ static int ldap_map_verify(CONF_SECTION *cs, UNUSED void *mod_inst, UNUSED void vp_tmpl_t const *src, UNUSED vp_map_t const *maps) { if (!src) { - cf_log_err_cs(cs, "Missing LDAP URI"); + cf_log_err(cs, "Missing LDAP URI"); return -1; } @@ -1165,7 +1165,7 @@ static rlm_rcode_t user_modify(rlm_ldap_t const *inst, REQUEST *request, ldap_ac goto error; } - cs = cf_subsection_find(cf_item_to_section(ci), "update"); + cs = cf_section_find(cf_item_to_section(ci), "update", NULL); if (!cs) { REDEBUG("Section must contain 'update' subsection"); @@ -1175,7 +1175,7 @@ static rlm_rcode_t user_modify(rlm_ldap_t const *inst, REQUEST *request, ldap_ac /* * Iterate over all the pairs, building our mods array */ - for (ci = cf_item_find_next(cs, NULL); ci != NULL; ci = cf_item_find_next(cs, ci)) { + for (ci = cf_item_next(cs, NULL); ci != NULL; ci = cf_item_next(cs, ci)) { bool do_xlat = false; if (total == LDAP_MAX_ATTRMAP) { @@ -1204,7 +1204,7 @@ static rlm_rcode_t user_modify(rlm_ldap_t const *inst, REQUEST *request, ldap_ac continue; } - switch (cf_pair_value_type(cp)) { + switch (cf_pair_value_quote(cp)) { case T_BARE_WORD: case T_SINGLE_QUOTED_STRING: break; @@ -1389,7 +1389,7 @@ static int parse_sub_section(rlm_ldap_t *inst, CONF_SECTION *parent, ldap_acct_s char const *name = section_type_value[comp].section; - cs = cf_subsection_find(parent, name); + cs = cf_section_find(parent, name, NULL); if (!cs) { DEBUG2("rlm_ldap (%s) - Couldn't find configuration for %s, will return NOOP for calls " "from this section", inst->name, name); @@ -1493,7 +1493,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) inst->cs = conf; - options = cf_subsection_find(conf, "options"); + options = cf_section_find(conf, "options", NULL); if (!options || !cf_pair_find(options, "chase_referrals")) { inst->handle_config.chase_referrals_unset = true; /* use OpenLDAP defaults */ } @@ -1503,7 +1503,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) */ if ((parse_sub_section(inst, conf, &inst->accounting, MOD_ACCOUNTING) < 0) || (parse_sub_section(inst, conf, &inst->postauth, MOD_POST_AUTH) < 0)) { - cf_log_err_cs(conf, "Failed parsing configuration"); + cf_log_err(conf, "Failed parsing configuration"); goto error; } @@ -1513,7 +1513,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) */ if (inst->cacheable_group_name && inst->groupobj_membership_filter) { if (!inst->groupobj_name_attr) { - cf_log_err_cs(conf, "Configuration item 'group.name_attribute' must be set if cacheable " + cf_log_err(conf, "Configuration item 'group.name_attribute' must be set if cacheable " "group names are enabled"); goto error; @@ -1527,20 +1527,20 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) */ if (!cf_pair_find(conf, "pool")) { if (!inst->handle_config.server_str) { - cf_log_err_cs(conf, "Configuration item 'server' must have a value"); + cf_log_err(conf, "Configuration item 'server' must have a value"); goto error; } } #ifndef WITH_SASL if (inst->user_sasl.mech) { - cf_log_err_cs(conf, "Configuration item 'user.sasl.mech' not supported. " + cf_log_err(conf, "Configuration item 'user.sasl.mech' not supported. " "Linked libldap does not provide fr_ldap_sasl_bind( function"); goto error; } if (inst->handle_config.admin_sasl.mech) { - cf_log_err_cs(conf, "Configuration item 'sasl.mech' not supported. " + cf_log_err(conf, "Configuration item 'sasl.mech' not supported. " "Linked libldap does not provide fr_ldap_sasl_interactive_bind function"); goto error; } @@ -1548,7 +1548,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) #ifndef HAVE_LDAP_CREATE_SORT_CONTROL if (inst->userobj_sort_by) { - cf_log_err_cs(conf, "Configuration item 'sort_by' not supported. " + cf_log_err(conf, "Configuration item 'sort_by' not supported. " "Linked libldap does not provide ldap_create_sort_control function"); goto error; } @@ -1556,7 +1556,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) #ifndef HAVE_LDAP_URL_PARSE if (inst->use_referral_credentials) { - cf_log_err_cs(conf, "Configuration item 'use_referral_credentials' not supported. " + cf_log_err(conf, "Configuration item 'use_referral_credentials' not supported. " "Linked libldap does not support URL parsing"); goto error; } @@ -1578,7 +1578,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) case ' ': case ',': case ';': - cf_log_err_cs(conf, "Invalid character '%c' found in 'server' configuration item", + cf_log_err(conf, "Invalid character '%c' found in 'server' configuration item", value[j]); goto error; @@ -1600,19 +1600,19 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) char *p; if (ldap_url_parse(value, &ldap_url)){ - cf_log_err_cs(conf, "Parsing LDAP URL \"%s\" failed", value); + cf_log_err(conf, "Parsing LDAP URL \"%s\" failed", value); ldap_url_error: ldap_free_urldesc(ldap_url); return -1; } if (ldap_url->lud_dn && (ldap_url->lud_dn[0] != '\0')) { - cf_log_err_cs(conf, "Base DN cannot be specified via server URL"); + cf_log_err(conf, "Base DN cannot be specified via server URL"); goto ldap_url_error; } if (ldap_url->lud_attrs && ldap_url->lud_attrs[0]) { - cf_log_err_cs(conf, "Attribute list cannot be specified via server URL"); + cf_log_err(conf, "Attribute list cannot be specified via server URL"); goto ldap_url_error; } @@ -1620,7 +1620,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) * ldap_url_parse sets this to base by default. */ if (ldap_url->lud_scope != LDAP_SCOPE_BASE) { - cf_log_err_cs(conf, "Scope cannot be specified via server URL"); + cf_log_err(conf, "Scope cannot be specified via server URL"); goto ldap_url_error; } ldap_url->lud_scope = -1; /* Otherwise LDAP adds ?base */ @@ -1648,7 +1648,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) if (ldap_url->lud_scheme) { if (strcmp(ldap_url->lud_scheme, "ldaps") == 0) { if (inst->handle_config.start_tls == true) { - cf_log_err_cs(conf, "ldaps:// scheme is not compatible " + cf_log_err(conf, "ldaps:// scheme is not compatible " "with 'start_tls'"); goto ldap_url_error; } @@ -1675,7 +1675,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) url = ldap_url_desc2str(ldap_url); if (!url) { - cf_log_err_cs(conf, "Failed recombining URL components"); + cf_log_err(conf, "Failed recombining URL components"); goto ldap_url_error; } inst->handle_config.server = talloc_asprintf_append(inst->handle_config.server, "%s ", url); @@ -1689,7 +1689,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) ((strcmp(ldap_url->lud_scheme, "ldaps") == 0) || (strcmp(ldap_url->lud_scheme, "ldapi") == 0) || (strcmp(ldap_url->lud_scheme, "cldap") == 0))) { - cf_log_err_cs(conf, "%s is not supported by linked libldap", + cf_log_err(conf, "%s is not supported by linked libldap", ldap_url->lud_scheme); return -1; } @@ -1740,10 +1740,10 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) if (strchr(value, '/')) { bad_server_fmt: #ifdef LDAP_CAN_PARSE_URLS - cf_log_err_cs(conf, "Invalid 'server' entry, must be in format [:] or " + cf_log_err(conf, "Invalid 'server' entry, must be in format [:] or " "an ldap URI (ldap|cldap|ldaps|ldapi)://:"); #else - cf_log_err_cs(conf, "Invalid 'server' entry, must be in format [:]"); + cf_log_err(conf, "Invalid 'server' entry, must be in format [:]"); #endif return -1; } @@ -1795,7 +1795,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) inst->handle_config.dereference = fr_str2int(fr_ldap_dereference, inst->handle_config.dereference_str, -1); if (inst->handle_config.dereference < 0) { - cf_log_err_cs(conf, "Invalid 'dereference' value \"%s\", expected 'never', 'searching', " + cf_log_err(conf, "Invalid 'dereference' value \"%s\", expected 'never', 'searching', " "'finding' or 'always'", inst->handle_config.dereference_str); goto error; } @@ -1807,7 +1807,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) * variable for the username, password, etc. */ if (inst->rebind == true) { - cf_log_err_cs(conf, "Cannot use 'rebind' configuration item as this version of libldap " + cf_log_err(conf, "Cannot use 'rebind' configuration item as this version of libldap " "does not support the API that we need"); goto error; @@ -1819,7 +1819,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) */ inst->userobj_scope = fr_str2int(fr_ldap_scope, inst->userobj_scope_str, -1); if (inst->userobj_scope < 0) { - cf_log_err_cs(conf, "Invalid 'user.scope' value \"%s\", expected 'sub', 'one'" + cf_log_err(conf, "Invalid 'user.scope' value \"%s\", expected 'sub', 'one'" #ifdef LDAP_SCOPE_CHILDREN ", 'base' or 'children'" #else @@ -1831,7 +1831,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) inst->groupobj_scope = fr_str2int(fr_ldap_scope, inst->groupobj_scope_str, -1); if (inst->groupobj_scope < 0) { - cf_log_err_cs(conf, "Invalid 'group.scope' value \"%s\", expected 'sub', 'one'" + cf_log_err(conf, "Invalid 'group.scope' value \"%s\", expected 'sub', 'one'" #ifdef LDAP_SCOPE_CHILDREN ", 'base' or 'children'" #else @@ -1843,7 +1843,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) inst->clientobj_scope = fr_str2int(fr_ldap_scope, inst->clientobj_scope_str, -1); if (inst->clientobj_scope < 0) { - cf_log_err_cs(conf, "Invalid 'client.scope' value \"%s\", expected 'sub', 'one'" + cf_log_err(conf, "Invalid 'client.scope' value \"%s\", expected 'sub', 'one'" #ifdef LDAP_SCOPE_CHILDREN ", 'base' or 'children'" #else @@ -1866,7 +1866,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) ret = ldap_create_sort_keylist(&keys, p); if (ret != LDAP_SUCCESS) { - cf_log_err_cs(conf, "Invalid user.sort_by value \"%s\": %s", + cf_log_err(conf, "Invalid user.sort_by value \"%s\": %s", inst->userobj_sort_by, ldap_err2string(ret)); goto error; } @@ -1892,12 +1892,12 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) inst->handle_config.tls_require_cert = fr_str2int(fr_ldap_tls_require_cert, inst->handle_config.tls_require_cert_str, -1); if (inst->handle_config.tls_require_cert < 0) { - cf_log_err_cs(conf, "Invalid 'tls.require_cert' value \"%s\", expected 'never', " + cf_log_err(conf, "Invalid 'tls.require_cert' value \"%s\", expected 'never', " "'demand', 'allow', 'try' or 'hard'", inst->handle_config.tls_require_cert_str); goto error; } #else - cf_log_err_cs(conf, "Modifying 'tls.require_cert' is not supported by current " + cf_log_err(conf, "Modifying 'tls.require_cert' is not supported by current " "version of libldap. Please upgrade or substitute current libldap and " "rebuild this module"); @@ -1908,7 +1908,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) /* * Build the attribute map */ - update = cf_subsection_find(inst->cs, "update"); + update = cf_section_find(inst->cs, "update", NULL); if (update && (map_afrom_cs(&inst->user_map, update, PAIR_LIST_REPLY, PAIR_LIST_REQUEST, fr_ldap_map_verify, NULL, LDAP_MAX_ATTRMAP) < 0)) { @@ -1933,22 +1933,22 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) if (inst->do_clients) { CONF_SECTION *cs, *map, *tmpl; - cs = cf_subsection_find(inst->cs, "client"); + cs = cf_section_find(inst->cs, "client", NULL); if (!cs) { - cf_log_err_cs(conf, "Told to load clients but no client section found"); + cf_log_err(conf, "Told to load clients but no client section found"); goto error; } - map = cf_subsection_find(cs, "attribute"); + map = cf_section_find(cs, "attribute", NULL); if (!map) { - cf_log_err_cs(cs, "Told to load clients but no attribute section found"); + cf_log_err(cs, "Told to load clients but no attribute section found"); goto error; } - tmpl = cf_subsection_find(cs, "template"); + tmpl = cf_section_find(cs, "template", NULL); if (rlm_ldap_client_load(inst, tmpl, map) < 0) { - cf_log_err_cs(cs, "Error loading clients"); + cf_log_err(cs, "Error loading clients"); return -1; } diff --git a/src/modules/rlm_linelog/rlm_linelog.c b/src/modules/rlm_linelog/rlm_linelog.c index 571a391e5e5..5701f17ee7c 100644 --- a/src/modules/rlm_linelog/rlm_linelog.c +++ b/src/modules/rlm_linelog/rlm_linelog.c @@ -311,12 +311,12 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) inst->log_dst = fr_str2int(linefr_log_dst_table, inst->log_dst_str, LINELOG_DST_INVALID); if (inst->log_dst == LINELOG_DST_INVALID) { - cf_log_err_cs(conf, "Invalid log destination \"%s\"", inst->log_dst_str); + cf_log_err(conf, "Invalid log destination \"%s\"", inst->log_dst_str); return -1; } if (!inst->log_src && !inst->log_ref) { - cf_log_err_cs(conf, "Must specify a log format, or reference"); + cf_log_err(conf, "Must specify a log format, or reference"); return -1; } @@ -332,13 +332,13 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) case LINELOG_DST_FILE: { if (!inst->file.name) { - cf_log_err_cs(conf, "No value provided for 'filename'"); + cf_log_err(conf, "No value provided for 'filename'"); return -1; } inst->file.ef = module_exfile_init(inst, conf, 256, 30, true, NULL, NULL); if (!inst->file.ef) { - cf_log_err_cs(conf, "Failed creating log file context"); + cf_log_err(conf, "Failed creating log file context"); return -1; } @@ -348,7 +348,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) inst->file.group = strtol(inst->file.group_str, &endptr, 10); if (*endptr != '\0') { if (rad_getgid(inst, &(inst->file.group), inst->file.group_str) < 0) { - cf_log_err_cs(conf, "Unable to find system group \"%s\"", + cf_log_err(conf, "Unable to find system group \"%s\"", inst->file.group_str); return -1; } @@ -362,13 +362,13 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) int num; #ifndef HAVE_SYSLOG_H - cf_log_err_cs(conf, "Syslog output is not supported on this system"); + cf_log_err(conf, "Syslog output is not supported on this system"); return -1; #else if (inst->syslog.facility) { num = fr_str2int(syslog_facility_table, inst->syslog.facility, -1); if (num < 0) { - cf_log_err_cs(conf, "Invalid syslog facility \"%s\"", inst->syslog.facility); + cf_log_err(conf, "Invalid syslog facility \"%s\"", inst->syslog.facility); return -1; } inst->syslog.priority |= num; @@ -376,7 +376,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) num = fr_str2int(syslog_severity_table, inst->syslog.severity, -1); if (num < 0) { - cf_log_err_cs(conf, "Invalid syslog severity \"%s\"", inst->syslog.severity); + cf_log_err(conf, "Invalid syslog severity \"%s\"", inst->syslog.severity); return -1; } inst->syslog.priority |= num; @@ -386,23 +386,23 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) case LINELOG_DST_UNIX: #ifndef HAVE_SYS_UN_H - cf_log_err_cs(conf, "Unix sockets are not supported on this sytem"); + cf_log_err(conf, "Unix sockets are not supported on this sytem"); return -1; #else - inst->pool = module_connection_pool_init(cf_subsection_find(conf, "unix"), + inst->pool = module_connection_pool_init(cf_section_find(conf, "unix", NULL), inst, mod_conn_create, NULL, prefix, NULL, NULL); if (!inst->pool) return -1; #endif break; case LINELOG_DST_UDP: - inst->pool = module_connection_pool_init(cf_subsection_find(conf, "udp"), + inst->pool = module_connection_pool_init(cf_section_find(conf, "udp", NULL), inst, mod_conn_create, NULL, prefix, NULL, NULL); if (!inst->pool) return -1; break; case LINELOG_DST_TCP: - inst->pool = module_connection_pool_init(cf_subsection_find(conf, "tcp"), + inst->pool = module_connection_pool_init(cf_section_find(conf, "tcp", NULL), inst, mod_conn_create, NULL, prefix, NULL, NULL); if (!inst->pool) return -1; break; @@ -535,7 +535,7 @@ static rlm_rcode_t mod_do_linelog(void *instance, UNUSED void *thread, REQUEST * * using request as the context (which will hopefully avoid an alloc). */ slen = tmpl_afrom_str(request, &vpt, tmpl_str, talloc_array_length(tmpl_str) - 1, - cf_pair_value_type(cp), REQUEST_CURRENT, PAIR_LIST_REQUEST, true); + cf_pair_value_quote(cp), REQUEST_CURRENT, PAIR_LIST_REQUEST, true); if (slen <= 0) { REMARKER(tmpl_str, -slen, fr_strerror()); return RLM_MODULE_FAIL; diff --git a/src/modules/rlm_logintime/rlm_logintime.c b/src/modules/rlm_logintime/rlm_logintime.c index 5a2db521cad..d468c1df365 100644 --- a/src/modules/rlm_logintime/rlm_logintime.c +++ b/src/modules/rlm_logintime/rlm_logintime.c @@ -206,7 +206,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) rlm_logintime_t *inst = instance; if (inst->min_time == 0) { - cf_log_err_cs(conf, "Invalid value '0' for minimum_timeout"); + cf_log_err(conf, "Invalid value '0' for minimum_timeout"); return -1; } diff --git a/src/modules/rlm_logtee/rlm_logtee.c b/src/modules/rlm_logtee/rlm_logtee.c index f7b63231e12..343e35aab6c 100644 --- a/src/modules/rlm_logtee/rlm_logtee.c +++ b/src/modules/rlm_logtee/rlm_logtee.c @@ -551,7 +551,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) inst->log_dst = fr_str2int(logtee_dst_table, inst->log_dst_str, LOGTEE_DST_INVALID); if (inst->log_dst == LOGTEE_DST_INVALID) { - cf_log_err_cs(conf, "Invalid log destination \"%s\"", inst->log_dst_str); + cf_log_err(conf, "Invalid log destination \"%s\"", inst->log_dst_str); return -1; } @@ -568,12 +568,12 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) */ switch (inst->log_dst) { case LOGTEE_DST_FILE: - cf_log_err_cs(conf, "Teeing to files NYI"); + cf_log_err(conf, "Teeing to files NYI"); return -1; case LOGTEE_DST_UNIX: #ifndef HAVE_SYS_UN_H - cf_log_err_cs(conf, "Unix sockets are not supported on this sytem"); + cf_log_err(conf, "Unix sockets are not supported on this sytem"); return -1; #endif diff --git a/src/modules/rlm_mruby/rlm_mruby.c b/src/modules/rlm_mruby/rlm_mruby.c index d176dffdf89..155757ab489 100644 --- a/src/modules/rlm_mruby/rlm_mruby.c +++ b/src/modules/rlm_mruby/rlm_mruby.c @@ -78,7 +78,7 @@ static void mruby_parse_config(mrb_state *mrb, CONF_SECTION *cs, int lvl, mrb_va DEBUG("%*s%s {", indent_section, " ", cf_section_name1(cs)); - while ((ci = cf_item_find_next(cs, ci))) { + while ((ci = cf_item_next(cs, ci))) { if (cf_item_is_section(ci)) { CONF_SECTION *sub_cs = cf_item_to_section(ci); char const *key = cf_section_name1(sub_cs); @@ -183,7 +183,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) /* Convert a FreeRADIUS config structure into a mruby hash */ inst->mrubyconf_hash = mrb_hash_new(mrb); - cs = cf_subsection_find(conf, "config"); + cs = cf_section_find(conf, "config", NULL); if (cs) mruby_parse_config(mrb, cs, 0, inst->mrubyconf_hash); /* Define the Request class */ diff --git a/src/modules/rlm_mschap/rlm_mschap.c b/src/modules/rlm_mschap/rlm_mschap.c index a1507fcd805..84693e55b1d 100644 --- a/src/modules/rlm_mschap/rlm_mschap.c +++ b/src/modules/rlm_mschap/rlm_mschap.c @@ -617,11 +617,11 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) inst->wb_pool = module_connection_pool_init(conf, inst, mod_conn_create, NULL, NULL, NULL, NULL); if (!inst->wb_pool) { - cf_log_err_cs(conf, "Unable to initialise winbind connection pool"); + cf_log_err(conf, "Unable to initialise winbind connection pool"); return -1; } #else - cf_log_err_cs(conf, "'winbind' auth not enabled at compiled time"); + cf_log_err(conf, "'winbind' auth not enabled at compiled time"); return -1; #endif } @@ -652,12 +652,12 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) inst->ntlm_auth_timeout = EXEC_TIMEOUT; } if (inst->ntlm_auth_timeout < 1) { - cf_log_err_cs(conf, "ntml_auth_timeout '%d' is too small (minimum: 1)", + cf_log_err(conf, "ntml_auth_timeout '%d' is too small (minimum: 1)", inst->ntlm_auth_timeout); return -1; } if (inst->ntlm_auth_timeout > 10) { - cf_log_err_cs(conf, "ntlm_auth_timeout '%d' is too large (maximum: 10)", + cf_log_err(conf, "ntlm_auth_timeout '%d' is too large (maximum: 10)", inst->ntlm_auth_timeout); return -1; } diff --git a/src/modules/rlm_passwd/rlm_passwd.c b/src/modules/rlm_passwd/rlm_passwd.c index cc0d5c1ef17..68f03a0eccc 100644 --- a/src/modules/rlm_passwd/rlm_passwd.c +++ b/src/modules/rlm_passwd/rlm_passwd.c @@ -394,7 +394,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) rad_assert(inst->format && *inst->format); if (inst->hash_size == 0) { - cf_log_err_cs(conf, "Invalid value '0' for hash_size"); + cf_log_err(conf, "Invalid value '0' for hash_size"); return -1; } @@ -429,7 +429,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) s++; }while(*s); if(keyfield < 0) { - cf_log_err_cs(conf, "no field marked as key in format: %s", + cf_log_err(conf, "no field marked as key in format: %s", inst->format); return -1; } @@ -465,7 +465,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) if (*inst->pwdfmt->field[i] == '~') inst->pwdfmt->field[i]++; } if (!*inst->pwdfmt->field[keyfield]) { - cf_log_err_cs(conf, "key field is empty"); + cf_log_err(conf, "key field is empty"); release_ht(inst->ht); inst->ht = NULL; return -1; diff --git a/src/modules/rlm_perl/rlm_perl.c b/src/modules/rlm_perl/rlm_perl.c index 0ab56af6d7b..fd00b009fdd 100644 --- a/src/modules/rlm_perl/rlm_perl.c +++ b/src/modules/rlm_perl/rlm_perl.c @@ -443,7 +443,7 @@ static void perl_parse_config(CONF_SECTION *cs, int lvl, HV *rad_hv) CONF_ITEM *ci = NULL; - while ((ci = cf_item_find_next(cs, ci))) { + while ((ci = cf_item_next(cs, ci))) { /* * This is a section. * Create a new HV, store it as a reference in current HV, @@ -603,7 +603,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) } /* parse perl configuration sub-section */ - cs = cf_subsection_find(conf, "config"); + cs = cf_section_find(conf, "config", NULL); if (cs) { inst->rad_perlconf_hv = get_hv("RAD_PERLCONF", 1); perl_parse_config(cs, 0, inst->rad_perlconf_hv); diff --git a/src/modules/rlm_python/rlm_python.c b/src/modules/rlm_python/rlm_python.c index 3cbef4939dc..a79a0241175 100644 --- a/src/modules/rlm_python/rlm_python.c +++ b/src/modules/rlm_python/rlm_python.c @@ -796,7 +796,7 @@ static void python_parse_config(CONF_SECTION *cs, int lvl, PyObject *dict) DEBUG("%*s%s {", indent_section, " ", cf_section_name1(cs)); - while ((ci = cf_item_find_next(cs, ci))) { + while ((ci = cf_item_next(cs, ci))) { /* * This is a section. * Create a new dict, store it in current dict, @@ -984,7 +984,7 @@ static int python_interpreter_init(rlm_python_t *inst, CONF_SECTION *conf) */ if (PyModule_AddObject(inst->module, "config", inst->pythonconf_dict) < 0) goto error; - cs = cf_subsection_find(conf, "config"); + cs = cf_section_find(conf, "config", NULL); if (cs) python_parse_config(cs, 0, inst->pythonconf_dict); } else { inst->module = main_module; diff --git a/src/modules/rlm_radius_client/rlm_radius_client.c b/src/modules/rlm_radius_client/rlm_radius_client.c index ee5a6badb44..47199c47efa 100644 --- a/src/modules/rlm_radius_client/rlm_radius_client.c +++ b/src/modules/rlm_radius_client/rlm_radius_client.c @@ -235,14 +235,14 @@ static rlm_rcode_t mod_resume_continue(REQUEST *request, void *instance, void *t } if (child->reply) { - unlang = cf_subsection_find_name2(inst->server_cs, "recv", fr_packet_codes[child->reply->code]); + unlang = cf_section_find(inst->server_cs, "recv", fr_packet_codes[child->reply->code]); } else { - unlang = cf_subsection_find_name2(inst->server_cs, "recv", "timeout"); + unlang = cf_section_find(inst->server_cs, "recv", "timeout"); } if (!unlang) goto done; - RDEBUG("Running 'recv %s' from file %s", cf_section_name2(unlang), cf_section_filename(unlang)); + RDEBUG("Running 'recv %s' from file %s", cf_section_name2(unlang), cf_filename(unlang)); unlang_push_section(child, unlang, RLM_MODULE_NOOP); child->request_state = REQUEST_RECV; @@ -592,11 +592,11 @@ static rlm_rcode_t CC_HINT(nonnull) mod_process(void *instance, void *thread, RE */ if (!inst->server_cs) return mod_wait_for_reply(request, inst, ccr); - unlang = cf_subsection_find_name2(inst->server_cs, "send", fr_packet_codes[packet->code]); + unlang = cf_section_find(inst->server_cs, "send", fr_packet_codes[packet->code]); if (!unlang) return mod_wait_for_reply(request, inst, ccr); - RDEBUG("Running 'send %s' from file %s", cf_section_name2(unlang), cf_section_filename(unlang)); + RDEBUG("Running 'send %s' from file %s", cf_section_name2(unlang), cf_filename(unlang)); unlang_push_section(child, unlang, RLM_MODULE_NOOP); child->request_state = REQUEST_SEND; @@ -634,13 +634,13 @@ static int mod_compile_section(CONF_SECTION *server_cs, char const *name1, char { CONF_SECTION *cs; - cs = cf_subsection_find_name2(server_cs, name1, name2); + cs = cf_section_find(server_cs, name1, name2); if (!cs) return 0; - cf_log_module(cs, "Loading %s %s {...}", name1, name2); + cf_log_debug(cs, "Loading %s %s {...}", name1, name2); if (unlang_compile(cs, MOD_AUTHORIZE) < 0) { - cf_log_err_cs(cs, "Failed compiling '%s %s { ... }' section", name1, name2); + cf_log_err(cs, "Failed compiling '%s %s { ... }' section", name1, name2); return -1; } @@ -657,32 +657,32 @@ static int mod_bootstrap(CONF_SECTION *config, void *instance) inst->name = cf_section_name2(config); if (!inst->name) inst->name = cf_section_name1(config); - cs = cf_subsection_find_next(config, NULL, "home_server"); + cs = cf_section_find(config, "home_server", NULL); if (!cs) { - cf_log_err_cs(config, "You must specify at least one home server"); + cf_log_err(config, "You must specify at least one home server"); return -1; } - if (cf_subsection_find_next(config, cs, "home_server") != NULL) { - cf_log_err_cs(config, "Too many home servers were given."); + if (cf_section_find_next(config, cs, "home_server", NULL) != NULL) { + cf_log_err(config, "Too many home servers were given."); return -1; } home = home_server_afrom_cs(config, NULL, cs); if (!home) { - cf_log_err_cs(config, "Failed parsing home server"); + cf_log_err(config, "Failed parsing home server"); return -1; } #ifdef WITH_TCP if (home->proto != IPPROTO_UDP) { - cf_log_err_cs(config, "Only home servers of 'proto = udp' are allowed."); + cf_log_err(config, "Only home servers of 'proto = udp' are allowed."); return -1; } #endif if (home->ping_check != HOME_PING_CHECK_NONE) { - cf_log_err_cs(config, "Only home servers of 'status_check = none' is allowed."); + cf_log_err(config, "Only home servers of 'status_check = none' is allowed."); return -1; } @@ -692,9 +692,9 @@ static int mod_bootstrap(CONF_SECTION *config, void *instance) if (!inst->virtual_server) return RLM_MODULE_OK; - cs = cf_subsection_find_name2(main_config.config, "server", inst->virtual_server); + cs = cf_section_find(main_config.config, "server", inst->virtual_server); if (!cs) { - cf_log_err_cs(config, "Unknown virtual server '%s'.", inst->virtual_server); + cf_log_err(config, "Unknown virtual server '%s'.", inst->virtual_server); return RLM_MODULE_FAIL; } @@ -730,7 +730,7 @@ static int mod_bootstrap(CONF_SECTION *config, void *instance) break; default: - cf_log_err_cs(config, "Internal sanity check error"); + cf_log_err(config, "Internal sanity check error"); return -1; } diff --git a/src/modules/rlm_realm/rlm_realm.c b/src/modules/rlm_realm/rlm_realm.c index 88012df732c..0dc0db221aa 100644 --- a/src/modules/rlm_realm/rlm_realm.c +++ b/src/modules/rlm_realm/rlm_realm.c @@ -370,7 +370,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) inst->format = REALM_FORMAT_PREFIX; } else { - cf_log_err_cs(conf, "Invalid value \"%s\" for format", + cf_log_err(conf, "Invalid value \"%s\" for format", inst->format_string); return -1; } @@ -378,7 +378,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) if (strcmp(inst->delim, "\\\\") == 0) { /* it's OK */ } else if (strlen(inst->delim) != 1) { - cf_log_err_cs(conf, "Invalid value \"%s\" for delimiter", + cf_log_err(conf, "Invalid value \"%s\" for delimiter", inst->delim); return -1; } diff --git a/src/modules/rlm_redis/cluster.c b/src/modules/rlm_redis/cluster.c index 57e7c84d0ec..4810948fc86 100644 --- a/src/modules/rlm_redis/cluster.c +++ b/src/modules/rlm_redis/cluster.c @@ -381,7 +381,7 @@ static cluster_rcode_t cluster_node_connect(fr_redis_cluster_t *cluster, cluster snprintf(buffer, sizeof(buffer), "%s [%i]", cluster->log_prefix, node->id); node->addr = node->pending_addr; - node->pool = fr_pool_init(cluster, cf_subsection_find(cluster->module, "pool"), node, + node->pool = fr_pool_init(cluster, cf_section_find(cluster->module, "pool", NULL), node, fr_redis_cluster_conn_create, NULL, buffer); if (!node->pool) return CLUSTER_OP_FAILED; fr_pool_reconnect_func(node->pool, _cluster_node_conf_apply); @@ -2240,7 +2240,7 @@ fr_redis_cluster_t *fr_redis_cluster_alloc(TALLOC_CTX *ctx, /* * Ensure we always have a pool section (even if it's empty) */ - mycs = cf_subsection_find(module, "pool"); + mycs = cf_section_find(module, "pool", NULL); if (!mycs) { mycs = cf_section_alloc(module, "pool", NULL); cf_section_add(module, mycs); diff --git a/src/modules/rlm_redis_ippool/rlm_redis_ippool.c b/src/modules/rlm_redis_ippool/rlm_redis_ippool.c index 3faa8a5ea48..a11bc47adaa 100644 --- a/src/modules/rlm_redis_ippool/rlm_redis_ippool.c +++ b/src/modules/rlm_redis_ippool/rlm_redis_ippool.c @@ -1292,7 +1292,7 @@ static rlm_rcode_t mod_post_auth(void *instance, UNUSED void *thread, REQUEST *r static int mod_instantiate(CONF_SECTION *conf, void *instance) { static bool done_hash = false; - CONF_SECTION *subcs = cf_subsection_find_next(conf, NULL, "redis"); + CONF_SECTION *subcs = cf_section_find(conf, "redis", NULL); rlm_redis_ippool_t *inst = instance; diff --git a/src/modules/rlm_redis_ippool/rlm_redis_ippool_tool.c b/src/modules/rlm_redis_ippool/rlm_redis_ippool_tool.c index 068a2a88720..d5309a0efac 100644 --- a/src/modules/rlm_redis_ippool/rlm_redis_ippool_tool.c +++ b/src/modules/rlm_redis_ippool/rlm_redis_ippool_tool.c @@ -1515,7 +1515,7 @@ do { \ /* * Set some alternative default pool settings */ - pool_cs = cf_subsection_find(conf->cs, "pool"); + pool_cs = cf_section_find(conf->cs, "pool", NULL); if (!pool_cs) { pool_cs = cf_section_alloc(conf->cs, "pool", NULL); cf_section_add(conf->cs, pool_cs); diff --git a/src/modules/rlm_rediswho/rlm_rediswho.c b/src/modules/rlm_rediswho/rlm_rediswho.c index 108d1052db5..9232b2ead3f 100644 --- a/src/modules/rlm_rediswho/rlm_rediswho.c +++ b/src/modules/rlm_rediswho/rlm_rediswho.c @@ -186,7 +186,7 @@ static rlm_rcode_t CC_HINT(nonnull) mod_accounting(void *instance, UNUSED void * return RLM_MODULE_NOOP; } - cs = cf_subsection_find(inst->cs, dv->alias); + cs = cf_section_find(inst->cs, dv->alias, NULL); if (!cs) { RDEBUG("No subsection %s", dv->alias); return RLM_MODULE_NOOP; diff --git a/src/modules/rlm_rest/rlm_rest.c b/src/modules/rlm_rest/rlm_rest.c index 5e02e278db3..303d415a2ec 100644 --- a/src/modules/rlm_rest/rlm_rest.c +++ b/src/modules/rlm_rest/rlm_rest.c @@ -755,7 +755,7 @@ static int parse_sub_section(rlm_rest_t *inst, CONF_SECTION *parent, CONF_PARSER { CONF_SECTION *cs; - cs = cf_subsection_find(parent, name); + cs = cf_section_find(parent, name, NULL); if (!cs) { config->name = NULL; return 0; @@ -775,7 +775,7 @@ static int parse_sub_section(rlm_rest_t *inst, CONF_SECTION *parent, CONF_PARSER * Sanity check */ if ((config->username && !config->password) || (!config->username && config->password)) { - cf_log_err_cs(cs, "'username' and 'password' must both be set or both be absent"); + cf_log_err(cs, "'username' and 'password' must both be set or both be absent"); return -1; } @@ -785,11 +785,11 @@ static int parse_sub_section(rlm_rest_t *inst, CONF_SECTION *parent, CONF_PARSER */ config->auth = fr_str2int(http_auth_table, config->auth_str, HTTP_AUTH_UNKNOWN); if (config->auth == HTTP_AUTH_UNKNOWN) { - cf_log_err_cs(cs, "Unknown HTTP auth type '%s'", config->auth_str); + cf_log_err(cs, "Unknown HTTP auth type '%s'", config->auth_str); return -1; } else if ((config->auth != HTTP_AUTH_NONE) && !http_curl_auth[config->auth]) { - cf_log_err_cs(cs, "Unsupported HTTP auth type \"%s\", check libcurl version, OpenSSL build " + cf_log_err(cs, "Unsupported HTTP auth type \"%s\", check libcurl version, OpenSSL build " "configuration, then recompile this module", config->auth_str); return -1; @@ -811,23 +811,23 @@ static int parse_sub_section(rlm_rest_t *inst, CONF_SECTION *parent, CONF_PARSER } if (config->body == HTTP_BODY_UNKNOWN) { - cf_log_err_cs(cs, "Unknown HTTP body type '%s'", config->body_str); + cf_log_err(cs, "Unknown HTTP body type '%s'", config->body_str); return -1; } switch (http_body_type_supported[config->body]) { case HTTP_BODY_UNSUPPORTED: - cf_log_err_cs(cs, "Unsupported HTTP body type \"%s\", please submit patches", + cf_log_err(cs, "Unsupported HTTP body type \"%s\", please submit patches", config->body_str); return -1; case HTTP_BODY_INVALID: - cf_log_err_cs(cs, "Invalid HTTP body type. \"%s\" is not a valid web API data " + cf_log_err(cs, "Invalid HTTP body type. \"%s\" is not a valid web API data " "markup format", config->body_str); return -1; case HTTP_BODY_UNAVAILABLE: - cf_log_err_cs(cs, "Unavailable HTTP body type. \"%s\" is not available in this " + cf_log_err(cs, "Unavailable HTTP body type. \"%s\" is not available in this " "build", config->body_str); return -1; @@ -857,18 +857,18 @@ static int parse_sub_section(rlm_rest_t *inst, CONF_SECTION *parent, CONF_PARSER } if (config->force_to == HTTP_BODY_UNKNOWN) { - cf_log_err_cs(cs, "Unknown forced response body type '%s'", config->force_to_str); + cf_log_err(cs, "Unknown forced response body type '%s'", config->force_to_str); return -1; } switch (http_body_type_supported[config->force_to]) { case HTTP_BODY_UNSUPPORTED: - cf_log_err_cs(cs, "Unsupported forced response body type \"%s\", please submit patches", + cf_log_err(cs, "Unsupported forced response body type \"%s\", please submit patches", config->force_to_str); return -1; case HTTP_BODY_INVALID: - cf_log_err_cs(cs, "Invalid HTTP forced response body type. \"%s\" is not a valid web API data " + cf_log_err(cs, "Invalid HTTP forced response body type. \"%s\" is not a valid web API data " "markup format", config->force_to_str); return -1; diff --git a/src/modules/rlm_sigtran/rlm_sigtran.c b/src/modules/rlm_sigtran/rlm_sigtran.c index 94a104a0a39..1536be542fb 100644 --- a/src/modules/rlm_sigtran/rlm_sigtran.c +++ b/src/modules/rlm_sigtran/rlm_sigtran.c @@ -213,14 +213,14 @@ static int sigtran_sccp_sockaddr_from_conf(TALLOC_CTX *ctx, rlm_sigtran_t *inst, * Fixme should be conf->gt_is_set */ if (!conf->ssn_is_set && !conf->pc_is_set && !conf->gt.address) { - cf_log_err_cs(cs, "At least one of 'pc', 'ssn', or 'gt', must be set"); + cf_log_err(cs, "At least one of 'pc', 'ssn', or 'gt', must be set"); return -1; } if (conf->ssn_is_set) out->ssn = conf->ssn; if (conf->pc_is_set) { if (conf->pc > 16777215) { - cf_log_err_cs(cs, "Invalid value \"%d\" for 'pc', must be between 0-" + cf_log_err(cs, "Invalid value \"%d\" for 'pc', must be between 0-" STRINGIFY(16777215), conf->pc); return -1; } @@ -239,25 +239,25 @@ static int sigtran_sccp_sockaddr_from_conf(TALLOC_CTX *ctx, rlm_sigtran_t *inst, size_t len = talloc_array_length(conf->gt.address) - 1; if (conf->gt.nai_is_set && (conf->gt.nai & 0x80)) { - cf_log_err_cs(cs, "Global title 'nai' must be between 0-127"); + cf_log_err(cs, "Global title 'nai' must be between 0-127"); return -1; } if (conf->gt.tt_is_set) { if ((conf->gt.np_is_set && !conf->gt.es_is_set) || (!conf->gt.np_is_set && conf->gt.np_is_set)) { - cf_log_err_cs(cs, "Global title 'np' and 'es' must be " + cf_log_err(cs, "Global title 'np' and 'es' must be " "specified together"); return -1; } if (conf->gt.np) { - cf_log_err_cs(cs, "Global title 'np' must be between 0-15"); + cf_log_err(cs, "Global title 'np' must be between 0-15"); return -1; } if (conf->gt.es > 0x0f) { - cf_log_err_cs(cs, "Global title 'es' must be between 0-15"); + cf_log_err(cs, "Global title 'es' must be between 0-15"); return -1; } @@ -273,7 +273,7 @@ static int sigtran_sccp_sockaddr_from_conf(TALLOC_CTX *ctx, rlm_sigtran_t *inst, for (i = 0; i < len; i++) { if (!is_char_tbcd[(uint8_t)conf->gt.address[i]]) { - cf_log_err_cs(cs, "Global title address contains invalid digit \"%c\". " + cf_log_err(cs, "Global title address contains invalid digit \"%c\". " "Valid digits are [0-9#*a-c]", conf->gt.address[i]); return -1; } @@ -313,7 +313,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) inst->conn_conf.m3ua_traffic_mode = fr_str2int(m3ua_traffic_mode_table, inst->conn_conf.m3ua_traffic_mode_str, -1); if (inst->conn_conf.m3ua_traffic_mode < 0) { - cf_log_err_cs(conf, "Invalid 'm3ua_traffic_mode' value \"%s\", expected 'override', " + cf_log_err(conf, "Invalid 'm3ua_traffic_mode' value \"%s\", expected 'override', " "'loadshare' or 'broadcast'", inst->conn_conf.m3ua_traffic_mode_str); return -1; } @@ -321,7 +321,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) #define MTP3_PC_CHECK(_x) \ do { \ if (inst->conn_conf.mtp3_##_x > 16777215) { \ - cf_log_err_cs(conf, "Invalid value \"%d\" for '#_x', must be between 0-16777215", \ + cf_log_err(conf, "Invalid value \"%d\" for '#_x', must be between 0-16777215", \ inst->conn_conf.mtp3_##_x); \ return -1; \ } \ diff --git a/src/modules/rlm_sometimes/rlm_sometimes.c b/src/modules/rlm_sometimes/rlm_sometimes.c index 82cbff89c45..50a1b5a130f 100644 --- a/src/modules/rlm_sometimes/rlm_sometimes.c +++ b/src/modules/rlm_sometimes/rlm_sometimes.c @@ -56,7 +56,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) */ inst->rcode = fr_str2int(mod_rcode_table, inst->rcode_str, RLM_MODULE_UNKNOWN); if (inst->rcode == RLM_MODULE_UNKNOWN) { - cf_log_err_cs(conf, "Unknown module return code '%s'", inst->rcode_str); + cf_log_err(conf, "Unknown module return code '%s'", inst->rcode_str); return -1; } diff --git a/src/modules/rlm_sql/drivers/rlm_sql_cassandra/rlm_sql_cassandra.c b/src/modules/rlm_sql/drivers/rlm_sql_cassandra/rlm_sql_cassandra.c index afbc05da03b..ebf36942818 100644 --- a/src/modules/rlm_sql/drivers/rlm_sql_cassandra/rlm_sql_cassandra.c +++ b/src/modules/rlm_sql/drivers/rlm_sql_cassandra/rlm_sql_cassandra.c @@ -714,8 +714,8 @@ do {\ * This has to be done before we call cf_section_parse * as it sets default values, and creates the section. */ - if (cf_subsection_find(cs, "tls")) do_tls = true; - if (cf_subsection_find(cs, "latency_aware_routing")) do_latency_aware_routing = true; + if (cf_section_find(cs, "tls"), NULL) do_tls = true; + if (cf_section_find(cs, "latency_aware_routing"), NULL) do_latency_aware_routing = true; DEBUG4("Configuring CassCluster structure"); cluster = inst->cluster = cass_cluster_new(); diff --git a/src/modules/rlm_sql/drivers/rlm_sql_postgresql/rlm_sql_postgresql.c b/src/modules/rlm_sql/drivers/rlm_sql_postgresql/rlm_sql_postgresql.c index 60fc55c717e..f52a6ba4ed3 100644 --- a/src/modules/rlm_sql/drivers/rlm_sql_postgresql/rlm_sql_postgresql.c +++ b/src/modules/rlm_sql/drivers/rlm_sql_postgresql/rlm_sql_postgresql.c @@ -440,7 +440,7 @@ static int mod_instantiate(rlm_sql_config_t const *config, void *instance, CONF_ CONF_SECTION *cs; char const *name; - cs = cf_section_parent(conf); + cs = cf_item_to_section(cf_parent(conf)); name = cf_section_name2(cs); if (!name) name = cf_section_name1(cs); diff --git a/src/modules/rlm_sql/rlm_sql.c b/src/modules/rlm_sql/rlm_sql.c index ef1be0b768d..b16b87e4e29 100644 --- a/src/modules/rlm_sql/rlm_sql.c +++ b/src/modules/rlm_sql/rlm_sql.c @@ -284,7 +284,7 @@ static int sql_map_verify(CONF_SECTION *cs, UNUSED void *mod_inst, UNUSED void * vp_tmpl_t const *src, UNUSED vp_map_t const *maps) { if (!src) { - cf_log_err_cs(cs, "Missing SQL query"); + cf_log_err(cs, "Missing SQL query"); return -1; } @@ -1074,7 +1074,7 @@ static int mod_bootstrap(CONF_SECTION *conf, void *instance) /* * Get the module's subsection or allocate one */ - driver_cs = cf_subsection_find(conf, name); + driver_cs = cf_section_find(conf, name, NULL); if (!driver_cs) { driver_cs = cf_section_alloc(conf, name, NULL); if (!driver_cs) return -1; @@ -1203,10 +1203,10 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) * configuration. So if that doesn't exist, we ignore * the whole subsection. */ - inst->config->accounting.cs = cf_subsection_find(conf, "accounting"); + inst->config->accounting.cs = cf_section_find(conf, "accounting", NULL); inst->config->accounting.reference_cp = (cf_pair_find(inst->config->accounting.cs, "reference") != NULL); - inst->config->postauth.cs = cf_subsection_find(conf, "post-auth"); + inst->config->postauth.cs = cf_section_find(conf, "post-auth", NULL); inst->config->postauth.reference_cp = (cf_pair_find(inst->config->postauth.cs, "reference") != NULL); /* @@ -1236,7 +1236,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) inst->ef = module_exfile_init(inst, conf, 256, 30, true, NULL, NULL); if (!inst->ef) { - cf_log_err_cs(conf, "Failed creating log file context"); + cf_log_err(conf, "Failed creating log file context"); return -1; } diff --git a/src/modules/rlm_sqlcounter/rlm_sqlcounter.c b/src/modules/rlm_sqlcounter/rlm_sqlcounter.c index 8d10ed171f4..44c1e113f4e 100644 --- a/src/modules/rlm_sqlcounter/rlm_sqlcounter.c +++ b/src/modules/rlm_sqlcounter/rlm_sqlcounter.c @@ -546,7 +546,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) inst->reset_time = 0; if (find_next_reset(inst, now) == -1) { - cf_log_err_cs(conf, "Invalid reset '%s'", inst->reset); + cf_log_err(conf, "Invalid reset '%s'", inst->reset); return -1; } @@ -556,7 +556,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) inst->last_reset = 0; if (find_prev_reset(inst, now) < 0) { - cf_log_err_cs(conf, "Invalid reset '%s'", inst->reset); + cf_log_err(conf, "Invalid reset '%s'", inst->reset); return -1; } @@ -577,30 +577,30 @@ static int mod_bootstrap(CONF_SECTION *conf, void *instance) memset(&flags, 0, sizeof(flags)); flags.compare = 1; /* ugly hack */ if (tmpl_define_undefined_attr(inst->paircmp_attr, FR_TYPE_UINT64, &flags) < 0) { - cf_log_err_cs(conf, "Failed defining counter attribute: %s", fr_strerror()); + cf_log_err(conf, "Failed defining counter attribute: %s", fr_strerror()); return -1; } flags.compare = 0; if (tmpl_define_undefined_attr(inst->limit_attr, FR_TYPE_UINT64, &flags) < 0) { - cf_log_err_cs(conf, "Failed defining check attribute: %s", fr_strerror()); + cf_log_err(conf, "Failed defining check attribute: %s", fr_strerror()); return -1; } if (inst->paircmp_attr->tmpl_da->type != FR_TYPE_UINT64) { - cf_log_err_cs(conf, "Counter attribute %s MUST be uint64", + cf_log_err(conf, "Counter attribute %s MUST be uint64", inst->paircmp_attr->tmpl_da->name); return -1; } if (paircompare_register_byname(inst->paircmp_attr->tmpl_da->name, NULL, true, counter_cmp, inst) < 0) { - cf_log_err_cs(conf, "Failed registering comparison function for counter attribute %s: %s", + cf_log_err(conf, "Failed registering comparison function for counter attribute %s: %s", inst->paircmp_attr->tmpl_da->name, fr_strerror()); return -1; } if (inst->limit_attr->tmpl_da->type != FR_TYPE_UINT64) { - cf_log_err_cs(conf, "Check attribute %s MUST be uint64", + cf_log_err(conf, "Check attribute %s MUST be uint64", inst->limit_attr->tmpl_da->name); return -1; } diff --git a/src/modules/rlm_sqlhpwippool/rlm_sqlhpwippool.c b/src/modules/rlm_sqlhpwippool/rlm_sqlhpwippool.c index 36d7f81a7d3..f4056fe0812 100644 --- a/src/modules/rlm_sqlhpwippool/rlm_sqlhpwippool.c +++ b/src/modules/rlm_sqlhpwippool/rlm_sqlhpwippool.c @@ -268,9 +268,9 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) inst->sincesync = 0; - sql_inst = module_find(cf_subsection_find(main_config.config, "modules"), inst->sql_instance_name); + sql_inst = module_find(cf_section_find(main_config.config, "modules", NULL), inst->sql_instance_name); if (!sql_inst) { - cf_log_err_cs(conf, "Cannot find SQL module instance named \"%s\"", + cf_log_err(conf, "Cannot find SQL module instance named \"%s\"", inst->sql_instance_name); return -1; } @@ -281,7 +281,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) /* check if the given instance is really a rlm_sql instance */ if (strcmp(inst->sql_inst->driver->name, "sql") != 0) { - cf_log_err_cs(conf, "Module \"%s\" is not an instance of the rlm_sql module", + cf_log_err(conf, "Module \"%s\" is not an instance of the rlm_sql module", inst->sql_instance_name); return -1; } diff --git a/src/modules/rlm_sqlippool/rlm_sqlippool.c b/src/modules/rlm_sqlippool/rlm_sqlippool.c index 7a914ec3498..44848225bc9 100644 --- a/src/modules/rlm_sqlippool/rlm_sqlippool.c +++ b/src/modules/rlm_sqlippool/rlm_sqlippool.c @@ -384,9 +384,9 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) } else { inst->pool_name = talloc_typed_strdup(inst, "ippool"); } - sql_inst = module_find(cf_subsection_find(main_config.config, "modules"), inst->sql_instance_name); + sql_inst = module_find(cf_section_find(main_config.config, "modules", NULL), inst->sql_instance_name); if (!sql_inst) { - cf_log_err_cs(conf, "failed to find sql instance named %s", + cf_log_err(conf, "failed to find sql instance named %s", inst->sql_instance_name); return -1; } @@ -400,7 +400,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) inst->sql_inst = (rlm_sql_t *) sql_inst->data; if (strcmp(inst->sql_inst->driver->name, "sql") != 0) { - cf_log_err_cs(conf, "Module \"%s\" is not an instance of the rlm_sql module", + cf_log_err(conf, "Module \"%s\" is not an instance of the rlm_sql module", inst->sql_instance_name); return -1; } diff --git a/src/modules/rlm_unbound/rlm_unbound.c b/src/modules/rlm_unbound/rlm_unbound.c index f081e7f4616..b3103d5de8a 100644 --- a/src/modules/rlm_unbound/rlm_unbound.c +++ b/src/modules/rlm_unbound/rlm_unbound.c @@ -376,7 +376,7 @@ static int mod_bootstrap(CONF_SECTION *conf, void *instance) if (!inst->name) inst->name = cf_section_name1(conf); if (inst->timeout > 10000) { - cf_log_err_cs(conf, "timeout must be 0 to 10000"); + cf_log_err(conf, "timeout must be 0 to 10000"); return -1; } @@ -387,7 +387,7 @@ static int mod_bootstrap(CONF_SECTION *conf, void *instance) if (xlat_register(inst, inst->xlat_a_name, xlat_a, NULL, NULL, 0, XLAT_DEFAULT_BUF_LEN) || xlat_register(inst, inst->xlat_aaaa_name, xlat_aaaa, NULL, NULL, 0, XLAT_DEFAULT_BUF_LEN) || xlat_register(inst, inst->xlat_ptr_name, xlat_ptr, NULL, NULL, 0, XLAT_DEFAULT_BUF_LEN)) { - cf_log_err_cs(conf, "Failed registering xlats"); + cf_log_err(conf, "Failed registering xlats"); return -1; } @@ -414,7 +414,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) inst->ub = ub_ctx_create(); if (!inst->ub) { - cf_log_err_cs(conf, "ub_ctx_create failed"); + cf_log_err(conf, "ub_ctx_create failed"); return -1; } @@ -588,13 +588,13 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) * dup it so libunbound doesn't close it on us. */ if (log_fd == -1) { - cf_log_err_cs(conf, "Could not dup fd"); + cf_log_err(conf, "Could not dup fd"); goto error_nores; } inst->log_stream = fdopen(log_fd, "w"); if (!inst->log_stream) { - cf_log_err_cs(conf, "error setting up log stream"); + cf_log_err(conf, "error setting up log stream"); goto error_nores; } @@ -639,7 +639,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) inst->log_fd = ub_fd(inst->ub); if (inst->log_fd >= 0) { if (fr_event_fd_insert(inst->el, inst->log_fd, ub_fd_handler, NULL, NULL, inst) < 0) { - cf_log_err_cs(conf, "could not insert async fd"); + cf_log_err(conf, "could not insert async fd"); inst->log_fd = -1; goto error_nores; } @@ -649,7 +649,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) return 0; error: - cf_log_err_cs(conf, "%s", ub_strerror(res)); + cf_log_err(conf, "%s", ub_strerror(res)); error_nores: if (log_fd > -1) close(log_fd); diff --git a/src/modules/rlm_winbind/rlm_winbind.c b/src/modules/rlm_winbind/rlm_winbind.c index d1cdafd830e..45a3930a0ae 100644 --- a/src/modules/rlm_winbind/rlm_winbind.c +++ b/src/modules/rlm_winbind/rlm_winbind.c @@ -350,13 +350,13 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) struct wbcInterfaceDetails *wb_info = NULL; if (!inst->wb_username) { - cf_log_err_cs(conf, "winbind_username must be defined to use rlm_winbind"); + cf_log_err(conf, "winbind_username must be defined to use rlm_winbind"); return -1; } inst->wb_pool = module_connection_pool_init(conf, inst, mod_conn_create, NULL, NULL, NULL, NULL); if (!inst->wb_pool) { - cf_log_err_cs(conf, "Unable to initialise winbind connection pool"); + cf_log_err(conf, "Unable to initialise winbind connection pool"); return -1; } @@ -368,12 +368,12 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) wbcErr err; struct wbcContext *wb_ctx; - cf_log_err_cs(conf, "winbind_domain unspecified; trying to get it from winbind"); + cf_log_err(conf, "winbind_domain unspecified; trying to get it from winbind"); wb_ctx = wbcCtxCreate(); if (!wb_ctx) { /* this should be very unusual */ - cf_log_err_cs(conf, "Unable to get libwbclient context, cannot get domain"); + cf_log_err(conf, "Unable to get libwbclient context, cannot get domain"); goto no_domain; } @@ -381,14 +381,14 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) wbcCtxFree(wb_ctx); if (err != WBC_ERR_SUCCESS) { - cf_log_err_cs(conf, "libwbclient returned wbcErr code %d; unable to get domain name.", err); - cf_log_err_cs(conf, "Is winbind running and does the winbind_privileged socket have"); - cf_log_err_cs(conf, "the correct permissions?"); + cf_log_err(conf, "libwbclient returned wbcErr code %d; unable to get domain name.", err); + cf_log_err(conf, "Is winbind running and does the winbind_privileged socket have"); + cf_log_err(conf, "the correct permissions?"); goto no_domain; } if (!wb_info->netbios_domain) { - cf_log_err_cs(conf, "winbind returned blank domain name"); + cf_log_err(conf, "winbind returned blank domain name"); goto no_domain; } @@ -396,7 +396,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) strlen(wb_info->netbios_domain), T_SINGLE_QUOTED_STRING, REQUEST_CURRENT, PAIR_LIST_REQUEST, false); - cf_log_err_cs(conf, "Using winbind_domain '%s'", inst->wb_domain->name); + cf_log_err(conf, "Using winbind_domain '%s'", inst->wb_domain->name); no_domain: wbcFreeMemory(wb_info); diff --git a/src/modules/rlm_yubikey/rlm_yubikey.c b/src/modules/rlm_yubikey/rlm_yubikey.c index 85411a7e012..51995dcde4b 100644 --- a/src/modules/rlm_yubikey/rlm_yubikey.c +++ b/src/modules/rlm_yubikey/rlm_yubikey.c @@ -126,7 +126,7 @@ static int mod_bootstrap(CONF_SECTION *conf, void *instance) #ifndef HAVE_YUBIKEY if (inst->decrypt) { - cf_log_err_cs(conf, "Requires libyubikey for OTP decryption"); + cf_log_err(conf, "Requires libyubikey for OTP decryption"); return -1; } #endif @@ -156,9 +156,9 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) #ifdef HAVE_YKCLIENT CONF_SECTION *cs; - cs = cf_subsection_find(conf, "validation"); + cs = cf_section_find(conf, "validation", CF_IDENT_ANY); if (!cs) { - cf_log_err_cs(conf, "Missing validation section"); + cf_log_err(conf, "Missing validation section"); return -1; } @@ -166,7 +166,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance) return -1; } #else - cf_log_err_cs(conf, "Requires libykclient for OTP validation against Yubicloud servers"); + cf_log_err(conf, "Requires libykclient for OTP validation against Yubicloud servers"); return -1; #endif } diff --git a/src/modules/rlm_yubikey/validate.c b/src/modules/rlm_yubikey/validate.c index 9b6ca315d6a..8165d4a2260 100644 --- a/src/modules/rlm_yubikey/validate.c +++ b/src/modules/rlm_yubikey/validate.c @@ -88,7 +88,7 @@ yk_error: status = ykclient_init(&inst->ykc); if (status != YKCLIENT_OK) goto yk_error; - servers = cf_subsection_find(conf, "servers"); + servers = cf_section_find(conf, "servers", CF_IDENT_ANY); if (servers) { CONF_PAIR *uri, *first; /* diff --git a/src/tests/config/test.conf b/src/tests/config/test.conf index f212d0c9ac0..3300be509a0 100644 --- a/src/tests/config/test.conf +++ b/src/tests/config/test.conf @@ -13,9 +13,18 @@ security { allow_vulnerable_openssl = yes } +home_server test.example.com { + ipaddr = 127.0.0.1 + port = ${test_port} + secret = testing123 +} + +home_server_pool test.example.com { + home_server = test.example.com +} + realm test.example.com { - authhost = 127.0.0.1:${test_port} - secret = testing123 + auth_pool = test.example.com } policy { diff --git a/user_password b/user_password new file mode 100644 index 00000000000..a0124c89351 --- /dev/null +++ b/user_password @@ -0,0 +1,2 @@ +User-Name := bob +User-Password := bob