/* Serval DNA configuration Copyright (C) 2012 Serval Project Inc. 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 (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* This file defines the internal API to the configuration file. See "conf_schema.h" for the * definition of the configuration schema, which is used to generate these API components. * * Each STRUCT(NAME, ...) schema declaration generates the following data declaration: * * struct config_NAME { * ... * }; * * A C struct definition containing exactly one element per schema declaration inside the * STRUCT..END_STRUCT block, in the defined order. The TYPE and NAME of each element depends * on the schema declaration that produces it: * * ATOM(TYPE, bar, ...) * NODE(TYPE, bar, ...) * * TYPE bar; * * STRING(SIZE, bar, ...) * * char bar[SIZE+1]; * * SUB_STRUCT(NAME, bar, ...) * NODE_STRUCT(NAME, bar, ...) * * struct config_NAME bar; * * Each ARRAY(NAME, ...) ... END_ARRAY(SIZE) schema declaration produces the following data * declaration: * * struct config_NAME { * unsigned ac; * struct config_NAME__element { * KEY-DECLARATION; * VALUE-DECLARATION; * } av[SIZE]; * }; * * A C struct definition containing a count 'ac' of the number of array elements 0..SIZE-1, * and 'av' an array of element values, each one consisting of a key and a value: * * KEY_ATOM(TYPE, ...) * * TYPE key; * * KEY_STRING(SIZE, ...) * * char key[SIZE+1]; * * VALUE_ATOM(NAME, SIZE, LABELLEN, TYPE, ...) * VALUE_NODE(NAME, SIZE, LABELLEN, TYPE, ...) * * TYPE value; * * VALUE_STRING(STRINGSIZE, ...) * * char value[STRINGSIZE+1]; * * VALUE_SUB_STRUCT(STRUCTNAME) * VALUE_NODE_STRUCT(STRUCTNAME, ...) * * struct config_STRUCTNAME value; * * Each STRUCT(NAME, ...) and ARRAY(NAME, ...) schema declaration generates the following API * functions: * * - int cf_dfl_config_NAME(struct config_NAME *dest); * * A C function which sets the entire contents of the given C structure to its default values * as defined in the schema. This will only return CFOK or CFERROR; see below. * * - int cf_opt_config_NAME(struct config_NAME *dest, const struct cf_om_node *node); * * A C function which parses the given COM (configuration object model) and assigns the parsed * result into the given C structure. See below for the return value. For arrays, this * function is used to parse each individual array element, and the parsed result is only * appended to the array if it returns CFOK. * * If a STRUCT(NAME, VALIDATOR) or ARRAY(NAME, FLAGS, VALIDATOR) schema declaration is given a * validator function, then the function must have the following signature: * * - int VALIDATOR(struct config_NAME *dest, int orig_result); * * A C function which validates the contents of the given C structure (struct or array) as * defined in the schema. This function is invoked by the cf_opt_config_NAME() parser function * just before it returns, so all the parse functions have already been called and the result * is assembled. The validator function is passed a pointer to the (non-const) structure, * which it may modify if desired, and the original CFxxx flags result code (not CFERROR) that * would be returned by the cf_opt_config_NAME() parser function. It returns a new CFxxx flags * result (which may simply be the same as was passed). * * In the case arrays, validator() is passed a *dest containing elements that were successfully * parsed from the COM, omitting any that did not parse successfully (in which case the * relevant CFxxx result flags will be set) and arbitrarily omitting others that did not fit * (in which case the CFOVERFLOW flag is set). It is up to validator() to decide whether to * return some, all or none of these elements (ie, alter dest->ac and/or dest->av), and whether * to set or clear the CFARRAYOVERFLOW bit, or set other bits (like CFINVALID for example). If * there is no validator function, then cf_opt_config_NAME() will return an empty array (dest->ac * == 0) in the case of CFARRAYOVERFLOW. * * All parse functions assign the result of their parsing into the struct given in their 'dest' * argument, and return a bitmask of the following flags: * * - CFERROR (all bits set, == -1) if an unrecoverable error occurs (eg, malloc() fails). The * result in *dest is undefined and may be malformed or inconsistent. * * - CFEMPTY if no items were parsed from the COM. In the case of a struct, this means that no * child nodes were found for any elements; if any child nodes were present but failed parsing * then CFEMPTY is not set but other flags will be set. In the case of arrays, CFEMPTY means * that the returned array has zero length for _any_ reason (overflow, element parsing failures, * or no elements present in the COM). * * - CFUNSUPPORTED if the config item (array or struct) is not supported. This flag is not * produced by the normal cf_opt_config_NAME() parse functions, but a validation function could set * it to indicate that a given option is not yet implemented or has been deprecated. In that * case, the validation function should also log a message to that effect. The CFUNSUPPORTED * flag is mainly used in its CFSUB(CFUNSUPPORTED) form (see below) to indicate that the COM * contains elements that are not defined in the STRUCT. This may indicate a typo in the name * of a config option, resulting in the intended option not being set. * * - CFDUPLICATE if a duplicate array entry was found. The result may be an empty array (in which * case CFEMPTY is also set), or an array that omits the duplicate element. It is not defined * which of the two conflicting elements will get omitted. Normal array parsing without a * validator function will return an empty array in the case of duplicate, but a validator * function may change this behaviour. * * - CFARRAYOVERFLOW if the size of any array was exceeded. The result in *dest may be empty (in * which case CFEMPTY is also set), or may contain elements parsed successfully from the COM (ie, * returned CFOK), omitting any that did not parse successfully (in which case the relevant * CFSUB() bits will be set) and arbitrarily omitting others that did not fit. It is not defined * which elements get omitted from an overflowed array. Normal array parsing without a validator * function will return an empty array in the case of overflow, but a validator function may * change this behaviour. * * - CFSTRINGFOVERFLOW if the size of any string element was exceeded. The result in *dest may be * unchanged or may contain a truncated string, depending on the parser that detected and * reported the string overflow. * * - CFINCOMPLETE if any MANDATORY element is missing (no node in the COM) or empty (as indicated * by the CFEMPTY bit in its parse result). The result in *dest is valid but the missing * mandatory element(s) are unchanged (in the case of a struct) or zero-length (in the case of an * array). * * - CFINVALID if any invalid configuration value was encountered, ie, any parse function returned * CFINVALID in its return flags. The result in *dest is valid and the elements that failed * to parse are unchanged. * * - CFSUB(CFxxx) if any element of a STRUCT or ARRAY produced a CFxxx result when being parsed, ie * any element's parse function returned CFxxx. In the case of a STRUCT, the failed elements are * usually left with their prior (default) values, but this depends on the parse functions' * behaviours. In the case of an ARRAY, failed elements are omitted from the array * * The difference between CFSUB(CFxxx) and CFxxx needs explaining. To illustrate, CFSUB(CFINVALID) * is different from CFINVALID because an element of a struct or array may have failed to parse, yet * the whole struct or array itself may still be valid (in the case of a struct, the element's prior * value may be retained, and in the case of an array, the failed element is simply omitted from the * result). A validator function may wish to reflect any CFSUB() bit as a CFINVALID result, but the * normal behaviour of cf_opt_config_NAME() is to not return CFINVALID unless the validator function * sets it. * * The special value CFOK is zero (no bits set); in this case a valid result is produced and all of * *dest is overwritten (except unused array elements). * * @author Andrew Bettison */ #ifndef __SERVALDNA_CONFIG_H #define __SERVALDNA_CONFIG_H #include #include #include "constants.h" #include "strbuf.h" #include "serval.h" #include "rhizome.h" #define CONFIG_FILE_MAX_SIZE (32 * 1024) #define INTERFACE_NAME_STRLEN 40 /* Return bit flags for config schema default cf_dfl_xxx() and parsing cf_opt_xxx() functions. */ #define CFERROR (~0) // all set #define CFOK 0 #define CFEMPTY (1<<0) #define CFDUPLICATE (1<<1) #define CFARRAYOVERFLOW (1<<2) #define CFSTRINGOVERFLOW (1<<3) #define CFINCOMPLETE (1<<4) #define CFINCOMPATIBLE (1<<5) #define CFINVALID (1<<6) #define CFUNSUPPORTED (1<<7) #define CF__SUB_SHIFT 16 #define CFSUB(f) ((f) << CF__SUB_SHIFT) #define CF__SUBFLAGS CFSUB(~0) #define CF__FLAGS (~0 & ~CF__SUBFLAGS) strbuf strbuf_cf_flags(strbuf, int); strbuf strbuf_cf_flag_reason(strbuf sb, int flags); /* The Configuration Object Model (COM). The config file is parsed into a tree of these structures * first, then those structures are passed as arguments to the schema parsing functions. */ struct cf_om_node { const char *source; // = parse_config() 'source' arg unsigned int line_number; const char *fullkey; // malloc() const char *key; // points inside fullkey, do not free() const char *text; // malloc() size_t nodc; struct cf_om_node *nodv[10]; // malloc() }; int is_configvarname(const char *); int is_configvarpattern(const char *); int cf_om_parse(const char *source, const char *buf, size_t len, struct cf_om_node **rootp); int cf_om_get_child(const struct cf_om_node *parent, const char *key, const char *keyend); const char *cf_om_get(const struct cf_om_node *root, const char *fullkey); int cf_om_set(struct cf_om_node **nodep, const char *fullkey, const char *text); int cf_om_add_child(struct cf_om_node **const parentp, const char *const key); void cf_om_free_node(struct cf_om_node **nodep); void cf_om_dump_node(const struct cf_om_node *node, int indent); int cf_om_match(const char *pattern, const struct cf_om_node *node); struct cf_om_iterator { const struct cf_om_node *node; unsigned sp; struct { const struct cf_om_node *node; unsigned index; } stack[20]; }; void cf_om_iter_start(struct cf_om_iterator *, const struct cf_om_node *); int cf_om_iter_next(struct cf_om_iterator *); struct cf_om_node *cf_om_root; int cf_om_load(); int cf_om_reload(); int cf_om_save(); /* Diagnostic functions for use in config schema parsing functions, cf_opt_xxx(). */ void _cf_warn_nodev(struct __sourceloc __whence, const struct cf_om_node *node, const char *key, const char *fmt, va_list ap); void _cf_warn_childrenv(struct __sourceloc __whence, const struct cf_om_node *parent, const char *fmt, va_list ap); void _cf_warn_node(struct __sourceloc __whence, const struct cf_om_node *node, const char *key, const char *fmt, ...); void _cf_warn_children(struct __sourceloc __whence, const struct cf_om_node *node, const char *fmt, ...); void _cf_warn_duplicate_node(struct __sourceloc __whence, const struct cf_om_node *parent, const char *key); void _cf_warn_missing_node(struct __sourceloc __whence, const struct cf_om_node *parent, const char *key); void _cf_warn_node_value(struct __sourceloc __whence, const struct cf_om_node *node, int reason); void _cf_warn_no_array(struct __sourceloc __whence, const struct cf_om_node *node, int reason); void _cf_warn_unsupported_node(struct __sourceloc __whence, const struct cf_om_node *node); void _cf_warn_unsupported_children(struct __sourceloc __whence, const struct cf_om_node *parent); void _cf_warn_list_overflow(struct __sourceloc __whence, const struct cf_om_node *node); void _cf_warn_incompatible(struct __sourceloc __whence, const struct cf_om_node *node, const struct cf_om_node *orig); void _cf_warn_incompatible_children(struct __sourceloc __whence, const struct cf_om_node *parent); void _cf_warn_array_key(struct __sourceloc __whence, const struct cf_om_node *node, int reason); void _cf_warn_array_value(struct __sourceloc __whence, const struct cf_om_node *node, int reason); #define cf_warn_nodev(node, key, fmt, ap) _cf_warn_nodev(__WHENCE__, node, key, fmt, ap) #define cf_warn_childrenv(parent, fmt, ap) _cf_warn_childrenv(__WHENCE__, parent, fmt, ap) #define cf_warn_node(node, key, fmt, ...) _cf_warn_node(__WHENCE__, node, key, fmt, ##__VA_ARGS__) #define cf_warn_children(node, fmt, ...) _cf_warn_children(__WHENCE__, node, fmt, ##__VA_ARGS__) #define cf_warn_duplicate_node(parent, key) _cf_warn_duplicate_node(__WHENCE__, parent, key) #define cf_warn_missing_node(parent, key) _cf_warn_missing_node(__WHENCE__, parent, key) #define cf_warn_node_value(node, reason) _cf_warn_node_value(__WHENCE__, node, reason) #define cf_warn_no_array(node, reason) _cf_warn_no_array(__WHENCE__, node, reason) #define cf_warn_unsupported_node(node) _cf_warn_unsupported_node(__WHENCE__, node) #define cf_warn_unsupported_children(parent) _cf_warn_unsupported_children(__WHENCE__, parent) #define cf_warn_list_overflow(node) _cf_warn_list_overflow(__WHENCE__, node) #define cf_warn_incompatible(node, orig) _cf_warn_incompatible(__WHENCE__, node, orig) #define cf_warn_incompatible_children(parent) _cf_warn_incompatible_children(__WHENCE__, parent) #define cf_warn_array_key(node, reason) _cf_warn_array_key(__WHENCE__, node, reason) #define cf_warn_array_value(node, reason) _cf_warn_array_value(__WHENCE__, node, reason) struct pattern_list { unsigned patc; char patv[16][INTERFACE_NAME_STRLEN + 1]; }; #define PATTERN_LIST_EMPTY ((struct pattern_list){.patc = 0}) // Generate config struct definitions, struct config_NAME. #define STRUCT(__name, __validator...) \ struct config_##__name { #define NODE(__type, __element, __default, __repr, __flags, __comment) \ __type __element; #define ATOM(__type, __element, __default, __repr, __flags, __comment) \ __type __element; #define STRING(__size, __element, __default, __repr, __flags, __comment) \ char __element[__size + 1]; #define SUB_STRUCT(__name, __element, __flags) \ struct config_##__name __element; #define NODE_STRUCT(__name, __element, __repr, __flags) \ struct config_##__name __element; #define END_STRUCT \ }; #define ARRAY(__name, __flags, __validator...) \ struct config_##__name { \ unsigned ac; \ struct config_##__name##__element { #define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \ __type key; #define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \ char key[(__strsize) + 1]; #define VALUE_ATOM(__type, __eltrepr) \ __type value; #define VALUE_STRING(__strsize, __eltrepr) \ char value[(__strsize) + 1]; #define VALUE_NODE(__type, __eltrepr) \ __type value; #define VALUE_SUB_STRUCT(__structname) \ struct config_##__structname value; #define VALUE_NODE_STRUCT(__structname, __eltrepr) \ struct config_##__structname value; #define END_ARRAY(__size) \ } av[(__size)]; \ }; #include "conf_schema.h" #undef STRUCT #undef NODE #undef ATOM #undef STRING #undef SUB_STRUCT #undef NODE_STRUCT #undef END_STRUCT #undef ARRAY #undef KEY_ATOM #undef KEY_STRING #undef VALUE_ATOM #undef VALUE_STRING #undef VALUE_NODE #undef VALUE_SUB_STRUCT #undef VALUE_NODE_STRUCT #undef END_ARRAY // Generate config function prototypes, cf_dfl_config_NAME(), cf_sch_config_NAME(). #define STRUCT(__name, __validator...) \ int cf_dfl_config_##__name(struct config_##__name *s); \ int cf_sch_config_##__name(struct cf_om_node **parentp); #define NODE(__type, __element, __default, __repr, __flags, __comment) #define ATOM(__type, __element, __default, __repr, __flags, __comment) #define STRING(__size, __element, __default, __repr, __flags, __comment) #define SUB_STRUCT(__name, __element, __flags) #define NODE_STRUCT(__name, __element, __repr, __flags) #define END_STRUCT #define ARRAY(__name, __flags, __validator...) \ int cf_dfl_config_##__name(struct config_##__name *a); \ int cf_sch_config_##__name(struct cf_om_node **parentp); #define KEY_ATOM(__type, __keyrepr, __cmpfunc...) #define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) #define VALUE_ATOM(__type, __eltrepr) #define VALUE_STRING(__strsize, __eltrepr) #define VALUE_NODE(__type, __eltrepr) #define VALUE_SUB_STRUCT(__structname) #define VALUE_NODE_STRUCT(__structname, __eltrepr) #define END_ARRAY(__size) #include "conf_schema.h" #undef STRUCT #undef NODE #undef ATOM #undef STRING #undef SUB_STRUCT #undef NODE_STRUCT #undef END_STRUCT #undef ARRAY #undef KEY_ATOM #undef KEY_STRING #undef VALUE_ATOM #undef VALUE_STRING #undef VALUE_NODE #undef VALUE_SUB_STRUCT #undef VALUE_NODE_STRUCT #undef END_ARRAY // Generate config parser function prototypes. #define __VALIDATOR(__name, __validator...) \ typedef int __validator_func__config_##__name##__t(const struct cf_om_node *, struct config_##__name *, int); \ __validator_func__config_##__name##__t __dummy__validator_func__config_##__name, ##__validator; #define STRUCT(__name, __validator...) \ int cf_opt_config_##__name(struct config_##__name *, const struct cf_om_node *); \ __VALIDATOR(__name, ##__validator) #define NODE(__type, __element, __default, __repr, __flags, __comment) \ int cf_opt_##__repr(__type *, const struct cf_om_node *); \ char * cf_fmt_##__repr(const __type *); #define ATOM(__type, __element, __default, __repr, __flags, __comment) \ int cf_opt_##__repr(__type *, const char *); \ char * cf_fmt_##__repr(const __type *); #define STRING(__size, __element, __default, __repr, __flags, __comment) \ int cf_opt_##__repr(char *, size_t, const char *); \ char * cf_fmt_##__repr(const char *); #define SUB_STRUCT(__name, __element, __flags) \ int cf_opt_config_##__name(struct config_##__name *, const struct cf_om_node *); \ struct cf_om_node * cf_fmt_config_##__name(struct config_##__name *); #define NODE_STRUCT(__name, __element, __repr, __flags) \ int cf_opt_##__repr(struct config_##__name *, const struct cf_om_node *); \ struct cf_om_node * cf_fmt_##__repr(struct config_##__name *); #define END_STRUCT #define ARRAY(__name, __flags, __validator...) \ int cf_opt_config_##__name(struct config_##__name *, const struct cf_om_node *); \ __VALIDATOR(__name, ##__validator) #define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \ int cf_opt_##__keyrepr(__type *, const char *); #define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \ int cf_opt_##__keyrepr(char *, size_t, const char *); #define VALUE_ATOM(__type, __eltrepr) \ int cf_opt_##__eltrepr(__type *, const char *); #define VALUE_STRING(__strsize, __eltrepr) \ int cf_opt_##__eltrepr(char *, size_t, const char *); #define VALUE_NODE(__type, __eltrepr) \ int cf_opt_##__eltrepr(__type *, const struct cf_om_node *); #define VALUE_SUB_STRUCT(__structname) \ int cf_opt_config_##__structname(struct config_##__structname *, const struct cf_om_node *); #define VALUE_NODE_STRUCT(__structname, __eltrepr) \ int cf_opt_##__eltrepr(struct config_##__structname *, const struct cf_om_node *); #define END_ARRAY(__size) #include "conf_schema.h" #undef __VALIDATOR #undef STRUCT #undef NODE #undef ATOM #undef STRING #undef SUB_STRUCT #undef NODE_STRUCT #undef END_STRUCT #undef ARRAY #undef KEY_ATOM #undef KEY_STRING #undef VALUE_ATOM #undef VALUE_STRING #undef VALUE_NODE #undef VALUE_SUB_STRUCT #undef VALUE_NODE_STRUCT #undef END_ARRAY // Generate config array key comparison function prototypes. #define STRUCT(__name, __validator...) #define NODE(__type, __element, __default, __repr, __flags, __comment) #define ATOM(__type, __element, __default, __repr, __flags, __comment) #define STRING(__size, __element, __default, __repr, __flags, __comment) #define SUB_STRUCT(__name, __element, __flags) #define NODE_STRUCT(__name, __element, __repr, __flags) #define END_STRUCT #define ARRAY(__name, __flags, __validator...) \ typedef int __compare_func__config_##__name##__t #define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \ (const __type *, const __type *); #define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \ (const char *, const char *); #define VALUE_ATOM(__type, __eltrepr) #define VALUE_STRING(__strsize, __eltrepr) #define VALUE_NODE(__type, __eltrepr) #define VALUE_SUB_STRUCT(__structname) #define VALUE_NODE_STRUCT(__structname, __eltrepr) #define END_ARRAY(__size) #include "conf_schema.h" #undef ARRAY #undef KEY_ATOM #undef KEY_STRING #define ARRAY(__name, __flags, __validator...) \ __compare_func__config_##__name##__t __dummy__compare_func__config_##__name #define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \ ,##__cmpfunc; #define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \ ,##__cmpfunc; #include "conf_schema.h" #undef STRUCT #undef NODE #undef ATOM #undef STRING #undef SUB_STRUCT #undef NODE_STRUCT #undef END_STRUCT #undef ARRAY #undef KEY_ATOM #undef KEY_STRING #undef VALUE_ATOM #undef VALUE_STRING #undef VALUE_NODE #undef VALUE_SUB_STRUCT #undef VALUE_NODE_STRUCT #undef END_ARRAY // Generate config array search-by-key function prototypes. #define STRUCT(__name, __validator...) #define NODE(__type, __element, __default, __repr, __flags, __comment) #define ATOM(__type, __element, __default, __repr, __flags, __comment) #define STRING(__size, __element, __default, __repr, __flags, __comment) #define SUB_STRUCT(__name, __element, __flags) #define NODE_STRUCT(__name, __element, __repr, __flags) #define END_STRUCT #define ARRAY(__name, __flags, __validator...) \ int config_##__name##__get(const struct config_##__name *, #define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \ const __type *); #define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \ const char *); #define VALUE_ATOM(__type, __eltrepr) #define VALUE_STRING(__strsize, __eltrepr) #define VALUE_NODE(__type, __eltrepr) #define VALUE_SUB_STRUCT(__structname) #define VALUE_NODE_STRUCT(__structname, __eltrepr) #define END_ARRAY(__size) #include "conf_schema.h" #undef STRUCT #undef NODE #undef ATOM #undef STRING #undef SUB_STRUCT #undef NODE_STRUCT #undef END_STRUCT #undef ARRAY #undef KEY_ATOM #undef KEY_STRING #undef VALUE_ATOM #undef VALUE_STRING #undef VALUE_NODE #undef VALUE_SUB_STRUCT #undef VALUE_NODE_STRUCT #undef END_ARRAY int cf_opt_char_boolean(char *booleanp, const char *text); int cf_opt_int_boolean(int *booleanp, const char *text); int cf_opt_absolute_path(char *str, size_t len, const char *text); int cf_opt_rhizome_peer(struct config_rhizome_peer *, const struct cf_om_node *node); int cf_opt_rhizome_peer_from_uri(struct config_rhizome_peer *, const char *uri); int cf_opt_str(char *str, size_t len, const char *text); int cf_opt_str_nonempty(char *str, size_t len, const char *text); int cf_opt_int(int *intp, const char *text); int cf_opt_uint16(uint16_t *intp, const char *text); int cf_opt_uint16_nonzero(uint16_t *intp, const char *text); int cf_opt_int32_nonneg(int32_t *intp, const char *text); int cf_opt_uint32_nonzero(uint32_t *intp, const char *text); int cf_opt_uint64_scaled(uint64_t *intp, const char *text); int cf_opt_protocol(char *str, size_t len, const char *text); int cf_opt_in_addr(struct in_addr *addrp, const char *text); int cf_opt_sid(sid_t *sidp, const char *text); int cf_opt_rhizome_bk(rhizome_bk_t *bkp, const char *text); int cf_opt_interface_type(short *typep, const char *text); int cf_opt_pattern_list(struct pattern_list *listp, const char *text); int cf_opt_network_interface(struct config_network_interface *nifp, const struct cf_om_node *node); int cf_opt_interface_list(struct config_interface_list *listp, const struct cf_om_node *node); int cf_opt_socket_type(int *typep, const char *text); int cf_opt_encapsulation(int *typep, const char *text); extern int cf_limbo; extern struct config_main config; int cf_init(); int cf_load(); int cf_load_permissive(); int cf_reload(); int cf_reload_permissive(); #endif //__SERVALDNA_CONFIG_H