/*% * Parse the zone update-policy statement. */ static isc_result_t configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone, const char *zname) { const cfg_obj_t *updatepolicy = NULL; const cfg_listelt_t *element, *element2; dns_ssutable_t *table = NULL; isc_mem_t *mctx = dns_zone_getmctx(zone); isc_boolean_t autoddns = ISC_FALSE; isc_result_t result; (void)cfg_map_get(zconfig, "update-policy", &updatepolicy); if (updatepolicy == NULL) { dns_zone_setssutable(zone, NULL); return (ISC_R_SUCCESS); } if (cfg_obj_isstring(updatepolicy) && strcmp("local", cfg_obj_asstring(updatepolicy)) == 0) { autoddns = ISC_TRUE; updatepolicy = NULL; } result = dns_ssutable_create(mctx, &table); if (result != ISC_R_SUCCESS) return (result); for (element = cfg_list_first(updatepolicy); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *stmt = cfg_listelt_value(element); const cfg_obj_t *mode = cfg_tuple_get(stmt, "mode"); const cfg_obj_t *identity = cfg_tuple_get(stmt, "identity"); const cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype"); const cfg_obj_t *dname = cfg_tuple_get(stmt, "name"); const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types"); const char *str; isc_boolean_t grant = ISC_FALSE; isc_boolean_t usezone = ISC_FALSE; unsigned int mtype = DNS_SSUMATCHTYPE_NAME; dns_fixedname_t fname, fident; isc_buffer_t b; dns_rdatatype_t *types; unsigned int i, n; str = cfg_obj_asstring(mode); if (strcasecmp(str, "grant") == 0) grant = ISC_TRUE; else if (strcasecmp(str, "deny") == 0) grant = ISC_FALSE; else INSIST(0); str = cfg_obj_asstring(matchtype); if (strcasecmp(str, "name") == 0) mtype = DNS_SSUMATCHTYPE_NAME; else if (strcasecmp(str, "subdomain") == 0) mtype = DNS_SSUMATCHTYPE_SUBDOMAIN; else if (strcasecmp(str, "wildcard") == 0) mtype = DNS_SSUMATCHTYPE_WILDCARD; else if (strcasecmp(str, "self") == 0) mtype = DNS_SSUMATCHTYPE_SELF; else if (strcasecmp(str, "selfsub") == 0) mtype = DNS_SSUMATCHTYPE_SELFSUB; else if (strcasecmp(str, "selfwild") == 0) mtype = DNS_SSUMATCHTYPE_SELFWILD; else if (strcasecmp(str, "ms-self") == 0) mtype = DNS_SSUMATCHTYPE_SELFMS; else if (strcasecmp(str, "krb5-self") == 0) mtype = DNS_SSUMATCHTYPE_SELFKRB5; else if (strcasecmp(str, "ms-subdomain") == 0) mtype = DNS_SSUMATCHTYPE_SUBDOMAINMS; else if (strcasecmp(str, "krb5-subdomain") == 0) mtype = DNS_SSUMATCHTYPE_SUBDOMAINKRB5; else if (strcasecmp(str, "tcp-self") == 0) mtype = DNS_SSUMATCHTYPE_TCPSELF; else if (strcasecmp(str, "6to4-self") == 0) mtype = DNS_SSUMATCHTYPE_6TO4SELF; else if (strcasecmp(str, "zonesub") == 0) { mtype = DNS_SSUMATCHTYPE_SUBDOMAIN; usezone = ISC_TRUE; } else if (strcasecmp(str, "external") == 0) mtype = DNS_SSUMATCHTYPE_EXTERNAL; else INSIST(0); dns_fixedname_init(&fident); str = cfg_obj_asstring(identity); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); result = dns_name_fromtext(dns_fixedname_name(&fident), &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, "'%s' is not a valid name", str); goto cleanup; } dns_fixedname_init(&fname); if (usezone) { result = dns_name_copy(dns_zone_getorigin(zone), dns_fixedname_name(&fname), NULL); if (result != ISC_R_SUCCESS) { cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, "error copying origin: %s", isc_result_totext(result)); goto cleanup; } } else { str = cfg_obj_asstring(dname); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); result = dns_name_fromtext(dns_fixedname_name(&fname), &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, "'%s' is not a valid name", str); goto cleanup; } } n = ns_config_listcount(typelist); if (n == 0) types = NULL; else { types = isc_mem_get(mctx, n * sizeof(dns_rdatatype_t)); if (types == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } } i = 0; for (element2 = cfg_list_first(typelist); element2 != NULL; element2 = cfg_list_next(element2)) { const cfg_obj_t *typeobj; isc_textregion_t r; INSIST(i < n); typeobj = cfg_listelt_value(element2); str = cfg_obj_asstring(typeobj); DE_CONST(str, r.base); r.length = strlen(str); result = dns_rdatatype_fromtext(&types[i++], &r); if (result != ISC_R_SUCCESS) { cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, "'%s' is not a valid type", str); isc_mem_put(mctx, types, n * sizeof(dns_rdatatype_t)); goto cleanup; } } INSIST(i == n); result = dns_ssutable_addrule(table, grant, dns_fixedname_name(&fident), mtype, dns_fixedname_name(&fname), n, types); if (types != NULL) isc_mem_put(mctx, types, n * sizeof(dns_rdatatype_t)); if (result != ISC_R_SUCCESS) { goto cleanup; } } /* * If "update-policy local;" and a session key exists, * then use the default policy, which is equivalent to: * update-policy { grant <session-keyname> zonesub any; }; */ if (autoddns) { dns_rdatatype_t any = dns_rdatatype_any; if (ns_g_server->session_keyname == NULL) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "failed to enable auto DDNS policy " "for zone %s: session key not found", zname); result = ISC_R_NOTFOUND; goto cleanup; } result = dns_ssutable_addrule(table, ISC_TRUE, ns_g_server->session_keyname, DNS_SSUMATCHTYPE_SUBDOMAIN, dns_zone_getorigin(zone), 1, &any); if (result != ISC_R_SUCCESS) goto cleanup; } result = ISC_R_SUCCESS; dns_zone_setssutable(zone, table); cleanup: dns_ssutable_detach(&table); return (result); }
isc_result_t ns_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list, in_port_t defport, isc_mem_t *mctx, isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp, isc_uint32_t *countp) { int count, i = 0; const cfg_obj_t *addrlist; const cfg_obj_t *portobj, *dscpobj; const cfg_listelt_t *element; isc_sockaddr_t *addrs; in_port_t port; isc_dscp_t dscp = -1, *dscps = NULL; isc_result_t result; INSIST(addrsp != NULL && *addrsp == NULL); INSIST(dscpsp == NULL || *dscpsp == NULL); INSIST(countp != NULL); addrlist = cfg_tuple_get(list, "addresses"); count = ns_config_listcount(addrlist); portobj = cfg_tuple_get(list, "port"); if (cfg_obj_isuint32(portobj)) { isc_uint32_t val = cfg_obj_asuint32(portobj); if (val > ISC_UINT16_MAX) { cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, "port '%u' out of range", val); return (ISC_R_RANGE); } port = (in_port_t) val; } else if (defport != 0) port = defport; else { result = ns_config_getport(config, &port); if (result != ISC_R_SUCCESS) return (result); } if (dscpsp != NULL) { dscpobj = cfg_tuple_get(list, "dscp"); if (dscpobj != NULL && cfg_obj_isuint32(dscpobj)) { if (cfg_obj_asuint32(dscpobj) > 63) { cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR, "dscp value '%u' is out of range", cfg_obj_asuint32(dscpobj)); return (ISC_R_RANGE); } dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj); } dscps = isc_mem_get(mctx, count * sizeof(isc_dscp_t)); if (dscps == NULL) return (ISC_R_NOMEMORY); } addrs = isc_mem_get(mctx, count * sizeof(isc_sockaddr_t)); if (addrs == NULL) { if (dscps != NULL) isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t)); return (ISC_R_NOMEMORY); } for (element = cfg_list_first(addrlist); element != NULL; element = cfg_list_next(element), i++) { const cfg_obj_t *addr; INSIST(i < count); addr = cfg_listelt_value(element); addrs[i] = *cfg_obj_assockaddr(addr); if (dscpsp != NULL) { isc_dscp_t innerdscp; innerdscp = cfg_obj_getdscp(addr); if (innerdscp == -1) innerdscp = dscp; dscps[i] = innerdscp; } if (isc_sockaddr_getport(&addrs[i]) == 0) isc_sockaddr_setport(&addrs[i], port); } INSIST(i == count); *addrsp = addrs; *countp = count; if (dscpsp != NULL) *dscpsp = dscps; return (ISC_R_SUCCESS); }