1 #ifndef _CONFFILE_H 2 #define _CONFFILE_H 3 4 /* 5 * conffile.h Defines for the conffile parsing routines. 6 * 7 * Version: $Id: b99688196bbb8acb01f9b222016302527e7e59c2 $ 8 * 9 */ 10 11 RCSIDH(conffile_h, "$Id: b99688196bbb8acb01f9b222016302527e7e59c2 $") 12 13 #include <stddef.h> 14 #include <freeradius-devel/token.h> 15 #include <sys/time.h> 16 17 #ifdef __cplusplus 18 extern "C" { 19 #endif 20 21 /* 22 * Export the minimum amount of information about these structs 23 */ 24 typedef struct conf_item CONF_ITEM; //!< Generic configuration element, extended to become 25 ///< a #CONF_PAIR, a #CONF_SECTION or #CONF_DATA. 26 typedef struct conf_pair CONF_PAIR; //!< #CONF_ITEM with an attribute, an operator and a value. 27 typedef struct conf_part CONF_SECTION; //!< #CONF_ITEM used to group multiple #CONF_PAIR and #CONF_SECTION, together. 28 typedef struct conf_data CONF_DATA; //!< #CONF_ITEM used to associate arbitrary data 29 ///< with a #CONF_PAIR or #CONF_SECTION. 30 31 32 typedef void conf_type_mismatch; //!< Dummy type used to indicate PW_TYPE_*/C type mismatch. 33 typedef void conf_type_invalid; //!< Dummy type used to indicate invalid PW_TYPE_*. 34 35 #if defined(HAVE_BUILTIN_CHOOSE_EXPR) && defined(HAVE_BUILTIN_TYPES_COMPATIBLE_P) 36 /* 37 * Dumb hack for GCC which explodes with lots of errors masking the real 38 * error cause, if we don't use typdefs for these structures. 39 */ 40 typedef struct timeval _timeval_t; 41 42 /** Check the type #_t matches the destination data type 43 * 44 * Validation macro to check the type of the pointer or offset #_p passed in 45 * matches the type #_t of the configuration item. 46 * 47 * Uses various magic builtin precompilation functions, so will likely only 48 * work with recent versions of clang and gcc. 49 * 50 * @note The warnings/errors emitted are usually awful. 51 * 52 * @param _t a #PW_TYPE value with optional PW_TYPE_* flags. 53 * @param _ct data type of global or struct field, obtained with ``__typeof__``. 54 * @param _p Pointer or offset. 55 */ 56 # define FR_CONF_TYPE_CHECK(_t, _ct, _p) \ 57 __builtin_choose_expr((_t & PW_TYPE_TMPL),\ 58 __builtin_choose_expr(__builtin_types_compatible_p(vp_tmpl_t **, _ct), _p, (conf_type_mismatch) 0),\ 59 __builtin_choose_expr((((_t) & 0xff) == PW_TYPE_STRING),\ 60 __builtin_choose_expr(__builtin_types_compatible_p(char const **, _ct), _p, (conf_type_mismatch) 0),\ 61 __builtin_choose_expr((((_t) & 0xff) == PW_TYPE_BOOLEAN),\ 62 __builtin_choose_expr(__builtin_types_compatible_p(bool *, _ct), _p, (conf_type_mismatch) 0),\ 63 __builtin_choose_expr((((_t) & 0xff) == PW_TYPE_SUBSECTION),\ 64 _p,\ 65 __builtin_choose_expr((((_t) & 0xff) == PW_TYPE_INTEGER),\ 66 __builtin_choose_expr(__builtin_types_compatible_p(uint32_t *, _ct), _p, (conf_type_mismatch) 0),\ 67 __builtin_choose_expr((((_t) & 0xff) == PW_TYPE_IPV4_ADDR),\ 68 __builtin_choose_expr(__builtin_types_compatible_p(fr_ipaddr_t *, _ct), _p, (conf_type_mismatch) 0),\ 69 __builtin_choose_expr((((_t) & 0xff) == PW_TYPE_DATE),\ 70 __builtin_choose_expr(__builtin_types_compatible_p(uint32_t *, _ct), _p, (conf_type_mismatch) 0),\ 71 __builtin_choose_expr((((_t) & 0xff) == PW_TYPE_ABINARY),\ 72 __builtin_choose_expr(__builtin_types_compatible_p(size_t[32/sizeof(size_t)], _ct), _p, (conf_type_mismatch) 0),\ 73 __builtin_choose_expr((((_t) & 0xff) == PW_TYPE_OCTETS),\ 74 __builtin_choose_expr(__builtin_types_compatible_p(uint8_t *, _ct), _p, (conf_type_mismatch) 0),\ 75 __builtin_choose_expr((((_t) & 0xff) == PW_TYPE_IFID),\ 76 __builtin_choose_expr(__builtin_types_compatible_p(uint8_t[8], _ct), _p, (conf_type_mismatch) 0),\ 77 __builtin_choose_expr((((_t) & 0xff) == PW_TYPE_IPV6_ADDR),\ 78 __builtin_choose_expr(__builtin_types_compatible_p(fr_ipaddr_t *, _ct), _p, (conf_type_mismatch) 0),\ 79 __builtin_choose_expr((((_t) & 0xff) == PW_TYPE_IPV6_PREFIX),\ 80 __builtin_choose_expr(__builtin_types_compatible_p(fr_ipaddr_t *, _ct), _p, (conf_type_mismatch) 0),\ 81 __builtin_choose_expr((((_t) & 0xff) == PW_TYPE_BYTE),\ 82 __builtin_choose_expr(__builtin_types_compatible_p(uint8_t *, _ct), _p, (conf_type_mismatch) 0),\ 83 __builtin_choose_expr((((_t) & 0xff) == PW_TYPE_SHORT),\ 84 __builtin_choose_expr(__builtin_types_compatible_p(uint16_t *, _ct), _p, (conf_type_mismatch) 0),\ 85 __builtin_choose_expr((((_t) & 0xff) == PW_TYPE_ETHERNET),\ 86 __builtin_choose_expr(__builtin_types_compatible_p(uint8_t[6], _ct), _p, (conf_type_mismatch) 0),\ 87 __builtin_choose_expr((((_t) & 0xff) == PW_TYPE_SIGNED),\ 88 __builtin_choose_expr(__builtin_types_compatible_p(int32_t *, _ct), _p, (conf_type_mismatch) 0),\ 89 __builtin_choose_expr((((_t) & 0xff) == PW_TYPE_COMBO_IP_ADDR),\ 90 __builtin_choose_expr(__builtin_types_compatible_p(fr_ipaddr_t *, _ct), _p, (conf_type_mismatch) 0),\ 91 __builtin_choose_expr((((_t) & 0xff) == PW_TYPE_INTEGER64),\ 92 __builtin_choose_expr(__builtin_types_compatible_p(uint64_t *, _ct), _p, (conf_type_mismatch) 0),\ 93 __builtin_choose_expr((((_t) & 0xff) == PW_TYPE_IPV4_PREFIX),\ 94 __builtin_choose_expr(__builtin_types_compatible_p(fr_ipaddr_t *, _ct), _p, (conf_type_mismatch) 0),\ 95 __builtin_choose_expr((((_t) & 0xff) == PW_TYPE_TIMEVAL),\ 96 __builtin_choose_expr(__builtin_types_compatible_p(_timeval_t *, _ct), _p, (conf_type_mismatch) 0),\ 97 __builtin_choose_expr((((_t) & 0xff) == PW_TYPE_COMBO_IP_PREFIX),\ 98 __builtin_choose_expr(__builtin_types_compatible_p(fr_ipaddr_t *, _ct), _p, (conf_type_mismatch) 0),\ 99 (conf_type_invalid) 0\ 100 ))))))))))))))))))))) 101 102 # define FR_CONF_OFFSET(_t, _s, _f) _t, FR_CONF_TYPE_CHECK((_t), __typeof__(&(((_s *)NULL)->_f)), offsetof(_s, _f)), NULL 103 # define FR_CONF_POINTER(_t, _p) _t, 0, FR_CONF_TYPE_CHECK((_t), __typeof__(_p), _p) 104 # define FR_ITEM_POINTER(_t, _p) _t, FR_CONF_TYPE_CHECK((_t), __typeof__(_p), _p) 105 #else 106 # define FR_CONF_OFFSET(_t, _s, _f) _t, offsetof(_s, _f), NULL 107 # define FR_CONF_POINTER(_t, _p) _t, 0, _p 108 # define FR_ITEM_POINTER(_t, _p) _t, _p 109 #endif 110 111 #define FR_CONF_DEPRECATED(_t, _p, _f) (_t) | PW_TYPE_DEPRECATED, 0, NULL 112 113 /* 114 * Instead of putting the information into a configuration structure, 115 * the configuration file routines MAY just parse it directly into 116 * user-supplied variables. 117 */ 118 #define PW_TYPE_SUBSECTION 102 119 120 /** @name #CONF_PARSER type flags 121 * 122 * These flags should be or'd with another PW_TYPE_* value to create validation 123 * rules for the #cf_item_parse function. 124 * 125 * @note File PW_TYPE_FILE_* types have a base type of string, so they're validated 126 * correctly by the config parser. 127 * @{ 128 */ 129 #define PW_TYPE_DEPRECATED (1 << 10) //!< If a matching #CONF_PAIR is found, error out with a deprecated message. 130 #define PW_TYPE_REQUIRED (1 << 11) //!< Error out if no matching #CONF_PAIR is found, and no dflt value is set. 131 #define PW_TYPE_ATTRIBUTE (1 << 12) //!< Value must resolve to attribute in dict (deprecated, use #PW_TYPE_TMPL). 132 #define PW_TYPE_SECRET (1 << 13) //!< Only print value if debug level >= 3. 133 134 #define PW_TYPE_FILE_INPUT ((1 << 14) | PW_TYPE_STRING) //!< File matching value must exist, and must be readable. 135 #define PW_TYPE_FILE_OUTPUT ((1 << 15) | PW_TYPE_STRING) //!< File matching value must exist, and must be writeable. 136 137 #define PW_TYPE_XLAT (1 << 16) //!< string will be dynamically expanded. 138 #define PW_TYPE_TMPL (1 << 17) //!< CONF_PAIR should be parsed as a template. 139 140 #define PW_TYPE_MULTI (1 << 18) //!< CONF_PAIR can have multiple copies. 141 #define PW_TYPE_NOT_EMPTY (1 << 19) //!< CONF_PAIR is required to have a non zero length value. 142 #define PW_TYPE_FILE_EXISTS ((1 << 20) | PW_TYPE_STRING) //!< File matching value must exist 143 /* @} **/ 144 145 #define FR_INTEGER_COND_CHECK(_name, _var, _cond, _new)\ 146 do {\ 147 if (!(_cond)) {\ 148 WARN("Ignoring \"" _name " = %i\", forcing to \"" _name " = %i\"", _var, _new);\ 149 _var = _new;\ 150 }\ 151 } while (0) 152 153 #define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound) FR_INTEGER_COND_CHECK(_name, _var, (_var _op _bound), _bound) 154 155 #define FR_TIMEVAL_BOUND_CHECK(_name, _var, _op, _bound_sec, _bound_usec)\ 156 do {\ 157 struct timeval _bound = {_bound_sec, _bound_usec};\ 158 if (!timercmp(_var, &_bound, _op)) {\ 159 WARN("Ignoring \"" _name " = %d.%.06d\", forcing to \"" _name " = %d.%06d\"",\ 160 (int)(_var)->tv_sec, (int)(_var)->tv_usec,\ 161 (int)_bound.tv_sec, (int)_bound.tv_usec);\ 162 *_var = _bound;\ 163 }\ 164 } while (0) 165 166 #define FR_TIMEVAL_TO_MS(_x) (((_x)->tv_usec * 1000) + ((_x)->tv_sec / 1000)) 167 extern bool check_config; 168 169 /** Defines a #CONF_PAIR to C data type mapping 170 * 171 * Is typically used to define mappings between module sections, and module instance structs. 172 * May also be used to set global configuration options. 173 * 174 * Offset/data values should be set using #FR_CONF_OFFSET or #FR_CONF_POINTER. 175 * 176 * Example with #FR_CONF_OFFSET : 177 @code{.c} 178 static CONF_PARSER module_config[] = { 179 { "example", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_NOT_EMPTY, example_instance_t, example), "default_value" }, 180 CONF_PARSER_TERMINATOR 181 } 182 @endcode 183 * 184 * Example with #FR_CONF_POINTER : 185 @code{.c} 186 static CONF_PARSER global_config[] = { 187 { "example", FR_CONF_POINTER(PW_TYPE_STRING | PW_TYPE_NOT_EMPTY, &my_global), "default_value" }, 188 CONF_PARSER_TERMINATOR 189 } 190 @endcode 191 * 192 * @see FR_CONF_OFFSET 193 * @see FR_CONF_POINTER 194 * @see cf_section_parse 195 * @see cf_item_parse 196 */ 197 typedef struct CONF_PARSER { 198 char const *name; //!< Name of the #CONF_ITEM to parse. 199 int type; //!< A #PW_TYPE value, may be or'd with one or more PW_TYPE_* flags. 200 //!< @see cf_item_parse. 201 202 size_t offset; //!< Relative offset of field or structure to write the parsed value to. 203 //!< When #type is set to #PW_TYPE_SUBSECTION, may be used to specify 204 //!< a base offset to add to all offsets contained within the 205 //!< subsection. 206 //!< @note Must be used exclusively to #data. 207 208 void *data; //!< Pointer to a static variable to write the parsed value to. 209 //!< @note Must be used exclusively to #offset. 210 211 const void *dflt; //!< Default as it would appear in radiusd.conf. 212 //!< When #type is set to #PW_TYPE_SUBSECTION, should be a pointer 213 //!< to the start of another array of #CONF_PARSER structs, forming 214 //!< the subsection. 215 } CONF_PARSER; 216 217 #define CONF_PARSER_TERMINATOR { NULL, -1, 0, NULL, NULL } 218 219 CONF_PAIR *cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value, 220 FR_TOKEN op, FR_TOKEN lhs_type, FR_TOKEN rhs_type); 221 CONF_PAIR *cf_pair_dup(CONF_SECTION *parent, CONF_PAIR *cp); 222 void cf_pair_add(CONF_SECTION *parent, CONF_PAIR *cp); 223 224 CONF_SECTION *cf_section_alloc(CONF_SECTION *parent, char const *name1, char const *name2); 225 CONF_SECTION *cf_section_dup(CONF_SECTION *parent, CONF_SECTION const *cs, 226 char const *name1, char const *name2, bool copy_meta); 227 void cf_section_add(CONF_SECTION *parent, CONF_SECTION *cs); 228 int cf_pair_replace(CONF_SECTION *cs, CONF_PAIR *cp, char const *value); 229 int cf_item_parse(CONF_SECTION *cs, char const *name, unsigned int type, void *data, char const *dflt); 230 int cf_section_parse(CONF_SECTION *, void *base, CONF_PARSER const *variables); 231 int cf_section_parse_pass2(CONF_SECTION *, void *base, CONF_PARSER const *variables); 232 const CONF_PARSER *cf_section_parse_table(CONF_SECTION *cs); 233 int cf_file_read(CONF_SECTION *cs, char const *file); 234 void cf_file_free(CONF_SECTION *cs); 235 236 CONF_PAIR *cf_pair_find(CONF_SECTION const *, char const *name); 237 CONF_PAIR *cf_pair_find_next(CONF_SECTION const *, CONF_PAIR const *, char const *name); 238 CONF_SECTION *cf_section_find(char const *name); 239 CONF_SECTION *cf_section_find_name2(CONF_SECTION const *section, 240 char const *name1, char const *name2); 241 CONF_SECTION *cf_section_sub_find(CONF_SECTION const *, char const *name); 242 CONF_SECTION *cf_section_sub_find_name2(CONF_SECTION const *, char const *name1, char const *name2); 243 char const *cf_section_value_find(CONF_SECTION const *, char const *attr); 244 CONF_SECTION *cf_top_section(CONF_SECTION *cs); 245 246 void *cf_data_find(CONF_SECTION const *, char const *); 247 int cf_data_add(CONF_SECTION *, char const *, void *, void (*)(void *)); 248 void *cf_data_remove(CONF_SECTION *cs, char const *name); 249 250 char const *cf_pair_attr(CONF_PAIR const *pair); 251 char const *cf_pair_value(CONF_PAIR const *pair); 252 FR_TOKEN cf_pair_operator(CONF_PAIR const *pair); 253 FR_TOKEN cf_pair_attr_type(CONF_PAIR const *pair); 254 FR_TOKEN cf_pair_value_type(CONF_PAIR const *pair); 255 VALUE_PAIR *cf_pairtovp(CONF_PAIR *pair); 256 char const *cf_section_name1(CONF_SECTION const *cs); 257 char const *cf_section_name2(CONF_SECTION const *cs); 258 char const *cf_section_name(CONF_SECTION const *cs); 259 FR_TOKEN cf_section_name2_type(CONF_SECTION const *cs); 260 int dump_config(CONF_SECTION const *cs); 261 CONF_SECTION *cf_subsection_find_next(CONF_SECTION const *section, 262 CONF_SECTION const *subsection, 263 char const *name1); 264 CONF_SECTION *cf_section_find_next(CONF_SECTION const *section, 265 CONF_SECTION const *subsection, 266 char const *name1); 267 int cf_section_lineno(CONF_SECTION const *section); 268 int cf_pair_lineno(CONF_PAIR const *pair); 269 char const *cf_pair_filename(CONF_PAIR const *pair); 270 char const *cf_section_filename(CONF_SECTION const *section); 271 CONF_ITEM *cf_item_find_next(CONF_SECTION const *section, CONF_ITEM const *item); 272 int cf_pair_count(CONF_SECTION const *cs); 273 CONF_SECTION *cf_item_parent(CONF_ITEM const *ci); 274 bool cf_item_is_section(CONF_ITEM const *item); 275 bool cf_item_is_pair(CONF_ITEM const *item); 276 bool cf_item_is_data(CONF_ITEM const *item); 277 CONF_PAIR *cf_item_to_pair(CONF_ITEM const *item); 278 CONF_SECTION *cf_item_to_section(CONF_ITEM const *item); 279 CONF_ITEM *cf_pair_to_item(CONF_PAIR const *cp); 280 CONF_ITEM *cf_section_to_item(CONF_SECTION const *cs); 281 282 void cf_log_err(CONF_ITEM const *ci, char const *fmt, ...) CC_HINT(format (printf, 2, 3)); 283 void cf_log_err_cs(CONF_SECTION const *cs, char const *fmt, ...) CC_HINT(format (printf, 2, 3)); 284 void cf_log_err_cp(CONF_PAIR const *cp, char const *fmt, ...) CC_HINT(format (printf, 2, 3)); 285 void cf_log_info(CONF_SECTION const *cs, char const *fmt, ...) CC_HINT(format (printf, 2, 3)); 286 void cf_log_module(CONF_SECTION const *cs, char const *fmt, ...) CC_HINT(format (printf, 2, 3)); 287 288 void cf_item_add(CONF_SECTION *cs, CONF_ITEM *ci); 289 CONF_ITEM *cf_reference_item(CONF_SECTION const *parentcs, 290 CONF_SECTION *outercs, 291 char const *ptr); 292 293 #define CF_FILE_NONE (0) 294 #define CF_FILE_ERROR (1) 295 #define CF_FILE_CONFIG (1 << 2) 296 #define CF_FILE_MODULE (1 << 3) 297 int cf_file_changed(CONF_SECTION *cs, rb_walker_t callback); 298 299 extern CONF_SECTION *root_config; 300 extern bool cf_new_escape; 301 302 #ifdef __cplusplus 303 } 304 #endif 305 306 #endif /* _CONFFILE_H */ 307