00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <config.h>
00020
00021 #include <isc/list.h>
00022 #include <isc/mem.h>
00023 #include <isc/netaddr.h>
00024 #include <isc/string.h>
00025 #include <isc/util.h>
00026
00027 #include <dns/acl.h>
00028 #include <dns/dns64.h>
00029 #include <dns/rdata.h>
00030 #include <dns/rdataset.h>
00031 #include <dns/result.h>
00032
00033 struct dns_dns64 {
00034 unsigned char bits[16];
00035
00036
00037 dns_acl_t * clients;
00038
00039
00040
00041 dns_acl_t * mapped;
00042
00043
00044 dns_acl_t * excluded;
00045
00046
00047
00048 unsigned int prefixlen;
00049
00050
00051 unsigned int flags;
00052 isc_mem_t * mctx;
00053 ISC_LINK(dns_dns64_t) link;
00054 };
00055
00056 isc_result_t
00057 dns_dns64_create(isc_mem_t *mctx, isc_netaddr_t *prefix,
00058 unsigned int prefixlen, isc_netaddr_t *suffix,
00059 dns_acl_t *clients, dns_acl_t *mapped, dns_acl_t *excluded,
00060 unsigned int flags, dns_dns64_t **dns64)
00061 {
00062 dns_dns64_t *new;
00063 unsigned int nbytes = 16;
00064
00065 REQUIRE(prefix != NULL && prefix->family == AF_INET6);
00066
00067 REQUIRE(prefixlen == 32 || prefixlen == 40 || prefixlen == 48 ||
00068 prefixlen == 56 || prefixlen == 64 || prefixlen == 96);
00069 REQUIRE(isc_netaddr_prefixok(prefix, prefixlen) == ISC_R_SUCCESS);
00070 REQUIRE(dns64 != NULL && *dns64 == NULL);
00071
00072 if (suffix != NULL) {
00073 static const unsigned char zeros[16];
00074 REQUIRE(prefix->family == AF_INET6);
00075 nbytes = prefixlen / 8 + 4;
00076
00077 if (prefixlen >= 32 && prefixlen <= 64)
00078 nbytes++;
00079 REQUIRE(memcmp(suffix->type.in6.s6_addr, zeros, nbytes) == 0);
00080 }
00081
00082 new = isc_mem_get(mctx, sizeof(dns_dns64_t));
00083 if (new == NULL)
00084 return (ISC_R_NOMEMORY);
00085 memset(new->bits, 0, sizeof(new->bits));
00086 memmove(new->bits, prefix->type.in6.s6_addr, prefixlen / 8);
00087 if (suffix != NULL)
00088 memmove(new->bits + nbytes, suffix->type.in6.s6_addr + nbytes,
00089 16 - nbytes);
00090 new->clients = NULL;
00091 if (clients != NULL)
00092 dns_acl_attach(clients, &new->clients);
00093 new->mapped = NULL;
00094 if (mapped != NULL)
00095 dns_acl_attach(mapped, &new->mapped);
00096 new->excluded = NULL;
00097 if (excluded != NULL)
00098 dns_acl_attach(excluded, &new->excluded);
00099 new->prefixlen = prefixlen;
00100 new->flags = flags;
00101 ISC_LINK_INIT(new, link);
00102 new->mctx = NULL;
00103 isc_mem_attach(mctx, &new->mctx);
00104 *dns64 = new;
00105 return (ISC_R_SUCCESS);
00106 }
00107
00108 void
00109 dns_dns64_destroy(dns_dns64_t **dns64p) {
00110 dns_dns64_t *dns64;
00111
00112 REQUIRE(dns64p != NULL && *dns64p != NULL);
00113
00114 dns64 = *dns64p;
00115 *dns64p = NULL;
00116
00117 REQUIRE(!ISC_LINK_LINKED(dns64, link));
00118
00119 if (dns64->clients != NULL)
00120 dns_acl_detach(&dns64->clients);
00121 if (dns64->mapped != NULL)
00122 dns_acl_detach(&dns64->mapped);
00123 if (dns64->excluded != NULL)
00124 dns_acl_detach(&dns64->excluded);
00125 isc_mem_putanddetach(&dns64->mctx, dns64, sizeof(*dns64));
00126 }
00127
00128 isc_result_t
00129 dns_dns64_aaaafroma(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
00130 const dns_name_t *reqsigner, const dns_aclenv_t *env,
00131 unsigned int flags, unsigned char *a, unsigned char *aaaa)
00132 {
00133 unsigned int nbytes, i;
00134 isc_result_t result;
00135 int match;
00136
00137 if ((dns64->flags & DNS_DNS64_RECURSIVE_ONLY) != 0 &&
00138 (flags & DNS_DNS64_RECURSIVE) == 0)
00139 return (DNS_R_DISALLOWED);
00140
00141 if ((dns64->flags & DNS_DNS64_BREAK_DNSSEC) == 0 &&
00142 (flags & DNS_DNS64_DNSSEC) != 0)
00143 return (DNS_R_DISALLOWED);
00144
00145 if (dns64->clients != NULL) {
00146 result = dns_acl_match(reqaddr, reqsigner, dns64->clients, env,
00147 &match, NULL);
00148 if (result != ISC_R_SUCCESS)
00149 return (result);
00150 if (match <= 0)
00151 return (DNS_R_DISALLOWED);
00152 }
00153
00154 if (dns64->mapped != NULL) {
00155 struct in_addr ina;
00156 isc_netaddr_t netaddr;
00157
00158 memmove(&ina.s_addr, a, 4);
00159 isc_netaddr_fromin(&netaddr, &ina);
00160 result = dns_acl_match(&netaddr, NULL, dns64->mapped, env,
00161 &match, NULL);
00162 if (result != ISC_R_SUCCESS)
00163 return (result);
00164 if (match <= 0)
00165 return (DNS_R_DISALLOWED);
00166 }
00167
00168 nbytes = dns64->prefixlen / 8;
00169 INSIST(nbytes <= 12);
00170
00171 memmove(aaaa, dns64->bits, nbytes);
00172
00173 if (nbytes == 8)
00174 aaaa[nbytes++] = 0;
00175
00176 for (i = 0; i < 4U; i++) {
00177 aaaa[nbytes++] = a[i];
00178
00179 if (nbytes == 8)
00180 aaaa[nbytes++] = 0;
00181 }
00182
00183 memmove(aaaa + nbytes, dns64->bits + nbytes, 16 - nbytes);
00184 return (ISC_R_SUCCESS);
00185 }
00186
00187 dns_dns64_t *
00188 dns_dns64_next(dns_dns64_t *dns64) {
00189 dns64 = ISC_LIST_NEXT(dns64, link);
00190 return (dns64);
00191 }
00192
00193 void
00194 dns_dns64_append(dns_dns64list_t *list, dns_dns64_t *dns64) {
00195 ISC_LIST_APPEND(*list, dns64, link);
00196 }
00197
00198 void
00199 dns_dns64_unlink(dns_dns64list_t *list, dns_dns64_t *dns64) {
00200 ISC_LIST_UNLINK(*list, dns64, link);
00201 }
00202
00203 isc_boolean_t
00204 dns_dns64_aaaaok(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
00205 const dns_name_t *reqsigner, const dns_aclenv_t *env,
00206 unsigned int flags, dns_rdataset_t *rdataset,
00207 isc_boolean_t *aaaaok, size_t aaaaoklen)
00208 {
00209 struct in6_addr in6;
00210 isc_netaddr_t netaddr;
00211 isc_result_t result;
00212 int match;
00213 isc_boolean_t answer = ISC_FALSE;
00214 isc_boolean_t found = ISC_FALSE;
00215 unsigned int i, ok;
00216
00217 REQUIRE(rdataset != NULL);
00218 REQUIRE(rdataset->type == dns_rdatatype_aaaa);
00219 REQUIRE(rdataset->rdclass == dns_rdataclass_in);
00220 if (aaaaok != NULL)
00221 REQUIRE(aaaaoklen == dns_rdataset_count(rdataset));
00222
00223 for (;dns64 != NULL; dns64 = ISC_LIST_NEXT(dns64, link)) {
00224 if ((dns64->flags & DNS_DNS64_RECURSIVE_ONLY) != 0 &&
00225 (flags & DNS_DNS64_RECURSIVE) == 0)
00226 continue;
00227
00228 if ((dns64->flags & DNS_DNS64_BREAK_DNSSEC) == 0 &&
00229 (flags & DNS_DNS64_DNSSEC) != 0)
00230 continue;
00231
00232
00233
00234 if (dns64->clients != NULL) {
00235 result = dns_acl_match(reqaddr, reqsigner,
00236 dns64->clients, env,
00237 &match, NULL);
00238 if (result != ISC_R_SUCCESS)
00239 continue;
00240 if (match <= 0)
00241 continue;
00242 }
00243
00244 if (!found && aaaaok != NULL) {
00245 for (i = 0; i < aaaaoklen; i++)
00246 aaaaok[i] = ISC_FALSE;
00247 }
00248 found = ISC_TRUE;
00249
00250
00251
00252
00253
00254 if (dns64->excluded == NULL) {
00255 answer = ISC_TRUE;
00256 if (aaaaok == NULL)
00257 goto done;
00258 for (i = 0; i < aaaaoklen; i++)
00259 aaaaok[i] = ISC_TRUE;
00260 goto done;
00261 }
00262
00263 i = 0; ok = 0;
00264 for (result = dns_rdataset_first(rdataset);
00265 result == ISC_R_SUCCESS;
00266 result = dns_rdataset_next(rdataset)) {
00267 dns_rdata_t rdata = DNS_RDATA_INIT;
00268 if (aaaaok == NULL || !aaaaok[i]) {
00269
00270 dns_rdataset_current(rdataset, &rdata);
00271 memmove(&in6.s6_addr, rdata.data, 16);
00272 isc_netaddr_fromin6(&netaddr, &in6);
00273
00274 result = dns_acl_match(&netaddr, NULL,
00275 dns64->excluded,
00276 env, &match, NULL);
00277 if (result == ISC_R_SUCCESS && match <= 0) {
00278 answer = ISC_TRUE;
00279 if (aaaaok == NULL)
00280 goto done;
00281 aaaaok[i] = ISC_TRUE;
00282 ok++;
00283 }
00284 } else
00285 ok++;
00286 i++;
00287 }
00288
00289
00290
00291 if (aaaaok != NULL && ok == aaaaoklen)
00292 goto done;
00293 }
00294
00295 done:
00296 if (!found && aaaaok != NULL) {
00297 for (i = 0; i < aaaaoklen; i++)
00298 aaaaok[i] = ISC_TRUE;
00299 }
00300 return (found ? answer : ISC_TRUE);
00301 }