2 * Copyright (C) 2004, 2005, 2007, 2009 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.45.128.4 2009/02/17 05:54:41 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
;
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
== 29);
479 REQUIRE(rdata
->length
!= 0);
481 dns_rdata_toregion(rdata
, &sr
);
483 /* version = sr.base[0]; */
485 INSIST((size
&0x0f) < 10 && (size
>>4) < 10);
487 sprintf(sbuf
, "%lum", (size
>>4) * poweroften
[(size
&0x0f)-2]);
489 sprintf(sbuf
, "0.%02lum", (size
>>4) * poweroften
[(size
&0x0f)]);
491 INSIST((hp
&0x0f) < 10 && (hp
>>4) < 10);
493 sprintf(hbuf
, "%lum", (hp
>>4) * poweroften
[(hp
&0x0f)-2]);
495 sprintf(hbuf
, "0.%02lum", (hp
>>4) * poweroften
[(hp
&0x0f)]);
497 INSIST((vp
&0x0f) < 10 && (vp
>>4) < 10);
499 sprintf(vbuf
, "%lum", (vp
>>4) * poweroften
[(vp
&0x0f)-2]);
501 sprintf(vbuf
, "0.%02lum", (vp
>>4) * poweroften
[(vp
&0x0f)]);
502 isc_region_consume(&sr
, 4);
504 latitude
= uint32_fromregion(&sr
);
505 isc_region_consume(&sr
, 4);
506 if (latitude
>= 0x80000000) {
508 latitude
-= 0x80000000;
511 latitude
= 0x80000000 - latitude
;
513 fs1
= (int)(latitude
% 1000);
515 s1
= (int)(latitude
% 60);
517 m1
= (int)(latitude
% 60);
520 INSIST(latitude
<= 90U);
522 longitude
= uint32_fromregion(&sr
);
523 isc_region_consume(&sr
, 4);
524 if (longitude
>= 0x80000000) {
526 longitude
-= 0x80000000;
529 longitude
= 0x80000000 - longitude
;
531 fs2
= (int)(longitude
% 1000);
533 s2
= (int)(longitude
% 60);
535 m2
= (int)(longitude
% 60);
538 INSIST(longitude
<= 180U);
540 altitude
= uint32_fromregion(&sr
);
541 isc_region_consume(&sr
, 4);
542 if (altitude
< 10000000U) {
544 altitude
= 10000000 - altitude
;
547 altitude
-= 10000000;
550 sprintf(buf
, "%d %d %d.%03d %s %d %d %d.%03d %s %s%ld.%02ldm %s %s %s",
551 d1
, m1
, s1
, fs1
, north
? "N" : "S",
552 d2
, m2
, s2
, fs2
, east
? "E" : "W",
553 below
? "-" : "", altitude
/100, altitude
% 100,
556 return (str_totext(buf
, target
));
559 static inline isc_result_t
560 fromwire_loc(ARGS_FROMWIRE
) {
563 unsigned long latitude
;
564 unsigned long longitude
;
573 isc_buffer_activeregion(source
, &sr
);
575 return (ISC_R_UNEXPECTEDEND
);
577 return (ISC_R_NOTIMPLEMENTED
);
579 return (ISC_R_UNEXPECTEDEND
);
586 if ((c
&0xf) > 9 || ((c
>>4)&0xf) > 9 || ((c
>>4)&0xf) == 0)
587 return (ISC_R_RANGE
);
590 * Horizontal precision.
594 if ((c
&0xf) > 9 || ((c
>>4)&0xf) > 9 || ((c
>>4)&0xf) == 0)
595 return (ISC_R_RANGE
);
598 * Vertical precision.
602 if ((c
&0xf) > 9 || ((c
>>4)&0xf) > 9 || ((c
>>4)&0xf) == 0)
603 return (ISC_R_RANGE
);
604 isc_region_consume(&sr
, 4);
609 latitude
= uint32_fromregion(&sr
);
610 if (latitude
< (0x80000000UL
- 90 * 3600000) ||
611 latitude
> (0x80000000UL
+ 90 * 3600000))
612 return (ISC_R_RANGE
);
613 isc_region_consume(&sr
, 4);
618 longitude
= uint32_fromregion(&sr
);
619 if (longitude
< (0x80000000UL
- 180 * 3600000) ||
620 longitude
> (0x80000000UL
+ 180 * 3600000))
621 return (ISC_R_RANGE
);
625 * All values possible.
628 isc_buffer_activeregion(source
, &sr
);
629 isc_buffer_forward(source
, 16);
630 return (mem_tobuffer(target
, sr
.base
, 16));
633 static inline isc_result_t
634 towire_loc(ARGS_TOWIRE
) {
637 REQUIRE(rdata
->type
== 29);
638 REQUIRE(rdata
->length
!= 0);
640 return (mem_tobuffer(target
, rdata
->data
, rdata
->length
));
644 compare_loc(ARGS_COMPARE
) {
648 REQUIRE(rdata1
->type
== rdata2
->type
);
649 REQUIRE(rdata1
->rdclass
== rdata2
->rdclass
);
650 REQUIRE(rdata1
->type
== 29);
651 REQUIRE(rdata1
->length
!= 0);
652 REQUIRE(rdata2
->length
!= 0);
654 dns_rdata_toregion(rdata1
, &r1
);
655 dns_rdata_toregion(rdata2
, &r2
);
656 return (isc_region_compare(&r1
, &r2
));
659 static inline isc_result_t
660 fromstruct_loc(ARGS_FROMSTRUCT
) {
661 dns_rdata_loc_t
*loc
= source
;
665 REQUIRE(source
!= NULL
);
666 REQUIRE(loc
->common
.rdtype
== type
);
667 REQUIRE(loc
->common
.rdclass
== rdclass
);
672 if (loc
->v
.v0
.version
!= 0)
673 return (ISC_R_NOTIMPLEMENTED
);
674 RETERR(uint8_tobuffer(loc
->v
.v0
.version
, target
));
677 if ((c
&0xf) > 9 || ((c
>>4)&0xf) > 9 || ((c
>>4)&0xf) == 0)
678 return (ISC_R_RANGE
);
679 RETERR(uint8_tobuffer(loc
->v
.v0
.size
, target
));
681 c
= loc
->v
.v0
.horizontal
;
682 if ((c
&0xf) > 9 || ((c
>>4)&0xf) > 9 || ((c
>>4)&0xf) == 0)
683 return (ISC_R_RANGE
);
684 RETERR(uint8_tobuffer(loc
->v
.v0
.horizontal
, target
));
686 c
= loc
->v
.v0
.vertical
;
687 if ((c
&0xf) > 9 || ((c
>>4)&0xf) > 9 || ((c
>>4)&0xf) == 0)
688 return (ISC_R_RANGE
);
689 RETERR(uint8_tobuffer(loc
->v
.v0
.vertical
, target
));
691 if (loc
->v
.v0
.latitude
< (0x80000000UL
- 90 * 3600000) ||
692 loc
->v
.v0
.latitude
> (0x80000000UL
+ 90 * 3600000))
693 return (ISC_R_RANGE
);
694 RETERR(uint32_tobuffer(loc
->v
.v0
.latitude
, target
));
696 if (loc
->v
.v0
.longitude
< (0x80000000UL
- 180 * 3600000) ||
697 loc
->v
.v0
.longitude
> (0x80000000UL
+ 180 * 3600000))
698 return (ISC_R_RANGE
);
699 RETERR(uint32_tobuffer(loc
->v
.v0
.longitude
, target
));
700 return (uint32_tobuffer(loc
->v
.v0
.altitude
, target
));
703 static inline isc_result_t
704 tostruct_loc(ARGS_TOSTRUCT
) {
705 dns_rdata_loc_t
*loc
= target
;
709 REQUIRE(rdata
->type
== 29);
710 REQUIRE(target
!= NULL
);
711 REQUIRE(rdata
->length
!= 0);
715 dns_rdata_toregion(rdata
, &r
);
716 version
= uint8_fromregion(&r
);
718 return (ISC_R_NOTIMPLEMENTED
);
720 loc
->common
.rdclass
= rdata
->rdclass
;
721 loc
->common
.rdtype
= rdata
->type
;
722 ISC_LINK_INIT(&loc
->common
, link
);
724 loc
->v
.v0
.version
= version
;
725 isc_region_consume(&r
, 1);
726 loc
->v
.v0
.size
= uint8_fromregion(&r
);
727 isc_region_consume(&r
, 1);
728 loc
->v
.v0
.horizontal
= uint8_fromregion(&r
);
729 isc_region_consume(&r
, 1);
730 loc
->v
.v0
.vertical
= uint8_fromregion(&r
);
731 isc_region_consume(&r
, 1);
732 loc
->v
.v0
.latitude
= uint32_fromregion(&r
);
733 isc_region_consume(&r
, 4);
734 loc
->v
.v0
.longitude
= uint32_fromregion(&r
);
735 isc_region_consume(&r
, 4);
736 loc
->v
.v0
.altitude
= uint32_fromregion(&r
);
737 isc_region_consume(&r
, 4);
738 return (ISC_R_SUCCESS
);
742 freestruct_loc(ARGS_FREESTRUCT
) {
743 dns_rdata_loc_t
*loc
= source
;
745 REQUIRE(source
!= NULL
);
746 REQUIRE(loc
->common
.rdtype
== 29);
752 static inline isc_result_t
753 additionaldata_loc(ARGS_ADDLDATA
) {
754 REQUIRE(rdata
->type
== 29);
760 return (ISC_R_SUCCESS
);
763 static inline isc_result_t
764 digest_loc(ARGS_DIGEST
) {
767 REQUIRE(rdata
->type
== 29);
769 dns_rdata_toregion(rdata
, &r
);
771 return ((digest
)(arg
, &r
));
774 static inline isc_boolean_t
775 checkowner_loc(ARGS_CHECKOWNER
) {
787 static inline isc_boolean_t
788 checknames_loc(ARGS_CHECKNAMES
) {
790 REQUIRE(rdata
->type
== 29);
799 #endif /* RDATA_GENERIC_LOC_29_C */