Merge branch 'vendor/GCC44'
[games.git] / contrib / bind-9.3 / 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.3.2.6 2004/03/06 08:14:06 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(options);
59
60         /*
61          * Defaults.
62          */
63         m1 = s1 = 0;
64         m2 = s2 = 0;
65         size = 0x12;    /* 1.00m */
66         hp = 0x16;      /* 10000.00 m */
67         vp = 0x13;      /* 10.00 m */
68         version = 0;
69
70         /*
71          * Degrees.
72          */
73         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
74                                       ISC_FALSE));
75         if (token.value.as_ulong > 90U)
76                 RETTOK(ISC_R_RANGE);
77         d1 = (int)token.value.as_ulong;
78         /*
79          * Minutes.
80          */
81         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
82                                       ISC_FALSE));
83         if (strcasecmp(DNS_AS_STR(token), "N") == 0)
84                 north = ISC_TRUE;
85         if (north || strcasecmp(DNS_AS_STR(token), "S") == 0)
86                 goto getlong;
87         m1 = strtol(DNS_AS_STR(token), &e, 10);
88         if (*e != 0)
89                 RETTOK(DNS_R_SYNTAX);
90         if (m1 < 0 || m1 > 59)
91                 RETTOK(ISC_R_RANGE);
92         if (d1 == 90 && m1 != 0)
93                 RETTOK(ISC_R_RANGE);
94
95         /*
96          * Seconds.
97          */
98         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
99                                       ISC_FALSE));
100         if (strcasecmp(DNS_AS_STR(token), "N") == 0)
101                 north = ISC_TRUE;
102         if (north || strcasecmp(DNS_AS_STR(token), "S") == 0)
103                 goto getlong;
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)
108                 RETTOK(ISC_R_RANGE);
109         if (*e == '.') {
110                 const char *l;
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                 l = e;
123                 while (*e != 0) {
124                         if (decvalue(*e++) < 0)
125                                 RETTOK(DNS_R_SYNTAX);
126                 }
127                 if (*l != '\0' && callbacks != NULL) {
128                         const char *file = isc_lex_getsourcename(lexer);
129                         unsigned long line = isc_lex_getsourceline(lexer);
130
131                         if (file == NULL)
132                                 file = "UNKNOWN";
133                         (*callbacks->warn)(callbacks, "%s: %s:%u: '%s' extra "
134                                            "precision digits ignored",
135                                            "dns_rdata_fromtext", file, line,
136                                            DNS_AS_STR(token));
137                 }
138         } else
139                 s1 *= 1000;
140         if (d1 == 90 && s1 != 0)
141                 RETTOK(ISC_R_RANGE);
142
143         /*
144          * Direction.
145          */
146         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
147                                       ISC_FALSE));
148         if (strcasecmp(DNS_AS_STR(token), "N") == 0)
149                 north = ISC_TRUE;
150         if (!north && strcasecmp(DNS_AS_STR(token), "S") != 0)
151                 RETTOK(DNS_R_SYNTAX);
152
153  getlong:
154         /*
155          * Degrees.
156          */
157         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
158                                       ISC_FALSE));
159         if (token.value.as_ulong > 180U)
160                 RETTOK(ISC_R_RANGE);
161         d2 = (int)token.value.as_ulong;
162
163         /*
164          * Minutes.
165          */
166         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
167                                       ISC_FALSE));
168         if (strcasecmp(DNS_AS_STR(token), "E") == 0)
169                 east = ISC_TRUE;
170         if (east || strcasecmp(DNS_AS_STR(token), "W") == 0)
171                 goto getalt;
172         m2 = strtol(DNS_AS_STR(token), &e, 10);
173         if (*e != 0)
174                 RETTOK(DNS_R_SYNTAX);
175         if (m2 < 0 || m2 > 59)
176                 RETTOK(ISC_R_RANGE);
177         if (d2 == 180 && m2 != 0)
178                 RETTOK(ISC_R_RANGE);
179
180         /*
181          * Seconds.
182          */
183         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
184                                       ISC_FALSE));
185         if (strcasecmp(DNS_AS_STR(token), "E") == 0)
186                 east = ISC_TRUE;
187         if (east || strcasecmp(DNS_AS_STR(token), "W") == 0)
188                 goto getalt;
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)
193                 RETTOK(ISC_R_RANGE);
194         if (*e == '.') {
195                 const char *l;
196                 e++;
197                 for (i = 0; i < 3; i++) {
198                         if (*e == 0)
199                                 break;
200                         if ((tmp = decvalue(*e++)) < 0)
201                                 RETTOK(DNS_R_SYNTAX);
202                         s2 *= 10;
203                         s2 += tmp;
204                 }
205                 for (; i < 3; i++)
206                         s2 *= 10;
207                 l = e;
208                 while (*e != 0) {
209                         if (decvalue(*e++) < 0)
210                                 RETTOK(DNS_R_SYNTAX);
211                 }
212                 if (*l != '\0' && callbacks != NULL) {
213                         const char *file = isc_lex_getsourcename(lexer);
214                         unsigned long line = isc_lex_getsourceline(lexer);
215
216                         if (file == NULL)
217                                 file = "UNKNOWN";
218                         (*callbacks->warn)(callbacks, "%s: %s:%u: '%s' extra "
219                                            "precision digits ignored",
220                                            "dns_rdata_fromtext",
221                                            file, line, DNS_AS_STR(token));
222                 }
223         } else
224                 s2 *= 1000;
225         if (d2 == 180 && s2 != 0)
226                 RETTOK(ISC_R_RANGE);
227
228         /*
229          * Direction.
230          */
231         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
232                                       ISC_FALSE));
233         if (strcasecmp(DNS_AS_STR(token), "E") == 0)
234                 east = ISC_TRUE;
235         if (!east && strcasecmp(DNS_AS_STR(token), "W") != 0)
236                 RETTOK(DNS_R_SYNTAX);
237
238  getalt:
239         /*
240          * Altitude.
241          */
242         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
243                                       ISC_FALSE));
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)
248                 RETTOK(ISC_R_RANGE);
249         cm = 0;
250         if (*e == '.') {
251                 e++;
252                 for (i = 0; i < 2; i++) {
253                         if (*e == 0 || *e == 'm')
254                                 break;
255                         if ((tmp = decvalue(*e++)) < 0)
256                                 return (DNS_R_SYNTAX);
257                         cm *= 10;
258                         if (m < 0)
259                                 cm -= tmp;
260                         else
261                                 cm += tmp;
262                 }
263                 for (; i < 2; i++)
264                         cm *= 10;
265         }
266         if (*e == 'm')
267                 e++;
268         if (*e != 0)
269                 RETTOK(DNS_R_SYNTAX);
270         if (m == -100000 && cm != 0)
271                 RETTOK(ISC_R_RANGE);
272         if (m == 42849672 && cm > 95)
273                 RETTOK(ISC_R_RANGE);
274         /*
275          * Adjust base.
276          */
277         altitude = m + 100000;
278         altitude *= 100;
279         altitude += cm;
280
281         /*
282          * Size: optional.
283          */
284         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
285                                       ISC_TRUE));
286         if (token.type == isc_tokentype_eol ||
287             token.type == isc_tokentype_eof) {
288                 isc_lex_ungettoken(lexer, &token);
289                 goto encode;
290         }
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)
295                 RETTOK(ISC_R_RANGE);
296         cm = 0;
297         if (*e == '.') {
298                 e++;
299                 for (i = 0; i < 2; i++) {
300                         if (*e == 0 || *e == 'm')
301                                 break;
302                         if ((tmp = decvalue(*e++)) < 0)
303                                 RETTOK(DNS_R_SYNTAX);
304                         cm *= 10;
305                         cm += tmp;
306                 }
307                 for (; i < 2; i++)
308                         cm *= 10;
309         }
310         if (*e == 'm')
311                 e++;
312         if (*e != 0)
313                 RETTOK(DNS_R_SYNTAX);
314         /*
315          * We don't just multiply out as we will overflow.
316          */
317         if (m > 0) {
318                 for (exp = 0; exp < 7; exp++)
319                         if (m < poweroften[exp+1])
320                                 break;
321                 man = m / poweroften[exp];
322                 exp += 2;
323         } else {
324                 if (cm >= 10) {
325                         man = cm / 10;
326                         exp = 1;
327                 } else {
328                         man = cm;
329                         exp = 0;
330                 }
331         }
332         size = (man << 4) + exp;
333
334         /*
335          * Horizontal precision: optional.
336          */
337         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
338                                       ISC_TRUE));
339         if (token.type == isc_tokentype_eol ||
340             token.type == isc_tokentype_eof) {
341                 isc_lex_ungettoken(lexer, &token);
342                 goto encode;
343         }
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)
348                 RETTOK(ISC_R_RANGE);
349         cm = 0;
350         if (*e == '.') {
351                 e++;
352                 for (i = 0; i < 2; i++) {
353                         if (*e == 0 || *e == 'm')
354                                 break;
355                         if ((tmp = decvalue(*e++)) < 0)
356                                 RETTOK(DNS_R_SYNTAX);
357                         cm *= 10;
358                         cm += tmp;
359                 }
360                 for (; i < 2; i++)
361                         cm *= 10;
362         }
363         if (*e == 'm')
364                 e++;
365         if (*e != 0)
366                 RETTOK(DNS_R_SYNTAX);
367         /*
368          * We don't just multiply out as we will overflow.
369          */
370         if (m > 0) {
371                 for (exp = 0; exp < 7; exp++)
372                         if (m < poweroften[exp+1])
373                                 break;
374                 man = m / poweroften[exp];
375                 exp += 2;
376         } else if (cm >= 10) {
377                 man = cm / 10;
378                 exp = 1;
379         } else  {
380                 man = cm;
381                 exp = 0;
382         }
383         hp = (man << 4) + exp;
384
385         /*
386          * Vertical precision: optional.
387          */
388         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
389                                       ISC_TRUE));
390         if (token.type == isc_tokentype_eol ||
391             token.type == isc_tokentype_eof) {
392                 isc_lex_ungettoken(lexer, &token);
393                 goto encode;
394         }
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)
399                 RETTOK(ISC_R_RANGE);
400         cm = 0;
401         if (*e == '.') {
402                 e++;
403                 for (i = 0; i < 2; i++) {
404                         if (*e == 0 || *e == 'm')
405                                 break;
406                         if ((tmp = decvalue(*e++)) < 0)
407                                 RETTOK(DNS_R_SYNTAX);
408                         cm *= 10;
409                         cm += tmp;
410                 }
411                 for (; i < 2; i++)
412                         cm *= 10;
413         }
414         if (*e == 'm')
415                 e++;
416         if (*e != 0)
417                 RETTOK(DNS_R_SYNTAX);
418         /*
419          * We don't just multiply out as we will overflow.
420          */
421         if (m > 0) {
422                 for (exp = 0; exp < 7; exp++)
423                         if (m < poweroften[exp+1])
424                                 break;
425                 man = m / poweroften[exp];
426                 exp += 2;
427         } else if (cm >= 10) {
428                 man = cm / 10;
429                 exp = 1;
430         } else {
431                 man = cm;
432                 exp = 0;
433         }
434         vp = (man << 4) + exp;
435
436  encode:
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));
441         if (north)
442                 latitude = 0x80000000 + ( d1 * 3600 + m1 * 60 ) * 1000 + s1;
443         else
444                 latitude = 0x80000000 - ( d1 * 3600 + m1 * 60 ) * 1000 - s1;
445         RETERR(uint32_tobuffer(latitude, target));
446
447         if (east)
448                 longitude = 0x80000000 + ( d2 * 3600 + m2 * 60 ) * 1000 + s2;
449         else
450                 longitude = 0x80000000 - ( d2 * 3600 + m2 * 60 ) * 1000 - s2;
451         RETERR(uint32_tobuffer(longitude, target));
452
453         return (uint32_tobuffer(altitude, target));
454 }
455
456 static inline isc_result_t
457 totext_loc(ARGS_TOTEXT) {
458         int d1, m1, s1, fs1;
459         int d2, m2, s2, fs2;
460         unsigned long latitude;
461         unsigned long longitude;
462         unsigned long altitude;
463         isc_boolean_t north;
464         isc_boolean_t east;
465         isc_boolean_t below;
466         isc_region_t sr;
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 };
475
476         UNUSED(tctx);
477
478         REQUIRE(rdata->type == 29);
479         REQUIRE(rdata->length != 0);
480
481         dns_rdata_toregion(rdata, &sr);
482
483         /* version = sr.base[0]; */
484         size = sr.base[1];
485         if ((size&0x0f)> 1)
486                 sprintf(sbuf, "%lum", (size>>4) * poweroften[(size&0x0f)-2]);
487         else
488                 sprintf(sbuf, "0.%02lum", (size>>4) * poweroften[(size&0x0f)]);
489         hp = sr.base[2];
490         if ((hp&0x0f)> 1)
491                 sprintf(hbuf, "%lum", (hp>>4) * poweroften[(hp&0x0f)-2]);
492         else
493                 sprintf(hbuf, "0.%02lum", (hp>>4) * poweroften[(hp&0x0f)]);
494         vp = sr.base[3];
495         if ((vp&0x0f)> 1)
496                 sprintf(vbuf, "%lum", (vp>>4) * poweroften[(vp&0x0f)-2]);
497         else
498                 sprintf(vbuf, "0.%02lum", (vp>>4) * poweroften[(vp&0x0f)]);
499         isc_region_consume(&sr, 4);
500
501         latitude = uint32_fromregion(&sr);
502         isc_region_consume(&sr, 4);
503         if (latitude >= 0x80000000) {
504                 north = ISC_TRUE;
505                 latitude -= 0x80000000;
506         } else {
507                 north = ISC_FALSE;
508                 latitude = 0x80000000 - latitude;
509         }
510         fs1 = (int)(latitude % 1000);
511         latitude /= 1000;
512         s1 = (int)(latitude % 60);
513         latitude /= 60;
514         m1 = (int)(latitude % 60);
515         latitude /= 60;
516         d1 = (int)latitude;
517
518         longitude = uint32_fromregion(&sr);
519         isc_region_consume(&sr, 4);
520         if (longitude >= 0x80000000) {
521                 east = ISC_TRUE;
522                 longitude -= 0x80000000;
523         } else {
524                 east = ISC_FALSE;
525                 longitude = 0x80000000 - longitude;
526         }
527         fs2 = (int)(longitude % 1000);
528         longitude /= 1000;
529         s2 = (int)(longitude % 60);
530         longitude /= 60;
531         m2 = (int)(longitude % 60);
532         longitude /= 60;
533         d2 = (int)longitude;
534
535         altitude = uint32_fromregion(&sr);
536         isc_region_consume(&sr, 4);
537         if (altitude < 10000000U) {
538                 below = ISC_TRUE;
539                 altitude = 10000000 - altitude;
540         } else {
541                 below =ISC_FALSE;
542                 altitude -= 10000000;
543         }
544
545         sprintf(buf, "%d %d %d.%03d %s %d %d %d.%03d %s %s%ld.%02ldm %s %s %s",
546                 d1, m1, s1, fs1, north ? "N" : "S",
547                 d2, m2, s2, fs2, east ? "E" : "W",
548                 below ? "-" : "", altitude/100, altitude % 100,
549                 sbuf, hbuf, vbuf);
550
551         return (str_totext(buf, target));
552 }
553
554 static inline isc_result_t
555 fromwire_loc(ARGS_FROMWIRE) {
556         isc_region_t sr;
557         unsigned char c;
558         unsigned long latitude;
559         unsigned long longitude;
560
561         REQUIRE(type == 29);
562
563         UNUSED(type);
564         UNUSED(rdclass);
565         UNUSED(dctx);
566         UNUSED(options);
567
568         isc_buffer_activeregion(source, &sr);
569         if (sr.length < 1)
570                 return (ISC_R_UNEXPECTEDEND);
571         if (sr.base[0] != 0)
572                 return (ISC_R_NOTIMPLEMENTED);
573         if (sr.length < 16)
574                 return (ISC_R_UNEXPECTEDEND);
575
576         /*
577          * Size.
578          */
579         c = sr.base[1];
580         if (c != 0)
581                 if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
582                         return (ISC_R_RANGE);
583
584         /*
585          * Horizontal precision.
586          */
587         c = sr.base[2];
588         if (c != 0)
589                 if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
590                         return (ISC_R_RANGE);
591
592         /*
593          * Vertical precision.
594          */
595         c = sr.base[3];
596         if (c != 0)
597                 if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
598                         return (ISC_R_RANGE);
599         isc_region_consume(&sr, 4);
600
601         /*
602          * Latitude.
603          */
604         latitude = uint32_fromregion(&sr);
605         if (latitude < (0x80000000UL - 90 * 3600000) ||
606             latitude > (0x80000000UL + 90 * 3600000))
607                 return (ISC_R_RANGE);
608         isc_region_consume(&sr, 4);
609
610         /*
611          * Longitude.
612          */
613         longitude = uint32_fromregion(&sr);
614         if (longitude < (0x80000000UL - 180 * 3600000) ||
615             longitude > (0x80000000UL + 180 * 3600000))
616                 return (ISC_R_RANGE);
617
618         /*
619          * Altitiude.
620          * All values possible.
621          */
622
623         isc_buffer_activeregion(source, &sr);
624         isc_buffer_forward(source, 16);
625         return (mem_tobuffer(target, sr.base, 16));
626 }
627
628 static inline isc_result_t
629 towire_loc(ARGS_TOWIRE) {
630         UNUSED(cctx);
631
632         REQUIRE(rdata->type == 29);
633         REQUIRE(rdata->length != 0);
634
635         return (mem_tobuffer(target, rdata->data, rdata->length));
636 }
637
638 static inline int
639 compare_loc(ARGS_COMPARE) {
640         isc_region_t r1;
641         isc_region_t r2;
642
643         REQUIRE(rdata1->type == rdata2->type);
644         REQUIRE(rdata1->rdclass == rdata2->rdclass);
645         REQUIRE(rdata1->type == 29);
646         REQUIRE(rdata1->length != 0);
647         REQUIRE(rdata2->length != 0);
648
649         dns_rdata_toregion(rdata1, &r1);
650         dns_rdata_toregion(rdata2, &r2);
651         return (isc_region_compare(&r1, &r2));
652 }
653
654 static inline isc_result_t
655 fromstruct_loc(ARGS_FROMSTRUCT) {
656         dns_rdata_loc_t *loc = source;
657         isc_uint8_t c;
658
659         REQUIRE(type == 29);
660         REQUIRE(source != NULL);
661         REQUIRE(loc->common.rdtype == type);
662         REQUIRE(loc->common.rdclass == rdclass);
663
664         UNUSED(type);
665         UNUSED(rdclass);
666
667         if (loc->v.v0.version != 0)
668                 return (ISC_R_NOTIMPLEMENTED);
669         RETERR(uint8_tobuffer(loc->v.v0.version, target));
670
671         c = loc->v.v0.size;
672         if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
673                 return (ISC_R_RANGE);
674         RETERR(uint8_tobuffer(loc->v.v0.size, target));
675
676         c = loc->v.v0.horizontal;
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.horizontal, target));
680
681         c = loc->v.v0.vertical;
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.vertical, target));
685
686         if (loc->v.v0.latitude < (0x80000000UL - 90 * 3600000) ||
687             loc->v.v0.latitude > (0x80000000UL + 90 * 3600000))
688                 return (ISC_R_RANGE);
689         RETERR(uint32_tobuffer(loc->v.v0.latitude, target));
690
691         if (loc->v.v0.longitude < (0x80000000UL - 180 * 3600000) ||
692             loc->v.v0.longitude > (0x80000000UL + 180 * 3600000))
693                 return (ISC_R_RANGE);
694         RETERR(uint32_tobuffer(loc->v.v0.longitude, target));
695         return (uint32_tobuffer(loc->v.v0.altitude, target));
696 }
697
698 static inline isc_result_t
699 tostruct_loc(ARGS_TOSTRUCT) {
700         dns_rdata_loc_t *loc = target;
701         isc_region_t r;
702         isc_uint8_t version;
703
704         REQUIRE(rdata->type == 29);
705         REQUIRE(target != NULL);
706         REQUIRE(rdata->length != 0);
707
708         UNUSED(mctx);
709
710         dns_rdata_toregion(rdata, &r);
711         version = uint8_fromregion(&r);
712         if (version != 0)
713                 return (ISC_R_NOTIMPLEMENTED);
714
715         loc->common.rdclass = rdata->rdclass;
716         loc->common.rdtype = rdata->type;
717         ISC_LINK_INIT(&loc->common, link);
718
719         loc->v.v0.version = version;
720         isc_region_consume(&r, 1);
721         loc->v.v0.size = uint8_fromregion(&r);
722         isc_region_consume(&r, 1);
723         loc->v.v0.horizontal = uint8_fromregion(&r);
724         isc_region_consume(&r, 1);
725         loc->v.v0.vertical = uint8_fromregion(&r);
726         isc_region_consume(&r, 1);
727         loc->v.v0.latitude = uint32_fromregion(&r);
728         isc_region_consume(&r, 4);
729         loc->v.v0.longitude = uint32_fromregion(&r);
730         isc_region_consume(&r, 4);
731         loc->v.v0.altitude = uint32_fromregion(&r);
732         isc_region_consume(&r, 4);
733         return (ISC_R_SUCCESS);
734 }
735
736 static inline void
737 freestruct_loc(ARGS_FREESTRUCT) {
738         dns_rdata_loc_t *loc = source;
739
740         REQUIRE(source != NULL);
741         REQUIRE(loc->common.rdtype == 29);
742
743         UNUSED(source);
744         UNUSED(loc);
745 }
746
747 static inline isc_result_t
748 additionaldata_loc(ARGS_ADDLDATA) {
749         REQUIRE(rdata->type == 29);
750
751         UNUSED(rdata);
752         UNUSED(add);
753         UNUSED(arg);
754
755         return (ISC_R_SUCCESS);
756 }
757
758 static inline isc_result_t
759 digest_loc(ARGS_DIGEST) {
760         isc_region_t r;
761
762         REQUIRE(rdata->type == 29);
763
764         dns_rdata_toregion(rdata, &r);
765
766         return ((digest)(arg, &r));
767 }
768
769 static inline isc_boolean_t
770 checkowner_loc(ARGS_CHECKOWNER) {
771
772         REQUIRE(type == 29);
773
774         UNUSED(name);
775         UNUSED(type);
776         UNUSED(rdclass);
777         UNUSED(wildcard);
778
779         return (ISC_TRUE);
780 }
781
782 static inline isc_boolean_t
783 checknames_loc(ARGS_CHECKNAMES) {
784
785         REQUIRE(rdata->type == 29);
786
787         UNUSED(rdata);
788         UNUSED(owner);
789         UNUSED(bad);
790
791         return (ISC_TRUE);
792 }
793
794 #endif  /* RDATA_GENERIC_LOC_29_C */