isc_result_t dns_peerlist_peerbyaddr(dns_peerlist_t *servers, isc_netaddr_t *addr, dns_peer_t **retval) { dns_peer_t *server; isc_result_t res; REQUIRE(retval != NULL); REQUIRE(DNS_PEERLIST_VALID(servers)); server = ISC_LIST_HEAD(servers->elements); while (server != NULL) { if (isc_netaddr_eqprefix(addr, &server->address, server->prefixlen)) break; server = ISC_LIST_NEXT(server, next); } if (server != NULL) { *retval = server; res = ISC_R_SUCCESS; } else { res = ISC_R_NOTFOUND; } return (res); }
isc_boolean_t dns_aclelement_equal(dns_aclelement_t *ea, dns_aclelement_t *eb) { if (ea->type != eb->type) return (ISC_FALSE); switch (ea->type) { case dns_aclelementtype_ipprefix: if (ea->u.ip_prefix.prefixlen != eb->u.ip_prefix.prefixlen) return (ISC_FALSE); return (isc_netaddr_eqprefix(&ea->u.ip_prefix.address, &eb->u.ip_prefix.address, ea->u.ip_prefix.prefixlen)); case dns_aclelementtype_keyname: return (dns_name_equal(&ea->u.keyname, &eb->u.keyname)); case dns_aclelementtype_nestedacl: return (dns_acl_equal(ea->u.nestedacl, eb->u.nestedacl)); case dns_aclelementtype_localhost: case dns_aclelementtype_localnets: case dns_aclelementtype_any: return (ISC_TRUE); default: INSIST(0); return (ISC_FALSE); } }
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 dns_aclelement_match(isc_netaddr_t *reqaddr, dns_name_t *reqsigner, dns_aclelement_t *e, dns_aclenv_t *env, dns_aclelement_t **matchelt) { dns_acl_t *inner = NULL; isc_netaddr_t *addr; isc_netaddr_t v4addr; int indirectmatch; isc_result_t result; switch (e->type) { case dns_aclelementtype_ipprefix: if (env == NULL || env->match_mapped == ISC_FALSE || reqaddr->family != AF_INET6 || !IN6_IS_ADDR_V4MAPPED(&reqaddr->type.in6)) addr = reqaddr; else { isc_netaddr_fromv4mapped(&v4addr, reqaddr); addr = &v4addr; } if (isc_netaddr_eqprefix(addr, &e->u.ip_prefix.address, e->u.ip_prefix.prefixlen)) goto matched; break; case dns_aclelementtype_keyname: if (reqsigner != NULL && dns_name_equal(reqsigner, &e->u.keyname)) goto matched; break; case dns_aclelementtype_nestedacl: inner = e->u.nestedacl; nested: result = dns_acl_match(reqaddr, reqsigner, inner, env, &indirectmatch, matchelt); INSIST(result == ISC_R_SUCCESS); /* * Treat negative matches in indirect ACLs as * "no match". * That way, a negated indirect ACL will never become * a surprise positive match through double negation. * XXXDCL this should be documented. */ if (indirectmatch > 0) goto matchelt_set; /* * A negative indirect match may have set *matchelt, * but we don't want it set when we return. */ if (matchelt != NULL) *matchelt = NULL; break; case dns_aclelementtype_any: matched: if (matchelt != NULL) *matchelt = e; matchelt_set: return (ISC_TRUE); case dns_aclelementtype_localhost: if (env != NULL && env->localhost != NULL) { inner = env->localhost; goto nested; } else { break; } case dns_aclelementtype_localnets: if (env != NULL && env->localnets != NULL) { inner = env->localnets; goto nested; } else { break; } default: INSIST(0); break; } return (ISC_FALSE); }