"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/lib/dns/rdata/generic/loc_29.c" (7 Sep 2020, 18755 Bytes) of package /linux/misc/dns/bind9/9.11.23/bind-9.11.23.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "loc_29.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 9.11.22_vs_9.11.23.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 /* RFC1876 */
   13 
   14 #ifndef RDATA_GENERIC_LOC_29_C
   15 #define RDATA_GENERIC_LOC_29_C
   16 
   17 #define RRTYPE_LOC_ATTRIBUTES (0)
   18 
   19 static isc_result_t
   20 loc_getdecimal(const char *str, unsigned long max, size_t precision, char units,
   21            unsigned long *valuep) {
   22     bool ok;
   23     char *e;
   24     size_t i;
   25     long tmp;
   26     unsigned long value;
   27 
   28     value = strtoul(str, &e, 10);
   29     if (*e != 0 && *e != '.' && *e != units) {
   30         return (DNS_R_SYNTAX);
   31     }
   32     if (value > max) {
   33         return (ISC_R_RANGE);
   34     }
   35     ok = e != str;
   36     if (*e == '.') {
   37         e++;
   38         for (i = 0; i < precision; i++) {
   39             if (*e == 0 || *e == units) {
   40                 break;
   41             }
   42             if ((tmp = decvalue(*e++)) < 0) {
   43                 return (DNS_R_SYNTAX);
   44             }
   45             ok = true;
   46             value *= 10;
   47             value += tmp;
   48         }
   49         for (; i < precision; i++) {
   50             value *= 10;
   51         }
   52     } else {
   53         for (i = 0; i < precision; i++) {
   54             value *= 10;
   55         }
   56     }
   57     if (*e != 0 && *e == units) {
   58         e++;
   59     }
   60     if (!ok || *e != 0) {
   61         return (DNS_R_SYNTAX);
   62     }
   63     *valuep = value;
   64     return (ISC_R_SUCCESS);
   65 }
   66 
   67 static isc_result_t
   68 loc_getprecision(const char *str, unsigned char *valuep) {
   69     unsigned long poweroften[8] = { 1,     10,     100, 1000,
   70                     10000, 100000, 1000000, 10000000 };
   71     unsigned long m, cm;
   72     bool ok;
   73     char *e;
   74     size_t i;
   75     long tmp;
   76     int man;
   77     int exp;
   78 
   79     m = strtoul(str, &e, 10);
   80     if (*e != 0 && *e != '.' && *e != 'm') {
   81         return (DNS_R_SYNTAX);
   82     }
   83     if (m > 90000000) {
   84         return (ISC_R_RANGE);
   85     }
   86     cm = 0;
   87     ok = e != str;
   88     if (*e == '.') {
   89         e++;
   90         for (i = 0; i < 2; i++) {
   91             if (*e == 0 || *e == 'm') {
   92                 break;
   93             }
   94             if ((tmp = decvalue(*e++)) < 0) {
   95                 return (DNS_R_SYNTAX);
   96             }
   97             ok = true;
   98             cm *= 10;
   99             cm += tmp;
  100         }
  101         for (; i < 2; i++) {
  102             cm *= 10;
  103         }
  104     }
  105     if (*e == 'm') {
  106         e++;
  107     }
  108     if (!ok || *e != 0) {
  109         return (DNS_R_SYNTAX);
  110     }
  111 
  112     /*
  113      * We don't just multiply out as we will overflow.
  114      */
  115     if (m > 0) {
  116         for (exp = 0; exp < 7; exp++) {
  117             if (m < poweroften[exp + 1]) {
  118                 break;
  119             }
  120         }
  121         man = m / poweroften[exp];
  122         exp += 2;
  123     } else if (cm >= 10) {
  124         man = cm / 10;
  125         exp = 1;
  126     } else {
  127         man = cm;
  128         exp = 0;
  129     }
  130     *valuep = (man << 4) + exp;
  131     return (ISC_R_SUCCESS);
  132 }
  133 
  134 static isc_result_t
  135 get_degrees(isc_lex_t *lexer, isc_token_t *token, unsigned long *d) {
  136     RETERR(isc_lex_getmastertoken(lexer, token, isc_tokentype_number,
  137                       false));
  138     *d = token->value.as_ulong;
  139 
  140     return (ISC_R_SUCCESS);
  141 }
  142 
  143 static isc_result_t
  144 check_coordinate(unsigned long d, unsigned long m, unsigned long s,
  145          unsigned long maxd) {
  146     if (d > maxd || m > 59U) {
  147         return (ISC_R_RANGE);
  148     }
  149     if (d == maxd && (m != 0 || s != 0)) {
  150         return (ISC_R_RANGE);
  151     }
  152 
  153     return (ISC_R_SUCCESS);
  154 }
  155 
  156 static isc_result_t
  157 get_minutes(isc_lex_t *lexer, isc_token_t *token, unsigned long *m) {
  158     RETERR(isc_lex_getmastertoken(lexer, token, isc_tokentype_number,
  159                       false));
  160 
  161     *m = token->value.as_ulong;
  162 
  163     return (ISC_R_SUCCESS);
  164 }
  165 
  166 static isc_result_t
  167 get_seconds(isc_lex_t *lexer, isc_token_t *token, unsigned long *s) {
  168     RETERR(isc_lex_getmastertoken(lexer, token, isc_tokentype_string,
  169                       false));
  170     RETERR(loc_getdecimal(DNS_AS_STR(*token), 59, 3, '\0', s));
  171 
  172     return (ISC_R_SUCCESS);
  173 }
  174 
  175 static isc_result_t
  176 get_direction(isc_lex_t *lexer, isc_token_t *token, const char *directions,
  177           int *direction) {
  178     RETERR(isc_lex_getmastertoken(lexer, token, isc_tokentype_string,
  179                       false));
  180     if (DNS_AS_STR(*token)[0] == directions[1] &&
  181         DNS_AS_STR(*token)[1] == 0) {
  182         *direction = DNS_AS_STR(*token)[0];
  183         return (ISC_R_SUCCESS);
  184     }
  185 
  186     if (DNS_AS_STR(*token)[0] == directions[0] &&
  187         DNS_AS_STR(*token)[1] == 0) {
  188         *direction = DNS_AS_STR(*token)[0];
  189         return (ISC_R_SUCCESS);
  190     }
  191 
  192     *direction = 0;
  193     isc_lex_ungettoken(lexer, token);
  194     return (ISC_R_SUCCESS);
  195 }
  196 
  197 static isc_result_t
  198 loc_getcoordinate(isc_lex_t *lexer, unsigned long *dp, unsigned long *mp,
  199           unsigned long *sp, const char *directions, int *directionp,
  200           unsigned long maxd) {
  201     isc_result_t result = ISC_R_SUCCESS;
  202     isc_token_t token;
  203     unsigned long d, m, s;
  204     int direction = 0;
  205 
  206     m = 0;
  207     s = 0;
  208 
  209     /*
  210      * Degrees.
  211      */
  212     RETERR(get_degrees(lexer, &token, &d));
  213     RETTOK(check_coordinate(d, m, s, maxd));
  214 
  215     /*
  216      * Minutes.
  217      */
  218     RETERR(get_direction(lexer, &token, directions, &direction));
  219     if (direction > 0) {
  220         goto done;
  221     }
  222 
  223     RETERR(get_minutes(lexer, &token, &m));
  224     RETTOK(check_coordinate(d, m, s, maxd));
  225 
  226     /*
  227      * Seconds.
  228      */
  229     RETERR(get_direction(lexer, &token, directions, &direction));
  230     if (direction > 0) {
  231         goto done;
  232     }
  233 
  234     result = get_seconds(lexer, &token, &s);
  235     if (result == ISC_R_RANGE || result == DNS_R_SYNTAX) {
  236         RETTOK(result);
  237     }
  238     RETERR(result);
  239     RETTOK(check_coordinate(d, m, s, maxd));
  240 
  241     /*
  242      * Direction.
  243      */
  244     RETERR(get_direction(lexer, &token, directions, &direction));
  245     if (direction == -1) {
  246         RETERR(DNS_R_SYNTAX);
  247     }
  248 done:
  249 
  250     *directionp = direction;
  251     *dp = d;
  252     *mp = m;
  253     *sp = s;
  254 
  255     return (ISC_R_SUCCESS);
  256 }
  257 
  258 static inline isc_result_t
  259 loc_getlatitude(isc_lex_t *lexer, unsigned long *latitude) {
  260     unsigned long d1 = 0, m1 = 0, s1 = 0;
  261     int direction = 0;
  262 
  263     RETERR(loc_getcoordinate(lexer, &d1, &m1, &s1, "SN", &direction, 90U));
  264 
  265     switch (direction) {
  266     case 'N':
  267         *latitude = 0x80000000 + (d1 * 3600 + m1 * 60) * 1000 + s1;
  268         break;
  269     case 'S':
  270         *latitude = 0x80000000 - (d1 * 3600 + m1 * 60) * 1000 - s1;
  271         break;
  272     default:
  273         INSIST(0);
  274         ISC_UNREACHABLE();
  275     }
  276 
  277     return (ISC_R_SUCCESS);
  278 }
  279 
  280 static inline isc_result_t
  281 loc_getlongitude(isc_lex_t *lexer, unsigned long *longitude) {
  282     unsigned long d2 = 0, m2 = 0, s2 = 0;
  283     int direction = 0;
  284 
  285     RETERR(loc_getcoordinate(lexer, &d2, &m2, &s2, "WE", &direction, 180U));
  286 
  287     switch (direction) {
  288     case 'E':
  289         *longitude = 0x80000000 + (d2 * 3600 + m2 * 60) * 1000 + s2;
  290         break;
  291     case 'W':
  292         *longitude = 0x80000000 - (d2 * 3600 + m2 * 60) * 1000 - s2;
  293         break;
  294     default:
  295         INSIST(0);
  296         ISC_UNREACHABLE();
  297     }
  298 
  299     return (ISC_R_SUCCESS);
  300 }
  301 
  302 static inline isc_result_t
  303 loc_getaltitude(isc_lex_t *lexer, unsigned long *altitude) {
  304     isc_token_t token;
  305     unsigned long cm;
  306     const char *str;
  307 
  308     RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
  309                       false));
  310     str = DNS_AS_STR(token);
  311     if (DNS_AS_STR(token)[0] == '-') {
  312         RETTOK(loc_getdecimal(str + 1, 100000, 2, 'm', &cm));
  313         if (cm > 10000000UL) {
  314             RETTOK(ISC_R_RANGE);
  315         }
  316         *altitude = 10000000 - cm;
  317     } else {
  318         RETTOK(loc_getdecimal(str, 42849672, 2, 'm', &cm));
  319         if (cm > 4284967295UL) {
  320             RETTOK(ISC_R_RANGE);
  321         }
  322         *altitude = 10000000 + cm;
  323     }
  324 
  325     return (ISC_R_SUCCESS);
  326 }
  327 
  328 static inline isc_result_t
  329 loc_getoptionalprecision(isc_lex_t *lexer, unsigned char *valuep) {
  330     isc_token_t token;
  331 
  332     RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
  333                       true));
  334     if (token.type == isc_tokentype_eol || token.type == isc_tokentype_eof)
  335     {
  336         isc_lex_ungettoken(lexer, &token);
  337         return (ISC_R_NOMORE);
  338     }
  339     RETTOK(loc_getprecision(DNS_AS_STR(token), valuep));
  340 
  341     return (ISC_R_SUCCESS);
  342 }
  343 
  344 static inline isc_result_t
  345 loc_getsize(isc_lex_t *lexer, unsigned char *sizep) {
  346     return (loc_getoptionalprecision(lexer, sizep));
  347 }
  348 
  349 static inline isc_result_t
  350 loc_gethorizontalprecision(isc_lex_t *lexer, unsigned char *hpp) {
  351     return (loc_getoptionalprecision(lexer, hpp));
  352 }
  353 
  354 static inline isc_result_t
  355 loc_getverticalprecision(isc_lex_t *lexer, unsigned char *vpp) {
  356     return (loc_getoptionalprecision(lexer, vpp));
  357 }
  358 
  359 /* The LOC record is expressed in a master file in the following format:
  360  *
  361  * <owner> <TTL> <class> LOC ( d1 [m1 [s1]] {"N"|"S"} d2 [m2 [s2]]
  362  *                             {"E"|"W"} alt["m"] [siz["m"] [hp["m"]
  363  *                             [vp["m"]]]] )
  364  *
  365  * (The parentheses are used for multi-line data as specified in [RFC
  366  * 1035] section 5.1.)
  367  *
  368  * where:
  369  *
  370  *     d1:     [0 .. 90]            (degrees latitude)
  371  *     d2:     [0 .. 180]           (degrees longitude)
  372  *     m1, m2: [0 .. 59]            (minutes latitude/longitude)
  373  *     s1, s2: [0 .. 59.999]        (seconds latitude/longitude)
  374  *     alt:    [-100000.00 .. 42849672.95] BY .01 (altitude in meters)
  375  *     siz, hp, vp: [0 .. 90000000.00] (size/precision in meters)
  376  *
  377  * If omitted, minutes and seconds default to zero, size defaults to 1m,
  378  * horizontal precision defaults to 10000m, and vertical precision
  379  * defaults to 10m.  These defaults are chosen to represent typical
  380  * ZIP/postal code area sizes, since it is often easy to find
  381  * approximate geographical location by ZIP/postal code.
  382  */
  383 static inline isc_result_t
  384 fromtext_loc(ARGS_FROMTEXT) {
  385     isc_result_t result = ISC_R_SUCCESS;
  386     unsigned long latitude = 0;
  387     unsigned long longitude = 0;
  388     unsigned long altitude = 0;
  389     unsigned char size = 0x12; /* Default: 1.00m */
  390     unsigned char hp = 0x16;   /* Default: 10000.00 m */
  391     unsigned char vp = 0x13;   /* Default: 10.00 m */
  392     unsigned char version = 0;
  393 
  394     REQUIRE(type == dns_rdatatype_loc);
  395 
  396     UNUSED(type);
  397     UNUSED(rdclass);
  398     UNUSED(origin);
  399     UNUSED(options);
  400     UNUSED(callbacks);
  401 
  402     RETERR(loc_getlatitude(lexer, &latitude));
  403     RETERR(loc_getlongitude(lexer, &longitude));
  404     RETERR(loc_getaltitude(lexer, &altitude));
  405     result = loc_getsize(lexer, &size);
  406     if (result == ISC_R_NOMORE) {
  407         result = ISC_R_SUCCESS;
  408         goto encode;
  409     }
  410     RETERR(result);
  411     result = loc_gethorizontalprecision(lexer, &hp);
  412     if (result == ISC_R_NOMORE) {
  413         result = ISC_R_SUCCESS;
  414         goto encode;
  415     }
  416     RETERR(result);
  417     result = loc_getverticalprecision(lexer, &vp);
  418     if (result == ISC_R_NOMORE) {
  419         result = ISC_R_SUCCESS;
  420         goto encode;
  421     }
  422     RETERR(result);
  423 encode:
  424     RETERR(mem_tobuffer(target, &version, 1));
  425     RETERR(mem_tobuffer(target, &size, 1));
  426     RETERR(mem_tobuffer(target, &hp, 1));
  427     RETERR(mem_tobuffer(target, &vp, 1));
  428 
  429     RETERR(uint32_tobuffer(latitude, target));
  430     RETERR(uint32_tobuffer(longitude, target));
  431     RETERR(uint32_tobuffer(altitude, target));
  432 
  433     return (result);
  434 }
  435 
  436 static inline isc_result_t
  437 totext_loc(ARGS_TOTEXT) {
  438     int d1, m1, s1, fs1;
  439     int d2, m2, s2, fs2;
  440     unsigned long latitude;
  441     unsigned long longitude;
  442     unsigned long altitude;
  443     bool north;
  444     bool east;
  445     bool below;
  446     isc_region_t sr;
  447     char sbuf[sizeof("90000000m")];
  448     char hbuf[sizeof("90000000m")];
  449     char vbuf[sizeof("90000000m")];
  450     /* "89 59 59.999 N 179 59 59.999 E " */
  451     /* "-42849672.95m 90000000m 90000000m 90000000m"; */
  452     char buf[8 * 6 + 12 * 1 + 2 * 10 + sizeof(sbuf) + sizeof(hbuf) +
  453          sizeof(vbuf)];
  454     unsigned char size, hp, vp;
  455     unsigned long poweroften[8] = { 1,     10,     100, 1000,
  456                     10000, 100000, 1000000, 10000000 };
  457 
  458     UNUSED(tctx);
  459 
  460     REQUIRE(rdata->type == dns_rdatatype_loc);
  461     REQUIRE(rdata->length != 0);
  462 
  463     dns_rdata_toregion(rdata, &sr);
  464 
  465     if (sr.base[0] != 0) {
  466         return (ISC_R_NOTIMPLEMENTED);
  467     }
  468 
  469     REQUIRE(rdata->length == 16);
  470 
  471     size = sr.base[1];
  472     INSIST((size & 0x0f) < 10 && (size >> 4) < 10);
  473     if ((size & 0x0f) > 1) {
  474         snprintf(sbuf, sizeof(sbuf), "%lum",
  475              (size >> 4) * poweroften[(size & 0x0f) - 2]);
  476     } else {
  477         snprintf(sbuf, sizeof(sbuf), "0.%02lum",
  478              (size >> 4) * poweroften[(size & 0x0f)]);
  479     }
  480     hp = sr.base[2];
  481     INSIST((hp & 0x0f) < 10 && (hp >> 4) < 10);
  482     if ((hp & 0x0f) > 1) {
  483         snprintf(hbuf, sizeof(hbuf), "%lum",
  484              (hp >> 4) * poweroften[(hp & 0x0f) - 2]);
  485     } else {
  486         snprintf(hbuf, sizeof(hbuf), "0.%02lum",
  487              (hp >> 4) * poweroften[(hp & 0x0f)]);
  488     }
  489     vp = sr.base[3];
  490     INSIST((vp & 0x0f) < 10 && (vp >> 4) < 10);
  491     if ((vp & 0x0f) > 1) {
  492         snprintf(vbuf, sizeof(vbuf), "%lum",
  493              (vp >> 4) * poweroften[(vp & 0x0f) - 2]);
  494     } else {
  495         snprintf(vbuf, sizeof(vbuf), "0.%02lum",
  496              (vp >> 4) * poweroften[(vp & 0x0f)]);
  497     }
  498     isc_region_consume(&sr, 4);
  499 
  500     latitude = uint32_fromregion(&sr);
  501     isc_region_consume(&sr, 4);
  502     if (latitude >= 0x80000000) {
  503         north = true;
  504         latitude -= 0x80000000;
  505     } else {
  506         north = false;
  507         latitude = 0x80000000 - latitude;
  508     }
  509     fs1 = (int)(latitude % 1000);
  510     latitude /= 1000;
  511     s1 = (int)(latitude % 60);
  512     latitude /= 60;
  513     m1 = (int)(latitude % 60);
  514     latitude /= 60;
  515     d1 = (int)latitude;
  516     INSIST(latitude <= 90U);
  517 
  518     longitude = uint32_fromregion(&sr);
  519     isc_region_consume(&sr, 4);
  520     if (longitude >= 0x80000000) {
  521         east = true;
  522         longitude -= 0x80000000;
  523     } else {
  524         east = false;
  525         longitude = 0x80000000 - longitude;
  526     }
  527     fs2 = (int)(longitude % 1000);
  528     longitude /= 1000;
  529     s2 = (int)(longitude % 60);
  530     longitude /= 60;
  531     m2 = (int)(longitude % 60);
  532     longitude /= 60;
  533     d2 = (int)longitude;
  534     INSIST(longitude <= 180U);
  535 
  536     altitude = uint32_fromregion(&sr);
  537     isc_region_consume(&sr, 4);
  538     if (altitude < 10000000U) {
  539         below = true;
  540         altitude = 10000000 - altitude;
  541     } else {
  542         below = false;
  543         altitude -= 10000000;
  544     }
  545 
  546     snprintf(buf, sizeof(buf),
  547          "%d %d %d.%03d %s %d %d %d.%03d %s %s%lu.%02lum %s %s %s", d1,
  548          m1, s1, fs1, north ? "N" : "S", d2, m2, s2, fs2,
  549          east ? "E" : "W", below ? "-" : "", altitude / 100,
  550          altitude % 100, sbuf, hbuf, vbuf);
  551 
  552     return (str_totext(buf, target));
  553 }
  554 
  555 static inline isc_result_t
  556 fromwire_loc(ARGS_FROMWIRE) {
  557     isc_region_t sr;
  558     unsigned char c;
  559     unsigned long latitude;
  560     unsigned long longitude;
  561 
  562     REQUIRE(type == dns_rdatatype_loc);
  563 
  564     UNUSED(type);
  565     UNUSED(rdclass);
  566     UNUSED(dctx);
  567     UNUSED(options);
  568 
  569     isc_buffer_activeregion(source, &sr);
  570     if (sr.length < 1)
  571         return (ISC_R_UNEXPECTEDEND);
  572     if (sr.base[0] != 0) {
  573         /* Treat as unknown. */
  574         isc_buffer_forward(source, sr.length);
  575         return (mem_tobuffer(target, sr.base, sr.length));
  576     }
  577     if (sr.length < 16)
  578         return (ISC_R_UNEXPECTEDEND);
  579 
  580     /*
  581      * Size.
  582      */
  583     c = sr.base[1];
  584     if (c != 0)
  585         if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
  586             return (ISC_R_RANGE);
  587 
  588     /*
  589      * Horizontal precision.
  590      */
  591     c = sr.base[2];
  592     if (c != 0)
  593         if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
  594             return (ISC_R_RANGE);
  595 
  596     /*
  597      * Vertical precision.
  598      */
  599     c = sr.base[3];
  600     if (c != 0)
  601         if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
  602             return (ISC_R_RANGE);
  603     isc_region_consume(&sr, 4);
  604 
  605     /*
  606      * Latitude.
  607      */
  608     latitude = uint32_fromregion(&sr);
  609     if (latitude < (0x80000000UL - 90 * 3600000) ||
  610         latitude > (0x80000000UL + 90 * 3600000))
  611         return (ISC_R_RANGE);
  612     isc_region_consume(&sr, 4);
  613 
  614     /*
  615      * Longitude.
  616      */
  617     longitude = uint32_fromregion(&sr);
  618     if (longitude < (0x80000000UL - 180 * 3600000) ||
  619         longitude > (0x80000000UL + 180 * 3600000))
  620         return (ISC_R_RANGE);
  621 
  622     /*
  623      * Altitude.
  624      * All values possible.
  625      */
  626 
  627     isc_buffer_activeregion(source, &sr);
  628     isc_buffer_forward(source, 16);
  629     return (mem_tobuffer(target, sr.base, 16));
  630 }
  631 
  632 static inline isc_result_t
  633 towire_loc(ARGS_TOWIRE) {
  634     UNUSED(cctx);
  635 
  636     REQUIRE(rdata->type == dns_rdatatype_loc);
  637     REQUIRE(rdata->length != 0);
  638 
  639     return (mem_tobuffer(target, rdata->data, rdata->length));
  640 }
  641 
  642 static inline int
  643 compare_loc(ARGS_COMPARE) {
  644     isc_region_t r1;
  645     isc_region_t r2;
  646 
  647     REQUIRE(rdata1->type == rdata2->type);
  648     REQUIRE(rdata1->rdclass == rdata2->rdclass);
  649     REQUIRE(rdata1->type == dns_rdatatype_loc);
  650     REQUIRE(rdata1->length != 0);
  651     REQUIRE(rdata2->length != 0);
  652 
  653     dns_rdata_toregion(rdata1, &r1);
  654     dns_rdata_toregion(rdata2, &r2);
  655     return (isc_region_compare(&r1, &r2));
  656 }
  657 
  658 static inline isc_result_t
  659 fromstruct_loc(ARGS_FROMSTRUCT) {
  660     dns_rdata_loc_t *loc;
  661     uint8_t c;
  662 
  663     REQUIRE(type == dns_rdatatype_loc);
  664     REQUIRE(((dns_rdata_loc_t *)source) != NULL);
  665     REQUIRE(((dns_rdata_loc_t *)source)->common.rdtype == type);
  666     REQUIRE(((dns_rdata_loc_t *)source)->common.rdclass == rdclass);
  667 
  668     loc = source;
  669 
  670     UNUSED(type);
  671     UNUSED(rdclass);
  672 
  673     if (loc->v.v0.version != 0)
  674         return (ISC_R_NOTIMPLEMENTED);
  675     RETERR(uint8_tobuffer(loc->v.v0.version, target));
  676 
  677     c = loc->v.v0.size;
  678     if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
  679         return (ISC_R_RANGE);
  680     RETERR(uint8_tobuffer(loc->v.v0.size, target));
  681 
  682     c = loc->v.v0.horizontal;
  683     if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
  684         return (ISC_R_RANGE);
  685     RETERR(uint8_tobuffer(loc->v.v0.horizontal, target));
  686 
  687     c = loc->v.v0.vertical;
  688     if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
  689         return (ISC_R_RANGE);
  690     RETERR(uint8_tobuffer(loc->v.v0.vertical, target));
  691 
  692     if (loc->v.v0.latitude < (0x80000000UL - 90 * 3600000) ||
  693         loc->v.v0.latitude > (0x80000000UL + 90 * 3600000))
  694         return (ISC_R_RANGE);
  695     RETERR(uint32_tobuffer(loc->v.v0.latitude, target));
  696 
  697     if (loc->v.v0.longitude < (0x80000000UL - 180 * 3600000) ||
  698         loc->v.v0.longitude > (0x80000000UL + 180 * 3600000))
  699         return (ISC_R_RANGE);
  700     RETERR(uint32_tobuffer(loc->v.v0.longitude, target));
  701     return (uint32_tobuffer(loc->v.v0.altitude, target));
  702 }
  703 
  704 static inline isc_result_t
  705 tostruct_loc(ARGS_TOSTRUCT) {
  706     dns_rdata_loc_t *loc;
  707     isc_region_t r;
  708     uint8_t version;
  709 
  710     REQUIRE(((dns_rdata_loc_t *)target) != NULL);
  711     REQUIRE(rdata->type == dns_rdatatype_loc);
  712     REQUIRE(rdata->length != 0);
  713 
  714     loc = target;
  715 
  716     UNUSED(mctx);
  717 
  718     dns_rdata_toregion(rdata, &r);
  719     version = uint8_fromregion(&r);
  720     if (version != 0)
  721         return (ISC_R_NOTIMPLEMENTED);
  722 
  723     loc->common.rdclass = rdata->rdclass;
  724     loc->common.rdtype = rdata->type;
  725     ISC_LINK_INIT(&loc->common, link);
  726 
  727     loc->v.v0.version = version;
  728     isc_region_consume(&r, 1);
  729     loc->v.v0.size = uint8_fromregion(&r);
  730     isc_region_consume(&r, 1);
  731     loc->v.v0.horizontal = uint8_fromregion(&r);
  732     isc_region_consume(&r, 1);
  733     loc->v.v0.vertical = uint8_fromregion(&r);
  734     isc_region_consume(&r, 1);
  735     loc->v.v0.latitude = uint32_fromregion(&r);
  736     isc_region_consume(&r, 4);
  737     loc->v.v0.longitude = uint32_fromregion(&r);
  738     isc_region_consume(&r, 4);
  739     loc->v.v0.altitude = uint32_fromregion(&r);
  740     isc_region_consume(&r, 4);
  741     return (ISC_R_SUCCESS);
  742 }
  743 
  744 static inline void
  745 freestruct_loc(ARGS_FREESTRUCT) {
  746     dns_rdata_loc_t *loc;
  747 
  748     REQUIRE(((dns_rdata_loc_t *)source) != NULL);
  749     REQUIRE(((dns_rdata_loc_t *)source)->common.rdtype ==
  750         dns_rdatatype_loc);
  751 
  752     loc = source;
  753 
  754     UNUSED(source);
  755     UNUSED(loc);
  756 }
  757 
  758 static inline isc_result_t
  759 additionaldata_loc(ARGS_ADDLDATA) {
  760     REQUIRE(rdata->type == dns_rdatatype_loc);
  761 
  762     UNUSED(rdata);
  763     UNUSED(add);
  764     UNUSED(arg);
  765 
  766     return (ISC_R_SUCCESS);
  767 }
  768 
  769 static inline isc_result_t
  770 digest_loc(ARGS_DIGEST) {
  771     isc_region_t r;
  772 
  773     REQUIRE(rdata->type == dns_rdatatype_loc);
  774 
  775     dns_rdata_toregion(rdata, &r);
  776 
  777     return ((digest)(arg, &r));
  778 }
  779 
  780 static inline bool
  781 checkowner_loc(ARGS_CHECKOWNER) {
  782 
  783     REQUIRE(type == dns_rdatatype_loc);
  784 
  785     UNUSED(name);
  786     UNUSED(type);
  787     UNUSED(rdclass);
  788     UNUSED(wildcard);
  789 
  790     return (true);
  791 }
  792 
  793 static inline bool
  794 checknames_loc(ARGS_CHECKNAMES) {
  795 
  796     REQUIRE(rdata->type == dns_rdatatype_loc);
  797 
  798     UNUSED(rdata);
  799     UNUSED(owner);
  800     UNUSED(bad);
  801 
  802     return (true);
  803 }
  804 
  805 static inline int
  806 casecompare_loc(ARGS_COMPARE) {
  807     return (compare_loc(rdata1, rdata2));
  808 }
  809 
  810 #endif  /* RDATA_GENERIC_LOC_29_C */