rdatalist.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004, 2005, 2007, 2008, 2010-2012, 2014, 2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 1999-2001, 2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /* $Id$ */
00019 
00020 /*! \file */
00021 
00022 #include <config.h>
00023 
00024 #include <stddef.h>
00025 #include <string.h>
00026 
00027 #include <isc/util.h>
00028 
00029 #include <dns/name.h>
00030 #include <dns/nsec3.h>
00031 #include <dns/rdata.h>
00032 #include <dns/rdatalist.h>
00033 #include <dns/rdataset.h>
00034 
00035 #include "rdatalist_p.h"
00036 
00037 static dns_rdatasetmethods_t methods = {
00038         isc__rdatalist_disassociate,
00039         isc__rdatalist_first,
00040         isc__rdatalist_next,
00041         isc__rdatalist_current,
00042         isc__rdatalist_clone,
00043         isc__rdatalist_count,
00044         isc__rdatalist_addnoqname,
00045         isc__rdatalist_getnoqname,
00046         isc__rdatalist_addclosest,
00047         isc__rdatalist_getclosest,
00048         NULL,
00049         NULL,
00050         NULL,
00051         NULL,
00052         NULL,
00053         NULL,
00054         isc__rdatalist_setownercase,
00055         isc__rdatalist_getownercase
00056 };
00057 
00058 void
00059 dns_rdatalist_init(dns_rdatalist_t *rdatalist) {
00060 
00061         REQUIRE(rdatalist != NULL);
00062 
00063         /*
00064          * Initialize rdatalist.
00065          */
00066 
00067         rdatalist->rdclass = 0;
00068         rdatalist->type = 0;
00069         rdatalist->covers = 0;
00070         rdatalist->ttl = 0;
00071         ISC_LIST_INIT(rdatalist->rdata);
00072         ISC_LINK_INIT(rdatalist, link);
00073         memset(rdatalist->upper, 0xeb, sizeof(rdatalist->upper));
00074         /*
00075          * Clear upper set bit.
00076          */
00077         rdatalist->upper[0] &= ~0x01;
00078 }
00079 
00080 isc_result_t
00081 dns_rdatalist_tordataset(dns_rdatalist_t *rdatalist,
00082                          dns_rdataset_t *rdataset)
00083 {
00084         /*
00085          * Make 'rdataset' refer to the rdata in 'rdatalist'.
00086          */
00087 
00088         REQUIRE(rdatalist != NULL);
00089         REQUIRE(DNS_RDATASET_VALID(rdataset));
00090         REQUIRE(! dns_rdataset_isassociated(rdataset));
00091 
00092         /* Check if dns_rdatalist_init has was called. */
00093         REQUIRE(rdatalist->upper[0] == 0xea);
00094 
00095         rdataset->methods = &methods;
00096         rdataset->rdclass = rdatalist->rdclass;
00097         rdataset->type = rdatalist->type;
00098         rdataset->covers = rdatalist->covers;
00099         rdataset->ttl = rdatalist->ttl;
00100         rdataset->trust = 0;
00101         rdataset->private1 = rdatalist;
00102         rdataset->private2 = NULL;
00103         rdataset->private3 = NULL;
00104         rdataset->privateuint4 = 0;
00105         rdataset->private5 = NULL;
00106 
00107         return (ISC_R_SUCCESS);
00108 }
00109 
00110 isc_result_t
00111 dns_rdatalist_fromrdataset(dns_rdataset_t *rdataset,
00112                            dns_rdatalist_t **rdatalist)
00113 {
00114         REQUIRE(rdatalist != NULL && rdataset != NULL);
00115         *rdatalist = rdataset->private1;
00116 
00117         return (ISC_R_SUCCESS);
00118 }
00119 
00120 void
00121 isc__rdatalist_disassociate(dns_rdataset_t *rdataset) {
00122         UNUSED(rdataset);
00123 }
00124 
00125 isc_result_t
00126 isc__rdatalist_first(dns_rdataset_t *rdataset) {
00127         dns_rdatalist_t *rdatalist;
00128 
00129         rdatalist = rdataset->private1;
00130         rdataset->private2 = ISC_LIST_HEAD(rdatalist->rdata);
00131 
00132         if (rdataset->private2 == NULL)
00133                 return (ISC_R_NOMORE);
00134 
00135         return (ISC_R_SUCCESS);
00136 }
00137 
00138 isc_result_t
00139 isc__rdatalist_next(dns_rdataset_t *rdataset) {
00140         dns_rdata_t *rdata;
00141 
00142         REQUIRE(rdataset != NULL);
00143 
00144         rdata = rdataset->private2;
00145         if (rdata == NULL)
00146                 return (ISC_R_NOMORE);
00147 
00148         rdataset->private2 = ISC_LIST_NEXT(rdata, link);
00149 
00150         if (rdataset->private2 == NULL)
00151                 return (ISC_R_NOMORE);
00152 
00153         return (ISC_R_SUCCESS);
00154 }
00155 
00156 void
00157 isc__rdatalist_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
00158         dns_rdata_t *list_rdata;
00159 
00160         REQUIRE(rdataset != NULL);
00161 
00162         list_rdata = rdataset->private2;
00163         INSIST(list_rdata != NULL);
00164 
00165         dns_rdata_clone(list_rdata, rdata);
00166 }
00167 
00168 void
00169 isc__rdatalist_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
00170 
00171         REQUIRE(source != NULL);
00172         REQUIRE(target != NULL);
00173 
00174         *target = *source;
00175 
00176         /*
00177          * Reset iterator state.
00178          */
00179         target->private2 = NULL;
00180 }
00181 
00182 unsigned int
00183 isc__rdatalist_count(dns_rdataset_t *rdataset) {
00184         dns_rdatalist_t *rdatalist;
00185         dns_rdata_t *rdata;
00186         unsigned int count;
00187 
00188         REQUIRE(rdataset != NULL);
00189 
00190         rdatalist = rdataset->private1;
00191 
00192         count = 0;
00193         for (rdata = ISC_LIST_HEAD(rdatalist->rdata);
00194              rdata != NULL;
00195              rdata = ISC_LIST_NEXT(rdata, link))
00196                 count++;
00197 
00198         return (count);
00199 }
00200 
00201 isc_result_t
00202 isc__rdatalist_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) {
00203         dns_rdataset_t *neg = NULL;
00204         dns_rdataset_t *negsig = NULL;
00205         dns_rdataset_t *rdset;
00206         dns_ttl_t ttl;
00207 
00208         REQUIRE(rdataset != NULL);
00209 
00210         for (rdset = ISC_LIST_HEAD(name->list);
00211              rdset != NULL;
00212              rdset = ISC_LIST_NEXT(rdset, link))
00213         {
00214                 if (rdset->rdclass != rdataset->rdclass)
00215                         continue;
00216                 if (rdset->type == dns_rdatatype_nsec ||
00217                     rdset->type == dns_rdatatype_nsec3)
00218                         neg = rdset;
00219         }
00220         if (neg == NULL)
00221                 return (ISC_R_NOTFOUND);
00222 
00223         for (rdset = ISC_LIST_HEAD(name->list);
00224              rdset != NULL;
00225              rdset = ISC_LIST_NEXT(rdset, link))
00226         {
00227                 if (rdset->type == dns_rdatatype_rrsig &&
00228                     rdset->covers == neg->type)
00229                         negsig = rdset;
00230         }
00231 
00232         if (negsig == NULL)
00233                 return (ISC_R_NOTFOUND);
00234         /*
00235          * Minimise ttl.
00236          */
00237         ttl = rdataset->ttl;
00238         if (neg->ttl < ttl)
00239                 ttl = neg->ttl;
00240         if (negsig->ttl < ttl)
00241                 ttl = negsig->ttl;
00242         rdataset->ttl = neg->ttl = negsig->ttl = ttl;
00243         rdataset->attributes |= DNS_RDATASETATTR_NOQNAME;
00244         rdataset->private6 = name;
00245         return (ISC_R_SUCCESS);
00246 }
00247 
00248 isc_result_t
00249 isc__rdatalist_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
00250                           dns_rdataset_t *neg, dns_rdataset_t *negsig)
00251 {
00252         dns_rdataclass_t rdclass = rdataset->rdclass;
00253         dns_rdataset_t *tneg = NULL;
00254         dns_rdataset_t *tnegsig = NULL;
00255         dns_name_t *noqname = rdataset->private6;
00256 
00257         REQUIRE(rdataset != NULL);
00258         REQUIRE((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0);
00259 
00260         (void)dns_name_dynamic(noqname);        /* Sanity Check. */
00261 
00262         for (rdataset = ISC_LIST_HEAD(noqname->list);
00263              rdataset != NULL;
00264              rdataset = ISC_LIST_NEXT(rdataset, link))
00265         {
00266                 if (rdataset->rdclass != rdclass)
00267                         continue;
00268                 if (rdataset->type == dns_rdatatype_nsec ||
00269                     rdataset->type == dns_rdatatype_nsec3)
00270                         tneg = rdataset;
00271         }
00272         if (tneg == NULL)
00273                 return (ISC_R_NOTFOUND);
00274 
00275         for (rdataset = ISC_LIST_HEAD(noqname->list);
00276              rdataset != NULL;
00277              rdataset = ISC_LIST_NEXT(rdataset, link))
00278         {
00279                 if (rdataset->type == dns_rdatatype_rrsig &&
00280                     rdataset->covers == tneg->type)
00281                         tnegsig = rdataset;
00282         }
00283         if (tnegsig == NULL)
00284                 return (ISC_R_NOTFOUND);
00285 
00286         dns_name_clone(noqname, name);
00287         dns_rdataset_clone(tneg, neg);
00288         dns_rdataset_clone(tnegsig, negsig);
00289         return (ISC_R_SUCCESS);
00290 }
00291 
00292 isc_result_t
00293 isc__rdatalist_addclosest(dns_rdataset_t *rdataset, dns_name_t *name) {
00294         dns_rdataset_t *neg = NULL;
00295         dns_rdataset_t *negsig = NULL;
00296         dns_rdataset_t *rdset;
00297         dns_ttl_t ttl;
00298 
00299         REQUIRE(rdataset != NULL);
00300 
00301         for (rdset = ISC_LIST_HEAD(name->list);
00302              rdset != NULL;
00303              rdset = ISC_LIST_NEXT(rdset, link))
00304         {
00305                 if (rdset->rdclass != rdataset->rdclass)
00306                         continue;
00307                 if (rdset->type == dns_rdatatype_nsec ||
00308                     rdset->type == dns_rdatatype_nsec3)
00309                         neg = rdset;
00310         }
00311         if (neg == NULL)
00312                 return (ISC_R_NOTFOUND);
00313 
00314         for (rdset = ISC_LIST_HEAD(name->list);
00315              rdset != NULL;
00316              rdset = ISC_LIST_NEXT(rdset, link))
00317         {
00318                 if (rdset->type == dns_rdatatype_rrsig &&
00319                     rdset->covers == neg->type)
00320                         negsig = rdset;
00321         }
00322 
00323         if (negsig == NULL)
00324                 return (ISC_R_NOTFOUND);
00325         /*
00326          * Minimise ttl.
00327          */
00328         ttl = rdataset->ttl;
00329         if (neg->ttl < ttl)
00330                 ttl = neg->ttl;
00331         if (negsig->ttl < ttl)
00332                 ttl = negsig->ttl;
00333         rdataset->ttl = neg->ttl = negsig->ttl = ttl;
00334         rdataset->attributes |= DNS_RDATASETATTR_CLOSEST;
00335         rdataset->private7 = name;
00336         return (ISC_R_SUCCESS);
00337 }
00338 
00339 isc_result_t
00340 isc__rdatalist_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
00341                           dns_rdataset_t *neg, dns_rdataset_t *negsig)
00342 {
00343         dns_rdataclass_t rdclass = rdataset->rdclass;
00344         dns_rdataset_t *tneg = NULL;
00345         dns_rdataset_t *tnegsig = NULL;
00346         dns_name_t *closest = rdataset->private7;
00347 
00348         REQUIRE(rdataset != NULL);
00349         REQUIRE((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) != 0);
00350 
00351         (void)dns_name_dynamic(closest);        /* Sanity Check. */
00352 
00353         for (rdataset = ISC_LIST_HEAD(closest->list);
00354              rdataset != NULL;
00355              rdataset = ISC_LIST_NEXT(rdataset, link))
00356         {
00357                 if (rdataset->rdclass != rdclass)
00358                         continue;
00359                 if (rdataset->type == dns_rdatatype_nsec ||
00360                     rdataset->type == dns_rdatatype_nsec3)
00361                         tneg = rdataset;
00362         }
00363         if (tneg == NULL)
00364                 return (ISC_R_NOTFOUND);
00365 
00366         for (rdataset = ISC_LIST_HEAD(closest->list);
00367              rdataset != NULL;
00368              rdataset = ISC_LIST_NEXT(rdataset, link))
00369         {
00370                 if (rdataset->type == dns_rdatatype_rrsig &&
00371                     rdataset->covers == tneg->type)
00372                         tnegsig = rdataset;
00373         }
00374         if (tnegsig == NULL)
00375                 return (ISC_R_NOTFOUND);
00376 
00377         dns_name_clone(closest, name);
00378         dns_rdataset_clone(tneg, neg);
00379         dns_rdataset_clone(tnegsig, negsig);
00380         return (ISC_R_SUCCESS);
00381 }
00382 
00383 void
00384 isc__rdatalist_setownercase(dns_rdataset_t *rdataset, const dns_name_t *name) {
00385         dns_rdatalist_t *rdatalist;
00386         unsigned int i;
00387 
00388         /*
00389          * We do not need to worry about label lengths as they are all
00390          * less than or equal to 63.
00391          */
00392         rdatalist = rdataset->private1;
00393         memset(rdatalist->upper, 0, sizeof(rdatalist->upper));
00394         for (i = 1; i < name->length; i++)
00395                 if (name->ndata[i] >= 0x41 && name->ndata[i] <= 0x5a)
00396                         rdatalist->upper[i/8] |= 1 << (i%8);
00397         /*
00398          * Record that upper has been set.
00399          */
00400         rdatalist->upper[0] |= 0x01;
00401 }
00402 
00403 void
00404 isc__rdatalist_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name) {
00405         dns_rdatalist_t *rdatalist;
00406         unsigned int i;
00407 
00408         rdatalist = rdataset->private1;
00409         if ((rdatalist->upper[0] & 0x01) == 0)
00410                 return;
00411         for (i = 0; i < name->length; i++) {
00412                 /*
00413                  * Set the case bit if it does not match the recorded bit.
00414                  */
00415                 if (name->ndata[i] >= 0x61 && name->ndata[i] <= 0x7a &&
00416                     (rdatalist->upper[i/8] & (1 << (i%8))) != 0)
00417                         name->ndata[i] &= ~0x20; /* clear the lower case bit */
00418                 else if (name->ndata[i] >= 0x41 && name->ndata[i] <= 0x5a &&
00419                     (rdatalist->upper[i/8] & (1 << (i%8))) == 0)
00420                         name->ndata[i] |= 0x20; /* set the lower case bit */
00421         }
00422 }

Generated on Tue Apr 28 17:41:00 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha