xref: /dragonfly/contrib/ldns/rdata.c (revision bcb3e04d)
1 /*
2  * rdata.c
3  *
4  * rdata implementation
5  *
6  * a Net::DNS like library for C
7  *
8  * (c) NLnet Labs, 2004-2006
9  *
10  * See the file LICENSE for the license
11  */
12 
13 #include <ldns/config.h>
14 
15 #include <ldns/ldns.h>
16 
17 /*
18  * Access functions
19  * do this as functions to get type checking
20  */
21 
22 /* read */
23 size_t
24 ldns_rdf_size(const ldns_rdf *rd)
25 {
26 	assert(rd != NULL);
27 	return rd->_size;
28 }
29 
30 ldns_rdf_type
31 ldns_rdf_get_type(const ldns_rdf *rd)
32 {
33 	assert(rd != NULL);
34 	return rd->_type;
35 }
36 
37 uint8_t *
38 ldns_rdf_data(const ldns_rdf *rd)
39 {
40 	assert(rd != NULL);
41 	return rd->_data;
42 }
43 
44 /* write */
45 void
46 ldns_rdf_set_size(ldns_rdf *rd, size_t size)
47 {
48 	assert(rd != NULL);
49 	rd->_size = size;
50 }
51 
52 void
53 ldns_rdf_set_type(ldns_rdf *rd, ldns_rdf_type type)
54 {
55 	assert(rd != NULL);
56 	rd->_type = type;
57 }
58 
59 void
60 ldns_rdf_set_data(ldns_rdf *rd, void *data)
61 {
62 	/* only copy the pointer */
63 	assert(rd != NULL);
64 	rd->_data = data;
65 }
66 
67 /* for types that allow it, return
68  * the native/host order type */
69 uint8_t
70 ldns_rdf2native_int8(const ldns_rdf *rd)
71 {
72 	uint8_t data;
73 
74 	/* only allow 8 bit rdfs */
75 	if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_BYTE) {
76 		return 0;
77 	}
78 
79 	memcpy(&data, ldns_rdf_data(rd), sizeof(data));
80 	return data;
81 }
82 
83 uint16_t
84 ldns_rdf2native_int16(const ldns_rdf *rd)
85 {
86 	uint16_t data;
87 
88 	/* only allow 16 bit rdfs */
89 	if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_WORD) {
90 		return 0;
91 	}
92 
93 	memcpy(&data, ldns_rdf_data(rd), sizeof(data));
94 	return ntohs(data);
95 }
96 
97 uint32_t
98 ldns_rdf2native_int32(const ldns_rdf *rd)
99 {
100 	uint32_t data;
101 
102 	/* only allow 32 bit rdfs */
103 	if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_DOUBLEWORD) {
104 		return 0;
105 	}
106 
107 	memcpy(&data, ldns_rdf_data(rd), sizeof(data));
108 	return ntohl(data);
109 }
110 
111 time_t
112 ldns_rdf2native_time_t(const ldns_rdf *rd)
113 {
114 	uint32_t data;
115 
116 	switch(ldns_rdf_get_type(rd)) {
117 		case LDNS_RDF_TYPE_TIME:
118 			memcpy(&data, ldns_rdf_data(rd), sizeof(data));
119 			return (time_t)ntohl(data);
120 		default:
121 			return 0;
122 	}
123 }
124 
125 ldns_rdf *
126 ldns_native2rdf_int8(ldns_rdf_type type, uint8_t value)
127 {
128 	return ldns_rdf_new_frm_data(type, LDNS_RDF_SIZE_BYTE, &value);
129 }
130 
131 ldns_rdf *
132 ldns_native2rdf_int16(ldns_rdf_type type, uint16_t value)
133 {
134 	uint16_t *rdf_data = LDNS_XMALLOC(uint16_t, 1);
135 	if (!rdf_data) {
136 		return NULL;
137 	}
138 	ldns_write_uint16(rdf_data, value);
139 	return ldns_rdf_new(type, LDNS_RDF_SIZE_WORD, rdf_data);
140 }
141 
142 ldns_rdf *
143 ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value)
144 {
145 	uint32_t *rdf_data = LDNS_XMALLOC(uint32_t, 1);
146 	if (!rdf_data) {
147 		return NULL;
148 	}
149 	ldns_write_uint32(rdf_data, value);
150 	return ldns_rdf_new(type, LDNS_RDF_SIZE_DOUBLEWORD, rdf_data);
151 }
152 
153 ldns_rdf *
154 ldns_native2rdf_int16_data(size_t size, uint8_t *data)
155 {
156 	uint8_t *rdf_data = LDNS_XMALLOC(uint8_t, size + 2);
157 	if (!rdf_data) {
158 		return NULL;
159 	}
160 	ldns_write_uint16(rdf_data, size);
161 	memcpy(rdf_data + 2, data, size);
162 	return ldns_rdf_new(LDNS_RDF_TYPE_INT16_DATA, size + 2, rdf_data);
163 }
164 
165 /* note: data must be allocated memory */
166 ldns_rdf *
167 ldns_rdf_new(ldns_rdf_type type, size_t size, void *data)
168 {
169 	ldns_rdf *rd;
170 	rd = LDNS_MALLOC(ldns_rdf);
171 	if (!rd) {
172 		return NULL;
173 	}
174 	ldns_rdf_set_size(rd, size);
175 	ldns_rdf_set_type(rd, type);
176 	ldns_rdf_set_data(rd, data);
177 	return rd;
178 }
179 
180 ldns_rdf *
181 ldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data)
182 {
183 	ldns_rdf *rdf;
184 
185 	/* if the size is too big, fail */
186 	if (size > LDNS_MAX_RDFLEN) {
187 		return NULL;
188 	}
189 
190 	/* allocate space */
191 	rdf = LDNS_MALLOC(ldns_rdf);
192 	if (!rdf) {
193 		return NULL;
194 	}
195 	rdf->_data = LDNS_XMALLOC(uint8_t, size);
196 	if (!rdf->_data) {
197 		LDNS_FREE(rdf);
198 		return NULL;
199 	}
200 
201 	/* set the values */
202 	ldns_rdf_set_type(rdf, type);
203 	ldns_rdf_set_size(rdf, size);
204 	memcpy(rdf->_data, data, size);
205 
206 	return rdf;
207 }
208 
209 ldns_rdf *
210 ldns_rdf_clone(const ldns_rdf *rd)
211 {
212 	assert(rd != NULL);
213 	return (ldns_rdf_new_frm_data( ldns_rdf_get_type(rd),
214 		ldns_rdf_size(rd), ldns_rdf_data(rd)));
215 }
216 
217 void
218 ldns_rdf_deep_free(ldns_rdf *rd)
219 {
220 	if (rd) {
221 		if (rd->_data) {
222 			LDNS_FREE(rd->_data);
223 		}
224 		LDNS_FREE(rd);
225 	}
226 }
227 
228 void
229 ldns_rdf_free(ldns_rdf *rd)
230 {
231 	if (rd) {
232 		LDNS_FREE(rd);
233 	}
234 }
235 
236 ldns_rdf *
237 ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str)
238 {
239 	ldns_rdf *rdf = NULL;
240 	ldns_status status;
241 
242 	switch (type) {
243 	case LDNS_RDF_TYPE_DNAME:
244 		status = ldns_str2rdf_dname(&rdf, str);
245 		break;
246 	case LDNS_RDF_TYPE_INT8:
247 		status = ldns_str2rdf_int8(&rdf, str);
248 		break;
249 	case LDNS_RDF_TYPE_INT16:
250 		status = ldns_str2rdf_int16(&rdf, str);
251 		break;
252 	case LDNS_RDF_TYPE_INT32:
253 		status = ldns_str2rdf_int32(&rdf, str);
254 		break;
255 	case LDNS_RDF_TYPE_A:
256 		status = ldns_str2rdf_a(&rdf, str);
257 		break;
258 	case LDNS_RDF_TYPE_AAAA:
259 		status = ldns_str2rdf_aaaa(&rdf, str);
260 		break;
261 	case LDNS_RDF_TYPE_STR:
262 		status = ldns_str2rdf_str(&rdf, str);
263 		break;
264 	case LDNS_RDF_TYPE_APL:
265 		status = ldns_str2rdf_apl(&rdf, str);
266 		break;
267 	case LDNS_RDF_TYPE_B64:
268 		status = ldns_str2rdf_b64(&rdf, str);
269 		break;
270 	case LDNS_RDF_TYPE_B32_EXT:
271 		status = ldns_str2rdf_b32_ext(&rdf, str);
272 		break;
273 	case LDNS_RDF_TYPE_HEX:
274 		status = ldns_str2rdf_hex(&rdf, str);
275 		break;
276 	case LDNS_RDF_TYPE_NSEC:
277 		status = ldns_str2rdf_nsec(&rdf, str);
278 		break;
279 	case LDNS_RDF_TYPE_TYPE:
280 		status = ldns_str2rdf_type(&rdf, str);
281 		break;
282 	case LDNS_RDF_TYPE_CLASS:
283 		status = ldns_str2rdf_class(&rdf, str);
284 		break;
285 	case LDNS_RDF_TYPE_CERT_ALG:
286 		status = ldns_str2rdf_cert_alg(&rdf, str);
287 		break;
288 	case LDNS_RDF_TYPE_ALG:
289 		status = ldns_str2rdf_alg(&rdf, str);
290 		break;
291 	case LDNS_RDF_TYPE_UNKNOWN:
292 		status = ldns_str2rdf_unknown(&rdf, str);
293 		break;
294 	case LDNS_RDF_TYPE_TIME:
295 		status = ldns_str2rdf_time(&rdf, str);
296 		break;
297 	case LDNS_RDF_TYPE_PERIOD:
298 		status = ldns_str2rdf_period(&rdf, str);
299 		break;
300 	case LDNS_RDF_TYPE_TSIG:
301 		status = ldns_str2rdf_tsig(&rdf, str);
302 		break;
303 	case LDNS_RDF_TYPE_SERVICE:
304 		status = ldns_str2rdf_service(&rdf, str);
305 		break;
306 	case LDNS_RDF_TYPE_LOC:
307 		status = ldns_str2rdf_loc(&rdf, str);
308 		break;
309 	case LDNS_RDF_TYPE_WKS:
310 		status = ldns_str2rdf_wks(&rdf, str);
311 		break;
312 	case LDNS_RDF_TYPE_NSAP:
313 		status = ldns_str2rdf_nsap(&rdf, str);
314 		break;
315 	case LDNS_RDF_TYPE_ATMA:
316 		status = ldns_str2rdf_atma(&rdf, str);
317 		break;
318 	case LDNS_RDF_TYPE_IPSECKEY:
319 		status = ldns_str2rdf_ipseckey(&rdf, str);
320 		break;
321 	case LDNS_RDF_TYPE_NSEC3_SALT:
322 		status = ldns_str2rdf_nsec3_salt(&rdf, str);
323 		break;
324 	case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
325 		status = ldns_str2rdf_b32_ext(&rdf, str);
326 		break;
327 	case LDNS_RDF_TYPE_NONE:
328 	default:
329 		/* default default ??? */
330 		status = LDNS_STATUS_ERR;
331 		break;
332 	}
333 	if (LDNS_STATUS_OK == status) {
334 		ldns_rdf_set_type(rdf, type);
335 		return rdf;
336 	}
337 	if (rdf) {
338 		LDNS_FREE(rdf);
339 	}
340 	return NULL;
341 }
342 
343 ldns_status
344 ldns_rdf_new_frm_fp(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp)
345 {
346 	return ldns_rdf_new_frm_fp_l(rdf, type, fp, NULL);
347 }
348 
349 ldns_status
350 ldns_rdf_new_frm_fp_l(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp, int *line_nr)
351 {
352 	char *line;
353 	ldns_rdf *r;
354 	ssize_t t;
355 
356 	line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
357 	if (!line) {
358 		return LDNS_STATUS_MEM_ERR;
359 	}
360 
361 	/* read an entire line in from the file */
362 	if ((t = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, 0, line_nr)) == -1) {
363 		LDNS_FREE(line);
364 		return LDNS_STATUS_SYNTAX_RDATA_ERR;
365 	}
366 	r =  ldns_rdf_new_frm_str(type, (const char*) line);
367 	LDNS_FREE(line);
368 	if (rdf) {
369 		*rdf = r;
370 		return LDNS_STATUS_OK;
371 	} else {
372 		return LDNS_STATUS_NULL;
373 	}
374 }
375 
376 ldns_rdf *
377 ldns_rdf_address_reverse(ldns_rdf *rd)
378 {
379 	uint8_t buf_4[LDNS_IP4ADDRLEN];
380 	uint8_t buf_6[LDNS_IP6ADDRLEN * 2];
381 	ldns_rdf *rev;
382 	ldns_rdf *in_addr;
383 	ldns_rdf *ret_dname;
384 	uint8_t octet;
385 	uint8_t nnibble;
386 	uint8_t nibble;
387 	uint8_t i, j;
388 
389 	char *char_dname;
390 	int nbit;
391 
392 	if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_A &&
393 			ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_AAAA) {
394 		return NULL;
395 	}
396 
397 	in_addr = NULL;
398 	ret_dname = NULL;
399 
400 	switch(ldns_rdf_get_type(rd)) {
401 		case LDNS_RDF_TYPE_A:
402 			/* the length of the buffer is 4 */
403 			buf_4[3] = ldns_rdf_data(rd)[0];
404 			buf_4[2] = ldns_rdf_data(rd)[1];
405 			buf_4[1] = ldns_rdf_data(rd)[2];
406 			buf_4[0] = ldns_rdf_data(rd)[3];
407 			in_addr = ldns_dname_new_frm_str("in-addr.arpa.");
408 			if (!in_addr) {
409 				return NULL;
410 			}
411 			/* make a new rdf and convert that back  */
412 			rev = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_A,
413 				LDNS_IP4ADDRLEN, (void*)&buf_4);
414 			if (!rev) {
415 				LDNS_FREE(in_addr);
416 				return NULL;
417 			}
418 
419 			/* convert rev to a string */
420 			char_dname = ldns_rdf2str(rev);
421 			if (!char_dname) {
422 				LDNS_FREE(in_addr);
423 				ldns_rdf_deep_free(rev);
424 				return NULL;
425 			}
426 			/* transform back to rdf with type dname */
427 			ret_dname = ldns_dname_new_frm_str(char_dname);
428 			if (!ret_dname) {
429 				LDNS_FREE(in_addr);
430 				ldns_rdf_deep_free(rev);
431 				LDNS_FREE(char_dname);
432 				return NULL;
433 			}
434 			/* not needed anymore */
435 			ldns_rdf_deep_free(rev);
436 			LDNS_FREE(char_dname);
437 			break;
438 		case LDNS_RDF_TYPE_AAAA:
439 			/* some foo magic to reverse the nibbles ... */
440 
441 			for (nbit = 127; nbit >= 0; nbit = nbit - 4) {
442 				/* calculate octett (8 bit) */
443 				octet = ( ((unsigned int) nbit) & 0x78) >> 3;
444 				/* calculate nibble */
445 				nnibble = ( ((unsigned int) nbit) & 0x04) >> 2;
446 				/* extract nibble */
447 				nibble = (ldns_rdf_data(rd)[octet] & ( 0xf << (4 * (1 -
448 						 nnibble)) ) ) >> ( 4 * (1 -
449 						nnibble));
450 
451 				buf_6[(LDNS_IP6ADDRLEN * 2 - 1) -
452 					(octet * 2 + nnibble)] =
453 						(uint8_t)ldns_int_to_hexdigit((int)nibble);
454 			}
455 
456 			char_dname = LDNS_XMALLOC(char, (LDNS_IP6ADDRLEN * 4));
457 			if (!char_dname) {
458 				return NULL;
459 			}
460 			char_dname[LDNS_IP6ADDRLEN * 4 - 1] = '\0'; /* closure */
461 
462 			/* walk the string and add . 's */
463 			for (i = 0, j = 0; i < LDNS_IP6ADDRLEN * 2; i++, j = j + 2) {
464 				char_dname[j] = (char)buf_6[i];
465 				if (i != LDNS_IP6ADDRLEN * 2 - 1) {
466 					char_dname[j + 1] = '.';
467 				}
468 			}
469 			in_addr = ldns_dname_new_frm_str("ip6.arpa.");
470 			if (!in_addr) {
471 				LDNS_FREE(char_dname);
472 				return NULL;
473 			}
474 
475 			/* convert rev to a string */
476 			ret_dname = ldns_dname_new_frm_str(char_dname);
477 			LDNS_FREE(char_dname);
478 			if (!ret_dname) {
479 				ldns_rdf_deep_free(in_addr);
480 				return NULL;
481 			}
482 			break;
483 		default:
484 			break;
485 	}
486 	/* add the suffix */
487 	rev = ldns_dname_cat_clone(ret_dname, in_addr);
488 
489 	ldns_rdf_deep_free(ret_dname);
490 	ldns_rdf_deep_free(in_addr);
491 	return rev;
492 }
493 
494 ldns_status
495 ldns_octet(char *word, size_t *length)
496 {
497     char *s;
498     char *p;
499     *length = 0;
500 
501     for (s = p = word; *s != '\0'; s++,p++) {
502         switch (*s) {
503             case '.':
504                 if (s[1] == '.') {
505 		    return LDNS_STATUS_EMPTY_LABEL;
506                 }
507                 *p = *s;
508                 (*length)++;
509                 break;
510             case '\\':
511                 if ('0' <= s[1] && s[1] <= '9' &&
512                     '0' <= s[2] && s[2] <= '9' &&
513                     '0' <= s[3] && s[3] <= '9') {
514                     /* \DDD seen */
515                     int val = ((s[1] - '0') * 100 +
516                            (s[2] - '0') * 10 + (s[3] - '0'));
517 
518                     if (0 <= val && val <= 255) {
519                         /* this also handles \0 */
520                         s += 3;
521                         *p = val;
522                         (*length)++;
523                     } else {
524                         return LDNS_STATUS_DDD_OVERFLOW;
525                     }
526                 } else {
527                     /* an espaced character, like \<space> ?
528                     * remove the '\' keep the rest */
529                     *p = *++s;
530                     (*length)++;
531                 }
532                 break;
533             case '\"':
534                 /* non quoted " Is either first or the last character in
535                  * the string */
536 
537                 *p = *++s; /* skip it */
538                 (*length)++;
539 		/* I'm not sure if this is needed in libdns... MG */
540                 if ( *s == '\0' ) {
541                     /* ok, it was the last one */
542                     *p  = '\0';
543 		    return LDNS_STATUS_OK;
544                 }
545                 break;
546             default:
547                 *p = *s;
548                 (*length)++;
549                 break;
550         }
551     }
552     *p = '\0';
553     return LDNS_STATUS_OK;
554 }
555 
556 int
557 ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2)
558 {
559 	uint16_t i1, i2, i;
560 	uint8_t *d1, *d2;
561 
562 	/* only when both are not NULL we can say anything about them */
563 	if (!rd1 && !rd2) {
564 		return 0;
565 	}
566 	if (!rd1 || !rd2) {
567 		return -1;
568 	}
569 	i1 = ldns_rdf_size(rd1);
570 	i2 = ldns_rdf_size(rd2);
571 
572 	if (i1 < i2) {
573 		return -1;
574 	} else if (i1 > i2) {
575 		return +1;
576 	} else {
577 		d1 = (uint8_t*)ldns_rdf_data(rd1);
578 		d2 = (uint8_t*)ldns_rdf_data(rd2);
579 		for(i = 0; i < i1; i++) {
580 			if (d1[i] < d2[i]) {
581 				return -1;
582 			} else if (d1[i] > d2[i]) {
583 				return +1;
584 			}
585 		}
586 	}
587 	return 0;
588 }
589 
590 uint32_t
591 ldns_str2period(const char *nptr, const char **endptr)
592 {
593 	int sign = 0;
594 	uint32_t i = 0;
595 	uint32_t seconds = 0;
596 
597 	for(*endptr = nptr; **endptr; (*endptr)++) {
598 		switch (**endptr) {
599 			case ' ':
600 			case '\t':
601 				break;
602 			case '-':
603 				if(sign == 0) {
604 					sign = -1;
605 				} else {
606 					return seconds;
607 				}
608 				break;
609 			case '+':
610 				if(sign == 0) {
611 					sign = 1;
612 				} else {
613 					return seconds;
614 				}
615 				break;
616 			case 's':
617 			case 'S':
618 				seconds += i;
619 				i = 0;
620 				break;
621 			case 'm':
622 			case 'M':
623 				seconds += i * 60;
624 				i = 0;
625 				break;
626 			case 'h':
627 			case 'H':
628 				seconds += i * 60 * 60;
629 				i = 0;
630 				break;
631 			case 'd':
632 			case 'D':
633 				seconds += i * 60 * 60 * 24;
634 				i = 0;
635 				break;
636 			case 'w':
637 			case 'W':
638 				seconds += i * 60 * 60 * 24 * 7;
639 				i = 0;
640 				break;
641 			case '0':
642 			case '1':
643 			case '2':
644 			case '3':
645 			case '4':
646 			case '5':
647 			case '6':
648 			case '7':
649 			case '8':
650 			case '9':
651 				i *= 10;
652 				i += (**endptr - '0');
653 				break;
654 			default:
655 				seconds += i;
656 				/* disregard signedness */
657 				return seconds;
658 		}
659 	}
660 	seconds += i;
661 	/* disregard signedness */
662 	return seconds;
663 }
664