Merge from vendor branch GCC:
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / dns / rdata / generic / loc_29.c
1 /*
2  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
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.
8  *
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.
16  */
17
18 /* $Id: loc_29.c,v 1.30.2.5 2004/03/09 06:11:29 marka Exp $ */
19
20 /* Reviewed: Wed Mar 15 18:13:09 PST 2000 by explorer */
21
22 /* RFC 1876 */
23
24 #ifndef RDATA_GENERIC_LOC_29_C
25 #define RDATA_GENERIC_LOC_29_C
26
27 #define RRTYPE_LOC_ATTRIBUTES (0)
28
29 static inline isc_result_t
30 fromtext_loc(ARGS_FROMTEXT) {
31         isc_token_t token;
32         int d1, m1, s1;
33         int d2, m2, s2;
34         unsigned char size;
35         unsigned char hp;
36         unsigned char vp;
37         unsigned char version;
38         isc_boolean_t east = ISC_FALSE;
39         isc_boolean_t north = ISC_FALSE;
40         long tmp;
41         long m;
42         long cm;
43         long poweroften[8] = { 1, 10, 100, 1000,
44                                10000, 100000, 1000000, 10000000 };
45         int man;
46         int exp;
47         char *e;
48         int i;
49         unsigned long latitude;
50         unsigned long longitude;
51         unsigned long altitude;
52
53         REQUIRE(type == 29);
54
55         UNUSED(type);
56         UNUSED(rdclass);
57         UNUSED(origin);
58         UNUSED(downcase);
59         UNUSED(callbacks);
60
61         /*
62          * Defaults.
63          */
64         m1 = s1 = 0;
65         m2 = s2 = 0;
66         size = 0x12;    /* 1.00m */
67         hp = 0x16;      /* 10000.00 m */
68         vp = 0x13;      /* 10.00 m */
69         version = 0;
70
71         /*
72          * Degrees.
73          */
74         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
75                                       ISC_FALSE));
76         if (token.value.as_ulong > 90U)
77                 RETTOK(ISC_R_RANGE);
78         d1 = (int)token.value.as_ulong;
79         /*
80          * Minutes.
81          */
82         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
83                                       ISC_FALSE));
84         if (strcasecmp(token.value.as_pointer, "N") == 0)
85                 north = ISC_TRUE;
86         if (north || strcasecmp(token.value.as_pointer, "S") == 0)
87                 goto getlong;
88         m1 = strtol(token.value.as_pointer, &e, 10);
89         if (*e != 0)
90                 RETTOK(DNS_R_SYNTAX);
91         if (m1 < 0 || m1 > 59)
92                 RETTOK(ISC_R_RANGE);
93         if (d1 == 90 && m1 != 0)
94                 RETTOK(ISC_R_RANGE);
95
96         /*
97          * Seconds.
98          */
99         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
100                                       ISC_FALSE));
101         if (strcasecmp(token.value.as_pointer, "N") == 0)
102                 north = ISC_TRUE;
103         if (north || strcasecmp(token.value.as_pointer, "S") == 0)
104                 goto getlong;
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)
109                 RETTOK(ISC_R_RANGE);
110         if (*e == '.') {
111                 e++;
112                 for (i = 0; i < 3 ; i++) {
113                         if (*e == 0)
114                                 break;
115                         if ((tmp = decvalue(*e++)) < 0)
116                                 RETTOK(DNS_R_SYNTAX);
117                         s1 *= 10;
118                         s1 += tmp;
119                 }
120                 for ( ; i < 3 ; i++)
121                         s1 *= 10;
122                 if (*e != 0)
123                         RETTOK(DNS_R_SYNTAX);
124         } else
125                 s1 *= 1000;
126         if (d1 == 90 && s1 != 0)
127                 RETTOK(ISC_R_RANGE);
128
129         /*
130          * Direction.
131          */
132         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
133                                       ISC_FALSE));
134         if (strcasecmp(token.value.as_pointer, "N") == 0)
135                 north = ISC_TRUE;
136         if (!north && strcasecmp(token.value.as_pointer, "S") != 0)
137                 RETTOK(DNS_R_SYNTAX);
138
139  getlong:
140         /*
141          * Degrees.
142          */
143         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
144                                       ISC_FALSE));
145         if (token.value.as_ulong > 180U)
146                 RETTOK(ISC_R_RANGE);
147         d2 = (int)token.value.as_ulong;
148
149         /*
150          * Minutes.
151          */
152         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
153                                       ISC_FALSE));
154         if (strcasecmp(token.value.as_pointer, "E") == 0)
155                 east = ISC_TRUE;
156         if (east || strcasecmp(token.value.as_pointer, "W") == 0)
157                 goto getalt;
158         m2 = strtol(token.value.as_pointer, &e, 10);
159         if (*e != 0)
160                 RETTOK(DNS_R_SYNTAX);
161         if (m2 < 0 || m2 > 59)
162                 RETTOK(ISC_R_RANGE);
163         if (d2 == 180 && m2 != 0)
164                 RETTOK(ISC_R_RANGE);
165
166         /*
167          * Seconds.
168          */
169         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
170                                       ISC_FALSE));
171         if (strcasecmp(token.value.as_pointer, "E") == 0)
172                 east = ISC_TRUE;
173         if (east || strcasecmp(token.value.as_pointer, "W") == 0)
174                 goto getalt;
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)
179                 RETTOK(ISC_R_RANGE);
180         if (*e == '.') {
181                 e++;
182                 for (i = 0; i < 3 ; i++) {
183                         if (*e == 0)
184                                 break;
185                         if ((tmp = decvalue(*e++)) < 0)
186                                 RETTOK(DNS_R_SYNTAX);
187                         s2 *= 10;
188                         s2 += tmp;
189                 }
190                 for ( ; i < 3 ; i++)
191                         s2 *= 10;
192                 if (*e != 0)
193                         RETTOK(DNS_R_SYNTAX);
194         } else
195                 s2 *= 1000;
196         if (d2 == 180 && s2 != 0)
197                 RETTOK(ISC_R_RANGE);
198
199         /*
200          * Direction.
201          */
202         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
203                                       ISC_FALSE));
204         if (strcasecmp(token.value.as_pointer, "E") == 0)
205                 east = ISC_TRUE;
206         if (!east && strcasecmp(token.value.as_pointer, "W") != 0)
207                 RETTOK(DNS_R_SYNTAX);
208
209  getalt:
210         /*
211          * Altitude.
212          */
213         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
214                                       ISC_FALSE));
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)
219                 RETTOK(ISC_R_RANGE);
220         cm = 0;
221         if (*e == '.') {
222                 e++;
223                 for (i = 0; i < 2 ; i++) {
224                         if (*e == 0 || *e == 'm')
225                                 break;
226                         if ((tmp = decvalue(*e++)) < 0)
227                                 return (DNS_R_SYNTAX);
228                         cm *= 10;
229                         if (m < 0)
230                                 cm -= tmp;
231                         else
232                                 cm += tmp;
233                 }
234                 for ( ; i < 2 ; i++)
235                         cm *= 10;
236         }
237         if (*e == 'm')
238                 e++;
239         if (*e != 0)
240                 RETTOK(DNS_R_SYNTAX);
241         if (m == -100000 && cm != 0)
242                 RETTOK(ISC_R_RANGE);
243         if (m == 42849672 && cm > 95)
244                 RETTOK(ISC_R_RANGE);
245         /*
246          * Adjust base.
247          */
248         altitude = m + 100000;
249         altitude *= 100;
250         altitude += cm;
251
252         /*
253          * Size: optional.
254          */
255         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
256                                       ISC_TRUE));
257         if (token.type == isc_tokentype_eol ||
258             token.type == isc_tokentype_eof) {
259                 isc_lex_ungettoken(lexer, &token);
260                 goto encode;
261         }
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)
266                 RETTOK(ISC_R_RANGE);
267         cm = 0;
268         if (*e == '.') {
269                 e++;
270                 for (i = 0; i < 2 ; i++) {
271                         if (*e == 0 || *e == 'm')
272                                 break;
273                         if ((tmp = decvalue(*e++)) < 0)
274                                 RETTOK(DNS_R_SYNTAX);
275                         cm *= 10;
276                         cm += tmp;
277                 }
278                 for ( ; i < 2 ; i++)
279                         cm *= 10;
280         }
281         if (*e == 'm')
282                 e++;
283         if (*e != 0)
284                 RETTOK(DNS_R_SYNTAX);
285         /*
286          * We don't just multiply out as we will overflow.
287          */
288         if (m > 0) {
289                 for (exp = 0 ; exp < 7 ; exp++)
290                         if (m < poweroften[exp+1])
291                                 break;
292                 man = m / poweroften[exp];
293                 exp += 2;
294         } else {
295                 if (cm >= 10) {
296                         man = cm / 10;
297                         exp = 1;
298                 } else {
299                         man = cm;
300                         exp = 0;
301                 }
302         }
303         size = (man << 4) + exp;
304
305         /*
306          * Horizontal precision: optional.
307          */
308         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
309                                       ISC_TRUE));
310         if (token.type == isc_tokentype_eol ||
311             token.type == isc_tokentype_eof) {
312                 isc_lex_ungettoken(lexer, &token);
313                 goto encode;
314         }
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)
319                 RETTOK(ISC_R_RANGE);
320         cm = 0;
321         if (*e == '.') {
322                 e++;
323                 for (i = 0; i < 2 ; i++) {
324                         if (*e == 0 || *e == 'm')
325                                 break;
326                         if ((tmp = decvalue(*e++)) < 0)
327                                 RETTOK(DNS_R_SYNTAX);
328                         cm *= 10;
329                         cm += tmp;
330                 }
331                 for ( ; i < 2 ; i++)
332                         cm *= 10;
333         }
334         if (*e == 'm')
335                 e++;
336         if (*e != 0)
337                 RETTOK(DNS_R_SYNTAX);
338         /*
339          * We don't just multiply out as we will overflow.
340          */
341         if (m > 0) {
342                 for (exp = 0 ; exp < 7 ; exp++)
343                         if (m < poweroften[exp+1])
344                                 break;
345                 man = m / poweroften[exp];
346                 exp += 2;
347         } else if (cm >= 10) {
348                 man = cm / 10;
349                 exp = 1;
350         } else  {
351                 man = cm;
352                 exp = 0;
353         }
354         hp = (man << 4) + exp;
355
356         /*
357          * Vertical precision: optional.
358          */
359         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
360                                       ISC_TRUE));
361         if (token.type == isc_tokentype_eol ||
362             token.type == isc_tokentype_eof) {
363                 isc_lex_ungettoken(lexer, &token);
364                 goto encode;
365         }
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)
370                 RETTOK(ISC_R_RANGE);
371         cm = 0;
372         if (*e == '.') {
373                 e++;
374                 for (i = 0; i < 2 ; i++) {
375                         if (*e == 0 || *e == 'm')
376                                 break;
377                         if ((tmp = decvalue(*e++)) < 0)
378                                 RETTOK(DNS_R_SYNTAX);
379                         cm *= 10;
380                         cm += tmp;
381                 }
382                 for ( ; i < 2 ; i++)
383                         cm *= 10;
384         }
385         if (*e == 'm')
386                 e++;
387         if (*e != 0)
388                 RETTOK(DNS_R_SYNTAX);
389         /*
390          * We don't just multiply out as we will overflow.
391          */
392         if (m > 0) {
393                 for (exp = 0 ; exp < 7 ; exp++)
394                         if (m < poweroften[exp+1])
395                                 break;
396                 man = m / poweroften[exp];
397                 exp += 2;
398         } else if (cm >= 10) {
399                 man = cm / 10;
400                 exp = 1;
401         } else {
402                 man = cm;
403                 exp = 0;
404         }
405         vp = (man << 4) + exp;
406
407  encode:
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));
412         if (north)
413                 latitude = 0x80000000 + ( d1 * 3600 + m1 * 60 ) * 1000 + s1;
414         else
415                 latitude = 0x80000000 - ( d1 * 3600 + m1 * 60 ) * 1000 - s1;
416         RETERR(uint32_tobuffer(latitude, target));
417
418         if (east)
419                 longitude = 0x80000000 + ( d2 * 3600 + m2 * 60 ) * 1000 + s2;
420         else
421                 longitude = 0x80000000 - ( d2 * 3600 + m2 * 60 ) * 1000 - s2;
422         RETERR(uint32_tobuffer(longitude, target));
423
424         return (uint32_tobuffer(altitude, target));
425 }
426
427 static inline isc_result_t
428 totext_loc(ARGS_TOTEXT) {
429         int d1, m1, s1, fs1;
430         int d2, m2, s2, fs2;
431         unsigned long latitude;
432         unsigned long longitude;
433         unsigned long altitude;
434         isc_boolean_t north;
435         isc_boolean_t east;
436         isc_boolean_t below;
437         isc_region_t sr;
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 };
446
447         UNUSED(tctx);
448
449         REQUIRE(rdata->type == 29);
450         REQUIRE(rdata->length != 0);
451
452         dns_rdata_toregion(rdata, &sr);
453
454         /* version = sr.base[0]; */
455         size = sr.base[1];
456         if ((size&0x0f)> 1)
457                 sprintf(sbuf, "%lum", (size>>4) * poweroften[(size&0x0f)-2]);
458         else
459                 sprintf(sbuf, "0.%02lum", (size>>4) * poweroften[(size&0x0f)]);
460         hp = sr.base[2];
461         if ((hp&0x0f)> 1)
462                 sprintf(hbuf, "%lum", (hp>>4) * poweroften[(hp&0x0f)-2]);
463         else
464                 sprintf(hbuf, "0.%02lum", (hp>>4) * poweroften[(hp&0x0f)]);
465         vp = sr.base[3];
466         if ((vp&0x0f)> 1)
467                 sprintf(vbuf, "%lum", (vp>>4) * poweroften[(vp&0x0f)-2]);
468         else
469                 sprintf(vbuf, "0.%02lum", (vp>>4) * poweroften[(vp&0x0f)]);
470         isc_region_consume(&sr, 4);
471
472         latitude = uint32_fromregion(&sr);
473         isc_region_consume(&sr, 4);
474         if (latitude >= 0x80000000) {
475                 north = ISC_TRUE;
476                 latitude -= 0x80000000;
477         } else {
478                 north = ISC_FALSE;
479                 latitude = 0x80000000 - latitude;
480         }
481         fs1 = (int)(latitude % 1000);
482         latitude /= 1000;
483         s1 = (int)(latitude % 60);
484         latitude /= 60;
485         m1 = (int)(latitude % 60);
486         latitude /= 60;
487         d1 = (int)latitude;
488
489         longitude = uint32_fromregion(&sr);
490         isc_region_consume(&sr, 4);
491         if (longitude >= 0x80000000) {
492                 east = ISC_TRUE;
493                 longitude -= 0x80000000;
494         } else {
495                 east = ISC_FALSE;
496                 longitude = 0x80000000 - longitude;
497         }
498         fs2 = (int)(longitude % 1000);
499         longitude /= 1000;
500         s2 = (int)(longitude % 60);
501         longitude /= 60;
502         m2 = (int)(longitude % 60);
503         longitude /= 60;
504         d2 = (int)longitude;
505
506         altitude = uint32_fromregion(&sr);
507         isc_region_consume(&sr, 4);
508         if (altitude < 10000000U) {
509                 below = ISC_TRUE;
510                 altitude = 10000000 - altitude;
511         } else {
512                 below =ISC_FALSE;
513                 altitude -= 10000000;
514         }
515
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,
520                 sbuf, hbuf, vbuf);
521
522         return (str_totext(buf, target));
523 }
524
525 static inline isc_result_t
526 fromwire_loc(ARGS_FROMWIRE) {
527         isc_region_t sr;
528         unsigned char c;
529         unsigned long latitude;
530         unsigned long longitude;
531
532         REQUIRE(type == 29);
533
534         UNUSED(type);
535         UNUSED(rdclass);
536         UNUSED(dctx);
537         UNUSED(downcase);
538
539         isc_buffer_activeregion(source, &sr);
540         if (sr.length < 1)
541                 return (ISC_R_UNEXPECTEDEND);
542         if (sr.base[0] != 0)
543                 return (ISC_R_NOTIMPLEMENTED);
544         if (sr.length < 16)
545                 return (ISC_R_UNEXPECTEDEND);
546
547         /*
548          * Size.
549          */
550         c = sr.base[1];
551         if (c != 0)
552                 if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
553                         return (ISC_R_RANGE);
554
555         /*
556          * Horizontal precision.
557          */
558         c = sr.base[2];
559         if (c != 0)
560                 if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
561                         return (ISC_R_RANGE);
562
563         /*
564          * Vertical precision.
565          */
566         c = sr.base[3];
567         if (c != 0)
568                 if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
569                         return (ISC_R_RANGE);
570         isc_region_consume(&sr, 4);
571
572         /*
573          * Latitude.
574          */
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);
580
581         /*
582          * Longitude.
583          */
584         longitude = uint32_fromregion(&sr);
585         if (longitude < (0x80000000UL - 180 * 3600000) ||
586             longitude > (0x80000000UL + 180 * 3600000))
587                 return (ISC_R_RANGE);
588
589         /*
590          * Altitiude.
591          * All values possible.
592          */
593
594         isc_buffer_activeregion(source, &sr);
595         isc_buffer_forward(source, 16);
596         return (mem_tobuffer(target, sr.base, 16));
597 }
598
599 static inline isc_result_t
600 towire_loc(ARGS_TOWIRE) {
601         UNUSED(cctx);
602
603         REQUIRE(rdata->type == 29);
604         REQUIRE(rdata->length != 0);
605
606         return (mem_tobuffer(target, rdata->data, rdata->length));
607 }
608
609 static inline int
610 compare_loc(ARGS_COMPARE) {
611         isc_region_t r1;
612         isc_region_t r2;
613
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);
619
620         dns_rdata_toregion(rdata1, &r1);
621         dns_rdata_toregion(rdata2, &r2);
622         return (compare_region(&r1, &r2));
623 }
624
625 static inline isc_result_t
626 fromstruct_loc(ARGS_FROMSTRUCT) {
627         dns_rdata_loc_t *loc = source;
628         isc_uint8_t c;
629
630         REQUIRE(type == 29);
631         REQUIRE(source != NULL);
632         REQUIRE(loc->common.rdtype == type);
633         REQUIRE(loc->common.rdclass == rdclass);
634
635         UNUSED(type);
636         UNUSED(rdclass);
637
638         if (loc->v.v0.version != 0)
639                 return (ISC_R_NOTIMPLEMENTED);
640         RETERR(uint8_tobuffer(loc->v.v0.version, target));
641
642         c = loc->v.v0.size;
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));
646
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));
651
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));
656
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));
661
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));
667 }
668
669 static inline isc_result_t
670 tostruct_loc(ARGS_TOSTRUCT) {
671         dns_rdata_loc_t *loc = target;
672         isc_region_t r;
673         isc_uint8_t version;
674
675         REQUIRE(rdata->type == 29);
676         REQUIRE(target != NULL);
677         REQUIRE(rdata->length != 0);
678
679         UNUSED(mctx);
680
681         dns_rdata_toregion(rdata, &r);
682         version = uint8_fromregion(&r);
683         if (version != 0)
684                 return (ISC_R_NOTIMPLEMENTED);
685
686         loc->common.rdclass = rdata->rdclass;
687         loc->common.rdtype = rdata->type;
688         ISC_LINK_INIT(&loc->common, link);
689
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);
705 }
706
707 static inline void
708 freestruct_loc(ARGS_FREESTRUCT) {
709         dns_rdata_loc_t *loc = source;
710
711         REQUIRE(source != NULL);
712         REQUIRE(loc->common.rdtype == 29);
713
714         UNUSED(source);
715         UNUSED(loc);
716 }
717
718 static inline isc_result_t
719 additionaldata_loc(ARGS_ADDLDATA) {
720         REQUIRE(rdata->type == 29);
721
722         UNUSED(rdata);
723         UNUSED(add);
724         UNUSED(arg);
725
726         return (ISC_R_SUCCESS);
727 }
728
729 static inline isc_result_t
730 digest_loc(ARGS_DIGEST) {
731         isc_region_t r;
732
733         REQUIRE(rdata->type == 29);
734
735         dns_rdata_toregion(rdata, &r);
736
737         return ((digest)(arg, &r));
738 }
739
740 #endif  /* RDATA_GENERIC_LOC_29_C */