isc_boolean_t isc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b, unsigned int prefixlen) { isc_netaddr_t na, nb; isc_netaddr_fromsockaddr(&na, a); isc_netaddr_fromsockaddr(&nb, b); return (isc_netaddr_eqprefix(&na, &nb, prefixlen)); }
static unsigned char GAA_find_prefix(isc_interfaceiter_t *iter) { IP_ADAPTER_PREFIX * ipap; IP_ADAPTER_PREFIX * ipap_match; int match_len; int max_len; isc_netaddr_t target; u_short af; isc_netaddr_t pfx; int pfx_len; size_t nbytes; unsigned char nbits; unsigned char * pbits; unsigned int octets; match_len = 0; ipap_match = NULL; isc_netaddr_fromsockaddr(&target, (isc_sockaddr_t *)iter->ipuaCur->Address.lpSockaddr); af = (u_short)target.family; INSIST(AF_INET == af || AF_INET6 == af); max_len = (AF_INET6 == af) ? 128 : 32; iter->current.netmask.family = af; for (ipap = iter->ipaaCur->FirstPrefix; ipap != NULL; ipap = ipap->Next) { if (ipap->Address.lpSockaddr->sa_family != af) continue; isc_netaddr_fromsockaddr(&pfx, (isc_sockaddr_t *)ipap->Address.lpSockaddr); pfx_len = ipap->PrefixLength; INSIST(0 <= pfx_len && pfx_len <= max_len); if (pfx_len > match_len && pfx_len < max_len && isc_netaddr_eqprefix(&target, &pfx, pfx_len)) { ipap_match = ipap; match_len = pfx_len; } } if (NULL == ipap_match) { /* presume all-ones mask */ if (AF_INET6 == af) octets = sizeof(iter->current.netmask.type.in6); else octets = sizeof(iter->current.netmask.type.in); memset(&iter->current.netmask.type, 0xFF, octets); return (8 * (unsigned char)octets); } nbytes = match_len / 8; nbits = match_len % 8; memset(&iter->current.netmask.type.in6, 0xFF, nbytes); pbits = (void *)&iter->current.netmask.type.in6; pbits += nbytes; *pbits |= 0xFF << (8 - nbits); return ((unsigned char)match_len); }
isc_boolean_t isc_sockaddr_ismulticast(isc_sockaddr_t *sockaddr) { isc_netaddr_t netaddr; isc_netaddr_fromsockaddr(&netaddr, sockaddr); return (isc_netaddr_ismulticast(&netaddr)); }
static isc_boolean_t client_ok(const isc_sockaddr_t *fromaddr, void *arg) { ns_statschannel_t *listener = arg; isc_netaddr_t netaddr; char socktext[ISC_SOCKADDR_FORMATSIZE]; int match; REQUIRE(listener != NULL); isc_netaddr_fromsockaddr(&netaddr, fromaddr); LOCK(&listener->lock); if (dns_acl_match(&netaddr, NULL, listener->acl, &ns_g_server->aclenv, &match, NULL) == ISC_R_SUCCESS && match > 0) { UNLOCK(&listener->lock); return (ISC_TRUE); } UNLOCK(&listener->lock); isc_sockaddr_format(fromaddr, socktext, sizeof(socktext)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "rejected statistics connection from %s", socktext); return (ISC_FALSE); }
isc_boolean_t isc_sockaddr_islinklocal(const isc_sockaddr_t *sockaddr) { isc_netaddr_t netaddr; if (sockaddr->type.sa.sa_family == AF_INET6) { isc_netaddr_fromsockaddr(&netaddr, sockaddr); return (isc_netaddr_islinklocal(&netaddr)); } return (ISC_FALSE); }
isc_boolean_t isc_sockaddr_isexperimental(isc_sockaddr_t *sockaddr) { isc_netaddr_t netaddr; if (sockaddr->type.sa.sa_family == AF_INET) { isc_netaddr_fromsockaddr(&netaddr, sockaddr); return (isc_netaddr_isexperimental(&netaddr)); } return (ISC_FALSE); }
void dns_dampening_score_qtype(dns_dampening_t * damp, const isc_sockaddr_t * addr, isc_stdtime_t now, dns_messageid_t message_id, int qtype) { isc_netaddr_t netaddr, prefix; dns_dampening_entry_t * entry; uint16_t points; dns_dampening_implementation_t *impl; RUNTIME_CHECK( damp != NULL ); RUNTIME_CHECK( addr != NULL ); isc_netaddr_fromsockaddr(&netaddr, addr); extract_prefix(&prefix, &netaddr, &(damp->prefixlen)); for(impl = damp->workers; impl - damp->workers < damp->workers_count; impl++) { if(damp->exempt != NULL) { int match; if (ISC_R_SUCCESS == dns_acl_match(&netaddr, NULL, damp->exempt, NULL, &match, NULL) && match > 0) { DAMPENING_STATISTICS_INC(impl,skipped); continue; } } DAMPENING_STATISTICS_DO(impl, lock, LOCK(&impl->lock)); DAMPENING_STATISTICS_DO(impl, search, entry = impl->search(impl->data, &prefix)); if(entry != NULL) { switch(qtype) { case dns_rdatatype_any: points = damp->score.qtype_any; break; default : points = 0; break; } if(entry->last_id == message_id) { points += (entry->last_id_count++)*damp->score.duplicates; } else { entry->last_id = message_id; entry->last_id_count = 1; } DAMPENING_STATISTICS_DO(impl, update, impl->update(impl->data, &entry, points, now)); } UNLOCK(&impl->lock); } }
static isc_result_t internal_current_GAA(isc_interfaceiter_t *iter) { IP_ADAPTER_ADDRESSES *adap; IP_ADAPTER_UNICAST_ADDRESS *addr; unsigned char prefix_len; REQUIRE(iter->ipaaCur != NULL); REQUIRE(iter->ipuaCur != NULL); adap = iter->ipaaCur; addr = iter->ipuaCur; if (IpDadStatePreferred != addr->DadState) return (ISC_R_IGNORE); memset(&iter->current, 0, sizeof(iter->current)); iter->current.af = addr->Address.lpSockaddr->sa_family; isc_netaddr_fromsockaddr(&iter->current.address, (isc_sockaddr_t *)addr->Address.lpSockaddr); if (AF_INET6 == iter->current.af) iter->current.ifindex = adap->Ipv6IfIndex; iter->current.name[0] = '\0'; WideCharToMultiByte( CP_ACP, 0, adap->FriendlyName, -1, iter->current.name, sizeof(iter->current.name), NULL, NULL); iter->current.name[sizeof(iter->current.name) - 1] = '\0'; if (IfOperStatusUp == adap->OperStatus) iter->current.flags |= INTERFACE_F_UP; if (IF_TYPE_PPP == adap->IfType) iter->current.flags |= INTERFACE_F_POINTTOPOINT; else if (IF_TYPE_SOFTWARE_LOOPBACK == adap->IfType) iter->current.flags |= INTERFACE_F_LOOPBACK; if ((IP_ADAPTER_NO_MULTICAST & adap->Flags) == 0) iter->current.flags |= INTERFACE_F_MULTICAST; if (IpSuffixOriginRandom == addr->SuffixOrigin) iter->current.flags |= INTERFACE_F_PRIVACY; prefix_len = GAA_find_prefix(iter); /* I'm failing to see a broadcast flag via GAA */ if (AF_INET == iter->current.af && prefix_len < 32 && (INTERFACE_F_LOOPBACK & iter->current.flags) == 0) { iter->current.flags |= INTERFACE_F_BROADCAST; get_broadcastaddr(&iter->current.broadcast, &iter->current.address, &iter->current.netmask); } return (ISC_R_SUCCESS); }
static void print_addresses(dns_adbfind_t *adbfind) { dns_adbaddrinfo_t *address; for (address = ISC_LIST_HEAD(adbfind->list); address != NULL; address = ISC_LIST_NEXT(address, publink)) { isc_netaddr_t netaddr; char text[ISC_NETADDR_FORMATSIZE]; isc_netaddr_fromsockaddr(&netaddr, &address->sockaddr); isc_netaddr_format(&netaddr, text, sizeof(text)); printf("%s\n", text); } }
isc_result_t isc_sockaddr_totext(const isc_sockaddr_t *sockaddr, isc_buffer_t *target) { isc_result_t result; isc_netaddr_t netaddr; char pbuf[sizeof("65000")]; unsigned int plen; isc_region_t avail; REQUIRE(sockaddr != NULL); /* * Do the port first, giving us the opportunity to check for * unsupported address families before calling * isc_netaddr_fromsockaddr(). */ switch (sockaddr->type.sa.sa_family) { case AF_INET: snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin.sin_port)); break; case AF_INET6: snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin6.sin6_port)); break; default: return (ISC_R_FAILURE); } plen = strlen(pbuf); INSIST(plen < sizeof(pbuf)); isc_netaddr_fromsockaddr(&netaddr, sockaddr); result = isc_netaddr_totext(&netaddr, target); if (result != ISC_R_SUCCESS) return (result); if (1 + plen + 1 > isc_buffer_availablelength(target)) return (ISC_R_NOSPACE); isc_buffer_putmem(target, (const unsigned char *)"#", 1); isc_buffer_putmem(target, (const unsigned char *)pbuf, plen); /* * Null terminate after used region. */ isc_buffer_availableregion(target, &avail); INSIST(avail.length >= 1); avail.base[0] = '\0'; return (ISC_R_SUCCESS); }
static isc_boolean_t address_ok(isc_sockaddr_t *sockaddr, dns_acl_t *acl) { isc_netaddr_t netaddr; isc_result_t result; int match; isc_netaddr_fromsockaddr(&netaddr, sockaddr); result = dns_acl_match(&netaddr, NULL, acl, &ns_g_server->aclenv, &match, NULL); if (result != ISC_R_SUCCESS || match <= 0) return (ISC_FALSE); else return (ISC_TRUE); }
static void sort_addresses(ns_lwdclient_t *client) { unsigned int naddrs; rankedaddress *addrs; isc_netaddr_t remote; dns_addressorderfunc_t order; const void *arg; ns_lwresd_t *lwresd = client->clientmgr->listener->manager; unsigned int i; isc_result_t result; naddrs = client->gabn.naddrs; if (naddrs <= 1 || lwresd->view->sortlist == NULL) return; addrs = isc_mem_get(lwresd->mctx, sizeof(rankedaddress) * naddrs); if (addrs == NULL) return; isc_netaddr_fromsockaddr(&remote, &client->address); ns_sortlist_byaddrsetup(lwresd->view->sortlist, &remote, &order, &arg); if (order == NULL) { isc_mem_put(lwresd->mctx, addrs, sizeof(rankedaddress) * naddrs); return; } for (i = 0; i < naddrs; i++) { result = lwaddr_netaddr_fromlwresaddr(&addrs[i].address, &client->addrs[i]); INSIST(result == ISC_R_SUCCESS); addrs[i].rank = (*order)(&addrs[i].address, arg); } qsort(addrs, naddrs, sizeof(rankedaddress), addr_compare); for (i = 0; i < naddrs; i++) { result = lwaddr_lwresaddr_fromnetaddr(&client->addrs[i], &addrs[i].address); INSIST(result == ISC_R_SUCCESS); } isc_mem_put(lwresd->mctx, addrs, sizeof(rankedaddress) * naddrs); }
void dns_dampening_score_size(dns_dampening_t * damp, const isc_sockaddr_t * addr, isc_stdtime_t now, int length) { isc_netaddr_t netaddr, prefix; dns_dampening_entry_t * entry; uint16_t points; dns_dampening_implementation_t *impl; RUNTIME_CHECK( damp != NULL ); RUNTIME_CHECK( addr != NULL ); isc_netaddr_fromsockaddr(&netaddr, addr); extract_prefix(&prefix, &netaddr, &(damp->prefixlen)); for(impl = damp->workers; impl - damp->workers < damp->workers_count; impl++) { if(damp->exempt != NULL) { int match; if (ISC_R_SUCCESS == dns_acl_match(&netaddr, NULL, damp->exempt, NULL, &match, NULL) && match > 0) { DAMPENING_STATISTICS_INC(impl,skipped); continue; } } DAMPENING_STATISTICS_DO(impl, lock, LOCK(&impl->lock)); DAMPENING_STATISTICS_DO(impl, search, entry = impl->search(impl->data, &prefix)); if(entry != NULL) { length = ISC_MAX(length, damp->score.minimum_size); length = ISC_MIN(length, damp->score.maximum_size); points = damp->score.size_penalty * (length - damp->score.minimum_size) / (damp->score.maximum_size - damp->score.minimum_size); DAMPENING_STATISTICS_DO(impl, update, impl->update(impl->data, &entry, points, now)); } UNLOCK(&impl->lock); } }
int sockaddr_masktoprefixlen( const sockaddr_u * psa ) { isc_netaddr_t isc_na; isc_sockaddr_t isc_sa; u_int pfxlen; bool result; int rc; ZERO(isc_sa); memcpy(&isc_sa.type, psa, min(sizeof(isc_sa.type), sizeof(*psa))); isc_netaddr_fromsockaddr(&isc_na, &isc_sa); result = isc_netaddr_masktoprefixlen_bool(&isc_na, &pfxlen); rc = (result) ? (int)pfxlen : -1; return rc; }
static void getaddresses(dig_lookup_t *lookup, const char *host) { isc_result_t result; isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES]; isc_netaddr_t netaddr; int count, i; dig_server_t *srv; char tmp[ISC_NETADDR_FORMATSIZE]; result = bind9_getaddresses(host, 0, sockaddrs, DIG_MAX_ADDRESSES, &count); if (result != ISC_R_SUCCESS) fatal("couldn't get address for '%s': %s", host, isc_result_totext(result)); for (i = 0; i < count; i++) { isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]); isc_netaddr_format(&netaddr, tmp, sizeof(tmp)); srv = make_server(tmp, host); ISC_LIST_APPEND(lookup->my_server_list, srv, link); } addresscount = count; }
isc_result_t lwaddr_lwresaddr_fromsockaddr(lwres_addr_t *la, isc_sockaddr_t *sa) { isc_netaddr_t na; isc_netaddr_fromsockaddr(&na, sa); return (lwaddr_lwresaddr_fromnetaddr(la, &na)); }
static isc_result_t internal_current(isc_interfaceiter_t *iter) { BOOL ifNamed = FALSE; unsigned long flags; REQUIRE(VALID_IFITER(iter)); REQUIRE(iter->numIF >= 0); memset(&iter->current, 0, sizeof(iter->current)); iter->current.af = AF_INET; isc_netaddr_fromsockaddr(&iter->current.address, (isc_sockaddr_t *)&(iter->IFData.iiAddress)); /* * Get interface flags. */ iter->current.flags = 0; flags = iter->IFData.iiFlags; if ((flags & IFF_UP) != 0) iter->current.flags |= INTERFACE_F_UP; if ((flags & IFF_BROADCAST) != 0) iter->current.flags |= INTERFACE_F_BROADCAST; if ((flags & IFF_MULTICAST) != 0) iter->current.flags |= INTERFACE_F_MULTICAST; if ((flags & IFF_POINTTOPOINT) != 0) { iter->current.flags |= INTERFACE_F_POINTTOPOINT; snprintf(iter->current.name, sizeof(iter->current.name), "PPP %d", iter->numIF); ifNamed = TRUE; } if ((flags & IFF_LOOPBACK) != 0) { iter->current.flags |= INTERFACE_F_LOOPBACK; snprintf(iter->current.name, sizeof(iter->current.name), "v4loop %d", iter->numIF); ifNamed = TRUE; } /* * If the interface is point-to-point, get the destination address. */ if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) isc_netaddr_fromsockaddr(&iter->current.dstaddress, (isc_sockaddr_t *)&(iter->IFData.iiBroadcastAddress)); /* * Get the network mask. */ isc_netaddr_fromsockaddr(&iter->current.netmask, (isc_sockaddr_t *)&(iter->IFData.iiNetmask)); /* * If the interface is broadcast, get the broadcast address, * based on the unicast address and network mask. */ if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0) get_broadcastaddr(&iter->current.broadcast, &iter->current.address, &iter->current.netmask); if (ifNamed == FALSE) snprintf(iter->current.name, sizeof(iter->current.name), "IPv4 %d", iter->numIF); return (ISC_R_SUCCESS); }
/*% * Configure an apex NS with glues for a static-stub zone. * For example, for the zone named "example.com", the following RRs will be * added to the zone DB: * example.com. NS example.com. * example.com. A 192.0.2.1 * example.com. AAAA 2001:db8::1 */ static isc_result_t configure_staticstub_serveraddrs(const cfg_obj_t *zconfig, dns_zone_t *zone, dns_rdatalist_t *rdatalist_ns, dns_rdatalist_t *rdatalist_a, dns_rdatalist_t *rdatalist_aaaa) { const cfg_listelt_t *element; isc_mem_t *mctx = dns_zone_getmctx(zone); isc_region_t region, sregion; dns_rdata_t *rdata; isc_result_t result = ISC_R_SUCCESS; for (element = cfg_list_first(zconfig); element != NULL; element = cfg_list_next(element)) { const isc_sockaddr_t* sa; isc_netaddr_t na; const cfg_obj_t *address = cfg_listelt_value(element); dns_rdatalist_t *rdatalist; sa = cfg_obj_assockaddr(address); if (isc_sockaddr_getport(sa) != 0) { cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, "port is not configurable for " "static stub server-addresses"); return (ISC_R_FAILURE); } isc_netaddr_fromsockaddr(&na, sa); if (isc_netaddr_getzone(&na) != 0) { cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, "scoped address is not allowed " "for static stub " "server-addresses"); return (ISC_R_FAILURE); } switch (na.family) { case AF_INET: region.length = sizeof(na.type.in); rdatalist = rdatalist_a; break; default: INSIST(na.family == AF_INET6); region.length = sizeof(na.type.in6); rdatalist = rdatalist_aaaa; break; } rdata = isc_mem_get(mctx, sizeof(*rdata) + region.length); if (rdata == NULL) return (ISC_R_NOMEMORY); region.base = (unsigned char *)(rdata + 1); memcpy(region.base, &na.type, region.length); dns_rdata_init(rdata); dns_rdata_fromregion(rdata, dns_zone_getclass(zone), rdatalist->type, ®ion); ISC_LIST_APPEND(rdatalist->rdata, rdata, link); } /* * If no address is specified (unlikely in this context, but possible), * there's nothing to do anymore. */ if (ISC_LIST_EMPTY(rdatalist_a->rdata) && ISC_LIST_EMPTY(rdatalist_aaaa->rdata)) { return (ISC_R_SUCCESS); } /* Add to the list an apex NS with the ns name being the origin name */ dns_name_toregion(dns_zone_getorigin(zone), &sregion); rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length); if (rdata == NULL) { /* * Already allocated data will be freed in the caller, so * we can simply return here. */ return (ISC_R_NOMEMORY); } region.length = sregion.length; region.base = (unsigned char *)(rdata + 1); memcpy(region.base, sregion.base, region.length); dns_rdata_init(rdata); dns_rdata_fromregion(rdata, dns_zone_getclass(zone), dns_rdatatype_ns, ®ion); ISC_LIST_APPEND(rdatalist_ns->rdata, rdata, link); return (result); }
static isc_result_t internal_current6(isc_interfaceiter_t *iter) { BOOL ifNamed = FALSE; struct sockaddr_in6 *psa6; BOOL localhostSeen; int i; REQUIRE(VALID_IFITER(iter)); REQUIRE(iter->pos6 >= 0); REQUIRE(iter->buf6 != 0); memset(&iter->current, 0, sizeof(iter->current)); iter->current.af = AF_INET6; /* * synthesize localhost ::1 before returning the rest, if ::1 * is not on the list. */ if (iter->pos6 >= (unsigned)iter->buf6->iAddressCount) { localhostSeen = FALSE; for (i = 0; i < iter->buf6->iAddressCount; i++) { psa6 = (struct sockaddr_in6 *) iter->buf6->Address[i].lpSockaddr; if (!memcmp(&iter->loop__1, &psa6->sin6_addr, sizeof(iter->loop__1))) { localhostSeen = TRUE; break; } } if (localhostSeen) iter->pos6 = iter->buf6->iAddressCount - 1; } if (iter->pos6 < (unsigned)iter->buf6->iAddressCount) { isc_netaddr_fromsockaddr(&iter->current.address, (isc_sockaddr_t *)iter->buf6->Address[iter->pos6].lpSockaddr); } else { iter->current.address.family = AF_INET6; memcpy(&iter->current.address.type.in6, &iter->loop__1, sizeof(iter->current.address.type.in6)); } /* * Get interface flags. */ iter->current.flags = INTERFACE_F_UP | INTERFACE_F_MULTICAST; if (!memcmp(&iter->current.address.type.in6, &iter->loop__1, sizeof(iter->current.address.type.in6)) || !memcmp(&iter->current.address.type.in6, &iter->loopfe80__1, sizeof(iter->current.address.type.in6))) { iter->current.flags |= INTERFACE_F_LOOPBACK; snprintf(iter->current.name, sizeof(iter->current.name), "v6loop %d", iter->buf6->iAddressCount - iter->pos6); ifNamed = TRUE; } if (ifNamed == FALSE) snprintf(iter->current.name, sizeof(iter->current.name), "IPv6 %d", iter->buf6->iAddressCount - iter->pos6); memset(iter->current.netmask.type.in6.s6_addr, 0xff, sizeof(iter->current.netmask.type.in6.s6_addr)); iter->current.netmask.family = AF_INET6; return (ISC_R_SUCCESS); }
void ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { isc_result_t result; dns_name_t *question_name; dns_rdataset_t *question_rdataset; dns_zone_t *zone = NULL, *raw = NULL, *mayberaw; dns_db_t *db = NULL; dns_dbversion_t *ver = NULL; dns_rdataclass_t question_class; rrstream_t *soa_stream = NULL; rrstream_t *data_stream = NULL; rrstream_t *stream = NULL; dns_difftuple_t *current_soa_tuple = NULL; dns_name_t *soa_name; dns_rdataset_t *soa_rdataset; dns_rdata_t soa_rdata = DNS_RDATA_INIT; isc_boolean_t have_soa = ISC_FALSE; const char *mnemonic = NULL; isc_mem_t *mctx = client->mctx; dns_message_t *request = client->message; xfrout_ctx_t *xfr = NULL; isc_quota_t *quota = NULL; dns_transfer_format_t format = client->view->transfer_format; isc_netaddr_t na; dns_peer_t *peer = NULL; isc_buffer_t *tsigbuf = NULL; char *journalfile; char msg[NS_CLIENT_ACLMSGSIZE("zone transfer")]; char keyname[DNS_NAME_FORMATSIZE]; isc_boolean_t is_poll = ISC_FALSE; isc_boolean_t is_dlz = ISC_FALSE; isc_boolean_t is_ixfr = ISC_FALSE; isc_uint32_t begin_serial = 0, current_serial; switch (reqtype) { case dns_rdatatype_axfr: mnemonic = "AXFR"; break; case dns_rdatatype_ixfr: mnemonic = "IXFR"; break; default: INSIST(0); break; } ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT, ISC_LOG_DEBUG(6), "%s request", mnemonic); /* * Apply quota. */ result = isc_quota_attach(&ns_g_server->xfroutquota, "a); if (result != ISC_R_SUCCESS) { isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING, "%s request denied: %s", mnemonic, isc_result_totext(result)); goto failure; } /* * Interpret the question section. */ result = dns_message_firstname(request, DNS_SECTION_QUESTION); INSIST(result == ISC_R_SUCCESS); /* * The question section must contain exactly one question, and * it must be for AXFR/IXFR as appropriate. */ question_name = NULL; dns_message_currentname(request, DNS_SECTION_QUESTION, &question_name); question_rdataset = ISC_LIST_HEAD(question_name->list); question_class = question_rdataset->rdclass; INSIST(question_rdataset->type == reqtype); if (ISC_LIST_NEXT(question_rdataset, link) != NULL) FAILC(DNS_R_FORMERR, "multiple questions"); result = dns_message_nextname(request, DNS_SECTION_QUESTION); if (result != ISC_R_NOMORE) FAILC(DNS_R_FORMERR, "multiple questions"); result = dns_zt_find(client->view->zonetable, question_name, 0, NULL, &zone); if (result != ISC_R_SUCCESS) { /* * Normal zone table does not have a match. * Try the DLZ database */ // Temporary: only searching the first DLZ database if (! ISC_LIST_EMPTY(client->view->dlz_searched)) { result = dns_dlzallowzonexfr(client->view, question_name, &client->peeraddr, &db); pfilter_notify(result, client, "zonexfr"); if (result == ISC_R_NOPERM) { char _buf1[DNS_NAME_FORMATSIZE]; char _buf2[DNS_RDATACLASS_FORMATSIZE]; result = DNS_R_REFUSED; dns_name_format(question_name, _buf1, sizeof(_buf1)); dns_rdataclass_format(question_class, _buf2, sizeof(_buf2)); ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_XFER_OUT, ISC_LOG_ERROR, "zone transfer '%s/%s' denied", _buf1, _buf2); goto failure; } if (result != ISC_R_SUCCESS) FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class); is_dlz = ISC_TRUE; } else { /* * not DLZ and not in normal zone table, we are * not authoritative */ FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class); } } else { /* zone table has a match */ switch(dns_zone_gettype(zone)) { /* Master and slave zones are OK for transfer. */ case dns_zone_master: case dns_zone_slave: case dns_zone_dlz: break; default: FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class); } CHECK(dns_zone_getdb(zone, &db)); dns_db_currentversion(db, &ver); } xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6), "%s question section OK", mnemonic); /* * Check the authority section. Look for a SOA record with * the same name and class as the question. */ for (result = dns_message_firstname(request, DNS_SECTION_AUTHORITY); result == ISC_R_SUCCESS; result = dns_message_nextname(request, DNS_SECTION_AUTHORITY)) { soa_name = NULL; dns_message_currentname(request, DNS_SECTION_AUTHORITY, &soa_name); /* * Ignore data whose owner name is not the zone apex. */ if (! dns_name_equal(soa_name, question_name)) continue; for (soa_rdataset = ISC_LIST_HEAD(soa_name->list); soa_rdataset != NULL; soa_rdataset = ISC_LIST_NEXT(soa_rdataset, link)) { /* * Ignore non-SOA data. */ if (soa_rdataset->type != dns_rdatatype_soa) continue; if (soa_rdataset->rdclass != question_class) continue; CHECK(dns_rdataset_first(soa_rdataset)); dns_rdataset_current(soa_rdataset, &soa_rdata); result = dns_rdataset_next(soa_rdataset); if (result == ISC_R_SUCCESS) FAILC(DNS_R_FORMERR, "IXFR authority section " "has multiple SOAs"); have_soa = ISC_TRUE; goto got_soa; } } got_soa: if (result != ISC_R_NOMORE) CHECK(result); xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6), "%s authority section OK", mnemonic); /* * If not a DLZ zone, decide whether to allow this transfer. */ if (!is_dlz) { ns_client_aclmsg("zone transfer", question_name, reqtype, client->view->rdclass, msg, sizeof(msg)); CHECK(ns_client_checkacl(client, NULL, msg, dns_zone_getxfracl(zone), ISC_TRUE, ISC_LOG_ERROR)); } /* * AXFR over UDP is not possible. */ if (reqtype == dns_rdatatype_axfr && (client->attributes & NS_CLIENTATTR_TCP) == 0) FAILC(DNS_R_FORMERR, "attempted AXFR over UDP"); /* * Look up the requesting server in the peer table. */ isc_netaddr_fromsockaddr(&na, &client->peeraddr); (void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer); /* * Decide on the transfer format (one-answer or many-answers). */ if (peer != NULL) (void)dns_peer_gettransferformat(peer, &format); /* * Get a dynamically allocated copy of the current SOA. */ if (is_dlz) dns_db_currentversion(db, &ver); CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS, ¤t_soa_tuple)); current_serial = dns_soa_getserial(¤t_soa_tuple->rdata); if (reqtype == dns_rdatatype_ixfr) { isc_boolean_t provide_ixfr; /* * Outgoing IXFR may have been disabled for this peer * or globally. */ provide_ixfr = client->view->provideixfr; if (peer != NULL) (void) dns_peer_getprovideixfr(peer, &provide_ixfr); if (provide_ixfr == ISC_FALSE) goto axfr_fallback; if (! have_soa) FAILC(DNS_R_FORMERR, "IXFR request missing SOA"); begin_serial = dns_soa_getserial(&soa_rdata); /* * RFC1995 says "If an IXFR query with the same or * newer version number than that of the server * is received, it is replied to with a single SOA * record of the server's current version, just as * in AXFR". The claim about AXFR is incorrect, * but other than that, we do as the RFC says. * * Sending a single SOA record is also how we refuse * IXFR over UDP (currently, we always do). */ if (DNS_SERIAL_GE(begin_serial, current_serial) || (client->attributes & NS_CLIENTATTR_TCP) == 0) { CHECK(soa_rrstream_create(mctx, db, ver, &stream)); is_poll = ISC_TRUE; goto have_stream; } journalfile = is_dlz ? NULL : dns_zone_getjournal(zone); if (journalfile != NULL) result = ixfr_rrstream_create(mctx, journalfile, begin_serial, current_serial, &data_stream); else result = ISC_R_NOTFOUND; if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) { xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(4), "IXFR version not in journal, " "falling back to AXFR"); mnemonic = "AXFR-style IXFR"; goto axfr_fallback; } CHECK(result); is_ixfr = ISC_TRUE; } else { axfr_fallback: CHECK(axfr_rrstream_create(mctx, db, ver, &data_stream)); } /* * Bracket the data stream with SOAs. */ CHECK(soa_rrstream_create(mctx, db, ver, &soa_stream)); CHECK(compound_rrstream_create(mctx, &soa_stream, &data_stream, &stream)); soa_stream = NULL; data_stream = NULL; have_stream: CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf)); /* * Create the xfrout context object. This transfers the ownership * of "stream", "db", "ver", and "quota" to the xfrout context object. */ if (is_dlz) CHECK(xfrout_ctx_create(mctx, client, request->id, question_name, reqtype, question_class, zone, db, ver, quota, stream, dns_message_gettsigkey(request), tsigbuf, 3600, 3600, (format == dns_many_answers) ? ISC_TRUE : ISC_FALSE, &xfr)); else CHECK(xfrout_ctx_create(mctx, client, request->id, question_name, reqtype, question_class, zone, db, ver, quota, stream, dns_message_gettsigkey(request), tsigbuf, dns_zone_getmaxxfrout(zone), dns_zone_getidleout(zone), (format == dns_many_answers) ? ISC_TRUE : ISC_FALSE, &xfr)); xfr->mnemonic = mnemonic; stream = NULL; quota = NULL; CHECK(xfr->stream->methods->first(xfr->stream)); if (xfr->tsigkey != NULL) dns_name_format(&xfr->tsigkey->name, keyname, sizeof(keyname)); else keyname[0] = '\0'; if (is_poll) xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(1), "IXFR poll up to date%s%s", (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname); else if (is_ixfr) xfrout_log1(client, question_name, question_class, ISC_LOG_INFO, "%s started%s%s (serial %u -> %u)", mnemonic, (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname, begin_serial, current_serial); else xfrout_log1(client, question_name, question_class, ISC_LOG_INFO, "%s started%s%s (serial %u)", mnemonic, (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname, current_serial); if (zone != NULL) { dns_zone_getraw(zone, &raw); mayberaw = (raw != NULL) ? raw : zone; if ((client->attributes & NS_CLIENTATTR_WANTEXPIRE) != 0 && dns_zone_gettype(mayberaw) == dns_zone_slave) { isc_time_t expiretime; isc_uint32_t secs; dns_zone_getexpiretime(zone, &expiretime); secs = isc_time_seconds(&expiretime); if (secs >= client->now && result == ISC_R_SUCCESS) { client->attributes |= NS_CLIENTATTR_HAVEEXPIRE; client->expire = secs - client->now; } } if (raw != NULL) dns_zone_detach(&raw); } /* * Hand the context over to sendstream(). Set xfr to NULL; * sendstream() is responsible for either passing the * context on to a later event handler or destroying it. */ sendstream(xfr); xfr = NULL; result = ISC_R_SUCCESS; failure: if (result == DNS_R_REFUSED) inc_stats(zone, dns_nsstatscounter_xfrrej); if (quota != NULL) isc_quota_detach("a); if (current_soa_tuple != NULL) dns_difftuple_free(¤t_soa_tuple); if (stream != NULL) stream->methods->destroy(&stream); if (soa_stream != NULL) soa_stream->methods->destroy(&soa_stream); if (data_stream != NULL) data_stream->methods->destroy(&data_stream); if (ver != NULL) dns_db_closeversion(db, &ver, ISC_FALSE); if (db != NULL) dns_db_detach(&db); if (zone != NULL) dns_zone_detach(&zone); /* XXX kludge */ if (xfr != NULL) { xfrout_fail(xfr, result, "setting up zone transfer"); } else if (result != ISC_R_SUCCESS) { ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT, ISC_LOG_DEBUG(3), "zone transfer setup failed"); ns_client_error(client, result); } }
/* * Convert a resolv.conf file into a config structure. */ isc_result_t ns_lwresd_parseeresolvconf(isc_mem_t *mctx, cfg_parser_t *pctx, cfg_obj_t **configp) { char text[4096]; char str[16]; isc_buffer_t b; lwres_context_t *lwctx = NULL; lwres_conf_t *lwc = NULL; isc_sockaddr_t sa; isc_netaddr_t na; int i; isc_result_t result; lwres_result_t lwresult; lwctx = NULL; lwresult = lwres_context_create(&lwctx, mctx, ns__lwresd_memalloc, ns__lwresd_memfree, LWRES_CONTEXT_SERVERMODE); if (lwresult != LWRES_R_SUCCESS) { result = ISC_R_NOMEMORY; goto cleanup; } lwresult = lwres_conf_parse(lwctx, lwresd_g_resolvconffile); if (lwresult != LWRES_R_SUCCESS) { result = DNS_R_SYNTAX; goto cleanup; } lwc = lwres_conf_get(lwctx); INSIST(lwc != NULL); isc_buffer_init(&b, text, sizeof(text)); CHECK(buffer_putstr(&b, "options {\n")); /* * Build the list of forwarders. */ if (lwc->nsnext > 0) { CHECK(buffer_putstr(&b, "\tforwarders {\n")); for (i = 0; i < lwc->nsnext; i++) { CHECK(lwaddr_sockaddr_fromlwresaddr( &sa, &lwc->nameservers[i], ns_g_port)); isc_netaddr_fromsockaddr(&na, &sa); CHECK(buffer_putstr(&b, "\t\t")); CHECK(isc_netaddr_totext(&na, &b)); CHECK(buffer_putstr(&b, ";\n")); } CHECK(buffer_putstr(&b, "\t};\n")); } /* * Build the sortlist */ if (lwc->sortlistnxt > 0) { CHECK(buffer_putstr(&b, "\tsortlist {\n")); CHECK(buffer_putstr(&b, "\t\t{\n")); CHECK(buffer_putstr(&b, "\t\t\tany;\n")); CHECK(buffer_putstr(&b, "\t\t\t{\n")); for (i = 0; i < lwc->sortlistnxt; i++) { lwres_addr_t *lwaddr = &lwc->sortlist[i].addr; lwres_addr_t *lwmask = &lwc->sortlist[i].mask; unsigned int mask; CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, lwmask, 0)); isc_netaddr_fromsockaddr(&na, &sa); result = isc_netaddr_masktoprefixlen(&na, &mask); if (result != ISC_R_SUCCESS) { char addrtext[ISC_NETADDR_FORMATSIZE]; isc_netaddr_format(&na, addrtext, sizeof(addrtext)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_ERROR, "processing sortlist: '%s' is " "not a valid netmask", addrtext); goto cleanup; } CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, lwaddr, 0)); isc_netaddr_fromsockaddr(&na, &sa); CHECK(buffer_putstr(&b, "\t\t\t\t")); CHECK(isc_netaddr_totext(&na, &b)); snprintf(str, sizeof(str), "%u", mask); CHECK(buffer_putstr(&b, "/")); CHECK(buffer_putstr(&b, str)); CHECK(buffer_putstr(&b, ";\n")); } CHECK(buffer_putstr(&b, "\t\t\t};\n")); CHECK(buffer_putstr(&b, "\t\t};\n")); CHECK(buffer_putstr(&b, "\t};\n")); } CHECK(buffer_putstr(&b, "};\n\n")); CHECK(buffer_putstr(&b, "lwres {\n")); /* * Build the search path */ if (lwc->searchnxt > 0) { if (lwc->searchnxt > 0) { CHECK(buffer_putstr(&b, "\tsearch {\n")); for (i = 0; i < lwc->searchnxt; i++) { CHECK(buffer_putstr(&b, "\t\t\"")); CHECK(buffer_putstr(&b, lwc->search[i])); CHECK(buffer_putstr(&b, "\";\n")); } CHECK(buffer_putstr(&b, "\t};\n")); } } /* * Build the ndots line */ if (lwc->ndots != 1) { CHECK(buffer_putstr(&b, "\tndots ")); snprintf(str, sizeof(str), "%u", lwc->ndots); CHECK(buffer_putstr(&b, str)); CHECK(buffer_putstr(&b, ";\n")); } /* * Build the listen-on line */ if (lwc->lwnext > 0) { CHECK(buffer_putstr(&b, "\tlisten-on {\n")); for (i = 0; i < lwc->lwnext; i++) { CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, &lwc->lwservers[i], 0)); isc_netaddr_fromsockaddr(&na, &sa); CHECK(buffer_putstr(&b, "\t\t")); CHECK(isc_netaddr_totext(&na, &b)); CHECK(buffer_putstr(&b, ";\n")); } CHECK(buffer_putstr(&b, "\t};\n")); } CHECK(buffer_putstr(&b, "};\n")); #if 0 printf("%.*s\n", (int)isc_buffer_usedlength(&b), (char *)isc_buffer_base(&b)); #endif lwres_conf_clear(lwctx); lwres_context_destroy(&lwctx); return (cfg_parse_buffer(pctx, &b, &cfg_type_namedconf, configp)); cleanup: if (lwctx != NULL) { lwres_conf_clear(lwctx); lwres_context_destroy(&lwctx); } return (result); }
dns_dampening_state_t dns_dampening_query(dns_dampening_t * damp, const isc_sockaddr_t * addr, isc_stdtime_t now, int * penalty) { isc_netaddr_t netaddr, prefix; dns_dampening_state_t final_state = DNS_DAMPENING_STATE_NORMAL, state = DNS_DAMPENING_STATE_NORMAL; dns_dampening_entry_t * entry; dns_dampening_implementation_t *impl; int max_penalty = -2; RUNTIME_CHECK( damp != NULL ); RUNTIME_CHECK( addr != NULL ); isc_netaddr_fromsockaddr(&netaddr, addr); extract_prefix(&prefix, &netaddr, &(damp->prefixlen)); for(impl = damp->workers; impl - damp->workers < damp->workers_count; impl++) { if(damp->exempt != NULL) { int match; if (ISC_R_SUCCESS == dns_acl_match(&netaddr, NULL, damp->exempt, NULL, &match, NULL) && match > 0) { max_penalty = ISC_MAX(max_penalty, -1); DAMPENING_STATISTICS_INC(impl,skipped); continue; } } DAMPENING_STATISTICS_DO(impl, lock, LOCK(&impl->lock)); if(damp->statistics.report_interval > 0 && damp->statistics.report_interval + impl->statistics.last_report <= now) { if(isc_log_wouldlog(dns_lctx, ISC_LOG_INFO)) isc_log_write(dns_lctx, DNS_LOGCATEGORY_DAMPENING, DNS_LOGMODULE_REQUEST, ISC_LOG_INFO, "Stats for #%d: queries %u/%u/%u: lock=%ld.%06ld, search=%ld.%06ld, update=%ld.%06ld, add=%ld.%06ld", impl - damp->workers, impl->statistics.allowed, impl->statistics.denied, impl->statistics.skipped, impl->statistics.lock.tv_sec, impl->statistics.lock.tv_usec, impl->statistics.search.tv_sec, impl->statistics.search.tv_usec, impl->statistics.update.tv_sec, impl->statistics.update.tv_usec, impl->statistics.add.tv_sec, impl->statistics.add.tv_usec); memset(&impl->statistics, 0, sizeof(impl->statistics)); impl->statistics.last_report = now; } DAMPENING_STATISTICS_DO(impl, search, entry = impl->search(impl->data, &prefix)); if(entry == NULL) { state = DNS_DAMPENING_STATE_NORMAL; DAMPENING_STATISTICS_DO(impl, add, impl->add(impl->data, &prefix, damp->score.first_query, now)); max_penalty = ISC_MAX(max_penalty, 0); } else { state = entry->dampening == 1 ? DNS_DAMPENING_STATE_SUPPRESS : DNS_DAMPENING_STATE_NORMAL; max_penalty = ISC_MAX(max_penalty, entry->penalty); DAMPENING_STATISTICS_DO(impl, update, impl->update(impl->data, &entry, damp->score.per_query, now)); } if(state == DNS_DAMPENING_STATE_NORMAL) { DAMPENING_STATISTICS_INC(impl, allowed); } else { DAMPENING_STATISTICS_INC(impl, denied); final_state = state; /* any dampening suffice */ } UNLOCK(&impl->lock); } if(penalty != NULL) *penalty = max_penalty; return final_state; }