📄 server.c
字号:
"no forwarders seen; disabling " "forwarding"); fwdpolicy = dns_fwdpolicy_none; } else { if (forwardtype == NULL) fwdpolicy = dns_fwdpolicy_first; else { char *forwardstr = cfg_obj_asstring(forwardtype); if (strcasecmp(forwardstr, "first") == 0) fwdpolicy = dns_fwdpolicy_first; else if (strcasecmp(forwardstr, "only") == 0) fwdpolicy = dns_fwdpolicy_only; else INSIST(0); } } result = dns_fwdtable_add(view->fwdtable, origin, &addresses, fwdpolicy); if (result != ISC_R_SUCCESS) { char namebuf[DNS_NAME_FORMATSIZE]; dns_name_format(origin, namebuf, sizeof(namebuf)); cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING, "could not set up forwarding for domain '%s': %s", namebuf, isc_result_totext(result)); goto cleanup; } result = ISC_R_SUCCESS; cleanup: while (!ISC_LIST_EMPTY(addresses)) { sa = ISC_LIST_HEAD(addresses); ISC_LIST_UNLINK(addresses, sa, link); isc_mem_put(view->mctx, sa, sizeof(isc_sockaddr_t)); } return (result);}/* * Create a new view and add it to the list. * * If 'vconfig' is NULL, create the default view. * * The view created is attached to '*viewp'. */static isc_result_tcreate_view(cfg_obj_t *vconfig, dns_viewlist_t *viewlist, dns_view_t **viewp) { isc_result_t result; const char *viewname; dns_rdataclass_t viewclass; dns_view_t *view = NULL; if (vconfig != NULL) { cfg_obj_t *classobj = NULL; viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); classobj = cfg_tuple_get(vconfig, "class"); result = ns_config_getclass(classobj, dns_rdataclass_in, &viewclass); } else { viewname = "_default"; viewclass = dns_rdataclass_in; } result = dns_viewlist_find(viewlist, viewname, viewclass, &view); if (result == ISC_R_SUCCESS) return (ISC_R_EXISTS); if (result != ISC_R_NOTFOUND) return (result); INSIST(view == NULL); result = dns_view_create(ns_g_mctx, viewclass, viewname, &view); if (result != ISC_R_SUCCESS) return (result); ISC_LIST_APPEND(*viewlist, view, link); dns_view_attach(view, viewp); return (ISC_R_SUCCESS);}/* * Configure or reconfigure a zone. */static isc_result_tconfigure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, ns_aclconfctx_t *aclconf){ dns_view_t *pview = NULL; /* Production view */ dns_zone_t *zone = NULL; /* New or reused zone */ dns_zone_t *dupzone = NULL; cfg_obj_t *options = NULL; cfg_obj_t *zoptions = NULL; cfg_obj_t *typeobj = NULL; cfg_obj_t *forwarders = NULL; cfg_obj_t *forwardtype = NULL; cfg_obj_t *only = NULL; isc_result_t result; isc_result_t tresult; isc_buffer_t buffer; dns_fixedname_t fixorigin; dns_name_t *origin; const char *zname; dns_rdataclass_t zclass; const char *ztypestr; options = NULL; (void)cfg_map_get(config, "options", &options); zoptions = cfg_tuple_get(zconfig, "options"); /* * Get the zone origin as a dns_name_t. */ zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); isc_buffer_init(&buffer, zname, strlen(zname)); isc_buffer_add(&buffer, strlen(zname)); dns_fixedname_init(&fixorigin); CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin), &buffer, dns_rootname, ISC_FALSE, NULL)); origin = dns_fixedname_name(&fixorigin); CHECK(ns_config_getclass(cfg_tuple_get(zconfig, "class"), view->rdclass, &zclass)); if (zclass != view->rdclass) { const char *vname = NULL; if (vconfig != NULL) vname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); else vname = "<default view>"; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "zone '%s': wrong class for view '%s'", zname, vname); result = ISC_R_FAILURE; goto cleanup; } (void)cfg_map_get(zoptions, "type", &typeobj); if (typeobj == NULL) { cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, "zone '%s' 'type' not specified", zname); return (ISC_R_FAILURE); } ztypestr = cfg_obj_asstring(typeobj); /* * "hints zones" aren't zones. If we've got one, * configure it and return. */ if (strcasecmp(ztypestr, "hint") == 0) { cfg_obj_t *fileobj = NULL; if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "zone '%s': 'file' not specified", zname); result = ISC_R_FAILURE; goto cleanup; } if (dns_name_equal(origin, dns_rootname)) { char *hintsfile = cfg_obj_asstring(fileobj); result = configure_hints(view, hintsfile); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "could not configure root hints " "from '%s': %s", hintsfile, isc_result_totext(result)); goto cleanup; } /* * Hint zones may also refer to delegation only points. */ only = NULL; tresult = cfg_map_get(zoptions, "delegation-only", &only); if (tresult == ISC_R_SUCCESS && cfg_obj_asboolean(only)) CHECK(dns_view_adddelegationonly(view, origin)); } else { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "ignoring non-root hint zone '%s'", zname); result = ISC_R_SUCCESS; } /* Skip ordinary zone processing. */ goto cleanup; } /* * "forward zones" aren't zones either. Translate this syntax into * the appropriate selective forwarding configuration and return. */ if (strcasecmp(ztypestr, "forward") == 0) { forwardtype = NULL; forwarders = NULL; (void)cfg_map_get(zoptions, "forward", &forwardtype); (void)cfg_map_get(zoptions, "forwarders", &forwarders); result = configure_forward(config, view, origin, forwarders, forwardtype); goto cleanup; } /* * "delegation-only zones" aren't zones either. */ if (strcasecmp(ztypestr, "delegation-only") == 0) { result = dns_view_adddelegationonly(view, origin); goto cleanup; } /* * Check for duplicates in the new zone table. */ result = dns_view_findzone(view, origin, &dupzone); if (result == ISC_R_SUCCESS) { /* * We already have this zone! */ cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, "zone '%s' already exists", zname); dns_zone_detach(&dupzone); result = ISC_R_EXISTS; goto cleanup; } INSIST(dupzone == NULL); /* * See if we can reuse an existing zone. This is * only possible if all of these are true: * - The zone's view exists * - A zone with the right name exists in the view * - The zone is compatible with the config * options (e.g., an existing master zone cannot * be reused if the options specify a slave zone) */ result = dns_viewlist_find(&ns_g_server->viewlist, view->name, view->rdclass, &pview); if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) goto cleanup; if (pview != NULL) result = dns_view_findzone(pview, origin, &zone); if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) goto cleanup; if (zone != NULL) { if (! ns_zone_reusable(zone, zconfig)) dns_zone_detach(&zone); } if (zone != NULL) { /* * We found a reusable zone. Make it use the * new view. */ dns_zone_setview(zone, view); } else { /* * We cannot reuse an existing zone, we have * to create a new one. */ CHECK(dns_zone_create(&zone, mctx)); CHECK(dns_zone_setorigin(zone, origin)); dns_zone_setview(zone, view); CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); } /* * If the zone contains a 'forwarders' statement, configure * selective forwarding. */ forwarders = NULL; if (cfg_map_get(zoptions, "forwarders", &forwarders) == ISC_R_SUCCESS) { forwardtype = NULL; (void)cfg_map_get(zoptions, "forward", &forwardtype); CHECK(configure_forward(config, view, origin, forwarders, forwardtype)); } /* * Stub and forward zones may also refer to delegation only points. */ only = NULL; if (cfg_map_get(zoptions, "delegation-only", &only) == ISC_R_SUCCESS) { if (cfg_obj_asboolean(only)) CHECK(dns_view_adddelegationonly(view, origin)); } /* * Configure the zone. */ CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, zone)); /* * Add the zone to its view in the new view list. */ CHECK(dns_view_addzone(view, zone)); cleanup: if (zone != NULL) dns_zone_detach(&zone); if (pview != NULL) dns_view_detach(&pview); return (result);}/* * Configure a single server quota. */static voidconfigure_server_quota(cfg_obj_t **maps, const char *name, isc_quota_t *quota){ cfg_obj_t *obj = NULL; isc_result_t result; result = ns_config_get(maps, name, &obj); INSIST(result == ISC_R_SUCCESS); quota->max = cfg_obj_asuint32(obj);}/* * This function is called as soon as the 'directory' statement has been * parsed. This can be extended to support other options if necessary. */static isc_result_tdirectory_callback(const char *clausename, cfg_obj_t *obj, void *arg) { isc_result_t result; char *directory; REQUIRE(strcasecmp("directory", clausename) == 0); UNUSED(arg); UNUSED(clausename); /* * Change directory. */ directory = cfg_obj_asstring(obj); if (! isc_file_ischdiridempotent(directory)) cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, "option 'directory' contains relative path '%s'", directory); result = isc_dir_chdir(directory); if (result != ISC_R_SUCCESS) { cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, "change directory to '%s' failed: %s", directory, isc_result_totext(result)); return (result); } return (ISC_R_SUCCESS);}static voidscan_interfaces(ns_server_t *server, isc_boolean_t verbose) { isc_boolean_t match_mapped = server->aclenv.match_mapped; ns_interfacemgr_scan(server->interfacemgr, verbose); /* * Update the "localhost" and "localnets" ACLs to match the * current set of network interfaces. */ dns_aclenv_copy(&server->aclenv, ns_interfacemgr_getaclenv(server->interfacemgr)); server->aclenv.match_mapped = match_mapped;}static isc_result_tadd_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr) { ns_listenelt_t *lelt = NULL; dns_acl_t *src_acl = NULL; dns_aclelement_t aelt; isc_result_t result; isc_sockaddr_t any_sa6; REQUIRE(isc_sockaddr_pf(addr) == AF_INET6); isc_sockaddr_any6(&any_sa6); if (!isc_sockaddr_equal(&any_sa6, addr)) { aelt.type = dns_aclelementtype_ipprefix; aelt.negative = ISC_FALSE; aelt.u.ip_prefix.prefixlen = 128; isc_netaddr_fromin6(&aelt.u.ip_prefix.address, &addr->type.sin6.sin6_addr); result = dns_acl_create(mctx, 1, &src_acl); if (result != ISC_R_SUCCESS) return (result); result = dns_acl_appendelement(src_acl, &aelt); if (result != ISC_R_SUCCESS) goto clean; result = ns_listenelt_create(mctx, isc_sockaddr_getport(addr), src_acl, &lelt); if (result != ISC_R_SUCCESS) goto clean; ISC_LIST_APPEND(list->elts, lelt, link); } return (ISC_R_SUCCESS); clean: INSIST(lelt == NULL); if (src_acl != NULL) dns_acl_detach(&src_acl); return (result);}/* * Make a list of xxx-source addresses and call ns_interfacemgr_adjust() * to update the listening interfaces accordingly. * We currently only consider IPv6, because this only affects IPv6 wildcard * sockets. */static voidadjust_interfaces(ns_server_t *server, isc_mem_t *mctx) { isc_result_t result; ns_listenlist_t *list = NULL; dns_view_t *view; dns_zone_t *zone, *next; isc_sockaddr_t addr, *addrp; result = ns_listenlist_create(mctx, &list); if (result != ISC_R_SUCCESS) return; for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { dns_dispatch_t *dispatch6; dispatch6 = dns_resolver_dispatchv6(view->resolver); INSIST(dispatch6 != NULL); result = dns_dispatch_getlocaladdress(dispatch6, &addr); if (result != ISC_R_SUCCESS) goto fail; result = add_listenelt(mctx, list, &addr); if (result != ISC_R_SUCCESS) goto fail; } zone = NULL; for (result = dns_zone_first(server->zonemgr, &zone); result == ISC_R_SUCCESS; next = NULL, result = dns_zone_next(zone, &next), zone = next) { dns_view_t *zoneview; /* * At this point the zone list may contain a stale zone * just removed from the configuration. To see the validity, * check if the corresponding view is in our current view list. */ zoneview = dns_zone_getview(zone); INSIST(zoneview != NULL); for (view = ISC_LIST_HEAD(server->viewlist); view != NULL && view != zoneview; view = ISC_LIST_NEXT(view, link)) ; if (view == NULL) continue; addrp = dns_zone_getnotifysrc6(zone); result = add_listenelt(mctx, list, addrp); if (result != ISC_R_SUCCESS) goto fail; addrp = dns_zone_getxfrsource6(zone); result = add_listenelt(mctx, list, addrp); if (result != ISC_R_SUCCESS) goto fail; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -