int confload_toplevel(struct ConfParse *parse, void *data, const struct CF_Child *node) { struct Configuration *cfg = (struct Configuration *)data; if (node->token_count == 0) return 0; switch (lookup_name(node)) { case S_ACL: load_acl(cfg, parse, node); break; case S_INCLUDE: { struct CF_Token token = confparse_node_gettoken(parse, node, 1); char *filename; if (filename_is_absolute(token.name)) filename = filename_combine("", token.name); else filename = filename_combine(cfg->options.directory, token.name); token.name = filename; token.name_length = (unsigned)strlen(filename); confload_configuration(cfg, filename, &token); free(filename); } break; case S_KEY: conf_load_key(cfg, parse, node); break; case S_OPTIONS: load_options(cfg, parse, node); break; case S_ZONE: conf_load_zone(cfg, parse, node); break; default: //print_node(parse, stdout, node, 0); { struct CF_Token value = confparse_node_gettoken(parse, node, 0); CONF_OPTION_UNKNOWN(parse, &value); } break; } return 0; }
static void load_acl(struct Configuration *cfg, const struct ConfParse *parse, const struct CF_Child *parent) { struct CF_Token value = confparse_node_gettoken(parse, parent, 1); struct Cfg_AddrMatchList *acl; /* address-lists must be named when inside an "acl" statement */ if (value.name_length == 0) { CONF_VALUE_MISSING(parse, &value); return; } /* parse the address-list */ acl = conf_load_addrlist(cfg, parse, parent, &value, 65536); if (acl == NULL) return; /* make sure it has a name */ acl->name = malloc(value.name_length + 1); memcpy(acl->name, value.name, value.name_length + 1); /* * Add to our named set of address-lists. This is so that later * configuration parameters can refer back to this list rather than * redefining their own */ if (cfg->acls_length == 0) cfg->acls = malloc(sizeof(cfg->acls[0])); else cfg->acls = realloc(cfg->acls, sizeof(cfg->acls[0]) * (cfg->acls_length + 1)); cfg->acls[cfg->acls_length++] = acl; }
void conf_load_zone( struct Configuration *cfg, const struct ConfParse *parse, const struct CF_Child *parent) { struct CF_Token value = confparse_node_gettoken(parse, parent, 1); struct Cfg_Zone *zone; size_t i; if (value.name_length == 0) { CONF_VALUE_MISSING(parse, &value); return; } zone = conf_zone_create(value.name, value.name_length); /* * Parse all the options */ for (i=0; i<parent->child_count; i++) { struct CF_Child child = confparse_node_getchild(parse, parent, i); conf_load_zone_item(cfg, parse, &child, zone); } /* * Add to our list of zones */ if (cfg->zones_length == 0) cfg->zones = malloc(sizeof(cfg->zones[0])); else cfg->zones = realloc(cfg->zones, sizeof(cfg->zones[0]) * (cfg->zones_length + 1)); cfg->zones[cfg->zones_length++] = zone; }
static void print_node(struct ConfParse *conf, FILE *fp, const struct CF_Child *node, unsigned depth) { size_t i; /* indent */ for (i=0; i < depth * 4; i++) fprintf(fp, " "); /* print all tokens */ for (i = 0; i < node->token_count; i++) { struct CF_Token token; const char *space = " "; token = confparse_node_gettoken(conf, node, i); if (i + 1 == node->token_count) space = ""; if (token.is_string) fprintf(fp, "\"%.*s\"%s", token.name_length, token.name, space); else fprintf(fp, "%.*s%s", token.name_length, token.name, space); } /* print all children */ if (node->child_count) { fprintf(fp, " {\n"); for (i = 0; i < node->child_count; i++) { struct CF_Child child; child = confparse_node_getchild(conf, node, i); print_node(conf, fp, &child, depth+1); } for (i=0; i < depth * 4; i++) fprintf(fp, " "); fprintf(fp, "};\n"); } else fprintf(fp, ";\n"); }
static void load_options(struct Configuration *cfg, const struct ConfParse *parse, const struct CF_Child *parent) { struct ConfigurationOptions *options = &cfg->options; size_t i; for (i=0; i<parent->child_count; i++) { struct CF_Child child = confparse_node_getchild(parse, parent, i); struct CF_Token name; struct CF_Token value; name = confparse_node_gettoken(parse, &child, 0); value = confparse_node_gettoken(parse, &child, 1); switch (lookup_token(&name)) { case S_DIRECTORY: if (options->directory) free(options->directory); if (filename_is_absolute(value.name)) { options->directory = filename_combine(value.name, ""); } else { char dir[2048]; if (getcwd(dir, sizeof(dir)) == NULL) { perror("getcwd"); exit(1); } options->directory = filename_combine(dir, value.name); } break; case S_PID_FILE: if (options->pid_file) free(options->pid_file); if (filename_is_absolute(value.name)) { options->pid_file = filename_combine(value.name, ""); if (*options->pid_file && options->pid_file[strlen(options->pid_file)-1] == '/') options->pid_file[strlen(options->pid_file)-1] = '\0'; } else if (options->directory == NULL || strcmp(options->directory, ".") == 0) { char dir[2048]; if (getcwd(dir, sizeof(dir)) == NULL) { perror("getcwd"); exit(1); } options->pid_file = filename_combine(dir, value.name); } else options->pid_file = filename_combine(options->directory, value.name); break; case S_PORT: if (!is_number(&value)) CONF_VALUE_BAD(parse, &value); else { unsigned n = to_number(&value); if (n > 65535) CONF_VALUE_BAD(parse, &value); else cfg->data_plane.port = n; } break; case S_LISTEN_ON: case S_LISTEN_ON_V6: break; case S_TRANSFER_SOURCE: case S_TRANSFER_SOURCE_V6: case S_ALT_TRANSFER_SOURCE: case S_ALT_TRANSFER_SOURCE_V6: break; case S_INTERFACE_INTERVAL: if (!is_number(&value)) CONF_VALUE_BAD(parse, &value); else { unsigned n = to_number(&value); if (n > 40320) CONF_VALUE_BAD(parse, &value); else cfg->data_plane.interface_interval = n; } break; case S_VERSION: switch (lookup_token(&value)) { case S_NONE: if (options->version) free(options->version); options->version = NULL; options->version_length = 0; break; default: if (options->version) free(options->version); options->version = malloc(value.name_length + 1); memcpy(options->version, value.name, value.name_length + 1); options->version_length = value.name_length; break; } break; case S_HOSTNAME: switch (lookup_token(&value)) { case S_NONE: if (options->hostname) free(options->hostname); options->hostname = NULL; break; case S_HOSTNAME: if (options->hostname) free(options->hostname); options->hostname = malloc(130); if (gethostname(options->hostname, 130) != 0) { perror("gethostname()"); free(options->hostname); options->hostname = 0; } break; default: if (options->hostname) free(options->hostname); options->hostname = malloc(value.name_length + 1); memcpy(options->hostname, value.name, value.name_length + 1); break; } break; case S_SERVER_ID: switch (lookup_token(&value)) { case S_NONE: if (options->server_id) free(options->server_id); options->server_id = NULL; options->server_id_length = 0; break; case S_HOSTNAME: if (options->server_id) free(options->server_id); options->server_id = malloc(130); if (gethostname(options->server_id, 130) != 0) { perror("gethostname()"); free(options->server_id); options->server_id = 0; options->server_id_length = 0; } else options->server_id_length = strlen(options->server_id); break; default: if (options->server_id) free(options->server_id); options->server_id = malloc(value.name_length + 1); memcpy(options->server_id, value.name, value.name_length + 1); options->server_id_length = value.name_length; break; } break; case S_ALLOW_NEW_ZONES: switch (lookup_token(&value)) { case S_YES: break; case S_NO: CONF_FEATURE_UNSUPPORTED(parse, &value); break; default: CONF_VALUE_BAD(parse, &value); break; } break; case S_RECURSION: switch (lookup_token(&value)) { case S_YES: CONF_FEATURE_UNSUPPORTED(parse, &value); break; case S_NO: //CONF_RECURSION_UNSUPPORTED(parse, &value); break; default: CONF_VALUE_BAD(parse, &value); break; } break; case S_AUTH_NXDOMAIN: switch (lookup_token(&value)) { case S_YES: CONF_FEATURE_UNSUPPORTED(parse, &value); break; case S_NO: break; default: CONF_VALUE_BAD(parse, &value); break; } break; case S_FORWARDERS: CONF_RECURSION_UNSUPPORTED(parse, &name); break; case S_DNSSEC_VALIDATION: CONF_FEATURE_UNSUPPORTED(parse, &name); break; default: CONF_OPTION_UNKNOWN(parse, &name); break; } } }
void conf_load_zone_item( struct Configuration *cfg, const struct ConfParse *parse, const struct CF_Child *parent, struct Cfg_Zone *zone ) { struct CF_Token token = confparse_node_gettoken(parse, parent, 0); struct CF_Token value = confparse_node_gettoken(parse, parent, 1); switch (lookup_token(&token)) { case S_TYPE: if (zone->type != 0) CONF_OPTION_DUPLICATE(parse, &token); switch (lookup_token(&value)) { case S_MASTER: zone->type = CFGZ_MASTER; break; case S_SLAVE: zone->type = CFGZ_SLAVE; break; default: CONF_VALUE_BAD(parse, &value); } break; case S_FILE: if (zone->file != 0) { CONF_OPTION_DUPLICATE(parse, &token); free(zone->file); zone->file = NULL; } if (value.name_length == 0) { CONF_VALUE_BAD(parse, &value); } else { zone->file = filename_combine(cfg->options.directory, value.name); } break; case S_ALLOW_NOTIFY: if (zone->allow_notify) { CONF_OPTION_DUPLICATE(parse, &token); conf_addrmatch_free(zone->allow_notify); zone->allow_notify = NULL; } zone->allow_notify = conf_load_addrlist(cfg, parse, parent, 0, 65536); break; case S_ALLOW_TRANSFER: if (zone->allow_transfer) { CONF_OPTION_DUPLICATE(parse, &token); conf_addrmatch_free(zone->allow_transfer); zone->allow_transfer = NULL; } zone->allow_transfer = conf_load_addrlist(cfg, parse, parent, 0, 65536); break; case S_ALSO_NOTIFY: if (zone->also_notify) { CONF_OPTION_DUPLICATE(parse, &token); conf_addrmatch_free(zone->also_notify); zone->also_notify = NULL; } zone->also_notify = conf_load_addrlist(cfg, parse, parent, 0, 65536); break; default: CONF_OPTION_UNKNOWN(parse, &token); break; } }