hip_55.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2009, 2011, 2013, 2014  Internet Systems Consortium, Inc. ("ISC")
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00009  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00010  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00011  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00012  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00013  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00014  * PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 /* $Id: hip_55.c,v 1.8 2011/01/13 04:59:26 tbox Exp $ */
00018 
00019 /* reviewed: TBC */
00020 
00021 /* RFC 5205 */
00022 
00023 #ifndef RDATA_GENERIC_HIP_5_C
00024 #define RDATA_GENERIC_HIP_5_C
00025 
00026 #define RRTYPE_HIP_ATTRIBUTES (0)
00027 
00028 static inline isc_result_t
00029 fromtext_hip(ARGS_FROMTEXT) {
00030         isc_token_t token;
00031         dns_name_t name;
00032         isc_buffer_t buffer;
00033         isc_buffer_t hit_len;
00034         isc_buffer_t key_len;
00035         unsigned char *start;
00036         size_t len;
00037 
00038         REQUIRE(type == 55);
00039 
00040         UNUSED(type);
00041         UNUSED(rdclass);
00042         UNUSED(callbacks);
00043 
00044         /*
00045          * Dummy HIT len.
00046          */
00047         hit_len = *target;
00048         RETERR(uint8_tobuffer(0, target));
00049 
00050         /*
00051          * Algorithm.
00052          */
00053         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
00054                                       ISC_FALSE));
00055         if (token.value.as_ulong > 0xffU)
00056                 RETTOK(ISC_R_RANGE);
00057         RETERR(uint8_tobuffer(token.value.as_ulong, target));
00058 
00059         /*
00060          * Dummy KEY len.
00061          */
00062         key_len = *target;
00063         RETERR(uint16_tobuffer(0, target));
00064 
00065         /*
00066          * HIT (base16).
00067          */
00068         start = isc_buffer_used(target);
00069         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
00070                                       ISC_FALSE));
00071         RETTOK(isc_hex_decodestring(DNS_AS_STR(token), target));
00072 
00073         /*
00074          * Fill in HIT len.
00075          */
00076         len = (unsigned char *)isc_buffer_used(target) - start;
00077         if (len > 0xffU)
00078                 RETTOK(ISC_R_RANGE);
00079         RETERR(uint8_tobuffer((isc_uint32_t)len, &hit_len));
00080 
00081         /*
00082          * Public key (base64).
00083          */
00084         start = isc_buffer_used(target);
00085         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
00086                                       ISC_FALSE));
00087         RETTOK(isc_base64_decodestring(DNS_AS_STR(token), target));
00088 
00089         /*
00090          * Fill in KEY len.
00091          */
00092         len = (unsigned char *)isc_buffer_used(target) - start;
00093         if (len > 0xffffU)
00094                 RETTOK(ISC_R_RANGE);
00095         RETERR(uint16_tobuffer((isc_uint32_t)len, &key_len));
00096 
00097         /*
00098          * Rendezvous Servers.
00099          */
00100         dns_name_init(&name, NULL);
00101         do {
00102                 RETERR(isc_lex_getmastertoken(lexer, &token,
00103                                               isc_tokentype_string,
00104                                               ISC_TRUE));
00105                 if (token.type != isc_tokentype_string)
00106                         break;
00107                 buffer_fromregion(&buffer, &token.value.as_region);
00108                 origin = (origin != NULL) ? origin : dns_rootname;
00109                 RETTOK(dns_name_fromtext(&name, &buffer, origin, options,
00110                                          target));
00111         } while (1);
00112 
00113         /*
00114          * Let upper layer handle eol/eof.
00115          */
00116         isc_lex_ungettoken(lexer, &token);
00117 
00118         return (ISC_R_SUCCESS);
00119 }
00120 
00121 static inline isc_result_t
00122 totext_hip(ARGS_TOTEXT) {
00123         isc_region_t region;
00124         dns_name_t name;
00125         unsigned int length, key_len, hit_len;
00126         unsigned char algorithm;
00127         char buf[sizeof("225 ")];
00128 
00129         REQUIRE(rdata->type == 55);
00130         REQUIRE(rdata->length != 0);
00131 
00132         dns_rdata_toregion(rdata, &region);
00133 
00134         hit_len = uint8_fromregion(&region);
00135         isc_region_consume(&region, 1);
00136 
00137         algorithm = uint8_fromregion(&region);
00138         isc_region_consume(&region, 1);
00139 
00140         key_len = uint16_fromregion(&region);
00141         isc_region_consume(&region, 2);
00142 
00143         if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
00144                 RETERR(str_totext("( ", target));
00145 
00146         /*
00147          * Algorithm
00148          */
00149         sprintf(buf, "%u ", algorithm);
00150         RETERR(str_totext(buf, target));
00151 
00152         /*
00153          * HIT.
00154          */
00155         INSIST(hit_len < region.length);
00156         length = region.length;
00157         region.length = hit_len;
00158         RETERR(isc_hex_totext(&region, 1, "", target));
00159         region.length = length - hit_len;
00160         RETERR(str_totext(tctx->linebreak, target));
00161 
00162         /*
00163          * Public KEY.
00164          */
00165         INSIST(key_len <= region.length);
00166         length = region.length;
00167         region.length = key_len;
00168         RETERR(isc_base64_totext(&region, 1, "", target));
00169         region.length = length - key_len;
00170         RETERR(str_totext(tctx->linebreak, target));
00171 
00172         /*
00173          * Rendezvous Servers.
00174          */
00175         dns_name_init(&name, NULL);
00176         while (region.length > 0) {
00177                 dns_name_fromregion(&name, &region);
00178 
00179                 RETERR(dns_name_totext(&name, ISC_FALSE, target));
00180                 isc_region_consume(&region, name.length);
00181                 if (region.length > 0)
00182                         RETERR(str_totext(tctx->linebreak, target));
00183         }
00184         if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
00185                 RETERR(str_totext(" )", target));
00186         return (ISC_R_SUCCESS);
00187 }
00188 
00189 static inline isc_result_t
00190 fromwire_hip(ARGS_FROMWIRE) {
00191         isc_region_t region, rr;
00192         dns_name_t name;
00193         isc_uint8_t hit_len;
00194         isc_uint16_t key_len;
00195 
00196         REQUIRE(type == 55);
00197 
00198         UNUSED(type);
00199         UNUSED(rdclass);
00200 
00201         isc_buffer_activeregion(source, &region);
00202         if (region.length < 4U)
00203                 RETERR(DNS_R_FORMERR);
00204 
00205         rr = region;
00206         hit_len = uint8_fromregion(&region);
00207         if (hit_len == 0)
00208                 RETERR(DNS_R_FORMERR);
00209         isc_region_consume(&region, 2);         /* hit length + algorithm */
00210         key_len = uint16_fromregion(&region);
00211         if (key_len == 0)
00212                 RETERR(DNS_R_FORMERR);
00213         isc_region_consume(&region, 2);
00214         if (region.length < (unsigned) (hit_len + key_len))
00215                 RETERR(DNS_R_FORMERR);
00216 
00217         RETERR(mem_tobuffer(target, rr.base, 4 + hit_len + key_len));
00218         isc_buffer_forward(source, 4 + hit_len + key_len);
00219 
00220         dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
00221         while (isc_buffer_activelength(source) > 0) {
00222                 dns_name_init(&name, NULL);
00223                 RETERR(dns_name_fromwire(&name, source, dctx, options, target));
00224         }
00225         return (ISC_R_SUCCESS);
00226 }
00227 
00228 static inline isc_result_t
00229 towire_hip(ARGS_TOWIRE) {
00230         isc_region_t region;
00231 
00232         REQUIRE(rdata->type == 55);
00233         REQUIRE(rdata->length != 0);
00234 
00235         UNUSED(cctx);
00236 
00237         dns_rdata_toregion(rdata, &region);
00238         return (mem_tobuffer(target, region.base, region.length));
00239 }
00240 
00241 static inline int
00242 compare_hip(ARGS_COMPARE) {
00243         isc_region_t region1;
00244         isc_region_t region2;
00245 
00246         REQUIRE(rdata1->type == rdata2->type);
00247         REQUIRE(rdata1->rdclass == rdata2->rdclass);
00248         REQUIRE(rdata1->type == 55);
00249         REQUIRE(rdata1->length != 0);
00250         REQUIRE(rdata2->length != 0);
00251 
00252         dns_rdata_toregion(rdata1, &region1);
00253         dns_rdata_toregion(rdata2, &region2);
00254         return (isc_region_compare(&region1, &region2));
00255 }
00256 
00257 static inline isc_result_t
00258 fromstruct_hip(ARGS_FROMSTRUCT) {
00259         dns_rdata_hip_t *hip = source;
00260         dns_rdata_hip_t myhip;
00261         isc_result_t result;
00262 
00263         REQUIRE(type == 55);
00264         REQUIRE(source != NULL);
00265         REQUIRE(hip->common.rdtype == type);
00266         REQUIRE(hip->common.rdclass == rdclass);
00267         REQUIRE(hip->hit_len > 0 && hip->hit != NULL);
00268         REQUIRE(hip->key_len > 0 && hip->key != NULL);
00269         REQUIRE((hip->servers == NULL && hip->servers_len == 0) ||
00270                  (hip->servers != NULL && hip->servers_len != 0));
00271 
00272         UNUSED(type);
00273         UNUSED(rdclass);
00274 
00275         RETERR(uint8_tobuffer(hip->hit_len, target));
00276         RETERR(uint8_tobuffer(hip->algorithm, target));
00277         RETERR(uint16_tobuffer(hip->key_len, target));
00278         RETERR(mem_tobuffer(target, hip->hit, hip->hit_len));
00279         RETERR(mem_tobuffer(target, hip->key, hip->key_len));
00280 
00281         myhip = *hip;
00282         for (result = dns_rdata_hip_first(&myhip);
00283              result == ISC_R_SUCCESS;
00284              result = dns_rdata_hip_next(&myhip))
00285                 /* empty */;
00286 
00287         return(mem_tobuffer(target, hip->servers, hip->servers_len));
00288 }
00289 
00290 static inline isc_result_t
00291 tostruct_hip(ARGS_TOSTRUCT) {
00292         isc_region_t region;
00293         dns_rdata_hip_t *hip = target;
00294 
00295         REQUIRE(rdata->type == 55);
00296         REQUIRE(target != NULL);
00297         REQUIRE(rdata->length != 0);
00298 
00299         hip->common.rdclass = rdata->rdclass;
00300         hip->common.rdtype = rdata->type;
00301         ISC_LINK_INIT(&hip->common, link);
00302 
00303         dns_rdata_toregion(rdata, &region);
00304 
00305         hip->hit_len = uint8_fromregion(&region);
00306         isc_region_consume(&region, 1);
00307 
00308         hip->algorithm = uint8_fromregion(&region);
00309         isc_region_consume(&region, 1);
00310 
00311         hip->key_len = uint16_fromregion(&region);
00312         isc_region_consume(&region, 2);
00313 
00314         hip->hit = hip->key = hip->servers = NULL;
00315 
00316         hip->hit = mem_maybedup(mctx, region.base, hip->hit_len);
00317         if (hip->hit == NULL)
00318                 goto cleanup;
00319         isc_region_consume(&region, hip->hit_len);
00320 
00321         INSIST(hip->key_len <= region.length);
00322 
00323         hip->key = mem_maybedup(mctx, region.base, hip->key_len);
00324         if (hip->key == NULL)
00325                 goto cleanup;
00326         isc_region_consume(&region, hip->key_len);
00327 
00328         hip->servers_len = region.length;
00329         if (hip->servers_len != 0) {
00330                 hip->servers = mem_maybedup(mctx, region.base, region.length);
00331                 if (hip->servers == NULL)
00332                         goto cleanup;
00333         }
00334 
00335         hip->offset = hip->servers_len;
00336         hip->mctx = mctx;
00337         return (ISC_R_SUCCESS);
00338 
00339  cleanup:
00340         if (hip->hit != NULL)
00341                 isc_mem_free(mctx, hip->hit);
00342         if (hip->key != NULL)
00343                 isc_mem_free(mctx, hip->key);
00344         if (hip->servers != NULL)
00345                 isc_mem_free(mctx, hip->servers);
00346         return (ISC_R_NOMEMORY);
00347 
00348 }
00349 
00350 static inline void
00351 freestruct_hip(ARGS_FREESTRUCT) {
00352         dns_rdata_hip_t *hip = source;
00353 
00354         REQUIRE(source != NULL);
00355 
00356         if (hip->mctx == NULL)
00357                 return;
00358 
00359         isc_mem_free(hip->mctx, hip->hit);
00360         isc_mem_free(hip->mctx, hip->key);
00361         if (hip->servers != NULL)
00362                 isc_mem_free(hip->mctx, hip->servers);
00363         hip->mctx = NULL;
00364 }
00365 
00366 static inline isc_result_t
00367 additionaldata_hip(ARGS_ADDLDATA) {
00368         UNUSED(rdata);
00369         UNUSED(add);
00370         UNUSED(arg);
00371 
00372         REQUIRE(rdata->type == 55);
00373 
00374         return (ISC_R_SUCCESS);
00375 }
00376 
00377 static inline isc_result_t
00378 digest_hip(ARGS_DIGEST) {
00379         isc_region_t r;
00380 
00381         REQUIRE(rdata->type == 55);
00382 
00383         dns_rdata_toregion(rdata, &r);
00384         return ((digest)(arg, &r));
00385 }
00386 
00387 static inline isc_boolean_t
00388 checkowner_hip(ARGS_CHECKOWNER) {
00389 
00390         REQUIRE(type == 55);
00391 
00392         UNUSED(name);
00393         UNUSED(type);
00394         UNUSED(rdclass);
00395         UNUSED(wildcard);
00396 
00397         return (ISC_TRUE);
00398 }
00399 
00400 static inline isc_boolean_t
00401 checknames_hip(ARGS_CHECKNAMES) {
00402 
00403         REQUIRE(rdata->type == 55);
00404 
00405         UNUSED(rdata);
00406         UNUSED(owner);
00407         UNUSED(bad);
00408 
00409         return (ISC_TRUE);
00410 }
00411 
00412 isc_result_t
00413 dns_rdata_hip_first(dns_rdata_hip_t *hip) {
00414         if (hip->servers_len == 0)
00415                 return (ISC_R_NOMORE);
00416         hip->offset = 0;
00417         return (ISC_R_SUCCESS);
00418 }
00419 
00420 isc_result_t
00421 dns_rdata_hip_next(dns_rdata_hip_t *hip) {
00422         isc_region_t region;
00423         dns_name_t name;
00424 
00425         if (hip->offset >= hip->servers_len)
00426                 return (ISC_R_NOMORE);
00427 
00428         region.base = hip->servers + hip->offset;
00429         region.length = hip->servers_len - hip->offset;
00430         dns_name_init(&name, NULL);
00431         dns_name_fromregion(&name, &region);
00432         hip->offset += name.length;
00433         INSIST(hip->offset <= hip->servers_len);
00434         return (ISC_R_SUCCESS);
00435 }
00436 
00437 void
00438 dns_rdata_hip_current(dns_rdata_hip_t *hip, dns_name_t *name) {
00439         isc_region_t region;
00440 
00441         REQUIRE(hip->offset < hip->servers_len);
00442 
00443         region.base = hip->servers + hip->offset;
00444         region.length = hip->servers_len - hip->offset;
00445         dns_name_fromregion(name, &region);
00446 
00447         INSIST(name->length + hip->offset <= hip->servers_len);
00448 }
00449 
00450 static inline int
00451 casecompare_hip(ARGS_COMPARE) {
00452         isc_region_t r1;
00453         isc_region_t r2;
00454         dns_name_t name1;
00455         dns_name_t name2;
00456         int order;
00457         isc_uint8_t hit_len;
00458         isc_uint16_t key_len;
00459 
00460         REQUIRE(rdata1->type == rdata2->type);
00461         REQUIRE(rdata1->rdclass == rdata2->rdclass);
00462         REQUIRE(rdata1->type == 55);
00463         REQUIRE(rdata1->length != 0);
00464         REQUIRE(rdata2->length != 0);
00465 
00466         dns_rdata_toregion(rdata1, &r1);
00467         dns_rdata_toregion(rdata2, &r2);
00468 
00469         INSIST(r1.length > 4);
00470         INSIST(r2.length > 4);
00471         order = memcmp(r1.base, r2.base, 4);
00472         if (order != 0)
00473                 return (order);
00474 
00475         hit_len = uint8_fromregion(&r1);
00476         isc_region_consume(&r1, 2);         /* hit length + algorithm */
00477         key_len = uint16_fromregion(&r1);
00478         isc_region_consume(&r1, 2);         /* key length */
00479         isc_region_consume(&r2, 4);
00480 
00481         INSIST(r1.length >= (unsigned) (hit_len + key_len));
00482         INSIST(r2.length >= (unsigned) (hit_len + key_len));
00483         order = memcmp(r1.base, r2.base, hit_len + key_len);
00484         if (order != 0)
00485                 return (order);
00486         isc_region_consume(&r1, hit_len + key_len);
00487         isc_region_consume(&r2, hit_len + key_len);
00488 
00489         dns_name_init(&name1, NULL);
00490         dns_name_init(&name2, NULL);
00491         while (r1.length != 0 && r2.length != 0) {
00492                 dns_name_fromregion(&name1, &r1);
00493                 dns_name_fromregion(&name2, &r2);
00494                 order = dns_name_rdatacompare(&name1, &name2);
00495                 if (order != 0)
00496                         return (order);
00497 
00498                 isc_region_consume(&r1, name_length(&name1));
00499                 isc_region_consume(&r2, name_length(&name2));
00500         }
00501         return (isc_region_compare(&r1, &r2));
00502 }
00503 
00504 #endif  /* RDATA_GENERIC_HIP_5_C */

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