naptr_35.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004, 2005, 2007-2009, 2011-2014  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 /* Reviewed: Thu Mar 16 16:52:50 PST 2000 by bwelling */
00021 
00022 /* RFC2915 */
00023 
00024 #ifndef RDATA_GENERIC_NAPTR_35_C
00025 #define RDATA_GENERIC_NAPTR_35_C
00026 
00027 #define RRTYPE_NAPTR_ATTRIBUTES (0)
00028 
00029 #include <isc/regex.h>
00030 
00031 /*
00032  * Check the wire format of the Regexp field.
00033  * Don't allow embeded NUL's.
00034  */
00035 static inline isc_result_t
00036 txt_valid_regex(const unsigned char *txt) {
00037         unsigned int nsub = 0;
00038         char regex[256];
00039         char *cp;
00040         isc_boolean_t flags = ISC_FALSE;
00041         isc_boolean_t replace = ISC_FALSE;
00042         unsigned char c;
00043         unsigned char delim;
00044         unsigned int len;
00045         int n;
00046 
00047         len = *txt++;
00048         if (len == 0U)
00049                 return (ISC_R_SUCCESS);
00050 
00051         delim = *txt++;
00052         len--;
00053 
00054         /*
00055          * Digits, backslash and flags can't be delimiters.
00056          */
00057         switch (delim) {
00058         case '0': case '1': case '2': case '3': case '4':
00059         case '5': case '6': case '7': case '8': case '9':
00060         case '\\': case 'i': case 0:
00061                 return (DNS_R_SYNTAX);
00062         }
00063 
00064         cp = regex;
00065         while (len-- > 0) {
00066                 c = *txt++;
00067                 if (c == 0)
00068                         return (DNS_R_SYNTAX);
00069                 if (c == delim && !replace) {
00070                         replace = ISC_TRUE;
00071                         continue;
00072                 } else if (c == delim && !flags) {
00073                         flags = ISC_TRUE;
00074                         continue;
00075                 } else if (c == delim)
00076                         return (DNS_R_SYNTAX);
00077                 /*
00078                  * Flags are not escaped.
00079                  */
00080                 if (flags) {
00081                         switch (c) {
00082                         case 'i':
00083                                 continue;
00084                         default:
00085                                 return (DNS_R_SYNTAX);
00086                         }
00087                 }
00088                 if (!replace)
00089                         *cp++ = c;
00090                 if (c == '\\') {
00091                         if (len == 0)
00092                                 return (DNS_R_SYNTAX);
00093                         c = *txt++;
00094                         if (c == 0)
00095                                 return (DNS_R_SYNTAX);
00096                         len--;
00097                         if (replace)
00098                                 switch (c) {
00099                                 case '0': return (DNS_R_SYNTAX);
00100                                 case '1': if (nsub < 1) nsub = 1; break;
00101                                 case '2': if (nsub < 2) nsub = 2; break;
00102                                 case '3': if (nsub < 3) nsub = 3; break;
00103                                 case '4': if (nsub < 4) nsub = 4; break;
00104                                 case '5': if (nsub < 5) nsub = 5; break;
00105                                 case '6': if (nsub < 6) nsub = 6; break;
00106                                 case '7': if (nsub < 7) nsub = 7; break;
00107                                 case '8': if (nsub < 8) nsub = 8; break;
00108                                 case '9': if (nsub < 9) nsub = 9; break;
00109                                 }
00110                         if (!replace)
00111                                 *cp++ = c;
00112                 }
00113         }
00114         if (!flags)
00115                 return (DNS_R_SYNTAX);
00116         *cp = '\0';
00117         n = isc_regex_validate(regex);
00118         if (n < 0 || nsub > (unsigned int)n)
00119                 return (DNS_R_SYNTAX);
00120         return (ISC_R_SUCCESS);
00121 }
00122 
00123 static inline isc_result_t
00124 fromtext_naptr(ARGS_FROMTEXT) {
00125         isc_token_t token;
00126         dns_name_t name;
00127         isc_buffer_t buffer;
00128         unsigned char *regex;
00129 
00130         REQUIRE(type == 35);
00131 
00132         UNUSED(type);
00133         UNUSED(rdclass);
00134         UNUSED(callbacks);
00135 
00136         /*
00137          * Order.
00138          */
00139         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
00140                                       ISC_FALSE));
00141         if (token.value.as_ulong > 0xffffU)
00142                 RETTOK(ISC_R_RANGE);
00143         RETERR(uint16_tobuffer(token.value.as_ulong, target));
00144 
00145         /*
00146          * Preference.
00147          */
00148         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
00149                                       ISC_FALSE));
00150         if (token.value.as_ulong > 0xffffU)
00151                 RETTOK(ISC_R_RANGE);
00152         RETERR(uint16_tobuffer(token.value.as_ulong, target));
00153 
00154         /*
00155          * Flags.
00156          */
00157         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
00158                                       ISC_FALSE));
00159         RETTOK(txt_fromtext(&token.value.as_textregion, target));
00160 
00161         /*
00162          * Service.
00163          */
00164         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
00165                                       ISC_FALSE));
00166         RETTOK(txt_fromtext(&token.value.as_textregion, target));
00167 
00168         /*
00169          * Regexp.
00170          */
00171         regex = isc_buffer_used(target);
00172         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
00173                                       ISC_FALSE));
00174         RETTOK(txt_fromtext(&token.value.as_textregion, target));
00175         RETTOK(txt_valid_regex(regex));
00176 
00177         /*
00178          * Replacement.
00179          */
00180         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
00181                                       ISC_FALSE));
00182         dns_name_init(&name, NULL);
00183         buffer_fromregion(&buffer, &token.value.as_region);
00184         origin = (origin != NULL) ? origin : dns_rootname;
00185         RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
00186         return (ISC_R_SUCCESS);
00187 }
00188 
00189 static inline isc_result_t
00190 totext_naptr(ARGS_TOTEXT) {
00191         isc_region_t region;
00192         dns_name_t name;
00193         dns_name_t prefix;
00194         isc_boolean_t sub;
00195         char buf[sizeof("64000")];
00196         unsigned short num;
00197 
00198         REQUIRE(rdata->type == 35);
00199         REQUIRE(rdata->length != 0);
00200 
00201         dns_name_init(&name, NULL);
00202         dns_name_init(&prefix, NULL);
00203 
00204         dns_rdata_toregion(rdata, &region);
00205 
00206         /*
00207          * Order.
00208          */
00209         num = uint16_fromregion(&region);
00210         isc_region_consume(&region, 2);
00211         sprintf(buf, "%u", num);
00212         RETERR(str_totext(buf, target));
00213         RETERR(str_totext(" ", target));
00214 
00215         /*
00216          * Preference.
00217          */
00218         num = uint16_fromregion(&region);
00219         isc_region_consume(&region, 2);
00220         sprintf(buf, "%u", num);
00221         RETERR(str_totext(buf, target));
00222         RETERR(str_totext(" ", target));
00223 
00224         /*
00225          * Flags.
00226          */
00227         RETERR(txt_totext(&region, ISC_TRUE, target));
00228         RETERR(str_totext(" ", target));
00229 
00230         /*
00231          * Service.
00232          */
00233         RETERR(txt_totext(&region, ISC_TRUE, target));
00234         RETERR(str_totext(" ", target));
00235 
00236         /*
00237          * Regexp.
00238          */
00239         RETERR(txt_totext(&region, ISC_TRUE, target));
00240         RETERR(str_totext(" ", target));
00241 
00242         /*
00243          * Replacement.
00244          */
00245         dns_name_fromregion(&name, &region);
00246         sub = name_prefix(&name, tctx->origin, &prefix);
00247         return (dns_name_totext(&prefix, sub, target));
00248 }
00249 
00250 static inline isc_result_t
00251 fromwire_naptr(ARGS_FROMWIRE) {
00252         dns_name_t name;
00253         isc_region_t sr;
00254         unsigned char *regex;
00255 
00256         REQUIRE(type == 35);
00257 
00258         UNUSED(type);
00259         UNUSED(rdclass);
00260 
00261         dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
00262 
00263         dns_name_init(&name, NULL);
00264 
00265         /*
00266          * Order, preference.
00267          */
00268         isc_buffer_activeregion(source, &sr);
00269         if (sr.length < 4)
00270                 return (ISC_R_UNEXPECTEDEND);
00271         RETERR(mem_tobuffer(target, sr.base, 4));
00272         isc_buffer_forward(source, 4);
00273 
00274         /*
00275          * Flags.
00276          */
00277         RETERR(txt_fromwire(source, target));
00278 
00279         /*
00280          * Service.
00281          */
00282         RETERR(txt_fromwire(source, target));
00283 
00284         /*
00285          * Regexp.
00286          */
00287         regex = isc_buffer_used(target);
00288         RETERR(txt_fromwire(source, target));
00289         RETERR(txt_valid_regex(regex));
00290 
00291         /*
00292          * Replacement.
00293          */
00294         return (dns_name_fromwire(&name, source, dctx, options, target));
00295 }
00296 
00297 static inline isc_result_t
00298 towire_naptr(ARGS_TOWIRE) {
00299         dns_name_t name;
00300         dns_offsets_t offsets;
00301         isc_region_t sr;
00302 
00303         REQUIRE(rdata->type == 35);
00304         REQUIRE(rdata->length != 0);
00305 
00306         dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
00307         /*
00308          * Order, preference.
00309          */
00310         dns_rdata_toregion(rdata, &sr);
00311         RETERR(mem_tobuffer(target, sr.base, 4));
00312         isc_region_consume(&sr, 4);
00313 
00314         /*
00315          * Flags.
00316          */
00317         RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
00318         isc_region_consume(&sr, sr.base[0] + 1);
00319 
00320         /*
00321          * Service.
00322          */
00323         RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
00324         isc_region_consume(&sr, sr.base[0] + 1);
00325 
00326         /*
00327          * Regexp.
00328          */
00329         RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
00330         isc_region_consume(&sr, sr.base[0] + 1);
00331 
00332         /*
00333          * Replacement.
00334          */
00335         dns_name_init(&name, offsets);
00336         dns_name_fromregion(&name, &sr);
00337         return (dns_name_towire(&name, cctx, target));
00338 }
00339 
00340 static inline int
00341 compare_naptr(ARGS_COMPARE) {
00342         dns_name_t name1;
00343         dns_name_t name2;
00344         isc_region_t region1;
00345         isc_region_t region2;
00346         int order, len;
00347 
00348         REQUIRE(rdata1->type == rdata2->type);
00349         REQUIRE(rdata1->rdclass == rdata2->rdclass);
00350         REQUIRE(rdata1->type == 35);
00351         REQUIRE(rdata1->length != 0);
00352         REQUIRE(rdata2->length != 0);
00353 
00354         dns_rdata_toregion(rdata1, &region1);
00355         dns_rdata_toregion(rdata2, &region2);
00356 
00357         /*
00358          * Order, preference.
00359          */
00360         order = memcmp(region1.base, region2.base, 4);
00361         if (order != 0)
00362                 return (order < 0 ? -1 : 1);
00363         isc_region_consume(&region1, 4);
00364         isc_region_consume(&region2, 4);
00365 
00366         /*
00367          * Flags.
00368          */
00369         len = ISC_MIN(region1.base[0], region2.base[0]);
00370         order = memcmp(region1.base, region2.base, len + 1);
00371         if (order != 0)
00372                 return (order < 0 ? -1 : 1);
00373         isc_region_consume(&region1, region1.base[0] + 1);
00374         isc_region_consume(&region2, region2.base[0] + 1);
00375 
00376         /*
00377          * Service.
00378          */
00379         len = ISC_MIN(region1.base[0], region2.base[0]);
00380         order = memcmp(region1.base, region2.base, len + 1);
00381         if (order != 0)
00382                 return (order < 0 ? -1 : 1);
00383         isc_region_consume(&region1, region1.base[0] + 1);
00384         isc_region_consume(&region2, region2.base[0] + 1);
00385 
00386         /*
00387          * Regexp.
00388          */
00389         len = ISC_MIN(region1.base[0], region2.base[0]);
00390         order = memcmp(region1.base, region2.base, len + 1);
00391         if (order != 0)
00392                 return (order < 0 ? -1 : 1);
00393         isc_region_consume(&region1, region1.base[0] + 1);
00394         isc_region_consume(&region2, region2.base[0] + 1);
00395 
00396         /*
00397          * Replacement.
00398          */
00399         dns_name_init(&name1, NULL);
00400         dns_name_init(&name2, NULL);
00401 
00402         dns_name_fromregion(&name1, &region1);
00403         dns_name_fromregion(&name2, &region2);
00404 
00405         return (dns_name_rdatacompare(&name1, &name2));
00406 }
00407 
00408 static inline isc_result_t
00409 fromstruct_naptr(ARGS_FROMSTRUCT) {
00410         dns_rdata_naptr_t *naptr = source;
00411         isc_region_t region;
00412 
00413         REQUIRE(type == 35);
00414         REQUIRE(source != NULL);
00415         REQUIRE(naptr->common.rdtype == type);
00416         REQUIRE(naptr->common.rdclass == rdclass);
00417         REQUIRE(naptr->flags != NULL || naptr->flags_len == 0);
00418         REQUIRE(naptr->service != NULL || naptr->service_len == 0);
00419         REQUIRE(naptr->regexp != NULL || naptr->regexp_len == 0);
00420 
00421         UNUSED(type);
00422         UNUSED(rdclass);
00423 
00424         RETERR(uint16_tobuffer(naptr->order, target));
00425         RETERR(uint16_tobuffer(naptr->preference, target));
00426         RETERR(uint8_tobuffer(naptr->flags_len, target));
00427         RETERR(mem_tobuffer(target, naptr->flags, naptr->flags_len));
00428         RETERR(uint8_tobuffer(naptr->service_len, target));
00429         RETERR(mem_tobuffer(target, naptr->service, naptr->service_len));
00430         RETERR(uint8_tobuffer(naptr->regexp_len, target));
00431         RETERR(mem_tobuffer(target, naptr->regexp, naptr->regexp_len));
00432         dns_name_toregion(&naptr->replacement, &region);
00433         return (isc_buffer_copyregion(target, &region));
00434 }
00435 
00436 static inline isc_result_t
00437 tostruct_naptr(ARGS_TOSTRUCT) {
00438         dns_rdata_naptr_t *naptr = target;
00439         isc_region_t r;
00440         isc_result_t result;
00441         dns_name_t name;
00442 
00443         REQUIRE(rdata->type == 35);
00444         REQUIRE(target != NULL);
00445         REQUIRE(rdata->length != 0);
00446 
00447         naptr->common.rdclass = rdata->rdclass;
00448         naptr->common.rdtype = rdata->type;
00449         ISC_LINK_INIT(&naptr->common, link);
00450 
00451         naptr->flags = NULL;
00452         naptr->service = NULL;
00453         naptr->regexp = NULL;
00454 
00455         dns_rdata_toregion(rdata, &r);
00456 
00457         naptr->order = uint16_fromregion(&r);
00458         isc_region_consume(&r, 2);
00459 
00460         naptr->preference = uint16_fromregion(&r);
00461         isc_region_consume(&r, 2);
00462 
00463         naptr->flags_len = uint8_fromregion(&r);
00464         isc_region_consume(&r, 1);
00465         INSIST(naptr->flags_len <= r.length);
00466         naptr->flags = mem_maybedup(mctx, r.base, naptr->flags_len);
00467         if (naptr->flags == NULL)
00468                 goto cleanup;
00469         isc_region_consume(&r, naptr->flags_len);
00470 
00471         naptr->service_len = uint8_fromregion(&r);
00472         isc_region_consume(&r, 1);
00473         INSIST(naptr->service_len <= r.length);
00474         naptr->service = mem_maybedup(mctx, r.base, naptr->service_len);
00475         if (naptr->service == NULL)
00476                 goto cleanup;
00477         isc_region_consume(&r, naptr->service_len);
00478 
00479         naptr->regexp_len = uint8_fromregion(&r);
00480         isc_region_consume(&r, 1);
00481         INSIST(naptr->regexp_len <= r.length);
00482         naptr->regexp = mem_maybedup(mctx, r.base, naptr->regexp_len);
00483         if (naptr->regexp == NULL)
00484                 goto cleanup;
00485         isc_region_consume(&r, naptr->regexp_len);
00486 
00487         dns_name_init(&name, NULL);
00488         dns_name_fromregion(&name, &r);
00489         dns_name_init(&naptr->replacement, NULL);
00490         result = name_duporclone(&name, mctx, &naptr->replacement);
00491         if (result != ISC_R_SUCCESS)
00492                 goto cleanup;
00493         naptr->mctx = mctx;
00494         return (ISC_R_SUCCESS);
00495 
00496  cleanup:
00497         if (mctx != NULL && naptr->flags != NULL)
00498                 isc_mem_free(mctx, naptr->flags);
00499         if (mctx != NULL && naptr->service != NULL)
00500                 isc_mem_free(mctx, naptr->service);
00501         if (mctx != NULL && naptr->regexp != NULL)
00502                 isc_mem_free(mctx, naptr->regexp);
00503         return (ISC_R_NOMEMORY);
00504 }
00505 
00506 static inline void
00507 freestruct_naptr(ARGS_FREESTRUCT) {
00508         dns_rdata_naptr_t *naptr = source;
00509 
00510         REQUIRE(source != NULL);
00511         REQUIRE(naptr->common.rdtype == 35);
00512 
00513         if (naptr->mctx == NULL)
00514                 return;
00515 
00516         if (naptr->flags != NULL)
00517                 isc_mem_free(naptr->mctx, naptr->flags);
00518         if (naptr->service != NULL)
00519                 isc_mem_free(naptr->mctx, naptr->service);
00520         if (naptr->regexp != NULL)
00521                 isc_mem_free(naptr->mctx, naptr->regexp);
00522         dns_name_free(&naptr->replacement, naptr->mctx);
00523         naptr->mctx = NULL;
00524 }
00525 
00526 static inline isc_result_t
00527 additionaldata_naptr(ARGS_ADDLDATA) {
00528         dns_name_t name;
00529         dns_offsets_t offsets;
00530         isc_region_t sr;
00531         dns_rdatatype_t atype;
00532         unsigned int i, flagslen;
00533         char *cp;
00534 
00535         REQUIRE(rdata->type == 35);
00536 
00537         /*
00538          * Order, preference.
00539          */
00540         dns_rdata_toregion(rdata, &sr);
00541         isc_region_consume(&sr, 4);
00542 
00543         /*
00544          * Flags.
00545          */
00546         atype = 0;
00547         flagslen = sr.base[0];
00548         cp = (char *)&sr.base[1];
00549         for (i = 0; i < flagslen; i++, cp++) {
00550                 if (*cp == 'S' || *cp == 's') {
00551                         atype = dns_rdatatype_srv;
00552                         break;
00553                 }
00554                 if (*cp == 'A' || *cp == 'a') {
00555                         atype = dns_rdatatype_a;
00556                         break;
00557                 }
00558         }
00559         isc_region_consume(&sr, flagslen + 1);
00560 
00561         /*
00562          * Service.
00563          */
00564         isc_region_consume(&sr, sr.base[0] + 1);
00565 
00566         /*
00567          * Regexp.
00568          */
00569         isc_region_consume(&sr, sr.base[0] + 1);
00570 
00571         /*
00572          * Replacement.
00573          */
00574         dns_name_init(&name, offsets);
00575         dns_name_fromregion(&name, &sr);
00576 
00577         if (atype != 0)
00578                 return ((add)(arg, &name, atype));
00579 
00580         return (ISC_R_SUCCESS);
00581 }
00582 
00583 static inline isc_result_t
00584 digest_naptr(ARGS_DIGEST) {
00585         isc_region_t r1, r2;
00586         unsigned int length, n;
00587         isc_result_t result;
00588         dns_name_t name;
00589 
00590         REQUIRE(rdata->type == 35);
00591 
00592         dns_rdata_toregion(rdata, &r1);
00593         r2 = r1;
00594         length = 0;
00595 
00596         /*
00597          * Order, preference.
00598          */
00599         length += 4;
00600         isc_region_consume(&r2, 4);
00601 
00602         /*
00603          * Flags.
00604          */
00605         n = r2.base[0] + 1;
00606         length += n;
00607         isc_region_consume(&r2, n);
00608 
00609         /*
00610          * Service.
00611          */
00612         n = r2.base[0] + 1;
00613         length += n;
00614         isc_region_consume(&r2, n);
00615 
00616         /*
00617          * Regexp.
00618          */
00619         n = r2.base[0] + 1;
00620         length += n;
00621         isc_region_consume(&r2, n);
00622 
00623         /*
00624          * Digest the RR up to the replacement name.
00625          */
00626         r1.length = length;
00627         result = (digest)(arg, &r1);
00628         if (result != ISC_R_SUCCESS)
00629                 return (result);
00630 
00631         /*
00632          * Replacement.
00633          */
00634 
00635         dns_name_init(&name, NULL);
00636         dns_name_fromregion(&name, &r2);
00637 
00638         return (dns_name_digest(&name, digest, arg));
00639 }
00640 
00641 static inline isc_boolean_t
00642 checkowner_naptr(ARGS_CHECKOWNER) {
00643 
00644         REQUIRE(type == 35);
00645 
00646         UNUSED(name);
00647         UNUSED(type);
00648         UNUSED(rdclass);
00649         UNUSED(wildcard);
00650 
00651         return (ISC_TRUE);
00652 }
00653 
00654 static inline isc_boolean_t
00655 checknames_naptr(ARGS_CHECKNAMES) {
00656 
00657         REQUIRE(rdata->type == 35);
00658 
00659         UNUSED(rdata);
00660         UNUSED(owner);
00661         UNUSED(bad);
00662 
00663         return (ISC_TRUE);
00664 }
00665 
00666 static inline int
00667 casecompare_naptr(ARGS_COMPARE) {
00668         return (compare_naptr(rdata1, rdata2));
00669 }
00670 
00671 #endif  /* RDATA_GENERIC_NAPTR_35_C */

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