2 * Copyright (C) 2004, 2005, 2007, 2009, 2015 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: loc_29.c,v 1.50 2009/12/04 21:09:33 marka Exp $ */
20 /* Reviewed: Wed Mar 15 18:13:09 PST 2000 by explorer */
24 #ifndef RDATA_GENERIC_LOC_29_C
25 #define RDATA_GENERIC_LOC_29_C
27 #define RRTYPE_LOC_ATTRIBUTES (0)
29 static inline isc_result_t
30 fromtext_loc(ARGS_FROMTEXT) {
37 unsigned char version;
38 isc_boolean_t east = ISC_FALSE;
39 isc_boolean_t north = ISC_FALSE;
43 long poweroften[8] = { 1, 10, 100, 1000,
44 10000, 100000, 1000000, 10000000 };
49 unsigned long latitude;
50 unsigned long longitude;
51 unsigned long altitude;
53 REQUIRE(type == dns_rdatatype_loc);
65 size = 0x12; /* 1.00m */
66 hp = 0x16; /* 10000.00 m */
67 vp = 0x13; /* 10.00 m */
73 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
75 if (token.value.as_ulong > 90U)
77 d1 = (int)token.value.as_ulong;
81 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
83 if (strcasecmp(DNS_AS_STR(token), "N") == 0)
85 if (north || strcasecmp(DNS_AS_STR(token), "S") == 0)
87 m1 = strtol(DNS_AS_STR(token), &e, 10);
90 if (m1 < 0 || m1 > 59)
92 if (d1 == 90 && m1 != 0)
98 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
100 if (strcasecmp(DNS_AS_STR(token), "N") == 0)
102 if (north || strcasecmp(DNS_AS_STR(token), "S") == 0)
104 s1 = strtol(DNS_AS_STR(token), &e, 10);
105 if (*e != 0 && *e != '.')
106 RETTOK(DNS_R_SYNTAX);
107 if (s1 < 0 || s1 > 59)
112 for (i = 0; i < 3; i++) {
115 if ((tmp = decvalue(*e++)) < 0)
116 RETTOK(DNS_R_SYNTAX);
124 if (decvalue(*e++) < 0)
125 RETTOK(DNS_R_SYNTAX);
127 if (*l != '\0' && callbacks != NULL) {
128 const char *file = isc_lex_getsourcename(lexer);
129 unsigned long line = isc_lex_getsourceline(lexer);
133 (*callbacks->warn)(callbacks, "%s: %s:%u: '%s' extra "
134 "precision digits ignored",
135 "dns_rdata_fromtext", file, line,
140 if (d1 == 90 && s1 != 0)
146 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
148 if (strcasecmp(DNS_AS_STR(token), "N") == 0)
150 if (!north && strcasecmp(DNS_AS_STR(token), "S") != 0)
151 RETTOK(DNS_R_SYNTAX);
157 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
159 if (token.value.as_ulong > 180U)
161 d2 = (int)token.value.as_ulong;
166 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
168 if (strcasecmp(DNS_AS_STR(token), "E") == 0)
170 if (east || strcasecmp(DNS_AS_STR(token), "W") == 0)
172 m2 = strtol(DNS_AS_STR(token), &e, 10);
174 RETTOK(DNS_R_SYNTAX);
175 if (m2 < 0 || m2 > 59)
177 if (d2 == 180 && m2 != 0)
183 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
185 if (strcasecmp(DNS_AS_STR(token), "E") == 0)
187 if (east || strcasecmp(DNS_AS_STR(token), "W") == 0)
189 s2 = strtol(DNS_AS_STR(token), &e, 10);
190 if (*e != 0 && *e != '.')
191 RETTOK(DNS_R_SYNTAX);
192 if (s2 < 0 || s2 > 59)
197 for (i = 0; i < 3; i++) {
200 if ((tmp = decvalue(*e++)) < 0)
201 RETTOK(DNS_R_SYNTAX);
209 if (decvalue(*e++) < 0)
210 RETTOK(DNS_R_SYNTAX);
212 if (*l != '\0' && callbacks != NULL) {
213 const char *file = isc_lex_getsourcename(lexer);
214 unsigned long line = isc_lex_getsourceline(lexer);
218 (*callbacks->warn)(callbacks, "%s: %s:%u: '%s' extra "
219 "precision digits ignored",
220 "dns_rdata_fromtext",
221 file, line, DNS_AS_STR(token));
225 if (d2 == 180 && s2 != 0)
231 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
233 if (strcasecmp(DNS_AS_STR(token), "E") == 0)
235 if (!east && strcasecmp(DNS_AS_STR(token), "W") != 0)
236 RETTOK(DNS_R_SYNTAX);
242 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
244 m = strtol(DNS_AS_STR(token), &e, 10);
245 if (*e != 0 && *e != '.' && *e != 'm')
246 RETTOK(DNS_R_SYNTAX);
247 if (m < -100000 || m > 42849672)
252 for (i = 0; i < 2; i++) {
253 if (*e == 0 || *e == 'm')
255 if ((tmp = decvalue(*e++)) < 0)
256 return (DNS_R_SYNTAX);
269 RETTOK(DNS_R_SYNTAX);
270 if (m == -100000 && cm != 0)
272 if (m == 42849672 && cm > 95)
277 altitude = m + 100000;
284 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
286 if (token.type == isc_tokentype_eol ||
287 token.type == isc_tokentype_eof) {
288 isc_lex_ungettoken(lexer, &token);
291 m = strtol(DNS_AS_STR(token), &e, 10);
292 if (*e != 0 && *e != '.' && *e != 'm')
293 RETTOK(DNS_R_SYNTAX);
294 if (m < 0 || m > 90000000)
299 for (i = 0; i < 2; i++) {
300 if (*e == 0 || *e == 'm')
302 if ((tmp = decvalue(*e++)) < 0)
303 RETTOK(DNS_R_SYNTAX);
313 RETTOK(DNS_R_SYNTAX);
315 * We don't just multiply out as we will overflow.
318 for (exp = 0; exp < 7; exp++)
319 if (m < poweroften[exp+1])
321 man = m / poweroften[exp];
332 size = (man << 4) + exp;
335 * Horizontal precision: optional.
337 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
339 if (token.type == isc_tokentype_eol ||
340 token.type == isc_tokentype_eof) {
341 isc_lex_ungettoken(lexer, &token);
344 m = strtol(DNS_AS_STR(token), &e, 10);
345 if (*e != 0 && *e != '.' && *e != 'm')
346 RETTOK(DNS_R_SYNTAX);
347 if (m < 0 || m > 90000000)
352 for (i = 0; i < 2; i++) {
353 if (*e == 0 || *e == 'm')
355 if ((tmp = decvalue(*e++)) < 0)
356 RETTOK(DNS_R_SYNTAX);
366 RETTOK(DNS_R_SYNTAX);
368 * We don't just multiply out as we will overflow.
371 for (exp = 0; exp < 7; exp++)
372 if (m < poweroften[exp+1])
374 man = m / poweroften[exp];
376 } else if (cm >= 10) {
383 hp = (man << 4) + exp;
386 * Vertical precision: optional.
388 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
390 if (token.type == isc_tokentype_eol ||
391 token.type == isc_tokentype_eof) {
392 isc_lex_ungettoken(lexer, &token);
395 m = strtol(DNS_AS_STR(token), &e, 10);
396 if (*e != 0 && *e != '.' && *e != 'm')
397 RETTOK(DNS_R_SYNTAX);
398 if (m < 0 || m > 90000000)
403 for (i = 0; i < 2; i++) {
404 if (*e == 0 || *e == 'm')
406 if ((tmp = decvalue(*e++)) < 0)
407 RETTOK(DNS_R_SYNTAX);
417 RETTOK(DNS_R_SYNTAX);
419 * We don't just multiply out as we will overflow.
422 for (exp = 0; exp < 7; exp++)
423 if (m < poweroften[exp+1])
425 man = m / poweroften[exp];
427 } else if (cm >= 10) {
434 vp = (man << 4) + exp;
437 RETERR(mem_tobuffer(target, &version, 1));
438 RETERR(mem_tobuffer(target, &size, 1));
439 RETERR(mem_tobuffer(target, &hp, 1));
440 RETERR(mem_tobuffer(target, &vp, 1));
442 latitude = 0x80000000 + ( d1 * 3600 + m1 * 60 ) * 1000 + s1;
444 latitude = 0x80000000 - ( d1 * 3600 + m1 * 60 ) * 1000 - s1;
445 RETERR(uint32_tobuffer(latitude, target));
448 longitude = 0x80000000 + ( d2 * 3600 + m2 * 60 ) * 1000 + s2;
450 longitude = 0x80000000 - ( d2 * 3600 + m2 * 60 ) * 1000 - s2;
451 RETERR(uint32_tobuffer(longitude, target));
453 return (uint32_tobuffer(altitude, target));
456 static inline isc_result_t
457 totext_loc(ARGS_TOTEXT) {
460 unsigned long latitude;
461 unsigned long longitude;
462 unsigned long altitude;
467 char buf[sizeof("89 59 59.999 N 179 59 59.999 E "
468 "42849672.95m 90000000m 90000000m 90000000m")];
469 char sbuf[sizeof("90000000m")];
470 char hbuf[sizeof("90000000m")];
471 char vbuf[sizeof("90000000m")];
472 unsigned char size, hp, vp;
473 unsigned long poweroften[8] = { 1, 10, 100, 1000,
474 10000, 100000, 1000000, 10000000 };
478 REQUIRE(rdata->type == dns_rdatatype_loc);
479 REQUIRE(rdata->length != 0);
481 dns_rdata_toregion(rdata, &sr);
484 return (ISC_R_NOTIMPLEMENTED);
486 REQUIRE(rdata->length == 16);
489 INSIST((size&0x0f) < 10 && (size>>4) < 10);
491 sprintf(sbuf, "%lum", (size>>4) * poweroften[(size&0x0f)-2]);
493 sprintf(sbuf, "0.%02lum", (size>>4) * poweroften[(size&0x0f)]);
495 INSIST((hp&0x0f) < 10 && (hp>>4) < 10);
497 sprintf(hbuf, "%lum", (hp>>4) * poweroften[(hp&0x0f)-2]);
499 sprintf(hbuf, "0.%02lum", (hp>>4) * poweroften[(hp&0x0f)]);
501 INSIST((vp&0x0f) < 10 && (vp>>4) < 10);
503 sprintf(vbuf, "%lum", (vp>>4) * poweroften[(vp&0x0f)-2]);
505 sprintf(vbuf, "0.%02lum", (vp>>4) * poweroften[(vp&0x0f)]);
506 isc_region_consume(&sr, 4);
508 latitude = uint32_fromregion(&sr);
509 isc_region_consume(&sr, 4);
510 if (latitude >= 0x80000000) {
512 latitude -= 0x80000000;
515 latitude = 0x80000000 - latitude;
517 fs1 = (int)(latitude % 1000);
519 s1 = (int)(latitude % 60);
521 m1 = (int)(latitude % 60);
524 INSIST(latitude <= 90U);
526 longitude = uint32_fromregion(&sr);
527 isc_region_consume(&sr, 4);
528 if (longitude >= 0x80000000) {
530 longitude -= 0x80000000;
533 longitude = 0x80000000 - longitude;
535 fs2 = (int)(longitude % 1000);
537 s2 = (int)(longitude % 60);
539 m2 = (int)(longitude % 60);
542 INSIST(longitude <= 180U);
544 altitude = uint32_fromregion(&sr);
545 isc_region_consume(&sr, 4);
546 if (altitude < 10000000U) {
548 altitude = 10000000 - altitude;
551 altitude -= 10000000;
554 sprintf(buf, "%d %d %d.%03d %s %d %d %d.%03d %s %s%ld.%02ldm %s %s %s",
555 d1, m1, s1, fs1, north ? "N" : "S",
556 d2, m2, s2, fs2, east ? "E" : "W",
557 below ? "-" : "", altitude/100, altitude % 100,
560 return (str_totext(buf, target));
563 static inline isc_result_t
564 fromwire_loc(ARGS_FROMWIRE) {
567 unsigned long latitude;
568 unsigned long longitude;
570 REQUIRE(type == dns_rdatatype_loc);
577 isc_buffer_activeregion(source, &sr);
579 return (ISC_R_UNEXPECTEDEND);
580 if (sr.base[0] != 0) {
581 /* Treat as unknown. */
582 isc_buffer_forward(source, sr.length);
583 return (mem_tobuffer(target, sr.base, sr.length));
586 return (ISC_R_UNEXPECTEDEND);
593 if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
594 return (ISC_R_RANGE);
597 * Horizontal precision.
601 if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
602 return (ISC_R_RANGE);
605 * Vertical precision.
609 if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
610 return (ISC_R_RANGE);
611 isc_region_consume(&sr, 4);
616 latitude = uint32_fromregion(&sr);
617 if (latitude < (0x80000000UL - 90 * 3600000) ||
618 latitude > (0x80000000UL + 90 * 3600000))
619 return (ISC_R_RANGE);
620 isc_region_consume(&sr, 4);
625 longitude = uint32_fromregion(&sr);
626 if (longitude < (0x80000000UL - 180 * 3600000) ||
627 longitude > (0x80000000UL + 180 * 3600000))
628 return (ISC_R_RANGE);
632 * All values possible.
635 isc_buffer_activeregion(source, &sr);
636 isc_buffer_forward(source, 16);
637 return (mem_tobuffer(target, sr.base, 16));
640 static inline isc_result_t
641 towire_loc(ARGS_TOWIRE) {
644 REQUIRE(rdata->type == dns_rdatatype_loc);
645 REQUIRE(rdata->length != 0);
647 return (mem_tobuffer(target, rdata->data, rdata->length));
651 compare_loc(ARGS_COMPARE) {
655 REQUIRE(rdata1->type == rdata2->type);
656 REQUIRE(rdata1->rdclass == rdata2->rdclass);
657 REQUIRE(rdata1->type == dns_rdatatype_loc);
658 REQUIRE(rdata1->length != 0);
659 REQUIRE(rdata2->length != 0);
661 dns_rdata_toregion(rdata1, &r1);
662 dns_rdata_toregion(rdata2, &r2);
663 return (isc_region_compare(&r1, &r2));
666 static inline isc_result_t
667 fromstruct_loc(ARGS_FROMSTRUCT) {
668 dns_rdata_loc_t *loc = source;
671 REQUIRE(type == dns_rdatatype_loc);
672 REQUIRE(source != NULL);
673 REQUIRE(loc->common.rdtype == type);
674 REQUIRE(loc->common.rdclass == rdclass);
679 if (loc->v.v0.version != 0)
680 return (ISC_R_NOTIMPLEMENTED);
681 RETERR(uint8_tobuffer(loc->v.v0.version, target));
684 if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
685 return (ISC_R_RANGE);
686 RETERR(uint8_tobuffer(loc->v.v0.size, target));
688 c = loc->v.v0.horizontal;
689 if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
690 return (ISC_R_RANGE);
691 RETERR(uint8_tobuffer(loc->v.v0.horizontal, target));
693 c = loc->v.v0.vertical;
694 if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
695 return (ISC_R_RANGE);
696 RETERR(uint8_tobuffer(loc->v.v0.vertical, target));
698 if (loc->v.v0.latitude < (0x80000000UL - 90 * 3600000) ||
699 loc->v.v0.latitude > (0x80000000UL + 90 * 3600000))
700 return (ISC_R_RANGE);
701 RETERR(uint32_tobuffer(loc->v.v0.latitude, target));
703 if (loc->v.v0.longitude < (0x80000000UL - 180 * 3600000) ||
704 loc->v.v0.longitude > (0x80000000UL + 180 * 3600000))
705 return (ISC_R_RANGE);
706 RETERR(uint32_tobuffer(loc->v.v0.longitude, target));
707 return (uint32_tobuffer(loc->v.v0.altitude, target));
710 static inline isc_result_t
711 tostruct_loc(ARGS_TOSTRUCT) {
712 dns_rdata_loc_t *loc = target;
716 REQUIRE(rdata->type == dns_rdatatype_loc);
717 REQUIRE(target != NULL);
718 REQUIRE(rdata->length != 0);
722 dns_rdata_toregion(rdata, &r);
723 version = uint8_fromregion(&r);
725 return (ISC_R_NOTIMPLEMENTED);
727 loc->common.rdclass = rdata->rdclass;
728 loc->common.rdtype = rdata->type;
729 ISC_LINK_INIT(&loc->common, link);
731 loc->v.v0.version = version;
732 isc_region_consume(&r, 1);
733 loc->v.v0.size = uint8_fromregion(&r);
734 isc_region_consume(&r, 1);
735 loc->v.v0.horizontal = uint8_fromregion(&r);
736 isc_region_consume(&r, 1);
737 loc->v.v0.vertical = uint8_fromregion(&r);
738 isc_region_consume(&r, 1);
739 loc->v.v0.latitude = uint32_fromregion(&r);
740 isc_region_consume(&r, 4);
741 loc->v.v0.longitude = uint32_fromregion(&r);
742 isc_region_consume(&r, 4);
743 loc->v.v0.altitude = uint32_fromregion(&r);
744 isc_region_consume(&r, 4);
745 return (ISC_R_SUCCESS);
749 freestruct_loc(ARGS_FREESTRUCT) {
750 dns_rdata_loc_t *loc = source;
752 REQUIRE(source != NULL);
753 REQUIRE(loc->common.rdtype == dns_rdatatype_loc);
759 static inline isc_result_t
760 additionaldata_loc(ARGS_ADDLDATA) {
761 REQUIRE(rdata->type == dns_rdatatype_loc);
767 return (ISC_R_SUCCESS);
770 static inline isc_result_t
771 digest_loc(ARGS_DIGEST) {
774 REQUIRE(rdata->type == dns_rdatatype_loc);
776 dns_rdata_toregion(rdata, &r);
778 return ((digest)(arg, &r));
781 static inline isc_boolean_t
782 checkowner_loc(ARGS_CHECKOWNER) {
784 REQUIRE(type == dns_rdatatype_loc);
794 static inline isc_boolean_t
795 checknames_loc(ARGS_CHECKNAMES) {
797 REQUIRE(rdata->type == dns_rdatatype_loc);
807 casecompare_loc(ARGS_COMPARE) {
808 return (compare_loc(rdata1, rdata2));
811 #endif /* RDATA_GENERIC_LOC_29_C */