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>