[BACK]Return to loc_29.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / mpl / bind / dist / lib / dns / rdata / generic

Annotation of src/external/mpl/bind/dist/lib/dns/rdata/generic/loc_29.c, Revision 1.8

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

CVSweb <webmaster@jp.NetBSD.org>