diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in index 761ba12b1b..9099800f8f 100644 --- a/lib/dns/Makefile.in +++ b/lib/dns/Makefile.in @@ -115,7 +115,7 @@ DNSSAFEOBJS = sec/dnssafe/ahchdig.@O@ sec/dnssafe/ahchencr.@O@ \ sec/dnssafe/rsakeygn.@O@ sec/dnssafe/seccbcd.@O@ \ sec/dnssafe/seccbce.@O@ sec/dnssafe/surrendr.@O@ -OBJS = callbacks.@O@ compress.@O@ db.@O@ dbiterator.@O@ \ +OBJS = a6.@O@ callbacks.@O@ compress.@O@ db.@O@ dbiterator.@O@ \ dbtable.@O@ dispatch.@O@ dnssec.@O@ lib.@O@ master.@O@ \ message.@O@ name.@O@ rbt.@O@ rbtdb.@O@ rbtdb64.@O@ rdata.@O@ \ rdatalist.@O@ rdataset.@O@ rdatasetiter.@O@ rdataslab.@O@ \ @@ -123,9 +123,9 @@ OBJS = callbacks.@O@ compress.@O@ db.@O@ dbiterator.@O@ \ ttl.@O@ tcpmsg.@O@ tsig.@O@ view.@O@ journal.@O@ zone.@O@ \ ${DSTOBJS} ${OPENSSLOBJS} ${DNSSAFEOBJS} ${CONFOBJS} -SRCS = callbacks.c compress.c db.c dbiterator.c \ - dbtable.c dispatch.c dnssec.c lib.c master.c message.c \ - name.c rbt.c rbtdb.c rbtdb64.c rdata.c \ +SRCS = a6.c callbacks.c compress.c db.c dbiterator.c \ + dbtable.c dispatch.c dnssec.c lib.c master.c \ + message.c name.c rbt.c rbtdb.c rbtdb64.c rdata.c \ rdatalist.c rdataset.c rdatasetiter.c rdataslab.c \ resolver.c result.c version.c masterdump.c time.c \ ttl.c tcpmsg.c tsig.c view.c journal.c zone.c diff --git a/lib/dns/a6.c b/lib/dns/a6.c new file mode 100644 index 0000000000..b1916dfbe5 --- /dev/null +++ b/lib/dns/a6.c @@ -0,0 +1,207 @@ +/* + * Copyright (C) 1999 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define A6CONTEXT_MAGIC 0x41365858U /* A6XX. */ +#define VALID_A6CONTEXT(ac) ((ac) != NULL && \ + (ac)->magic == A6CONTEXT_MAGIC) + + +#define MAX_CHAINS 8 +#define MAX_DEPTH 16 + +/* XXXRTH BEGIN XXX */ + +#include + +static void +printname(dns_name_t *name) { + unsigned char data[256]; + isc_buffer_t buffer; + isc_region_t r; + + isc_buffer_init(&buffer, data, sizeof data, ISC_BUFFERTYPE_TEXT); + if (dns_name_totext(name, ISC_FALSE, &buffer) == ISC_R_SUCCESS) { + isc_buffer_used(&buffer, &r); + printf("A6: %.*s\n", (int)r.length, r.base); + } +} + +static void +printaddr(dns_a6context_t *a6ctx) { + int i; + unsigned char *cp; + + cp = (unsigned char *)&a6ctx->in6addr.s6_addr; + for (i = 0; i < 16; i++, cp++) { + if (i > 0 && i % 2 == 0) + printf(":"); + printf("%02x", *cp); + } + printf("\n"); +} + +/* XXXRTH END XXX */ + +static isc_result_t +foreach(dns_a6context_t *a6ctx, dns_rdataset_t *parent, unsigned int depth, + unsigned int oprefixlen) +{ + dns_rdata_t rdata; + isc_region_t r; + dns_name_t name; + dns_rdataset_t child; + dns_rdataset_t childsig; + isc_result_t result; + isc_uint8_t prefixlen, octets; + isc_bitstring_t bitstring; + + depth++; + result = dns_rdataset_first(parent); + while (result == ISC_R_SUCCESS) { + dns_rdataset_current(parent, &rdata); + dns_rdata_toregion(&rdata, &r); + prefixlen = r.base[0]; + if (prefixlen > oprefixlen) { + /* + * Trying to go to a longer prefix is illegal. + */ + goto next_a6; + } + if (prefixlen < 128) { + isc_bitstring_init(&bitstring, &r.base[1], + 128 - prefixlen, 128 - prefixlen, + ISC_TRUE); + isc_bitstring_copy(&bitstring, 128 - oprefixlen, + &a6ctx->bitstring, 128 - oprefixlen, + oprefixlen - prefixlen); + } + octets = 16 - prefixlen / 8; + if (prefixlen != 0) { + if (depth < MAX_DEPTH) { + isc_region_consume(&r, octets + 1); + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &r); + printname(&name); + dns_rdataset_init(&child); + dns_rdataset_init(&childsig); + result = (a6ctx->find)(a6ctx->arg, &name, + dns_rdatatype_a6, + &child, &childsig); + if (result == ISC_R_SUCCESS) { + /* + * We've found a new A6 rrset. + */ + if (a6ctx->rrset != NULL) + (a6ctx->rrset)(a6ctx->arg, + &name, + &child, + &childsig); + /* + * Keep following the chain. + */ + result = foreach(a6ctx, &child, depth, + prefixlen); + dns_rdataset_disassociate(&child); + if (childsig.methods != NULL) + dns_rdataset_disassociate(&childsig); + if (result != ISC_R_SUCCESS) + break; + } else if (result == DNS_R_NOTFOUND && + a6ctx->missing != NULL) { + /* + * We can't follow this chain, because + * we don't know the next link. + */ + (a6ctx->missing)(a6ctx->arg, &name, + dns_rdatatype_a6); + } + } + } else { + /* + * We have a complete chain. + */ + if (a6ctx->address != NULL) + (a6ctx->address)(a6ctx->arg, &a6ctx->in6addr); + printaddr(a6ctx); + } + next_a6: + result = dns_rdataset_next(parent); + if (result == ISC_R_SUCCESS) { + a6ctx->chains++; + if (a6ctx->chains > MAX_CHAINS) + return (ISC_R_QUOTA); + } + } + if (result != DNS_R_NOMORE) + return (result); + return (ISC_R_SUCCESS); +} + +void +dns_a6_init(dns_a6context_t *a6ctx, dns_findfunc_t find, dns_rrsetfunc_t rrset, + dns_in6addrfunc_t address, dns_missingfunc_t missing, void *arg) +{ + REQUIRE(a6ctx != NULL); + REQUIRE(a6ctx->find != NULL); + + a6ctx->magic = A6CONTEXT_MAGIC; + a6ctx->find = find; + a6ctx->rrset = rrset; + a6ctx->missing = missing; + a6ctx->address = address; + a6ctx->arg = arg; + a6ctx->chains = 0; +} + +void +dns_a6_invalidate(dns_a6context_t *a6ctx) { + REQUIRE(VALID_A6CONTEXT(a6ctx)); + + a6ctx->magic = 0; +} + +isc_result_t +dns_a6_foreach(dns_a6context_t *a6ctx, dns_rdataset_t *rdataset) { + isc_result_t result; + + REQUIRE(VALID_A6CONTEXT(a6ctx)); + REQUIRE(rdataset->type == dns_rdatatype_a6); + + a6ctx->chains = 1; + isc_bitstring_init(&a6ctx->bitstring, + (unsigned char *)&a6ctx->in6addr.s6_addr, + 128, 128, ISC_TRUE); + + result = foreach(a6ctx, rdataset, 0, 128); + if (result == ISC_R_QUOTA) + result = ISC_R_SUCCESS; + + return (result); +} diff --git a/lib/dns/include/dns/a6.h b/lib/dns/include/dns/a6.h new file mode 100644 index 0000000000..54c531e53c --- /dev/null +++ b/lib/dns/include/dns/a6.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 1999 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef DNS_A6_H +#define DNS_A6_H 1 + +#include +#include +#include +#include +#include + +#include + +ISC_LANG_BEGINDECLS + +typedef isc_result_t (*dns_findfunc_t)(void *arg, dns_name_t *name, + dns_rdatatype_t type, + dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset); + +typedef void (*dns_rrsetfunc_t)(void *arg, dns_name_t *name, + dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset); + +typedef void (*dns_in6addrfunc_t)(void *arg, struct in6_addr *address); + +typedef void (*dns_missingfunc_t)(void *arg, dns_name_t *name, + dns_rdatatype_t type); + +struct dns_a6context { + unsigned int magic; + /* Public. */ + dns_findfunc_t find; + dns_rrsetfunc_t rrset; + dns_in6addrfunc_t address; + dns_missingfunc_t missing; + void * arg; + /* Private. */ + unsigned int chains; + struct in6_addr in6addr; + isc_bitstring_t bitstring; +}; + +void +dns_a6_init(dns_a6context_t *a6ctx, dns_findfunc_t find, dns_rrsetfunc_t rrset, + dns_in6addrfunc_t address, dns_missingfunc_t missing, void *arg); + +void +dns_a6_invalidate(dns_a6context_t *a6ctx); + +isc_result_t +dns_a6_foreach(dns_a6context_t *a6ctx, dns_rdataset_t *rdataset); + +ISC_LANG_ENDDECLS + +#endif /* DNS_RESULT_H */ diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h index 811d583de0..e820158aea 100644 --- a/lib/dns/include/dns/types.h +++ b/lib/dns/include/dns/types.h @@ -73,6 +73,7 @@ typedef struct dns_dispatchevent dns_dispatchevent_t; typedef struct dns_tsig_key dns_tsig_key_t; typedef struct dns_view dns_view_t; typedef ISC_LIST(dns_view_t) dns_viewlist_t; +typedef struct dns_a6context dns_a6context_t; typedef enum { dns_labeltype_ordinary = 0,