/* parses subnet mask, fills 0 mask as well */ void parse_acl_range_subnet(char* p, void* addr, int maxbits) { int subnet_bits = atoi(p); uint8_t* addr_bytes = (uint8_t*)addr; if(subnet_bits == 0 && strcmp(p, "0")!=0) { c_error_msg("bad subnet range '%s'", p); return; } if(subnet_bits < 0 || subnet_bits > maxbits) { c_error_msg("subnet of %d bits out of range [0..%d]", subnet_bits, maxbits); return; } /* fill addr with n bits of 1s (struct has been zeroed) */ while(subnet_bits >= 8) { *addr_bytes++ = 0xff; subnet_bits -= 8; } if(subnet_bits > 0) { uint8_t shifts[] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; *addr_bytes = shifts[subnet_bits]; } }
void config_apply_pattern(const char* name) { /* find the pattern */ pattern_options_t* pat = pattern_options_find(cfg_parser->opt, name); pattern_options_t* a = cfg_parser->current_pattern; if(!pat) { c_error_msg("could not find pattern %s", name); return; } /* apply settings */ if(pat->zonefile) a->zonefile = region_strdup(cfg_parser->opt->region, pat->zonefile); if(pat->zonestats) a->zonestats = region_strdup(cfg_parser->opt->region, pat->zonestats); if(!pat->allow_axfr_fallback_is_default) { a->allow_axfr_fallback = pat->allow_axfr_fallback; a->allow_axfr_fallback_is_default = 0; } if(!pat->notify_retry_is_default) { a->notify_retry = pat->notify_retry; a->notify_retry_is_default = 0; } #ifdef RATELIMIT a->rrl_whitelist |= pat->rrl_whitelist; #endif /* append acl items */ append_acl(&a->allow_notify, &cfg_parser->current_allow_notify, pat->allow_notify); append_acl(&a->request_xfr, &cfg_parser->current_request_xfr, pat->request_xfr); append_acl(&a->notify, &cfg_parser->current_notify, pat->notify); append_acl(&a->provide_xfr, &cfg_parser->current_provide_xfr, pat->provide_xfr); append_acl(&a->outgoing_interface, &cfg_parser-> current_outgoing_interface, pat->outgoing_interface); }
void c_error(const char* str) { c_error_msg("%s", str); }
acl_options_t* parse_acl_info(region_type* region, char* ip, const char* key) { char* p; acl_options_t* acl = (acl_options_t*)region_alloc(region, sizeof(acl_options_t)); acl->next = 0; /* ip */ acl->ip_address_spec = region_strdup(region, ip); acl->use_axfr_only = 0; acl->allow_udp = 0; acl->ixfr_disabled = 0; acl->bad_xfr_count = 0; acl->key_options = 0; acl->is_ipv6 = 0; acl->port = 0; memset(&acl->addr, 0, sizeof(union acl_addr_storage)); memset(&acl->range_mask, 0, sizeof(union acl_addr_storage)); if((p=strrchr(ip, '@'))!=0) { if(atoi(p+1) == 0) c_error("expected port number after '@'"); else acl->port = atoi(p+1); *p=0; } acl->rangetype = parse_acl_range_type(ip, &p); if(parse_acl_is_ipv6(ip)) { acl->is_ipv6 = 1; #ifdef INET6 if(inet_pton(AF_INET6, ip, &acl->addr.addr6) != 1) c_error_msg("Bad ip6 address '%s'", ip); if(acl->rangetype==acl_range_mask || acl->rangetype==acl_range_minmax) if(inet_pton(AF_INET6, p, &acl->range_mask.addr6) != 1) c_error_msg("Bad ip6 address mask '%s'", p); if(acl->rangetype==acl_range_subnet) parse_acl_range_subnet(p, &acl->range_mask.addr6, 128); #else c_error_msg("encountered IPv6 address '%s'.", ip); #endif /* INET6 */ } else { acl->is_ipv6 = 0; if(inet_pton(AF_INET, ip, &acl->addr.addr) != 1) c_error_msg("Bad ip4 address '%s'", ip); if(acl->rangetype==acl_range_mask || acl->rangetype==acl_range_minmax) if(inet_pton(AF_INET, p, &acl->range_mask.addr) != 1) c_error_msg("Bad ip4 address mask '%s'", p); if(acl->rangetype==acl_range_subnet) parse_acl_range_subnet(p, &acl->range_mask.addr, 32); } /* key */ if(strcmp(key, "NOKEY")==0) { acl->nokey = 1; acl->blocked = 0; acl->key_name = 0; } else if(strcmp(key, "BLOCKED")==0) { acl->nokey = 0; acl->blocked = 1; acl->key_name = 0; } else { acl->nokey = 0; acl->blocked = 0; acl->key_name = region_strdup(region, key); } return acl; }
int parse_options_file(nsd_options_t* opt, const char* file, void (*err)(void*,const char*), void* err_arg) { FILE *in = 0; pattern_options_t* pat; acl_options_t* acl; if(!cfg_parser) { cfg_parser = (config_parser_state_t*)region_alloc( opt->region, sizeof(config_parser_state_t)); cfg_parser->chroot = 0; } cfg_parser->err = err; cfg_parser->err_arg = err_arg; cfg_parser->filename = (char*)file; cfg_parser->line = 1; cfg_parser->errors = 0; cfg_parser->server_settings_seen = 0; cfg_parser->opt = opt; cfg_parser->current_pattern = 0; cfg_parser->current_zone = 0; cfg_parser->current_key = 0; cfg_parser->current_ip_address_option = opt->ip_addresses; while(cfg_parser->current_ip_address_option && cfg_parser->current_ip_address_option->next) cfg_parser->current_ip_address_option = cfg_parser->current_ip_address_option->next; cfg_parser->current_allow_notify = 0; cfg_parser->current_request_xfr = 0; cfg_parser->current_notify = 0; cfg_parser->current_provide_xfr = 0; in = fopen(cfg_parser->filename, "r"); if(!in) { if(err) { char m[MAXSYSLOGMSGLEN]; snprintf(m, sizeof(m), "Could not open %s: %s\n", file, strerror(errno)); err(err_arg, m); } else { fprintf(stderr, "Could not open %s: %s\n", file, strerror(errno)); } return 0; } c_in = in; c_parse(); fclose(in); opt->configfile = region_strdup(opt->region, file); if(cfg_parser->current_pattern) { if(!cfg_parser->current_pattern->pname) c_error("last pattern has no name"); else { if(!nsd_options_insert_pattern(cfg_parser->opt, cfg_parser->current_pattern)) c_error("duplicate pattern"); } } if(cfg_parser->current_zone) { if(!cfg_parser->current_zone->name) c_error("last zone has no name"); else { if(!nsd_options_insert_zone(opt, cfg_parser->current_zone)) c_error("duplicate zone"); } if(!cfg_parser->current_zone->pattern) c_error("last zone has no pattern"); } if(cfg_parser->current_key) { if(!cfg_parser->current_key->name) c_error("last key has no name"); if(!cfg_parser->current_key->algorithm) c_error("last key has no algorithm"); if(!cfg_parser->current_key->secret) c_error("last key has no secret blob"); key_options_insert(opt, cfg_parser->current_key); } RBTREE_FOR(pat, pattern_options_t*, opt->patterns) { /* lookup keys for acls */ for(acl=pat->allow_notify; acl; acl=acl->next) { if(acl->nokey || acl->blocked) continue; acl->key_options = key_options_find(opt, acl->key_name); if(!acl->key_options) c_error_msg("key %s in pattern %s could not be found", acl->key_name, pat->pname); } for(acl=pat->notify; acl; acl=acl->next) { if(acl->nokey || acl->blocked) continue; acl->key_options = key_options_find(opt, acl->key_name); if(!acl->key_options) c_error_msg("key %s in pattern %s could not be found", acl->key_name, pat->pname); } for(acl=pat->request_xfr; acl; acl=acl->next) { if(acl->nokey || acl->blocked) continue; acl->key_options = key_options_find(opt, acl->key_name); if(!acl->key_options) c_error_msg("key %s in pattern %s could not be found", acl->key_name, pat->pname); } for(acl=pat->provide_xfr; acl; acl=acl->next) { if(acl->nokey || acl->blocked) continue; acl->key_options = key_options_find(opt, acl->key_name); if(!acl->key_options) c_error_msg("key %s in pattern %s could not be found", acl->key_name, pat->pname); } } if(cfg_parser->errors > 0) { if(err) { char m[MAXSYSLOGMSGLEN]; snprintf(m, sizeof(m), "read %s failed: %d errors in " "configuration file\n", file, cfg_parser->errors); err(err_arg, m); } else { fprintf(stderr, "read %s failed: %d errors in " "configuration file\n", file, cfg_parser->errors); } return 0; } return 1; }
int parse_options_file(nsd_options_t* opt, const char* file) { FILE *in = 0; zone_options_t* zone; acl_options_t* acl; if(!cfg_parser) cfg_parser = (config_parser_state_t*)region_alloc( opt->region, sizeof(config_parser_state_t)); cfg_parser->filename = file; cfg_parser->line = 1; cfg_parser->errors = 0; cfg_parser->opt = opt; cfg_parser->current_zone = 0; cfg_parser->current_key = opt->keys; while(cfg_parser->current_key && cfg_parser->current_key->next) cfg_parser->current_key = cfg_parser->current_key->next; cfg_parser->current_ip_address_option = opt->ip_addresses; while(cfg_parser->current_ip_address_option && cfg_parser->current_ip_address_option->next) cfg_parser->current_ip_address_option = cfg_parser->current_ip_address_option->next; cfg_parser->current_allow_notify = 0; cfg_parser->current_request_xfr = 0; cfg_parser->current_notify = 0; cfg_parser->current_provide_xfr = 0; in = fopen(cfg_parser->filename, "r"); if(!in) { fprintf(stderr, "Could not open %s: %s\n", file, strerror(errno)); return 0; } c_in = in; c_parse(); fclose(in); if(cfg_parser->current_zone) { if(!cfg_parser->current_zone->name) c_error("last zone has no name"); else { if(!nsd_options_insert_zone(opt, cfg_parser->current_zone)) c_error("duplicate zone"); } if(!cfg_parser->current_zone->zonefile) c_error("last zone has no zonefile"); } if(opt->keys) { if(!opt->keys->name) c_error("last key has no name"); if(!opt->keys->algorithm) c_error("last key has no algorithm"); if(!opt->keys->secret) c_error("last key has no secret blob"); } RBTREE_FOR(zone, zone_options_t*, opt->zone_options) { if(!zone->name) continue; if(!zone->zonefile) continue; /* lookup keys for acls */ for(acl=zone->allow_notify; acl; acl=acl->next) { if(acl->nokey || acl->blocked) continue; acl->key_options = key_options_find(opt, acl->key_name); if(!acl->key_options) c_error_msg("key %s in zone %s could not be found", acl->key_name, zone->name); } for(acl=zone->notify; acl; acl=acl->next) { if(acl->nokey || acl->blocked) continue; acl->key_options = key_options_find(opt, acl->key_name); if(!acl->key_options) c_error_msg("key %s in zone %s could not be found", acl->key_name, zone->name); } for(acl=zone->request_xfr; acl; acl=acl->next) { if(acl->nokey || acl->blocked) continue; acl->key_options = key_options_find(opt, acl->key_name); if(!acl->key_options) c_error_msg("key %s in zone %s could not be found", acl->key_name, zone->name); } for(acl=zone->provide_xfr; acl; acl=acl->next) { if(acl->nokey || acl->blocked) continue; acl->key_options = key_options_find(opt, acl->key_name); if(!acl->key_options) c_error_msg("key %s in zone %s could not be found", acl->key_name, zone->name); } } if(cfg_parser->errors > 0) { fprintf(stderr, "read %s failed: %d errors in configuration file\n", cfg_parser->filename, cfg_parser->errors); return 0; } return 1; }