Import bind 9.5.2 vendor sources.
[dragonfly.git] / contrib / bind-9.5.2 / lib / dns / rdata / generic / loc_29.c
1 /*
2  * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
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.
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.45.128.4 2009/02/17 05:54:41 marka Exp $ */
19
20 /* Reviewed: Wed Mar 15 18:13:09 PST 2000 by explorer */
21
22 /* RFC1876 */
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         INSIST((size&0x0f) < 10 && (size>>4) < 10);
486         if ((size&0x0f)> 1)
487                 sprintf(sbuf, "%lum", (size>>4) * poweroften[(size&0x0f)-2]);
488         else
489                 sprintf(sbuf, "0.%02lum", (size>>4) * poweroften[(size&0x0f)]);
490         hp = sr.base[2];
491         INSIST((hp&0x0f) < 10 && (hp>>4) < 10);
492         if ((hp&0x0f)> 1)
493                 sprintf(hbuf, "%lum", (hp>>4) * poweroften[(hp&0x0f)-2]);
494         else
495                 sprintf(hbuf, "0.%02lum", (hp>>4) * poweroften[(hp&0x0f)]);
496         vp = sr.base[3];
497         INSIST((vp&0x0f) < 10 && (vp>>4) < 10);
498         if ((vp&0x0f)> 1)
499                 sprintf(vbuf, "%lum", (vp>>4) * poweroften[(vp&0x0f)-2]);
500         else
501                 sprintf(vbuf, "0.%02lum", (vp>>4) * poweroften[(vp&0x0f)]);
502         isc_region_consume(&sr, 4);
503
504         latitude = uint32_fromregion(&sr);
505         isc_region_consume(&sr, 4);
506         if (latitude >= 0x80000000) {
507                 north = ISC_TRUE;
508                 latitude -= 0x80000000;
509         } else {
510                 north = ISC_FALSE;
511                 latitude = 0x80000000 - latitude;
512         }
513         fs1 = (int)(latitude % 1000);
514         latitude /= 1000;
515         s1 = (int)(latitude % 60);
516         latitude /= 60;
517         m1 = (int)(latitude % 60);
518         latitude /= 60;
519         d1 = (int)latitude;
520         INSIST(latitude <= 90U);
521
522         longitude = uint32_fromregion(&sr);
523         isc_region_consume(&sr, 4);
524         if (longitude >= 0x80000000) {
525                 east = ISC_TRUE;
526                 longitude -= 0x80000000;
527         } else {
528                 east = ISC_FALSE;
529                 longitude = 0x80000000 - longitude;
530         }
531         fs2 = (int)(longitude % 1000);
532         longitude /= 1000;
533         s2 = (int)(longitude % 60);
534         longitude /= 60;
535         m2 = (int)(longitude % 60);
536         longitude /= 60;
537         d2 = (int)longitude;
538         INSIST(longitude <= 180U);
539
540         altitude = uint32_fromregion(&sr);
541         isc_region_consume(&sr, 4);
542         if (altitude < 10000000U) {
543                 below = ISC_TRUE;
544                 altitude = 10000000 - altitude;
545         } else {
546                 below =ISC_FALSE;
547                 altitude -= 10000000;
548         }
549
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,
554                 sbuf, hbuf, vbuf);
555
556         return (str_totext(buf, target));
557 }
558
559 static inline isc_result_t
560 fromwire_loc(ARGS_FROMWIRE) {
561         isc_region_t sr;
562         unsigned char c;
563         unsigned long latitude;
564         unsigned long longitude;
565
566         REQUIRE(type == 29);
567
568         UNUSED(type);
569         UNUSED(rdclass);
570         UNUSED(dctx);
571         UNUSED(options);
572
573         isc_buffer_activeregion(source, &sr);
574         if (sr.length < 1)
575                 return (ISC_R_UNEXPECTEDEND);
576         if (sr.base[0] != 0)
577                 return (ISC_R_NOTIMPLEMENTED);
578         if (sr.length < 16)
579                 return (ISC_R_UNEXPECTEDEND);
580
581         /*
582          * Size.
583          */
584         c = sr.base[1];
585         if (c != 0)
586                 if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
587                         return (ISC_R_RANGE);
588
589         /*
590          * Horizontal precision.
591          */
592         c = sr.base[2];
593         if (c != 0)
594                 if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
595                         return (ISC_R_RANGE);
596
597         /*
598          * Vertical precision.
599          */
600         c = sr.base[3];
601         if (c != 0)
602                 if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
603                         return (ISC_R_RANGE);
604         isc_region_consume(&sr, 4);
605
606         /*
607          * Latitude.
608          */
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);
614
615         /*
616          * Longitude.
617          */
618         longitude = uint32_fromregion(&sr);
619         if (longitude < (0x80000000UL - 180 * 3600000) ||
620             longitude > (0x80000000UL + 180 * 3600000))
621                 return (ISC_R_RANGE);
622
623         /*
624          * Altitude.
625          * All values possible.
626          */
627
628         isc_buffer_activeregion(source, &sr);
629         isc_buffer_forward(source, 16);
630         return (mem_tobuffer(target, sr.base, 16));
631 }
632
633 static inline isc_result_t
634 towire_loc(ARGS_TOWIRE) {
635         UNUSED(cctx);
636
637         REQUIRE(rdata->type == 29);
638         REQUIRE(rdata->length != 0);
639
640         return (mem_tobuffer(target, rdata->data, rdata->length));
641 }
642
643 static inline int
644 compare_loc(ARGS_COMPARE) {
645         isc_region_t r1;
646         isc_region_t r2;
647
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);
653
654         dns_rdata_toregion(rdata1, &r1);
655         dns_rdata_toregion(rdata2, &r2);
656         return (isc_region_compare(&r1, &r2));
657 }
658
659 static inline isc_result_t
660 fromstruct_loc(ARGS_FROMSTRUCT) {
661         dns_rdata_loc_t *loc = source;
662         isc_uint8_t c;
663
664         REQUIRE(type == 29);
665         REQUIRE(source != NULL);
666         REQUIRE(loc->common.rdtype == type);
667         REQUIRE(loc->common.rdclass == rdclass);
668
669         UNUSED(type);
670         UNUSED(rdclass);
671
672         if (loc->v.v0.version != 0)
673                 return (ISC_R_NOTIMPLEMENTED);
674         RETERR(uint8_tobuffer(loc->v.v0.version, target));
675
676         c = loc->v.v0.size;
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));
680
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));
685
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));
690
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));
695
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));
701 }
702
703 static inline isc_result_t
704 tostruct_loc(ARGS_TOSTRUCT) {
705         dns_rdata_loc_t *loc = target;
706         isc_region_t r;
707         isc_uint8_t version;
708
709         REQUIRE(rdata->type == 29);
710         REQUIRE(target != NULL);
711         REQUIRE(rdata->length != 0);
712
713         UNUSED(mctx);
714
715         dns_rdata_toregion(rdata, &r);
716         version = uint8_fromregion(&r);
717         if (version != 0)
718                 return (ISC_R_NOTIMPLEMENTED);
719
720         loc->common.rdclass = rdata->rdclass;
721         loc->common.rdtype = rdata->type;
722         ISC_LINK_INIT(&loc->common, link);
723
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);
739 }
740
741 static inline void
742 freestruct_loc(ARGS_FREESTRUCT) {
743         dns_rdata_loc_t *loc = source;
744
745         REQUIRE(source != NULL);
746         REQUIRE(loc->common.rdtype == 29);
747
748         UNUSED(source);
749         UNUSED(loc);
750 }
751
752 static inline isc_result_t
753 additionaldata_loc(ARGS_ADDLDATA) {
754         REQUIRE(rdata->type == 29);
755
756         UNUSED(rdata);
757         UNUSED(add);
758         UNUSED(arg);
759
760         return (ISC_R_SUCCESS);
761 }
762
763 static inline isc_result_t
764 digest_loc(ARGS_DIGEST) {
765         isc_region_t r;
766
767         REQUIRE(rdata->type == 29);
768
769         dns_rdata_toregion(rdata, &r);
770
771         return ((digest)(arg, &r));
772 }
773
774 static inline isc_boolean_t
775 checkowner_loc(ARGS_CHECKOWNER) {
776
777         REQUIRE(type == 29);
778
779         UNUSED(name);
780         UNUSED(type);
781         UNUSED(rdclass);
782         UNUSED(wildcard);
783
784         return (ISC_TRUE);
785 }
786
787 static inline isc_boolean_t
788 checknames_loc(ARGS_CHECKNAMES) {
789
790         REQUIRE(rdata->type == 29);
791
792         UNUSED(rdata);
793         UNUSED(owner);
794         UNUSED(bad);
795
796         return (ISC_TRUE);
797 }
798
799 #endif  /* RDATA_GENERIC_LOC_29_C */