2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and 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.30.2.5 2004/03/09 06:11:29 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
;
66 size
= 0x12; /* 1.00m */
67 hp
= 0x16; /* 10000.00 m */
68 vp
= 0x13; /* 10.00 m */
74 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_number
,
76 if (token
.value
.as_ulong
> 90U)
78 d1
= (int)token
.value
.as_ulong
;
82 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
84 if (strcasecmp(token
.value
.as_pointer
, "N") == 0)
86 if (north
|| strcasecmp(token
.value
.as_pointer
, "S") == 0)
88 m1
= strtol(token
.value
.as_pointer
, &e
, 10);
91 if (m1
< 0 || m1
> 59)
93 if (d1
== 90 && m1
!= 0)
99 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
101 if (strcasecmp(token
.value
.as_pointer
, "N") == 0)
103 if (north
|| strcasecmp(token
.value
.as_pointer
, "S") == 0)
105 s1
= strtol(token
.value
.as_pointer
, &e
, 10);
106 if (*e
!= 0 && *e
!= '.')
107 RETTOK(DNS_R_SYNTAX
);
108 if (s1
< 0 || s1
> 59)
112 for (i
= 0; i
< 3 ; i
++) {
115 if ((tmp
= decvalue(*e
++)) < 0)
116 RETTOK(DNS_R_SYNTAX
);
123 RETTOK(DNS_R_SYNTAX
);
126 if (d1
== 90 && s1
!= 0)
132 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
134 if (strcasecmp(token
.value
.as_pointer
, "N") == 0)
136 if (!north
&& strcasecmp(token
.value
.as_pointer
, "S") != 0)
137 RETTOK(DNS_R_SYNTAX
);
143 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_number
,
145 if (token
.value
.as_ulong
> 180U)
147 d2
= (int)token
.value
.as_ulong
;
152 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
154 if (strcasecmp(token
.value
.as_pointer
, "E") == 0)
156 if (east
|| strcasecmp(token
.value
.as_pointer
, "W") == 0)
158 m2
= strtol(token
.value
.as_pointer
, &e
, 10);
160 RETTOK(DNS_R_SYNTAX
);
161 if (m2
< 0 || m2
> 59)
163 if (d2
== 180 && m2
!= 0)
169 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
171 if (strcasecmp(token
.value
.as_pointer
, "E") == 0)
173 if (east
|| strcasecmp(token
.value
.as_pointer
, "W") == 0)
175 s2
= strtol(token
.value
.as_pointer
, &e
, 10);
176 if (*e
!= 0 && *e
!= '.')
177 RETTOK(DNS_R_SYNTAX
);
178 if (s2
< 0 || s2
> 59)
182 for (i
= 0; i
< 3 ; i
++) {
185 if ((tmp
= decvalue(*e
++)) < 0)
186 RETTOK(DNS_R_SYNTAX
);
193 RETTOK(DNS_R_SYNTAX
);
196 if (d2
== 180 && s2
!= 0)
202 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
204 if (strcasecmp(token
.value
.as_pointer
, "E") == 0)
206 if (!east
&& strcasecmp(token
.value
.as_pointer
, "W") != 0)
207 RETTOK(DNS_R_SYNTAX
);
213 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
215 m
= strtol(token
.value
.as_pointer
, &e
, 10);
216 if (*e
!= 0 && *e
!= '.' && *e
!= 'm')
217 RETTOK(DNS_R_SYNTAX
);
218 if (m
< -100000 || m
> 42849672)
223 for (i
= 0; i
< 2 ; i
++) {
224 if (*e
== 0 || *e
== 'm')
226 if ((tmp
= decvalue(*e
++)) < 0)
227 return (DNS_R_SYNTAX
);
240 RETTOK(DNS_R_SYNTAX
);
241 if (m
== -100000 && cm
!= 0)
243 if (m
== 42849672 && cm
> 95)
248 altitude
= m
+ 100000;
255 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
257 if (token
.type
== isc_tokentype_eol
||
258 token
.type
== isc_tokentype_eof
) {
259 isc_lex_ungettoken(lexer
, &token
);
262 m
= strtol(token
.value
.as_pointer
, &e
, 10);
263 if (*e
!= 0 && *e
!= '.' && *e
!= 'm')
264 RETTOK(DNS_R_SYNTAX
);
265 if (m
< 0 || m
> 90000000)
270 for (i
= 0; i
< 2 ; i
++) {
271 if (*e
== 0 || *e
== 'm')
273 if ((tmp
= decvalue(*e
++)) < 0)
274 RETTOK(DNS_R_SYNTAX
);
284 RETTOK(DNS_R_SYNTAX
);
286 * We don't just multiply out as we will overflow.
289 for (exp
= 0 ; exp
< 7 ; exp
++)
290 if (m
< poweroften
[exp
+1])
292 man
= m
/ poweroften
[exp
];
303 size
= (man
<< 4) + exp
;
306 * Horizontal precision: optional.
308 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
310 if (token
.type
== isc_tokentype_eol
||
311 token
.type
== isc_tokentype_eof
) {
312 isc_lex_ungettoken(lexer
, &token
);
315 m
= strtol(token
.value
.as_pointer
, &e
, 10);
316 if (*e
!= 0 && *e
!= '.' && *e
!= 'm')
317 RETTOK(DNS_R_SYNTAX
);
318 if (m
< 0 || m
> 90000000)
323 for (i
= 0; i
< 2 ; i
++) {
324 if (*e
== 0 || *e
== 'm')
326 if ((tmp
= decvalue(*e
++)) < 0)
327 RETTOK(DNS_R_SYNTAX
);
337 RETTOK(DNS_R_SYNTAX
);
339 * We don't just multiply out as we will overflow.
342 for (exp
= 0 ; exp
< 7 ; exp
++)
343 if (m
< poweroften
[exp
+1])
345 man
= m
/ poweroften
[exp
];
347 } else if (cm
>= 10) {
354 hp
= (man
<< 4) + exp
;
357 * Vertical precision: optional.
359 RETERR(isc_lex_getmastertoken(lexer
, &token
, isc_tokentype_string
,
361 if (token
.type
== isc_tokentype_eol
||
362 token
.type
== isc_tokentype_eof
) {
363 isc_lex_ungettoken(lexer
, &token
);
366 m
= strtol(token
.value
.as_pointer
, &e
, 10);
367 if (*e
!= 0 && *e
!= '.' && *e
!= 'm')
368 RETTOK(DNS_R_SYNTAX
);
369 if (m
< 0 || m
> 90000000)
374 for (i
= 0; i
< 2 ; i
++) {
375 if (*e
== 0 || *e
== 'm')
377 if ((tmp
= decvalue(*e
++)) < 0)
378 RETTOK(DNS_R_SYNTAX
);
388 RETTOK(DNS_R_SYNTAX
);
390 * We don't just multiply out as we will overflow.
393 for (exp
= 0 ; exp
< 7 ; exp
++)
394 if (m
< poweroften
[exp
+1])
396 man
= m
/ poweroften
[exp
];
398 } else if (cm
>= 10) {
405 vp
= (man
<< 4) + exp
;
408 RETERR(mem_tobuffer(target
, &version
, 1));
409 RETERR(mem_tobuffer(target
, &size
, 1));
410 RETERR(mem_tobuffer(target
, &hp
, 1));
411 RETERR(mem_tobuffer(target
, &vp
, 1));
413 latitude
= 0x80000000 + ( d1
* 3600 + m1
* 60 ) * 1000 + s1
;
415 latitude
= 0x80000000 - ( d1
* 3600 + m1
* 60 ) * 1000 - s1
;
416 RETERR(uint32_tobuffer(latitude
, target
));
419 longitude
= 0x80000000 + ( d2
* 3600 + m2
* 60 ) * 1000 + s2
;
421 longitude
= 0x80000000 - ( d2
* 3600 + m2
* 60 ) * 1000 - s2
;
422 RETERR(uint32_tobuffer(longitude
, target
));
424 return (uint32_tobuffer(altitude
, target
));
427 static inline isc_result_t
428 totext_loc(ARGS_TOTEXT
) {
431 unsigned long latitude
;
432 unsigned long longitude
;
433 unsigned long altitude
;
438 char buf
[sizeof("89 59 59.999 N 179 59 59.999 E "
439 "42849672.95m 90000000m 90000000m 90000000m")];
440 char sbuf
[sizeof("90000000m")];
441 char hbuf
[sizeof("90000000m")];
442 char vbuf
[sizeof("90000000m")];
443 unsigned char size
, hp
, vp
;
444 unsigned long poweroften
[8] = { 1, 10, 100, 1000,
445 10000, 100000, 1000000, 10000000 };
449 REQUIRE(rdata
->type
== 29);
450 REQUIRE(rdata
->length
!= 0);
452 dns_rdata_toregion(rdata
, &sr
);
454 /* version = sr.base[0]; */
457 sprintf(sbuf
, "%lum", (size
>>4) * poweroften
[(size
&0x0f)-2]);
459 sprintf(sbuf
, "0.%02lum", (size
>>4) * poweroften
[(size
&0x0f)]);
462 sprintf(hbuf
, "%lum", (hp
>>4) * poweroften
[(hp
&0x0f)-2]);
464 sprintf(hbuf
, "0.%02lum", (hp
>>4) * poweroften
[(hp
&0x0f)]);
467 sprintf(vbuf
, "%lum", (vp
>>4) * poweroften
[(vp
&0x0f)-2]);
469 sprintf(vbuf
, "0.%02lum", (vp
>>4) * poweroften
[(vp
&0x0f)]);
470 isc_region_consume(&sr
, 4);
472 latitude
= uint32_fromregion(&sr
);
473 isc_region_consume(&sr
, 4);
474 if (latitude
>= 0x80000000) {
476 latitude
-= 0x80000000;
479 latitude
= 0x80000000 - latitude
;
481 fs1
= (int)(latitude
% 1000);
483 s1
= (int)(latitude
% 60);
485 m1
= (int)(latitude
% 60);
489 longitude
= uint32_fromregion(&sr
);
490 isc_region_consume(&sr
, 4);
491 if (longitude
>= 0x80000000) {
493 longitude
-= 0x80000000;
496 longitude
= 0x80000000 - longitude
;
498 fs2
= (int)(longitude
% 1000);
500 s2
= (int)(longitude
% 60);
502 m2
= (int)(longitude
% 60);
506 altitude
= uint32_fromregion(&sr
);
507 isc_region_consume(&sr
, 4);
508 if (altitude
< 10000000U) {
510 altitude
= 10000000 - altitude
;
513 altitude
-= 10000000;
516 sprintf(buf
, "%d %d %d.%03d %s %d %d %d.%03d %s %s%ld.%02ldm %s %s %s",
517 d1
, m1
, s1
, fs1
, north
? "N" : "S",
518 d2
, m2
, s2
, fs2
, east
? "E" : "W",
519 below
? "-" : "", altitude
/100, altitude
% 100,
522 return (str_totext(buf
, target
));
525 static inline isc_result_t
526 fromwire_loc(ARGS_FROMWIRE
) {
529 unsigned long latitude
;
530 unsigned long longitude
;
539 isc_buffer_activeregion(source
, &sr
);
541 return (ISC_R_UNEXPECTEDEND
);
543 return (ISC_R_NOTIMPLEMENTED
);
545 return (ISC_R_UNEXPECTEDEND
);
552 if ((c
&0xf) > 9 || ((c
>>4)&0xf) > 9 || ((c
>>4)&0xf) == 0)
553 return (ISC_R_RANGE
);
556 * Horizontal precision.
560 if ((c
&0xf) > 9 || ((c
>>4)&0xf) > 9 || ((c
>>4)&0xf) == 0)
561 return (ISC_R_RANGE
);
564 * Vertical precision.
568 if ((c
&0xf) > 9 || ((c
>>4)&0xf) > 9 || ((c
>>4)&0xf) == 0)
569 return (ISC_R_RANGE
);
570 isc_region_consume(&sr
, 4);
575 latitude
= uint32_fromregion(&sr
);
576 if (latitude
< (0x80000000UL
- 90 * 3600000) ||
577 latitude
> (0x80000000UL
+ 90 * 3600000))
578 return (ISC_R_RANGE
);
579 isc_region_consume(&sr
, 4);
584 longitude
= uint32_fromregion(&sr
);
585 if (longitude
< (0x80000000UL
- 180 * 3600000) ||
586 longitude
> (0x80000000UL
+ 180 * 3600000))
587 return (ISC_R_RANGE
);
591 * All values possible.
594 isc_buffer_activeregion(source
, &sr
);
595 isc_buffer_forward(source
, 16);
596 return (mem_tobuffer(target
, sr
.base
, 16));
599 static inline isc_result_t
600 towire_loc(ARGS_TOWIRE
) {
603 REQUIRE(rdata
->type
== 29);
604 REQUIRE(rdata
->length
!= 0);
606 return (mem_tobuffer(target
, rdata
->data
, rdata
->length
));
610 compare_loc(ARGS_COMPARE
) {
614 REQUIRE(rdata1
->type
== rdata2
->type
);
615 REQUIRE(rdata1
->rdclass
== rdata2
->rdclass
);
616 REQUIRE(rdata1
->type
== 29);
617 REQUIRE(rdata1
->length
!= 0);
618 REQUIRE(rdata2
->length
!= 0);
620 dns_rdata_toregion(rdata1
, &r1
);
621 dns_rdata_toregion(rdata2
, &r2
);
622 return (compare_region(&r1
, &r2
));
625 static inline isc_result_t
626 fromstruct_loc(ARGS_FROMSTRUCT
) {
627 dns_rdata_loc_t
*loc
= source
;
631 REQUIRE(source
!= NULL
);
632 REQUIRE(loc
->common
.rdtype
== type
);
633 REQUIRE(loc
->common
.rdclass
== rdclass
);
638 if (loc
->v
.v0
.version
!= 0)
639 return (ISC_R_NOTIMPLEMENTED
);
640 RETERR(uint8_tobuffer(loc
->v
.v0
.version
, target
));
643 if ((c
&0xf) > 9 || ((c
>>4)&0xf) > 9 || ((c
>>4)&0xf) == 0)
644 return (ISC_R_RANGE
);
645 RETERR(uint8_tobuffer(loc
->v
.v0
.size
, target
));
647 c
= loc
->v
.v0
.horizontal
;
648 if ((c
&0xf) > 9 || ((c
>>4)&0xf) > 9 || ((c
>>4)&0xf) == 0)
649 return (ISC_R_RANGE
);
650 RETERR(uint8_tobuffer(loc
->v
.v0
.horizontal
, target
));
652 c
= loc
->v
.v0
.vertical
;
653 if ((c
&0xf) > 9 || ((c
>>4)&0xf) > 9 || ((c
>>4)&0xf) == 0)
654 return (ISC_R_RANGE
);
655 RETERR(uint8_tobuffer(loc
->v
.v0
.vertical
, target
));
657 if (loc
->v
.v0
.latitude
< (0x80000000UL
- 90 * 3600000) ||
658 loc
->v
.v0
.latitude
> (0x80000000UL
+ 90 * 3600000))
659 return (ISC_R_RANGE
);
660 RETERR(uint32_tobuffer(loc
->v
.v0
.latitude
, target
));
662 if (loc
->v
.v0
.longitude
< (0x80000000UL
- 180 * 3600000) ||
663 loc
->v
.v0
.longitude
> (0x80000000UL
+ 180 * 3600000))
664 return (ISC_R_RANGE
);
665 RETERR(uint32_tobuffer(loc
->v
.v0
.longitude
, target
));
666 return (uint32_tobuffer(loc
->v
.v0
.altitude
, target
));
669 static inline isc_result_t
670 tostruct_loc(ARGS_TOSTRUCT
) {
671 dns_rdata_loc_t
*loc
= target
;
675 REQUIRE(rdata
->type
== 29);
676 REQUIRE(target
!= NULL
);
677 REQUIRE(rdata
->length
!= 0);
681 dns_rdata_toregion(rdata
, &r
);
682 version
= uint8_fromregion(&r
);
684 return (ISC_R_NOTIMPLEMENTED
);
686 loc
->common
.rdclass
= rdata
->rdclass
;
687 loc
->common
.rdtype
= rdata
->type
;
688 ISC_LINK_INIT(&loc
->common
, link
);
690 loc
->v
.v0
.version
= version
;
691 isc_region_consume(&r
, 1);
692 loc
->v
.v0
.size
= uint8_fromregion(&r
);
693 isc_region_consume(&r
, 1);
694 loc
->v
.v0
.horizontal
= uint8_fromregion(&r
);
695 isc_region_consume(&r
, 1);
696 loc
->v
.v0
.vertical
= uint8_fromregion(&r
);
697 isc_region_consume(&r
, 1);
698 loc
->v
.v0
.latitude
= uint32_fromregion(&r
);
699 isc_region_consume(&r
, 4);
700 loc
->v
.v0
.longitude
= uint32_fromregion(&r
);
701 isc_region_consume(&r
, 4);
702 loc
->v
.v0
.altitude
= uint32_fromregion(&r
);
703 isc_region_consume(&r
, 4);
704 return (ISC_R_SUCCESS
);
708 freestruct_loc(ARGS_FREESTRUCT
) {
709 dns_rdata_loc_t
*loc
= source
;
711 REQUIRE(source
!= NULL
);
712 REQUIRE(loc
->common
.rdtype
== 29);
718 static inline isc_result_t
719 additionaldata_loc(ARGS_ADDLDATA
) {
720 REQUIRE(rdata
->type
== 29);
726 return (ISC_R_SUCCESS
);
729 static inline isc_result_t
730 digest_loc(ARGS_DIGEST
) {
733 REQUIRE(rdata
->type
== 29);
735 dns_rdata_toregion(rdata
, &r
);
737 return ((digest
)(arg
, &r
));
740 #endif /* RDATA_GENERIC_LOC_29_C */