1 /*	$NetBSD: loc_29.c,v 1.4 2014/12/10 04:37:59 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
5  * Copyright (C) 1999-2003  Internet Software Consortium.
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /* Id: loc_29.c,v 1.50 2009/12/04 21:09:33 marka Exp  */
21 
22 /* Reviewed: Wed Mar 15 18:13:09 PST 2000 by explorer */
23 
24 /* RFC1876 */
25 
26 #ifndef RDATA_GENERIC_LOC_29_C
27 #define RDATA_GENERIC_LOC_29_C
28 
29 #define RRTYPE_LOC_ATTRIBUTES (0)
30 
31 static inline isc_result_t
fromtext_loc(ARGS_FROMTEXT)32 fromtext_loc(ARGS_FROMTEXT) {
33 	isc_token_t token;
34 	int d1, m1, s1;
35 	int d2, m2, s2;
36 	unsigned char size;
37 	unsigned char hp;
38 	unsigned char vp;
39 	unsigned char version;
40 	isc_boolean_t east = ISC_FALSE;
41 	isc_boolean_t north = ISC_FALSE;
42 	long tmp;
43 	long m;
44 	long cm;
45 	long poweroften[8] = { 1, 10, 100, 1000,
46 			       10000, 100000, 1000000, 10000000 };
47 	int man;
48 	int exp;
49 	char *e;
50 	int i;
51 	unsigned long latitude;
52 	unsigned long longitude;
53 	unsigned long altitude;
54 
55 	REQUIRE(type == 29);
56 
57 	UNUSED(type);
58 	UNUSED(rdclass);
59 	UNUSED(origin);
60 	UNUSED(options);
61 
62 	/*
63 	 * Defaults.
64 	 */
65 	m1 = s1 = 0;
66 	m2 = s2 = 0;
67 	size = 0x12;	/* 1.00m */
68 	hp = 0x16;	/* 10000.00 m */
69 	vp = 0x13;	/* 10.00 m */
70 	version = 0;
71 
72 	/*
73 	 * Degrees.
74 	 */
75 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
76 				      ISC_FALSE));
77 	if (token.value.as_ulong > 90U)
78 		RETTOK(ISC_R_RANGE);
79 	d1 = (int)token.value.as_ulong;
80 	/*
81 	 * Minutes.
82 	 */
83 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
84 				      ISC_FALSE));
85 	if (strcasecmp(DNS_AS_STR(token), "N") == 0)
86 		north = ISC_TRUE;
87 	if (north || strcasecmp(DNS_AS_STR(token), "S") == 0)
88 		goto getlong;
89 	m1 = strtol(DNS_AS_STR(token), &e, 10);
90 	if (*e != 0)
91 		RETTOK(DNS_R_SYNTAX);
92 	if (m1 < 0 || m1 > 59)
93 		RETTOK(ISC_R_RANGE);
94 	if (d1 == 90 && m1 != 0)
95 		RETTOK(ISC_R_RANGE);
96 
97 	/*
98 	 * Seconds.
99 	 */
100 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
101 				      ISC_FALSE));
102 	if (strcasecmp(DNS_AS_STR(token), "N") == 0)
103 		north = ISC_TRUE;
104 	if (north || strcasecmp(DNS_AS_STR(token), "S") == 0)
105 		goto getlong;
106 	s1 = strtol(DNS_AS_STR(token), &e, 10);
107 	if (*e != 0 && *e != '.')
108 		RETTOK(DNS_R_SYNTAX);
109 	if (s1 < 0 || s1 > 59)
110 		RETTOK(ISC_R_RANGE);
111 	if (*e == '.') {
112 		const char *l;
113 		e++;
114 		for (i = 0; i < 3; i++) {
115 			if (*e == 0)
116 				break;
117 			if ((tmp = decvalue(*e++)) < 0)
118 				RETTOK(DNS_R_SYNTAX);
119 			s1 *= 10;
120 			s1 += tmp;
121 		}
122 		for (; i < 3; i++)
123 			s1 *= 10;
124 		l = e;
125 		while (*e != 0) {
126 			if (decvalue(*e++) < 0)
127 				RETTOK(DNS_R_SYNTAX);
128 		}
129 		if (*l != '\0' && callbacks != NULL) {
130 			const char *file = isc_lex_getsourcename(lexer);
131 			unsigned long line = isc_lex_getsourceline(lexer);
132 
133 			if (file == NULL)
134 				file = "UNKNOWN";
135 			(*callbacks->warn)(callbacks, "%s: %s:%u: '%s' extra "
136 					   "precision digits ignored",
137 					   "dns_rdata_fromtext", file, line,
138 					   DNS_AS_STR(token));
139 		}
140 	} else
141 		s1 *= 1000;
142 	if (d1 == 90 && s1 != 0)
143 		RETTOK(ISC_R_RANGE);
144 
145 	/*
146 	 * Direction.
147 	 */
148 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
149 				      ISC_FALSE));
150 	if (strcasecmp(DNS_AS_STR(token), "N") == 0)
151 		north = ISC_TRUE;
152 	if (!north && strcasecmp(DNS_AS_STR(token), "S") != 0)
153 		RETTOK(DNS_R_SYNTAX);
154 
155  getlong:
156 	/*
157 	 * Degrees.
158 	 */
159 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
160 				      ISC_FALSE));
161 	if (token.value.as_ulong > 180U)
162 		RETTOK(ISC_R_RANGE);
163 	d2 = (int)token.value.as_ulong;
164 
165 	/*
166 	 * Minutes.
167 	 */
168 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
169 				      ISC_FALSE));
170 	if (strcasecmp(DNS_AS_STR(token), "E") == 0)
171 		east = ISC_TRUE;
172 	if (east || strcasecmp(DNS_AS_STR(token), "W") == 0)
173 		goto getalt;
174 	m2 = strtol(DNS_AS_STR(token), &e, 10);
175 	if (*e != 0)
176 		RETTOK(DNS_R_SYNTAX);
177 	if (m2 < 0 || m2 > 59)
178 		RETTOK(ISC_R_RANGE);
179 	if (d2 == 180 && m2 != 0)
180 		RETTOK(ISC_R_RANGE);
181 
182 	/*
183 	 * Seconds.
184 	 */
185 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
186 				      ISC_FALSE));
187 	if (strcasecmp(DNS_AS_STR(token), "E") == 0)
188 		east = ISC_TRUE;
189 	if (east || strcasecmp(DNS_AS_STR(token), "W") == 0)
190 		goto getalt;
191 	s2 = strtol(DNS_AS_STR(token), &e, 10);
192 	if (*e != 0 && *e != '.')
193 		RETTOK(DNS_R_SYNTAX);
194 	if (s2 < 0 || s2 > 59)
195 		RETTOK(ISC_R_RANGE);
196 	if (*e == '.') {
197 		const char *l;
198 		e++;
199 		for (i = 0; i < 3; i++) {
200 			if (*e == 0)
201 				break;
202 			if ((tmp = decvalue(*e++)) < 0)
203 				RETTOK(DNS_R_SYNTAX);
204 			s2 *= 10;
205 			s2 += tmp;
206 		}
207 		for (; i < 3; i++)
208 			s2 *= 10;
209 		l = e;
210 		while (*e != 0) {
211 			if (decvalue(*e++) < 0)
212 				RETTOK(DNS_R_SYNTAX);
213 		}
214 		if (*l != '\0' && callbacks != NULL) {
215 			const char *file = isc_lex_getsourcename(lexer);
216 			unsigned long line = isc_lex_getsourceline(lexer);
217 
218 			if (file == NULL)
219 				file = "UNKNOWN";
220 			(*callbacks->warn)(callbacks, "%s: %s:%u: '%s' extra "
221 					   "precision digits ignored",
222 					   "dns_rdata_fromtext",
223 					   file, line, DNS_AS_STR(token));
224 		}
225 	} else
226 		s2 *= 1000;
227 	if (d2 == 180 && s2 != 0)
228 		RETTOK(ISC_R_RANGE);
229 
230 	/*
231 	 * Direction.
232 	 */
233 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
234 				      ISC_FALSE));
235 	if (strcasecmp(DNS_AS_STR(token), "E") == 0)
236 		east = ISC_TRUE;
237 	if (!east && strcasecmp(DNS_AS_STR(token), "W") != 0)
238 		RETTOK(DNS_R_SYNTAX);
239 
240  getalt:
241 	/*
242 	 * Altitude.
243 	 */
244 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
245 				      ISC_FALSE));
246 	m = strtol(DNS_AS_STR(token), &e, 10);
247 	if (*e != 0 && *e != '.' && *e != 'm')
248 		RETTOK(DNS_R_SYNTAX);
249 	if (m < -100000 || m > 42849672)
250 		RETTOK(ISC_R_RANGE);
251 	cm = 0;
252 	if (*e == '.') {
253 		e++;
254 		for (i = 0; i < 2; i++) {
255 			if (*e == 0 || *e == 'm')
256 				break;
257 			if ((tmp = decvalue(*e++)) < 0)
258 				return (DNS_R_SYNTAX);
259 			cm *= 10;
260 			if (m < 0)
261 				cm -= tmp;
262 			else
263 				cm += tmp;
264 		}
265 		for (; i < 2; i++)
266 			cm *= 10;
267 	}
268 	if (*e == 'm')
269 		e++;
270 	if (*e != 0)
271 		RETTOK(DNS_R_SYNTAX);
272 	if (m == -100000 && cm != 0)
273 		RETTOK(ISC_R_RANGE);
274 	if (m == 42849672 && cm > 95)
275 		RETTOK(ISC_R_RANGE);
276 	/*
277 	 * Adjust base.
278 	 */
279 	altitude = m + 100000;
280 	altitude *= 100;
281 	altitude += cm;
282 
283 	/*
284 	 * Size: optional.
285 	 */
286 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
287 				      ISC_TRUE));
288 	if (token.type == isc_tokentype_eol ||
289 	    token.type == isc_tokentype_eof) {
290 		isc_lex_ungettoken(lexer, &token);
291 		goto encode;
292 	}
293 	m = strtol(DNS_AS_STR(token), &e, 10);
294 	if (*e != 0 && *e != '.' && *e != 'm')
295 		RETTOK(DNS_R_SYNTAX);
296 	if (m < 0 || m > 90000000)
297 		RETTOK(ISC_R_RANGE);
298 	cm = 0;
299 	if (*e == '.') {
300 		e++;
301 		for (i = 0; i < 2; i++) {
302 			if (*e == 0 || *e == 'm')
303 				break;
304 			if ((tmp = decvalue(*e++)) < 0)
305 				RETTOK(DNS_R_SYNTAX);
306 			cm *= 10;
307 			cm += tmp;
308 		}
309 		for (; i < 2; i++)
310 			cm *= 10;
311 	}
312 	if (*e == 'm')
313 		e++;
314 	if (*e != 0)
315 		RETTOK(DNS_R_SYNTAX);
316 	/*
317 	 * We don't just multiply out as we will overflow.
318 	 */
319 	if (m > 0) {
320 		for (exp = 0; exp < 7; exp++)
321 			if (m < poweroften[exp+1])
322 				break;
323 		man = m / poweroften[exp];
324 		exp += 2;
325 	} else {
326 		if (cm >= 10) {
327 			man = cm / 10;
328 			exp = 1;
329 		} else {
330 			man = cm;
331 			exp = 0;
332 		}
333 	}
334 	size = (man << 4) + exp;
335 
336 	/*
337 	 * Horizontal precision: optional.
338 	 */
339 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
340 				      ISC_TRUE));
341 	if (token.type == isc_tokentype_eol ||
342 	    token.type == isc_tokentype_eof) {
343 		isc_lex_ungettoken(lexer, &token);
344 		goto encode;
345 	}
346 	m = strtol(DNS_AS_STR(token), &e, 10);
347 	if (*e != 0 && *e != '.' && *e != 'm')
348 		RETTOK(DNS_R_SYNTAX);
349 	if (m < 0 || m > 90000000)
350 		RETTOK(ISC_R_RANGE);
351 	cm = 0;
352 	if (*e == '.') {
353 		e++;
354 		for (i = 0; i < 2; i++) {
355 			if (*e == 0 || *e == 'm')
356 				break;
357 			if ((tmp = decvalue(*e++)) < 0)
358 				RETTOK(DNS_R_SYNTAX);
359 			cm *= 10;
360 			cm += tmp;
361 		}
362 		for (; i < 2; i++)
363 			cm *= 10;
364 	}
365 	if (*e == 'm')
366 		e++;
367 	if (*e != 0)
368 		RETTOK(DNS_R_SYNTAX);
369 	/*
370 	 * We don't just multiply out as we will overflow.
371 	 */
372 	if (m > 0) {
373 		for (exp = 0; exp < 7; exp++)
374 			if (m < poweroften[exp+1])
375 				break;
376 		man = m / poweroften[exp];
377 		exp += 2;
378 	} else if (cm >= 10) {
379 		man = cm / 10;
380 		exp = 1;
381 	} else  {
382 		man = cm;
383 		exp = 0;
384 	}
385 	hp = (man << 4) + exp;
386 
387 	/*
388 	 * Vertical precision: optional.
389 	 */
390 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
391 				      ISC_TRUE));
392 	if (token.type == isc_tokentype_eol ||
393 	    token.type == isc_tokentype_eof) {
394 		isc_lex_ungettoken(lexer, &token);
395 		goto encode;
396 	}
397 	m = strtol(DNS_AS_STR(token), &e, 10);
398 	if (*e != 0 && *e != '.' && *e != 'm')
399 		RETTOK(DNS_R_SYNTAX);
400 	if (m < 0 || m > 90000000)
401 		RETTOK(ISC_R_RANGE);
402 	cm = 0;
403 	if (*e == '.') {
404 		e++;
405 		for (i = 0; i < 2; i++) {
406 			if (*e == 0 || *e == 'm')
407 				break;
408 			if ((tmp = decvalue(*e++)) < 0)
409 				RETTOK(DNS_R_SYNTAX);
410 			cm *= 10;
411 			cm += tmp;
412 		}
413 		for (; i < 2; i++)
414 			cm *= 10;
415 	}
416 	if (*e == 'm')
417 		e++;
418 	if (*e != 0)
419 		RETTOK(DNS_R_SYNTAX);
420 	/*
421 	 * We don't just multiply out as we will overflow.
422 	 */
423 	if (m > 0) {
424 		for (exp = 0; exp < 7; exp++)
425 			if (m < poweroften[exp+1])
426 				break;
427 		man = m / poweroften[exp];
428 		exp += 2;
429 	} else if (cm >= 10) {
430 		man = cm / 10;
431 		exp = 1;
432 	} else {
433 		man = cm;
434 		exp = 0;
435 	}
436 	vp = (man << 4) + exp;
437 
438  encode:
439 	RETERR(mem_tobuffer(target, &version, 1));
440 	RETERR(mem_tobuffer(target, &size, 1));
441 	RETERR(mem_tobuffer(target, &hp, 1));
442 	RETERR(mem_tobuffer(target, &vp, 1));
443 	if (north)
444 		latitude = 0x80000000 + ( d1 * 3600 + m1 * 60 ) * 1000 + s1;
445 	else
446 		latitude = 0x80000000 - ( d1 * 3600 + m1 * 60 ) * 1000 - s1;
447 	RETERR(uint32_tobuffer(latitude, target));
448 
449 	if (east)
450 		longitude = 0x80000000 + ( d2 * 3600 + m2 * 60 ) * 1000 + s2;
451 	else
452 		longitude = 0x80000000 - ( d2 * 3600 + m2 * 60 ) * 1000 - s2;
453 	RETERR(uint32_tobuffer(longitude, target));
454 
455 	return (uint32_tobuffer(altitude, target));
456 }
457 
458 static inline isc_result_t
totext_loc(ARGS_TOTEXT)459 totext_loc(ARGS_TOTEXT) {
460 	int d1, m1, s1, fs1;
461 	int d2, m2, s2, fs2;
462 	unsigned long latitude;
463 	unsigned long longitude;
464 	unsigned long altitude;
465 	isc_boolean_t north;
466 	isc_boolean_t east;
467 	isc_boolean_t below;
468 	isc_region_t sr;
469 	char buf[sizeof("89 59 59.999 N 179 59 59.999 E "
470 			"42849672.95m 90000000m 90000000m 90000000m")];
471 	char sbuf[sizeof("90000000m")];
472 	char hbuf[sizeof("90000000m")];
473 	char vbuf[sizeof("90000000m")];
474 	unsigned char size, hp, vp;
475 	unsigned long poweroften[8] = { 1, 10, 100, 1000,
476 					10000, 100000, 1000000, 10000000 };
477 
478 	UNUSED(tctx);
479 
480 	REQUIRE(rdata->type == 29);
481 	REQUIRE(rdata->length != 0);
482 
483 	dns_rdata_toregion(rdata, &sr);
484 
485 	/* version = sr.base[0]; */
486 	size = sr.base[1];
487 	INSIST((size&0x0f) < 10 && (size>>4) < 10);
488 	if ((size&0x0f)> 1)
489 		sprintf(sbuf, "%lum", (size>>4) * poweroften[(size&0x0f)-2]);
490 	else
491 		sprintf(sbuf, "0.%02lum", (size>>4) * poweroften[(size&0x0f)]);
492 	hp = sr.base[2];
493 	INSIST((hp&0x0f) < 10 && (hp>>4) < 10);
494 	if ((hp&0x0f)> 1)
495 		sprintf(hbuf, "%lum", (hp>>4) * poweroften[(hp&0x0f)-2]);
496 	else
497 		sprintf(hbuf, "0.%02lum", (hp>>4) * poweroften[(hp&0x0f)]);
498 	vp = sr.base[3];
499 	INSIST((vp&0x0f) < 10 && (vp>>4) < 10);
500 	if ((vp&0x0f)> 1)
501 		sprintf(vbuf, "%lum", (vp>>4) * poweroften[(vp&0x0f)-2]);
502 	else
503 		sprintf(vbuf, "0.%02lum", (vp>>4) * poweroften[(vp&0x0f)]);
504 	isc_region_consume(&sr, 4);
505 
506 	latitude = uint32_fromregion(&sr);
507 	isc_region_consume(&sr, 4);
508 	if (latitude >= 0x80000000) {
509 		north = ISC_TRUE;
510 		latitude -= 0x80000000;
511 	} else {
512 		north = ISC_FALSE;
513 		latitude = 0x80000000 - latitude;
514 	}
515 	fs1 = (int)(latitude % 1000);
516 	latitude /= 1000;
517 	s1 = (int)(latitude % 60);
518 	latitude /= 60;
519 	m1 = (int)(latitude % 60);
520 	latitude /= 60;
521 	d1 = (int)latitude;
522 	INSIST(latitude <= 90U);
523 
524 	longitude = uint32_fromregion(&sr);
525 	isc_region_consume(&sr, 4);
526 	if (longitude >= 0x80000000) {
527 		east = ISC_TRUE;
528 		longitude -= 0x80000000;
529 	} else {
530 		east = ISC_FALSE;
531 		longitude = 0x80000000 - longitude;
532 	}
533 	fs2 = (int)(longitude % 1000);
534 	longitude /= 1000;
535 	s2 = (int)(longitude % 60);
536 	longitude /= 60;
537 	m2 = (int)(longitude % 60);
538 	longitude /= 60;
539 	d2 = (int)longitude;
540 	INSIST(longitude <= 180U);
541 
542 	altitude = uint32_fromregion(&sr);
543 	isc_region_consume(&sr, 4);
544 	if (altitude < 10000000U) {
545 		below = ISC_TRUE;
546 		altitude = 10000000 - altitude;
547 	} else {
548 		below =ISC_FALSE;
549 		altitude -= 10000000;
550 	}
551 
552 	sprintf(buf, "%d %d %d.%03d %s %d %d %d.%03d %s %s%ld.%02ldm %s %s %s",
553 		d1, m1, s1, fs1, north ? "N" : "S",
554 		d2, m2, s2, fs2, east ? "E" : "W",
555 		below ? "-" : "", altitude/100, altitude % 100,
556 		sbuf, hbuf, vbuf);
557 
558 	return (str_totext(buf, target));
559 }
560 
561 static inline isc_result_t
fromwire_loc(ARGS_FROMWIRE)562 fromwire_loc(ARGS_FROMWIRE) {
563 	isc_region_t sr;
564 	unsigned char c;
565 	unsigned long latitude;
566 	unsigned long longitude;
567 
568 	REQUIRE(type == 29);
569 
570 	UNUSED(type);
571 	UNUSED(rdclass);
572 	UNUSED(dctx);
573 	UNUSED(options);
574 
575 	isc_buffer_activeregion(source, &sr);
576 	if (sr.length < 1)
577 		return (ISC_R_UNEXPECTEDEND);
578 	if (sr.base[0] != 0)
579 		return (ISC_R_NOTIMPLEMENTED);
580 	if (sr.length < 16)
581 		return (ISC_R_UNEXPECTEDEND);
582 
583 	/*
584 	 * Size.
585 	 */
586 	c = sr.base[1];
587 	if (c != 0)
588 		if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
589 			return (ISC_R_RANGE);
590 
591 	/*
592 	 * Horizontal precision.
593 	 */
594 	c = sr.base[2];
595 	if (c != 0)
596 		if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
597 			return (ISC_R_RANGE);
598 
599 	/*
600 	 * Vertical precision.
601 	 */
602 	c = sr.base[3];
603 	if (c != 0)
604 		if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
605 			return (ISC_R_RANGE);
606 	isc_region_consume(&sr, 4);
607 
608 	/*
609 	 * Latitude.
610 	 */
611 	latitude = uint32_fromregion(&sr);
612 	if (latitude < (0x80000000UL - 90 * 3600000) ||
613 	    latitude > (0x80000000UL + 90 * 3600000))
614 		return (ISC_R_RANGE);
615 	isc_region_consume(&sr, 4);
616 
617 	/*
618 	 * Longitude.
619 	 */
620 	longitude = uint32_fromregion(&sr);
621 	if (longitude < (0x80000000UL - 180 * 3600000) ||
622 	    longitude > (0x80000000UL + 180 * 3600000))
623 		return (ISC_R_RANGE);
624 
625 	/*
626 	 * Altitude.
627 	 * All values possible.
628 	 */
629 
630 	isc_buffer_activeregion(source, &sr);
631 	isc_buffer_forward(source, 16);
632 	return (mem_tobuffer(target, sr.base, 16));
633 }
634 
635 static inline isc_result_t
towire_loc(ARGS_TOWIRE)636 towire_loc(ARGS_TOWIRE) {
637 	UNUSED(cctx);
638 
639 	REQUIRE(rdata->type == 29);
640 	REQUIRE(rdata->length != 0);
641 
642 	return (mem_tobuffer(target, rdata->data, rdata->length));
643 }
644 
645 static inline int
compare_loc(ARGS_COMPARE)646 compare_loc(ARGS_COMPARE) {
647 	isc_region_t r1;
648 	isc_region_t r2;
649 
650 	REQUIRE(rdata1->type == rdata2->type);
651 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
652 	REQUIRE(rdata1->type == 29);
653 	REQUIRE(rdata1->length != 0);
654 	REQUIRE(rdata2->length != 0);
655 
656 	dns_rdata_toregion(rdata1, &r1);
657 	dns_rdata_toregion(rdata2, &r2);
658 	return (isc_region_compare(&r1, &r2));
659 }
660 
661 static inline isc_result_t
fromstruct_loc(ARGS_FROMSTRUCT)662 fromstruct_loc(ARGS_FROMSTRUCT) {
663 	dns_rdata_loc_t *loc = source;
664 	isc_uint8_t c;
665 
666 	REQUIRE(type == 29);
667 	REQUIRE(source != NULL);
668 	REQUIRE(loc->common.rdtype == type);
669 	REQUIRE(loc->common.rdclass == rdclass);
670 
671 	UNUSED(type);
672 	UNUSED(rdclass);
673 
674 	if (loc->v.v0.version != 0)
675 		return (ISC_R_NOTIMPLEMENTED);
676 	RETERR(uint8_tobuffer(loc->v.v0.version, target));
677 
678 	c = loc->v.v0.size;
679 	if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
680 		return (ISC_R_RANGE);
681 	RETERR(uint8_tobuffer(loc->v.v0.size, target));
682 
683 	c = loc->v.v0.horizontal;
684 	if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
685 		return (ISC_R_RANGE);
686 	RETERR(uint8_tobuffer(loc->v.v0.horizontal, target));
687 
688 	c = loc->v.v0.vertical;
689 	if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
690 		return (ISC_R_RANGE);
691 	RETERR(uint8_tobuffer(loc->v.v0.vertical, target));
692 
693 	if (loc->v.v0.latitude < (0x80000000UL - 90 * 3600000) ||
694 	    loc->v.v0.latitude > (0x80000000UL + 90 * 3600000))
695 		return (ISC_R_RANGE);
696 	RETERR(uint32_tobuffer(loc->v.v0.latitude, target));
697 
698 	if (loc->v.v0.longitude < (0x80000000UL - 180 * 3600000) ||
699 	    loc->v.v0.longitude > (0x80000000UL + 180 * 3600000))
700 		return (ISC_R_RANGE);
701 	RETERR(uint32_tobuffer(loc->v.v0.longitude, target));
702 	return (uint32_tobuffer(loc->v.v0.altitude, target));
703 }
704 
705 static inline isc_result_t
tostruct_loc(ARGS_TOSTRUCT)706 tostruct_loc(ARGS_TOSTRUCT) {
707 	dns_rdata_loc_t *loc = target;
708 	isc_region_t r;
709 	isc_uint8_t version;
710 
711 	REQUIRE(rdata->type == 29);
712 	REQUIRE(target != NULL);
713 	REQUIRE(rdata->length != 0);
714 
715 	UNUSED(mctx);
716 
717 	dns_rdata_toregion(rdata, &r);
718 	version = uint8_fromregion(&r);
719 	if (version != 0)
720 		return (ISC_R_NOTIMPLEMENTED);
721 
722 	loc->common.rdclass = rdata->rdclass;
723 	loc->common.rdtype = rdata->type;
724 	ISC_LINK_INIT(&loc->common, link);
725 
726 	loc->v.v0.version = version;
727 	isc_region_consume(&r, 1);
728 	loc->v.v0.size = uint8_fromregion(&r);
729 	isc_region_consume(&r, 1);
730 	loc->v.v0.horizontal = uint8_fromregion(&r);
731 	isc_region_consume(&r, 1);
732 	loc->v.v0.vertical = uint8_fromregion(&r);
733 	isc_region_consume(&r, 1);
734 	loc->v.v0.latitude = uint32_fromregion(&r);
735 	isc_region_consume(&r, 4);
736 	loc->v.v0.longitude = uint32_fromregion(&r);
737 	isc_region_consume(&r, 4);
738 	loc->v.v0.altitude = uint32_fromregion(&r);
739 	isc_region_consume(&r, 4);
740 	return (ISC_R_SUCCESS);
741 }
742 
743 static inline void
freestruct_loc(ARGS_FREESTRUCT)744 freestruct_loc(ARGS_FREESTRUCT) {
745 	dns_rdata_loc_t *loc = source;
746 
747 	REQUIRE(source != NULL);
748 	REQUIRE(loc->common.rdtype == 29);
749 
750 	UNUSED(source);
751 	UNUSED(loc);
752 }
753 
754 static inline isc_result_t
additionaldata_loc(ARGS_ADDLDATA)755 additionaldata_loc(ARGS_ADDLDATA) {
756 	REQUIRE(rdata->type == 29);
757 
758 	UNUSED(rdata);
759 	UNUSED(add);
760 	UNUSED(arg);
761 
762 	return (ISC_R_SUCCESS);
763 }
764 
765 static inline isc_result_t
digest_loc(ARGS_DIGEST)766 digest_loc(ARGS_DIGEST) {
767 	isc_region_t r;
768 
769 	REQUIRE(rdata->type == 29);
770 
771 	dns_rdata_toregion(rdata, &r);
772 
773 	return ((digest)(arg, &r));
774 }
775 
776 static inline isc_boolean_t
checkowner_loc(ARGS_CHECKOWNER)777 checkowner_loc(ARGS_CHECKOWNER) {
778 
779 	REQUIRE(type == 29);
780 
781 	UNUSED(name);
782 	UNUSED(type);
783 	UNUSED(rdclass);
784 	UNUSED(wildcard);
785 
786 	return (ISC_TRUE);
787 }
788 
789 static inline isc_boolean_t
checknames_loc(ARGS_CHECKNAMES)790 checknames_loc(ARGS_CHECKNAMES) {
791 
792 	REQUIRE(rdata->type == 29);
793 
794 	UNUSED(rdata);
795 	UNUSED(owner);
796 	UNUSED(bad);
797 
798 	return (ISC_TRUE);
799 }
800 
801 static inline int
casecompare_loc(ARGS_COMPARE)802 casecompare_loc(ARGS_COMPARE) {
803 	return (compare_loc(rdata1, rdata2));
804 }
805 
806 #endif	/* RDATA_GENERIC_LOC_29_C */
807