1 /* $NetBSD: loc_29.c,v 1.4 2014/12/10 04:37:59 christos Exp $ */
4 * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: loc_29.c,v 1.50 2009/12/04 21:09:33 marka Exp */
22 /* Reviewed: Wed Mar 15 18:13:09 PST 2000 by explorer */
26 #ifndef RDATA_GENERIC_LOC_29_C
27 #define RDATA_GENERIC_LOC_29_C
29 #define RRTYPE_LOC_ATTRIBUTES (0)
31 static inline isc_result_t
32 fromtext_loc(ARGS_FROMTEXT
) {
39 unsigned char version
;
40 isc_boolean_t east
= ISC_FALSE
;
41 isc_boolean_t north
= ISC_FALSE
;
45 long poweroften
[8] = { 1, 10, 100, 1000,
46 10000, 100000, 1000000, 10000000 };
51 unsigned long latitude
;
52 unsigned long longitude
;
53 unsigned long altitude
;
67 size
= 0x12; /* 1.00m */
68 hp
= 0x16; /* 10000.00 m */
69 vp
= 0x13; /* 10.00 m */
75 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_number
,
77 if (token
.value
.as_ulong
> 90U)
79 d1
= (int)token
.value
.as_ulong
;
83 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
85 if (strcasecmp(DNS_AS_STR(token
), "N") == 0)
87 if (north
|| strcasecmp(DNS_AS_STR(token
), "S") == 0)
89 m1
= strtol(DNS_AS_STR(token
), &e
, 10);
92 if (m1
< 0 || m1
> 59)
94 if (d1
== 90 && m1
!= 0)
100 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
102 if (strcasecmp(DNS_AS_STR(token
), "N") == 0)
104 if (north
|| strcasecmp(DNS_AS_STR(token
), "S") == 0)
106 s1
= strtol(DNS_AS_STR(token
), &e
, 10);
107 if (*e
!= 0 && *e
!= '.')
108 RETTOK(DNS_R_SYNTAX
);
109 if (s1
< 0 || s1
> 59)
114 for (i
= 0; i
< 3; i
++) {
117 if ((tmp
= decvalue(*e
++)) < 0)
118 RETTOK(DNS_R_SYNTAX
);
126 if (decvalue(*e
++) < 0)
127 RETTOK(DNS_R_SYNTAX
);
129 if (*l
!= '\0' && callbacks
!= NULL
) {
130 const char *file
= isc_lex_getsourcename(lexer
);
131 unsigned long line
= isc_lex_getsourceline(lexer
);
135 (*callbacks
->warn
)(callbacks
, "%s: %s:%u: '%s' extra "
136 "precision digits ignored",
137 "dns_rdata_fromtext", file
, line
,
142 if (d1
== 90 && s1
!= 0)
148 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
150 if (strcasecmp(DNS_AS_STR(token
), "N") == 0)
152 if (!north
&& strcasecmp(DNS_AS_STR(token
), "S") != 0)
153 RETTOK(DNS_R_SYNTAX
);
159 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_number
,
161 if (token
.value
.as_ulong
> 180U)
163 d2
= (int)token
.value
.as_ulong
;
168 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
170 if (strcasecmp(DNS_AS_STR(token
), "E") == 0)
172 if (east
|| strcasecmp(DNS_AS_STR(token
), "W") == 0)
174 m2
= strtol(DNS_AS_STR(token
), &e
, 10);
176 RETTOK(DNS_R_SYNTAX
);
177 if (m2
< 0 || m2
> 59)
179 if (d2
== 180 && m2
!= 0)
185 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
187 if (strcasecmp(DNS_AS_STR(token
), "E") == 0)
189 if (east
|| strcasecmp(DNS_AS_STR(token
), "W") == 0)
191 s2
= strtol(DNS_AS_STR(token
), &e
, 10);
192 if (*e
!= 0 && *e
!= '.')
193 RETTOK(DNS_R_SYNTAX
);
194 if (s2
< 0 || s2
> 59)
199 for (i
= 0; i
< 3; i
++) {
202 if ((tmp
= decvalue(*e
++)) < 0)
203 RETTOK(DNS_R_SYNTAX
);
211 if (decvalue(*e
++) < 0)
212 RETTOK(DNS_R_SYNTAX
);
214 if (*l
!= '\0' && callbacks
!= NULL
) {
215 const char *file
= isc_lex_getsourcename(lexer
);
216 unsigned long line
= isc_lex_getsourceline(lexer
);
220 (*callbacks
->warn
)(callbacks
, "%s: %s:%u: '%s' extra "
221 "precision digits ignored",
222 "dns_rdata_fromtext",
223 file
, line
, DNS_AS_STR(token
));
227 if (d2
== 180 && s2
!= 0)
233 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
235 if (strcasecmp(DNS_AS_STR(token
), "E") == 0)
237 if (!east
&& strcasecmp(DNS_AS_STR(token
), "W") != 0)
238 RETTOK(DNS_R_SYNTAX
);
244 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
246 m
= strtol(DNS_AS_STR(token
), &e
, 10);
247 if (*e
!= 0 && *e
!= '.' && *e
!= 'm')
248 RETTOK(DNS_R_SYNTAX
);
249 if (m
< -100000 || m
> 42849672)
254 for (i
= 0; i
< 2; i
++) {
255 if (*e
== 0 || *e
== 'm')
257 if ((tmp
= decvalue(*e
++)) < 0)
258 return (DNS_R_SYNTAX
);
271 RETTOK(DNS_R_SYNTAX
);
272 if (m
== -100000 && cm
!= 0)
274 if (m
== 42849672 && cm
> 95)
279 altitude
= m
+ 100000;
286 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
288 if (token
.type
== isc_tokentype_eol
||
289 token
.type
== isc_tokentype_eof
) {
290 isc_lex_ungettoken(lexer
, &token
);
293 m
= strtol(DNS_AS_STR(token
), &e
, 10);
294 if (*e
!= 0 && *e
!= '.' && *e
!= 'm')
295 RETTOK(DNS_R_SYNTAX
);
296 if (m
< 0 || m
> 90000000)
301 for (i
= 0; i
< 2; i
++) {
302 if (*e
== 0 || *e
== 'm')
304 if ((tmp
= decvalue(*e
++)) < 0)
305 RETTOK(DNS_R_SYNTAX
);
315 RETTOK(DNS_R_SYNTAX
);
317 * We don't just multiply out as we will overflow.
320 for (exp
= 0; exp
< 7; exp
++)
321 if (m
< poweroften
[exp
+1])
323 man
= m
/ poweroften
[exp
];
334 size
= (man
<< 4) + exp
;
337 * Horizontal precision: optional.
339 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
341 if (token
.type
== isc_tokentype_eol
||
342 token
.type
== isc_tokentype_eof
) {
343 isc_lex_ungettoken(lexer
, &token
);
346 m
= strtol(DNS_AS_STR(token
), &e
, 10);
347 if (*e
!= 0 && *e
!= '.' && *e
!= 'm')
348 RETTOK(DNS_R_SYNTAX
);
349 if (m
< 0 || m
> 90000000)
354 for (i
= 0; i
< 2; i
++) {
355 if (*e
== 0 || *e
== 'm')
357 if ((tmp
= decvalue(*e
++)) < 0)
358 RETTOK(DNS_R_SYNTAX
);
368 RETTOK(DNS_R_SYNTAX
);
370 * We don't just multiply out as we will overflow.
373 for (exp
= 0; exp
< 7; exp
++)
374 if (m
< poweroften
[exp
+1])
376 man
= m
/ poweroften
[exp
];
378 } else if (cm
>= 10) {
385 hp
= (man
<< 4) + exp
;
388 * Vertical precision: optional.
390 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
392 if (token
.type
== isc_tokentype_eol
||
393 token
.type
== isc_tokentype_eof
) {
394 isc_lex_ungettoken(lexer
, &token
);
397 m
= strtol(DNS_AS_STR(token
), &e
, 10);
398 if (*e
!= 0 && *e
!= '.' && *e
!= 'm')
399 RETTOK(DNS_R_SYNTAX
);
400 if (m
< 0 || m
> 90000000)
405 for (i
= 0; i
< 2; i
++) {
406 if (*e
== 0 || *e
== 'm')
408 if ((tmp
= decvalue(*e
++)) < 0)
409 RETTOK(DNS_R_SYNTAX
);
419 RETTOK(DNS_R_SYNTAX
);
421 * We don't just multiply out as we will overflow.
424 for (exp
= 0; exp
< 7; exp
++)
425 if (m
< poweroften
[exp
+1])
427 man
= m
/ poweroften
[exp
];
429 } else if (cm
>= 10) {
436 vp
= (man
<< 4) + exp
;
439 RETERR(mem_tobuffer(target
, &version
, 1));
440 RETERR(mem_tobuffer(target
, &size
, 1));
441 RETERR(mem_tobuffer(target
, &hp
, 1));
442 RETERR(mem_tobuffer(target
, &vp
, 1));
444 latitude
= 0x80000000 + ( d1
* 3600 + m1
* 60 ) * 1000 + s1
;
446 latitude
= 0x80000000 - ( d1
* 3600 + m1
* 60 ) * 1000 - s1
;
447 RETERR(uint32_tobuffer(latitude
, target
));
450 longitude
= 0x80000000 + ( d2
* 3600 + m2
* 60 ) * 1000 + s2
;
452 longitude
= 0x80000000 - ( d2
* 3600 + m2
* 60 ) * 1000 - s2
;
453 RETERR(uint32_tobuffer(longitude
, target
));
455 return (uint32_tobuffer(altitude
, target
));
458 static inline isc_result_t
459 totext_loc(ARGS_TOTEXT
) {
462 unsigned long latitude
;
463 unsigned long longitude
;
464 unsigned long altitude
;
469 char buf
[sizeof("89 59 59.999 N 179 59 59.999 E "
470 "42849672.95m 90000000m 90000000m 90000000m")];
471 char sbuf
[sizeof("90000000m")];
472 char hbuf
[sizeof("90000000m")];
473 char vbuf
[sizeof("90000000m")];
474 unsigned char size
, hp
, vp
;
475 unsigned long poweroften
[8] = { 1, 10, 100, 1000,
476 10000, 100000, 1000000, 10000000 };
480 REQUIRE(rdata
->type
== 29);
481 REQUIRE(rdata
->length
!= 0);
483 dns_rdata_toregion(rdata
, &sr
);
485 /* version = sr.base[0]; */
487 INSIST((size
&0x0f) < 10 && (size
>>4) < 10);
489 sprintf(sbuf
, "%lum", (size
>>4) * poweroften
[(size
&0x0f)-2]);
491 sprintf(sbuf
, "0.%02lum", (size
>>4) * poweroften
[(size
&0x0f)]);
493 INSIST((hp
&0x0f) < 10 && (hp
>>4) < 10);
495 sprintf(hbuf
, "%lum", (hp
>>4) * poweroften
[(hp
&0x0f)-2]);
497 sprintf(hbuf
, "0.%02lum", (hp
>>4) * poweroften
[(hp
&0x0f)]);
499 INSIST((vp
&0x0f) < 10 && (vp
>>4) < 10);
501 sprintf(vbuf
, "%lum", (vp
>>4) * poweroften
[(vp
&0x0f)-2]);
503 sprintf(vbuf
, "0.%02lum", (vp
>>4) * poweroften
[(vp
&0x0f)]);
504 isc_region_consume(&sr
, 4);
506 latitude
= uint32_fromregion(&sr
);
507 isc_region_consume(&sr
, 4);
508 if (latitude
>= 0x80000000) {
510 latitude
-= 0x80000000;
513 latitude
= 0x80000000 - latitude
;
515 fs1
= (int)(latitude
% 1000);
517 s1
= (int)(latitude
% 60);
519 m1
= (int)(latitude
% 60);
522 INSIST(latitude
<= 90U);
524 longitude
= uint32_fromregion(&sr
);
525 isc_region_consume(&sr
, 4);
526 if (longitude
>= 0x80000000) {
528 longitude
-= 0x80000000;
531 longitude
= 0x80000000 - longitude
;
533 fs2
= (int)(longitude
% 1000);
535 s2
= (int)(longitude
% 60);
537 m2
= (int)(longitude
% 60);
540 INSIST(longitude
<= 180U);
542 altitude
= uint32_fromregion(&sr
);
543 isc_region_consume(&sr
, 4);
544 if (altitude
< 10000000U) {
546 altitude
= 10000000 - altitude
;
549 altitude
-= 10000000;
552 sprintf(buf
, "%d %d %d.%03d %s %d %d %d.%03d %s %s%ld.%02ldm %s %s %s",
553 d1
, m1
, s1
, fs1
, north
? "N" : "S",
554 d2
, m2
, s2
, fs2
, east
? "E" : "W",
555 below
? "-" : "", altitude
/100, altitude
% 100,
558 return (str_totext(buf
, target
));
561 static inline isc_result_t
562 fromwire_loc(ARGS_FROMWIRE
) {
565 unsigned long latitude
;
566 unsigned long longitude
;
575 isc_buffer_activeregion(source
, &sr
);
577 return (ISC_R_UNEXPECTEDEND
);
579 return (ISC_R_NOTIMPLEMENTED
);
581 return (ISC_R_UNEXPECTEDEND
);
588 if ((c
&0xf) > 9 || ((c
>>4)&0xf) > 9 || ((c
>>4)&0xf) == 0)
589 return (ISC_R_RANGE
);
592 * Horizontal precision.
596 if ((c
&0xf) > 9 || ((c
>>4)&0xf) > 9 || ((c
>>4)&0xf) == 0)
597 return (ISC_R_RANGE
);
600 * Vertical precision.
604 if ((c
&0xf) > 9 || ((c
>>4)&0xf) > 9 || ((c
>>4)&0xf) == 0)
605 return (ISC_R_RANGE
);
606 isc_region_consume(&sr
, 4);
611 latitude
= uint32_fromregion(&sr
);
612 if (latitude
< (0x80000000UL
- 90 * 3600000) ||
613 latitude
> (0x80000000UL
+ 90 * 3600000))
614 return (ISC_R_RANGE
);
615 isc_region_consume(&sr
, 4);
620 longitude
= uint32_fromregion(&sr
);
621 if (longitude
< (0x80000000UL
- 180 * 3600000) ||
622 longitude
> (0x80000000UL
+ 180 * 3600000))
623 return (ISC_R_RANGE
);
627 * All values possible.
630 isc_buffer_activeregion(source
, &sr
);
631 isc_buffer_forward(source
, 16);
632 return (mem_tobuffer(target
, sr
.base
, 16));
635 static inline isc_result_t
636 towire_loc(ARGS_TOWIRE
) {
639 REQUIRE(rdata
->type
== 29);
640 REQUIRE(rdata
->length
!= 0);
642 return (mem_tobuffer(target
, rdata
->data
, rdata
->length
));
646 compare_loc(ARGS_COMPARE
) {
650 REQUIRE(rdata1
->type
== rdata2
->type
);
651 REQUIRE(rdata1
->rdclass
== rdata2
->rdclass
);
652 REQUIRE(rdata1
->type
== 29);
653 REQUIRE(rdata1
->length
!= 0);
654 REQUIRE(rdata2
->length
!= 0);
656 dns_rdata_toregion(rdata1
, &r1
);
657 dns_rdata_toregion(rdata2
, &r2
);
658 return (isc_region_compare(&r1
, &r2
));
661 static inline isc_result_t
662 fromstruct_loc(ARGS_FROMSTRUCT
) {
663 dns_rdata_loc_t
*loc
= source
;
667 REQUIRE(source
!= NULL
);
668 REQUIRE(loc
->common
.rdtype
== type
);
669 REQUIRE(loc
->common
.rdclass
== rdclass
);
674 if (loc
->v
.v0
.version
!= 0)
675 return (ISC_R_NOTIMPLEMENTED
);
676 RETERR(uint8_tobuffer(loc
->v
.v0
.version
, target
));
679 if ((c
&0xf) > 9 || ((c
>>4)&0xf) > 9 || ((c
>>4)&0xf) == 0)
680 return (ISC_R_RANGE
);
681 RETERR(uint8_tobuffer(loc
->v
.v0
.size
, target
));
683 c
= loc
->v
.v0
.horizontal
;
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
.horizontal
, target
));
688 c
= loc
->v
.v0
.vertical
;
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
.vertical
, target
));
693 if (loc
->v
.v0
.latitude
< (0x80000000UL
- 90 * 3600000) ||
694 loc
->v
.v0
.latitude
> (0x80000000UL
+ 90 * 3600000))
695 return (ISC_R_RANGE
);
696 RETERR(uint32_tobuffer(loc
->v
.v0
.latitude
, target
));
698 if (loc
->v
.v0
.longitude
< (0x80000000UL
- 180 * 3600000) ||
699 loc
->v
.v0
.longitude
> (0x80000000UL
+ 180 * 3600000))
700 return (ISC_R_RANGE
);
701 RETERR(uint32_tobuffer(loc
->v
.v0
.longitude
, target
));
702 return (uint32_tobuffer(loc
->v
.v0
.altitude
, target
));
705 static inline isc_result_t
706 tostruct_loc(ARGS_TOSTRUCT
) {
707 dns_rdata_loc_t
*loc
= target
;
711 REQUIRE(rdata
->type
== 29);
712 REQUIRE(target
!= NULL
);
713 REQUIRE(rdata
->length
!= 0);
717 dns_rdata_toregion(rdata
, &r
);
718 version
= uint8_fromregion(&r
);
720 return (ISC_R_NOTIMPLEMENTED
);
722 loc
->common
.rdclass
= rdata
->rdclass
;
723 loc
->common
.rdtype
= rdata
->type
;
724 ISC_LINK_INIT(&loc
->common
, link
);
726 loc
->v
.v0
.version
= version
;
727 isc_region_consume(&r
, 1);
728 loc
->v
.v0
.size
= uint8_fromregion(&r
);
729 isc_region_consume(&r
, 1);
730 loc
->v
.v0
.horizontal
= uint8_fromregion(&r
);
731 isc_region_consume(&r
, 1);
732 loc
->v
.v0
.vertical
= uint8_fromregion(&r
);
733 isc_region_consume(&r
, 1);
734 loc
->v
.v0
.latitude
= uint32_fromregion(&r
);
735 isc_region_consume(&r
, 4);
736 loc
->v
.v0
.longitude
= uint32_fromregion(&r
);
737 isc_region_consume(&r
, 4);
738 loc
->v
.v0
.altitude
= uint32_fromregion(&r
);
739 isc_region_consume(&r
, 4);
740 return (ISC_R_SUCCESS
);
744 freestruct_loc(ARGS_FREESTRUCT
) {
745 dns_rdata_loc_t
*loc
= source
;
747 REQUIRE(source
!= NULL
);
748 REQUIRE(loc
->common
.rdtype
== 29);
754 static inline isc_result_t
755 additionaldata_loc(ARGS_ADDLDATA
) {
756 REQUIRE(rdata
->type
== 29);
762 return (ISC_R_SUCCESS
);
765 static inline isc_result_t
766 digest_loc(ARGS_DIGEST
) {
769 REQUIRE(rdata
->type
== 29);
771 dns_rdata_toregion(rdata
, &r
);
773 return ((digest
)(arg
, &r
));
776 static inline isc_boolean_t
777 checkowner_loc(ARGS_CHECKOWNER
) {
789 static inline isc_boolean_t
790 checknames_loc(ARGS_CHECKNAMES
) {
792 REQUIRE(rdata
->type
== 29);
802 casecompare_loc(ARGS_COMPARE
) {
803 return (compare_loc(rdata1
, rdata2
));
806 #endif /* RDATA_GENERIC_LOC_29_C */