Prevent crash from using app_page with no confbridge.conf file provided.
[asterisk/asterisk.git] / main / config_options.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2012, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  * \brief Configuration Option-handling
21  * \author Terry Wilson <twilson@digium.com>
22  */
23
24 /*** MODULEINFO
25         <support_level>core</support_level>
26  ***/
27
28 #include "asterisk.h"
29
30 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
31
32 #include <regex.h>
33
34 #include "asterisk/config.h"
35 #include "asterisk/config_options.h"
36 #include "asterisk/stringfields.h"
37 #include "asterisk/acl.h"
38 #include "asterisk/frame.h"
39
40 #ifdef LOW_MEMORY
41 #define CONFIG_OPT_BUCKETS 5
42 #else
43 #define CONFIG_OPT_BUCKETS 53
44 #endif /* LOW_MEMORY */
45
46 /*! \brief Bits of aco_info that shouldn't be assigned outside this file
47  * \internal
48  */
49 struct aco_info_internal {
50         void *pending;              /*!< The user-defined config object awaiting application */
51 };
52
53 struct aco_type_internal {
54         regex_t *regex;
55         struct ao2_container *opts; /*!< The container of options registered to the aco_info */
56 };
57
58 struct aco_option {
59         const char *name;
60         const char *aliased_to;
61         const char *default_val;
62         enum aco_matchtype match_type;
63         regex_t *name_regex;
64         struct aco_type **obj;
65         enum aco_option_type type;
66         aco_option_handler handler;
67         unsigned int flags;
68         unsigned char deprecated:1;
69         size_t argc;
70         intptr_t args[0];
71 };
72
73 void *aco_pending_config(struct aco_info *info)
74 {
75         if (!(info && info->internal)) {
76                 ast_log(LOG_ERROR, "This may not be called without an initialized aco_info!\n");
77                 return NULL;
78         }
79         return info->internal->pending;
80 }
81
82 static void config_option_destroy(void *obj)
83 {
84         struct aco_option *opt = obj;
85         if (opt->match_type == ACO_REGEX && opt->name_regex) {
86                 regfree(opt->name_regex);
87                 ast_free(opt->name_regex);
88         }
89 }
90
91 static int int_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
92 static int uint_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
93 static int double_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
94 static int sockaddr_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
95 static int stringfield_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
96 static int bool_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
97 static int boolflag_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
98 static int acl_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
99 static int codec_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
100 static int noop_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
101 static int chararray_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
102
103 static aco_option_handler ast_config_option_default_handler(enum aco_option_type type)
104 {
105         switch(type) {
106         case OPT_ACL_T: return acl_handler_fn;
107         case OPT_BOOL_T: return bool_handler_fn;
108         case OPT_BOOLFLAG_T: return boolflag_handler_fn;
109         case OPT_CHAR_ARRAY_T: return chararray_handler_fn;
110         case OPT_CODEC_T: return codec_handler_fn;
111         case OPT_DOUBLE_T: return double_handler_fn;
112         case OPT_INT_T: return int_handler_fn;
113         case OPT_NOOP_T: return noop_handler_fn;
114         case OPT_SOCKADDR_T: return sockaddr_handler_fn;
115         case OPT_STRINGFIELD_T: return stringfield_handler_fn;
116         case OPT_UINT_T: return uint_handler_fn;
117
118         case OPT_CUSTOM_T: return NULL;
119         }
120
121         return NULL;
122 }
123
124 static regex_t *build_regex(const char *text)
125 {
126         int res;
127         regex_t *regex;
128
129         if (!(regex = ast_malloc(sizeof(*regex)))) {
130                 return NULL;
131         }
132
133         if ((res = regcomp(regex, text, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
134                 size_t len = regerror(res, regex, NULL, 0);
135                 char buf[len];
136                 regerror(res, regex, buf, len);
137                 ast_log(LOG_ERROR, "Could not compile regex '%s': %s\n", text, buf);
138                 ast_free(regex);
139                 return NULL;
140         }
141
142         return regex;
143 }
144
145 static int link_option_to_types(struct aco_type **types, struct aco_option *opt)
146 {
147         size_t idx = 0;
148         struct aco_type *type;
149
150         while ((type = types[idx++])) {
151                 if (!type->internal) {
152                         ast_log(LOG_ERROR, "Attempting to register option using uninitialized type\n");
153                         return -1;
154                 }
155                 if (!ao2_link(type->internal->opts, opt)) {
156                         while (--idx) {
157                                 ao2_unlink(types[idx]->internal->opts, opt);
158                         }
159                         return -1;
160                 }
161         }
162         return 0;
163 }
164
165 int aco_option_register_deprecated(struct aco_info *info, const char *name, struct aco_type **types, const char *aliased_to)
166 {
167         struct aco_option *opt;
168
169         if (!info || ast_strlen_zero(name) || ast_strlen_zero(aliased_to)) {
170                 return -1;
171         }
172
173         if (!(opt = ao2_alloc(sizeof(*opt), config_option_destroy))) {
174                 return -1;
175         }
176
177         opt->name = name;
178         opt->aliased_to = aliased_to;
179         opt->deprecated = 1;
180         opt->match_type = ACO_EXACT;
181
182         if (link_option_to_types(types, opt)) {
183                 ao2_ref(opt, -1);
184                 return -1;
185         }
186
187         return 0;
188 }
189
190 int __aco_option_register(struct aco_info *info, const char *name, enum aco_matchtype matchtype, struct aco_type **types,
191         const char *default_val, enum aco_option_type kind, aco_option_handler handler, unsigned int flags, size_t argc, ...)
192 {
193         struct aco_option *opt;
194         va_list ap;
195         int tmp;
196
197         /* Custom option types require a handler */
198         if (!handler && kind == OPT_CUSTOM_T) {
199                 return -1;
200         }
201
202         if (!(types && types[0])) {
203                 return -1;
204         }
205
206         if (!(opt = ao2_alloc(sizeof(*opt) + argc * sizeof(opt->args[0]), config_option_destroy))) {
207                 return -1;
208         }
209
210         if (matchtype == ACO_REGEX && !(opt->name_regex = build_regex(name))) {
211                 ao2_ref(opt, -1);
212                 return -1;
213         }
214
215         va_start(ap, argc);
216         for (tmp = 0; tmp < argc; tmp++) {
217                 opt->args[tmp] = va_arg(ap, size_t);
218         }
219         va_end(ap);
220
221         opt->name = name;
222         opt->match_type = matchtype;
223         opt->default_val = default_val;
224         opt->type = kind;
225         opt->handler = handler;
226         opt->flags = flags;
227         opt->argc = argc;
228
229         if (!opt->handler && !(opt->handler = ast_config_option_default_handler(opt->type))) {
230                 /* This should never happen */
231                 ast_log(LOG_ERROR, "No handler provided, and no default handler exists for type %d\n", opt->type);
232                 ao2_ref(opt, -1);
233                 return -1;
234         };
235
236         if (link_option_to_types(types, opt)) {
237                 ao2_ref(opt, -1);
238                 return -1;
239         }
240
241         return 0;
242 }
243
244 static int config_opt_hash(const void *obj, const int flags)
245 {
246         const struct aco_option *opt = obj;
247         const char *name = (flags & OBJ_KEY) ? obj : opt->name;
248         return ast_str_case_hash(name);
249 }
250
251 static int config_opt_cmp(void *obj, void *arg, int flags)
252 {
253         struct aco_option *opt1 = obj, *opt2 = arg;
254         const char *name = (flags & OBJ_KEY) ? arg : opt2->name;
255         return strcasecmp(opt1->name, name) ? 0 : CMP_MATCH | CMP_STOP;
256 }
257
258 static int find_option_cb(void *obj, void *arg, int flags)
259 {
260         struct aco_option *match = obj;
261         const char *name = arg;
262
263         switch (match->match_type) {
264         case ACO_EXACT:
265                 return strcasecmp(name, match->name) ? 0 : CMP_MATCH | CMP_STOP;
266         case ACO_REGEX:
267                 return regexec(match->name_regex, name, 0, NULL, 0) ? 0 : CMP_MATCH | CMP_STOP;
268         }
269         ast_log(LOG_ERROR, "Unknown match type. This should not be possible.\n");
270         return CMP_STOP;
271 }
272
273 static struct aco_option *aco_option_find(struct aco_type *type, const char *name)
274 {
275         struct aco_option *opt;
276
277         if (!type || !type->internal || !type->internal->opts) {
278                 ast_log(LOG_NOTICE, "Attempting to use NULL or unitialized config type\n");
279                 return NULL;
280         }
281
282         /* Try an exact match with OBJ_KEY for the common/fast case, then iterate through
283          * all options for the regex cases */
284         if (!(opt = ao2_callback(type->internal->opts, OBJ_KEY, find_option_cb, (void *) name))) {
285                 opt = ao2_callback(type->internal->opts, 0, find_option_cb, (void *) name);
286         }
287         return opt;
288 }
289
290 struct ao2_container *aco_option_container_alloc(void)
291 {
292         return ao2_container_alloc(CONFIG_OPT_BUCKETS, config_opt_hash, config_opt_cmp);
293 }
294
295 static struct aco_type *internal_aco_type_find(struct aco_file *file, struct ast_config *cfg, const char *category)
296 {
297         size_t x;
298         struct aco_type *match;
299         const char *val;
300
301         for (x = 0, match = file->types[x]; match; match = file->types[++x]) {
302                 /* First make sure we are an object that can service this category */
303                 if (!regexec(match->internal->regex, category, 0, NULL, 0) == !match->category_match) {
304                         continue;
305                 }
306
307                 /* Then, see if we need to match a particular field */
308                 if (!ast_strlen_zero(match->matchfield) && (!ast_strlen_zero(match->matchvalue) || match->matchfunc)) {
309                         if (!(val = ast_variable_retrieve(cfg, category, match->matchfield))) {
310                                 ast_log(LOG_ERROR, "Required match field '%s' not found\n", match->matchfield);
311                                 return NULL;
312                         }
313                         if (match->matchfunc) {
314                                 if (!match->matchfunc(val)) {
315                                         continue;
316                                 }
317                         } else if (strcasecmp(val, match->matchvalue)) {
318                                 continue;
319                         }
320                 }
321                 /* If we get this far, we're a match */
322                 break;
323         }
324
325         return match;
326 }
327
328 static int is_preload(struct aco_file *file, const char *cat)
329 {
330         int i;
331
332         if (!file->preload) {
333                 return 0;
334         }
335
336         for (i = 0; !ast_strlen_zero(file->preload[i]); i++) {
337                 if (!strcasecmp(cat, file->preload[i])) {
338                         return 1;
339                 }
340         }
341         return 0;
342 }
343
344 static int process_category(struct ast_config *cfg, struct aco_info *info, struct aco_file *file, const char *cat, int preload) {
345         RAII_VAR(void *, new_item, NULL, ao2_cleanup);
346         struct aco_type *type;
347         /* For global types, field is the global option struct. For non-global, it is the container for items.
348          * We do not grab a reference to these objects, as the info already holds references to them. This
349          * pointer is just a convenience. Do not actually store it somewhere. */
350         void **field;
351
352         /* Skip preloaded categories if we aren't preloading */
353         if (!preload && is_preload(file, cat)) {
354                 return 0;
355         }
356
357         /* Find aco_type by category, if not found it is an error */
358         if (!(type = internal_aco_type_find(file, cfg, cat))) {
359                 ast_log(LOG_ERROR, "Could not find config type for category '%s' in '%s'\n", cat, file->filename);
360                 return -1;
361         }
362
363         field = info->internal->pending + type->item_offset;
364         if (!*field) {
365                 ast_log(LOG_ERROR, "No object to update!\n");
366                 return -1;
367         }
368
369         if (type->type == ACO_GLOBAL && *field) {
370                 if (aco_set_defaults(type, cat, *field)) {
371                         ast_log(LOG_ERROR, "In %s: Setting defaults for %s failed\n", file->filename, cat);
372                         return -1;
373                 }
374                 if (aco_process_category_options(type, cfg, cat, *field)) {
375                         ast_log(LOG_ERROR, "In %s: Processing options for %s failed\n", file->filename, cat);
376                         return -1;
377                 }
378         } else if (type->type == ACO_ITEM) {
379                 int new = 0;
380                 /* If we have multiple definitions of a category in a file, or can set the values from multiple
381                  * files, look up the entry if we've already added it so we can merge the values together.
382                  * Otherwise, alloc a new item. */
383                 if (*field) {
384                         if (!(new_item = type->item_find(*field, cat))) {
385                                 if (!(new_item = type->item_alloc(cat))) {
386                                         ast_log(LOG_ERROR, "In %s: Could not create item for %s\n", file->filename, cat);
387                                         return -1;
388                                 }
389                                 if (aco_set_defaults(type, cat, new_item)) {
390                                         ast_log(LOG_ERROR, "In %s: Setting defaults for %s failed\n", file->filename, cat);
391                                         return -1;
392                                 }
393                                 new = 1;
394                         }
395                 }
396
397                 if (type->item_pre_process && type->item_pre_process(new_item)) {
398                         ast_log(LOG_ERROR, "In %s: Preprocess callback for %s failed\n", file->filename, cat);
399                         return -1;
400                 }
401
402                 if (aco_process_category_options(type, cfg, cat, new_item)) {
403                         ast_log(LOG_ERROR, "In %s: Processing options for %s failed\n", file->filename, cat);
404                         return -1;
405                 }
406
407                 if (type->item_prelink && type->item_prelink(new_item)) {
408                         ast_log(LOG_ERROR, "In %s: Pre-link callback for %s failed\n", file->filename, cat);
409                         return -1;
410                 }
411
412                 if (new && !ao2_link(*field, new_item)) {
413                         ast_log(LOG_ERROR, "In %s: Linking config for %s failed\n", file->filename, cat);
414                         return -1;
415                 }
416         }
417         return 0;
418 }
419
420 static int apply_config(struct aco_info *info)
421 {
422         ao2_global_obj_replace_unref(*info->global_obj, info->internal->pending);
423
424         return 0;
425 }
426
427 static enum aco_process_status internal_process_ast_config(struct aco_info *info, struct aco_file *file, struct ast_config *cfg)
428 {
429         const char *cat = NULL;
430
431         if (file->preload) {
432                 int i;
433                 for (i = 0; !ast_strlen_zero(file->preload[i]); i++) {
434                         if (process_category(cfg, info, file, file->preload[i], 1)) {
435                                 return ACO_PROCESS_ERROR;
436                         }
437                 }
438         }
439
440         while ((cat = ast_category_browse(cfg, cat))) {
441                 if (process_category(cfg, info, file, cat, 0)) {
442                         return ACO_PROCESS_ERROR;
443                 }
444         }
445         return ACO_PROCESS_OK;
446 }
447
448 enum aco_process_status aco_process_ast_config(struct aco_info *info, struct aco_file *file, struct ast_config *cfg)
449 {
450         if (!info->internal) {
451                 ast_log(LOG_ERROR, "Attempt to process %s with uninitialized aco_info\n", file->filename);
452                 goto error;
453         }
454
455         if (!(info->internal->pending = info->snapshot_alloc())) {
456                 ast_log(LOG_ERROR, "In %s: Could not allocate temporary objects\n", file->filename);
457                 goto error;
458         }
459
460         if (internal_process_ast_config(info, file, cfg)) {
461                 goto error;
462         }
463
464         if (info->pre_apply_config && info->pre_apply_config()) {
465                 goto error;
466         }
467
468         if (apply_config(info)) {
469                 goto error;
470         };
471
472         ao2_cleanup(info->internal->pending);
473         return ACO_PROCESS_OK;
474
475 error:
476         ao2_cleanup(info->internal->pending);
477         return ACO_PROCESS_ERROR;
478 }
479
480 enum aco_process_status aco_process_config(struct aco_info *info, int reload)
481 {
482         struct ast_config *cfg;
483         struct ast_flags cfg_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0, };
484         int res = ACO_PROCESS_OK, x = 0;
485         struct aco_file *file;
486
487         if (!(info->files[0])) {
488                 ast_log(LOG_ERROR, "No filename given, cannot proceed!\n");
489                 return ACO_PROCESS_ERROR;
490         }
491
492         if (!info->internal) {
493                 ast_log(LOG_ERROR, "Attempting to process uninitialized aco_info\n");
494                 return ACO_PROCESS_ERROR;
495         }
496
497         if (!(info->internal->pending = info->snapshot_alloc())) {
498                 ast_log(LOG_ERROR, "In %s: Could not allocate temporary objects\n", info->module);
499                 return ACO_PROCESS_ERROR;
500         }
501
502         while (res != ACO_PROCESS_ERROR && (file = info->files[x++])) {
503                 const char *filename = file->filename;
504 try_alias:
505                 if (!(cfg = ast_config_load(filename, cfg_flags))) {
506                         if (file->alias && strcmp(file->alias, filename)) {
507                                 filename = file->alias;
508                                 goto try_alias;
509                         }
510                         ast_log(LOG_ERROR, "Unable to load config file '%s'\n", file->filename);
511                         res = ACO_PROCESS_ERROR;
512                         break;
513                 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
514                         ast_debug(1, "%s was unchanged\n", file->filename);
515                         res = ACO_PROCESS_UNCHANGED;
516                         continue;
517                 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
518                         ast_log(LOG_ERROR, "Contents of %s are invalid and cannot be parsed\n", file->filename);
519                         res = ACO_PROCESS_ERROR;
520                         break;
521                 } else if (cfg == CONFIG_STATUS_FILEMISSING) {
522                         if (file->alias && strcmp(file->alias, filename)) {
523                                 filename = file->alias;
524                                 goto try_alias;
525                         }
526                         ast_log(LOG_ERROR, "%s is missing! Cannot load %s\n", file->filename, info->module);
527                         res = ACO_PROCESS_ERROR;
528                         break;
529                 }
530
531                 res = internal_process_ast_config(info, file, cfg);
532                 ast_config_destroy(cfg);
533         }
534
535         if (res != ACO_PROCESS_OK) {
536            goto end;
537         }
538
539         if (info->pre_apply_config && (info->pre_apply_config()))  {
540                 res = ACO_PROCESS_ERROR;
541                 goto end;
542         }
543
544         if (apply_config(info)) {
545                 res = ACO_PROCESS_ERROR;
546                 goto end;
547         }
548
549         if (info->post_apply_config) {
550                 info->post_apply_config();
551         }
552
553 end:
554         ao2_cleanup(info->internal->pending);
555         return res;
556 }
557 int aco_process_var(struct aco_type *type, const char *cat, struct ast_variable *var, void *obj)
558 {
559         RAII_VAR(struct aco_option *, opt, aco_option_find(type, var->name), ao2_cleanup);
560         if (opt && opt->deprecated && !ast_strlen_zero(opt->aliased_to)) {
561                 const char *alias = ast_strdupa(opt->aliased_to);
562                 ast_log(LOG_WARNING, "At line %d of %s option '%s' is deprecated. Use '%s' instead\n", var->lineno, var->file, var->name, alias);
563                 ao2_ref(opt, -1);
564                 opt = aco_option_find(type, alias);
565         }
566
567         if (!opt) {
568                 ast_log(LOG_ERROR, "Could not find option suitable for category '%s' named '%s' at line %d of %s\n", cat, var->name, var->lineno, var->file);
569                 return -1;
570         }
571
572         if (!opt->handler) {
573                 /* It should be impossible for an option to not have a handler */
574                 ast_log(LOG_ERROR, "BUG! Somehow a config option for %s/%s was created with no handler!\n", cat, var->name);
575                 return -1;
576         }
577         if (opt->handler(opt, var, obj)) {
578                 ast_log(LOG_ERROR, "Error parsing %s=%s at line %d of %s\n", var->name, var->value, var->lineno, var->file);
579                 return -1;
580         }
581
582         return 0;
583 }
584
585 int aco_process_category_options(struct aco_type *type, struct ast_config *cfg, const char *cat, void *obj)
586 {
587         struct ast_variable *var;
588
589         for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
590                 if (aco_process_var(type, cat, var, obj)) {
591                         return -1;
592                 }
593         }
594
595         return 0;
596 }
597
598 static void internal_type_destroy(struct aco_type *type)
599 {
600         /* If we've already had all our internal data cleared out,
601          * then there's no need to proceed further
602          */
603         if (!type->internal) {
604                 return;
605         }
606
607         if (type->internal->regex) {
608                 regfree(type->internal->regex);
609                 ast_free(type->internal->regex);
610         }
611         ao2_cleanup(type->internal->opts);
612         type->internal->opts = NULL;
613         ast_free(type->internal);
614         type->internal = NULL;
615 }
616
617 static void internal_file_types_destroy(struct aco_file *file)
618 {
619         size_t x;
620         struct aco_type *t;
621
622         for (x = 0, t = file->types[x]; t; t = file->types[++x]) {
623                 internal_type_destroy(t);
624                 t = NULL;
625         }
626 }
627
628 static int internal_type_init(struct aco_type *type)
629 {
630         if (!(type->internal = ast_calloc(1, sizeof(*type->internal)))) {
631                 return -1;
632         }
633
634         if (!(type->internal->regex = build_regex(type->category))) {
635                 internal_type_destroy(type);
636                 return -1;
637         }
638
639         if (!(type->internal->opts = aco_option_container_alloc())) {
640                 internal_type_destroy(type);
641                 return -1;
642         }
643
644         return 0;
645 }
646
647 int aco_info_init(struct aco_info *info)
648 {
649         size_t x, y;
650
651         if (!(info->internal = ast_calloc(1, sizeof(*info->internal)))) {
652                 return -1;
653         }
654
655         for (x = 0; info->files[x]; x++) {
656                 for (y = 0; info->files[x]->types[y]; y++) {
657                         if (internal_type_init(info->files[x]->types[y])) {
658                                 goto error;
659                         }
660                 }
661         }
662
663         return 0;
664 error:
665         aco_info_destroy(info);
666         return -1;
667 }
668
669 void aco_info_destroy(struct aco_info *info)
670 {
671         int x;
672         /* It shouldn't be possible for internal->pending to be in use when this is called because
673          * of the locks in loader.c around reloads and unloads and the fact that internal->pending
674          * only exists while those locks are held */
675         ast_free(info->internal);
676         info->internal = NULL;
677
678         for (x = 0; info->files[x]; x++) {
679                 internal_file_types_destroy(info->files[x]);
680         }
681 }
682
683 int aco_set_defaults(struct aco_type *type, const char *category, void *obj)
684 {
685         struct aco_option *opt;
686         struct ao2_iterator iter;
687
688         iter = ao2_iterator_init(type->internal->opts, 0);
689
690         while ((opt = ao2_iterator_next(&iter))) {
691                 RAII_VAR(struct ast_variable *, var, NULL, ast_variables_destroy);
692
693                 if (ast_strlen_zero(opt->default_val)) {
694                         ao2_ref(opt, -1);
695                         continue;
696                 }
697                 if (!(var = ast_variable_new(opt->name, opt->default_val, ""))) {
698                         ao2_ref(opt, -1);
699                         ao2_iterator_destroy(&iter);
700                         return -1;
701                 }
702                 if (opt->handler(opt, var, obj)) {
703                         ast_log(LOG_ERROR, "Unable to set default for %s, %s=%s\n", category, var->name, var->value);
704                         ao2_ref(opt, -1);
705                         ao2_iterator_destroy(&iter);
706                         return -1;
707                 }
708                 ao2_ref(opt, -1);
709         }
710         ao2_iterator_destroy(&iter);
711
712         return 0;
713 }
714
715 /* Default config option handlers */
716
717 /*! \brief Default option handler for signed integers
718  * \note For a description of the opt->flags and opt->args values, see the documentation for
719  * enum aco_option_type in config_options.h
720  */
721 static int int_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj) {
722         int *field = (int *)(obj + opt->args[0]);
723         unsigned int flags = PARSE_INT32 | opt->flags;
724         int res = 0;
725         if (opt->flags & PARSE_IN_RANGE) {
726                 res = opt->flags & PARSE_DEFAULT ?
727                         ast_parse_arg(var->value, flags, field, (int) opt->args[1], (int) opt->args[2], opt->args[3]) :
728                         ast_parse_arg(var->value, flags, field, (int) opt->args[1], (int) opt->args[2]);
729                 if (res) {
730                         if (opt->flags & PARSE_RANGE_DEFAULTS) {
731                                 ast_log(LOG_WARNING, "Failed to set %s=%s. Set to  %d instead due to range limit (%d, %d)\n", var->name, var->value, *field, (int) opt->args[1], (int) opt->args[2]);
732                                 res = 0;
733                         } else if (opt->flags & PARSE_DEFAULT) {
734                                 ast_log(LOG_WARNING, "Failed to set %s=%s, Set to default value %d instead.\n", var->name, var->value, *field);
735                                 res = 0;
736                         }
737                 }
738         } else if ((opt->flags & PARSE_DEFAULT) && ast_parse_arg(var->value, flags, field, (int) opt->args[1])) {
739                 ast_log(LOG_WARNING, "Attempted to set %s=%s, but set it to %d instead due to default)\n", var->name, var->value, *field);
740         } else {
741                 res = ast_parse_arg(var->value, flags, field);
742         }
743
744         return res;
745 }
746
747 /*! \brief Default option handler for unsigned integers
748  * \note For a description of the opt->flags and opt->args values, see the documentation for
749  * enum aco_option_type in config_options.h
750  */
751 static int uint_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj) {
752         unsigned int *field = (unsigned int *)(obj + opt->args[0]);
753         unsigned int flags = PARSE_INT32 | opt->flags;
754         int res = 0;
755         if (opt->flags & PARSE_IN_RANGE) {
756                 res = opt->flags & PARSE_DEFAULT ?
757                         ast_parse_arg(var->value, flags, field, (unsigned int) opt->args[1], (unsigned int) opt->args[2], opt->args[3]) :
758                         ast_parse_arg(var->value, flags, field, (unsigned int) opt->args[1], (unsigned int) opt->args[2]);
759                 if (res) {
760                         if (opt->flags & PARSE_RANGE_DEFAULTS) {
761                                 ast_log(LOG_WARNING, "Failed to set %s=%s. Set to  %d instead due to range limit (%d, %d)\n", var->name, var->value, *field, (int) opt->args[1], (int) opt->args[2]);
762                                 res = 0;
763                         } else if (opt->flags & PARSE_DEFAULT) {
764                                 ast_log(LOG_WARNING, "Failed to set %s=%s, Set to default value %d instead.\n", var->name, var->value, *field);
765                                 res = 0;
766                         }
767                 }
768         } else if ((opt->flags & PARSE_DEFAULT) && ast_parse_arg(var->value, flags, field, (unsigned int) opt->args[1])) {
769                 ast_log(LOG_WARNING, "Attempted to set %s=%s, but set it to %u instead due to default)\n", var->name, var->value, *field);
770         } else {
771                 res = ast_parse_arg(var->value, flags, field);
772         }
773
774         return res;
775 }
776
777 /*! \brief Default option handler for doubles
778  * \note For a description of the opt->flags and opt->args values, see the documentation for
779  * enum aco_option_type in config_options.h
780  */
781 static int double_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj) {
782         double *field = (double *)(obj + opt->args[0]);
783         return ast_parse_arg(var->value, PARSE_DOUBLE | opt->flags, field);
784 }
785
786 /*! \brief Default handler for ACLs
787  * \note For a description of the opt->flags and opt->args values, see the documentation for
788  * enum aco_option_type in config_options.h
789  */
790 static int acl_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj) {
791         struct ast_ha **ha = (struct ast_ha **)(obj + opt->args[0]);
792         int error = 0;
793         *ha = ast_append_ha(opt->flags ? "permit" : "deny", var->value, *ha, &error);
794         return error;
795 }
796
797 /*! \brief Default option handler for codec preferences/capabilities
798  * \note For a description of the opt->flags and opt->args values, see the documentation for
799  * enum aco_option_type in config_options.h
800  */
801 static int codec_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj) {
802         struct ast_codec_pref *pref = (struct ast_codec_pref *)(obj + opt->args[0]);
803         struct ast_format_cap **cap = (struct ast_format_cap **)(obj + opt->args[1]);
804         return ast_parse_allow_disallow(pref, *cap, var->value, opt->flags);
805 }
806
807 /*! \brief Default option handler for stringfields
808  * \note For a description of the opt->flags and opt->args values, see the documentation for
809  * enum aco_option_type in config_options.h
810  */
811 static int stringfield_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj)
812 {
813         ast_string_field *field = (const char **)(obj + opt->args[0]);
814         struct ast_string_field_pool **pool = (struct ast_string_field_pool **)(obj + opt->args[1]);
815         struct ast_string_field_mgr *mgr = (struct ast_string_field_mgr *)(obj + opt->args[2]);
816         ast_string_field_ptr_set_by_fields(*pool, *mgr, field, var->value);
817         return 0;
818 }
819
820 /*! \brief Default option handler for bools (ast_true/ast_false)
821  * \note For a description of the opt->flags and opt->args values, see the documentation for
822  * enum aco_option_type in config_options.h
823  */
824 static int bool_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj)
825 {
826         unsigned int *field = (unsigned int *)(obj + opt->args[0]);
827         *field = opt->flags ? ast_true(var->value) : ast_false(var->value);
828         return 0;
829 }
830
831 /*! \brief Default option handler for bools (ast_true/ast_false) that are stored as flags
832  * \note For a description of the opt->flags and opt->args values, see the documentation for
833  * enum aco_option_type in config_options.h
834  */
835 static int boolflag_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj)
836 {
837         unsigned int *flags_field = (unsigned int *)(obj + opt->args[0]);
838         unsigned int val = opt->flags ? ast_true(var->value) : ast_false(var->value);
839         unsigned int flag = opt->args[1];
840         if (val) {
841                 *flags_field |= flag;
842         } else {
843                 *flags_field &= ~flag;
844         }
845         return 0;
846 }
847
848 /*! \brief Default handler for ast_sockaddrs
849  * \note For a description of the opt->flags and opt->args values, see the documentation for
850  * enum aco_option_type in config_options.h
851  */
852 static int sockaddr_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj)
853 {
854         struct ast_sockaddr *field = (struct ast_sockaddr *)(obj + opt->args[0]);
855         return ast_parse_arg(var->value, PARSE_ADDR | opt->flags, field);
856 }
857
858 /*! \brief Default handler for doing noithing
859  */
860 static int noop_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj)
861 {
862         return 0;
863 }
864
865 /*! \brief Default handler for character arrays
866  * \note For a description of the opt->flags and opt->args values, see the documentation for
867  * enum aco_option_type in config_options.h
868  */
869 static int chararray_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj)
870 {
871         char *field = (char *)(obj + opt->args[0]);
872         size_t len = opt->args[1];
873
874         ast_copy_string(field, var->value, len);
875         return 0;
876 }