xref: /dragonfly/contrib/ldns/rdata.c (revision 26720ae0)
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 	/* only allow 32 bit rdfs */
117 	if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_DOUBLEWORD ||
118 			ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_TIME) {
119 		return 0;
120 	}
121 	memcpy(&data, ldns_rdf_data(rd), sizeof(data));
122 	return (time_t)ntohl(data);
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         ldns_rdf* rdf;
136 	if (!rdf_data) {
137 		return NULL;
138 	}
139 	ldns_write_uint16(rdf_data, value);
140 	rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_WORD, rdf_data);
141         if(!rdf)
142                 LDNS_FREE(rdf_data);
143         return rdf;
144 }
145 
146 ldns_rdf *
147 ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value)
148 {
149 	uint32_t *rdf_data = LDNS_XMALLOC(uint32_t, 1);
150         ldns_rdf* rdf;
151 	if (!rdf_data) {
152 		return NULL;
153 	}
154 	ldns_write_uint32(rdf_data, value);
155 	rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_DOUBLEWORD, rdf_data);
156         if(!rdf)
157                 LDNS_FREE(rdf_data);
158         return rdf;
159 }
160 
161 ldns_rdf *
162 ldns_native2rdf_int16_data(size_t size, uint8_t *data)
163 {
164 	uint8_t *rdf_data = LDNS_XMALLOC(uint8_t, size + 2);
165         ldns_rdf* rdf;
166 	if (!rdf_data) {
167 		return NULL;
168 	}
169 	ldns_write_uint16(rdf_data, size);
170 	memcpy(rdf_data + 2, data, size);
171 	rdf = ldns_rdf_new(LDNS_RDF_TYPE_INT16_DATA, size + 2, rdf_data);
172         if(!rdf)
173                 LDNS_FREE(rdf_data);
174         return rdf;
175 }
176 
177 /* note: data must be allocated memory */
178 ldns_rdf *
179 ldns_rdf_new(ldns_rdf_type type, size_t size, void *data)
180 {
181 	ldns_rdf *rd;
182 	rd = LDNS_MALLOC(ldns_rdf);
183 	if (!rd) {
184 		return NULL;
185 	}
186 	ldns_rdf_set_size(rd, size);
187 	ldns_rdf_set_type(rd, type);
188 	ldns_rdf_set_data(rd, data);
189 	return rd;
190 }
191 
192 ldns_rdf *
193 ldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data)
194 {
195 	ldns_rdf *rdf;
196 
197 	/* if the size is too big, fail */
198 	if (size > LDNS_MAX_RDFLEN) {
199 		return NULL;
200 	}
201 
202 	/* allocate space */
203 	rdf = LDNS_MALLOC(ldns_rdf);
204 	if (!rdf) {
205 		return NULL;
206 	}
207 	rdf->_data = LDNS_XMALLOC(uint8_t, size);
208 	if (!rdf->_data) {
209 		LDNS_FREE(rdf);
210 		return NULL;
211 	}
212 
213 	/* set the values */
214 	ldns_rdf_set_type(rdf, type);
215 	ldns_rdf_set_size(rdf, size);
216 	memcpy(rdf->_data, data, size);
217 
218 	return rdf;
219 }
220 
221 ldns_rdf *
222 ldns_rdf_clone(const ldns_rdf *rd)
223 {
224 	assert(rd != NULL);
225 	return (ldns_rdf_new_frm_data( ldns_rdf_get_type(rd),
226 		ldns_rdf_size(rd), ldns_rdf_data(rd)));
227 }
228 
229 void
230 ldns_rdf_deep_free(ldns_rdf *rd)
231 {
232 	if (rd) {
233 		if (rd->_data) {
234 			LDNS_FREE(rd->_data);
235 		}
236 		LDNS_FREE(rd);
237 	}
238 }
239 
240 void
241 ldns_rdf_free(ldns_rdf *rd)
242 {
243 	if (rd) {
244 		LDNS_FREE(rd);
245 	}
246 }
247 
248 ldns_rdf *
249 ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str)
250 {
251 	ldns_rdf *rdf = NULL;
252 	ldns_status status;
253 
254 	switch (type) {
255 	case LDNS_RDF_TYPE_DNAME:
256 		status = ldns_str2rdf_dname(&rdf, str);
257 		break;
258 	case LDNS_RDF_TYPE_INT8:
259 		status = ldns_str2rdf_int8(&rdf, str);
260 		break;
261 	case LDNS_RDF_TYPE_INT16:
262 		status = ldns_str2rdf_int16(&rdf, str);
263 		break;
264 	case LDNS_RDF_TYPE_INT32:
265 		status = ldns_str2rdf_int32(&rdf, str);
266 		break;
267 	case LDNS_RDF_TYPE_A:
268 		status = ldns_str2rdf_a(&rdf, str);
269 		break;
270 	case LDNS_RDF_TYPE_AAAA:
271 		status = ldns_str2rdf_aaaa(&rdf, str);
272 		break;
273 	case LDNS_RDF_TYPE_STR:
274 		status = ldns_str2rdf_str(&rdf, str);
275 		break;
276 	case LDNS_RDF_TYPE_APL:
277 		status = ldns_str2rdf_apl(&rdf, str);
278 		break;
279 	case LDNS_RDF_TYPE_B64:
280 		status = ldns_str2rdf_b64(&rdf, str);
281 		break;
282 	case LDNS_RDF_TYPE_B32_EXT:
283 		status = ldns_str2rdf_b32_ext(&rdf, str);
284 		break;
285 	case LDNS_RDF_TYPE_HEX:
286 		status = ldns_str2rdf_hex(&rdf, str);
287 		break;
288 	case LDNS_RDF_TYPE_NSEC:
289 		status = ldns_str2rdf_nsec(&rdf, str);
290 		break;
291 	case LDNS_RDF_TYPE_TYPE:
292 		status = ldns_str2rdf_type(&rdf, str);
293 		break;
294 	case LDNS_RDF_TYPE_CLASS:
295 		status = ldns_str2rdf_class(&rdf, str);
296 		break;
297 	case LDNS_RDF_TYPE_CERT_ALG:
298 		status = ldns_str2rdf_cert_alg(&rdf, str);
299 		break;
300 	case LDNS_RDF_TYPE_ALG:
301 		status = ldns_str2rdf_alg(&rdf, str);
302 		break;
303 	case LDNS_RDF_TYPE_UNKNOWN:
304 		status = ldns_str2rdf_unknown(&rdf, str);
305 		break;
306 	case LDNS_RDF_TYPE_TIME:
307 		status = ldns_str2rdf_time(&rdf, str);
308 		break;
309 	case LDNS_RDF_TYPE_PERIOD:
310 		status = ldns_str2rdf_period(&rdf, str);
311 		break;
312 	case LDNS_RDF_TYPE_HIP:
313 		status = ldns_str2rdf_hip(&rdf, str);
314 		break;
315 	case LDNS_RDF_TYPE_SERVICE:
316 		status = ldns_str2rdf_service(&rdf, str);
317 		break;
318 	case LDNS_RDF_TYPE_LOC:
319 		status = ldns_str2rdf_loc(&rdf, str);
320 		break;
321 	case LDNS_RDF_TYPE_WKS:
322 		status = ldns_str2rdf_wks(&rdf, str);
323 		break;
324 	case LDNS_RDF_TYPE_NSAP:
325 		status = ldns_str2rdf_nsap(&rdf, str);
326 		break;
327 	case LDNS_RDF_TYPE_ATMA:
328 		status = ldns_str2rdf_atma(&rdf, str);
329 		break;
330 	case LDNS_RDF_TYPE_IPSECKEY:
331 		status = ldns_str2rdf_ipseckey(&rdf, str);
332 		break;
333 	case LDNS_RDF_TYPE_NSEC3_SALT:
334 		status = ldns_str2rdf_nsec3_salt(&rdf, str);
335 		break;
336 	case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
337 		status = ldns_str2rdf_b32_ext(&rdf, str);
338 		break;
339 	case LDNS_RDF_TYPE_ILNP64:
340 		status = ldns_str2rdf_ilnp64(&rdf, str);
341 		break;
342 	case LDNS_RDF_TYPE_EUI48:
343 		status = ldns_str2rdf_eui48(&rdf, str);
344 		break;
345 	case LDNS_RDF_TYPE_EUI64:
346 		status = ldns_str2rdf_eui64(&rdf, str);
347 		break;
348 	case LDNS_RDF_TYPE_TAG:
349 		status = ldns_str2rdf_tag(&rdf, str);
350 		break;
351 	case LDNS_RDF_TYPE_LONG_STR:
352 		status = ldns_str2rdf_long_str(&rdf, str);
353 		break;
354 	case LDNS_RDF_TYPE_CERTIFICATE_USAGE:
355 		status = ldns_str2rdf_certificate_usage(&rdf, str);
356 		break;
357 	case LDNS_RDF_TYPE_SELECTOR:
358 		status = ldns_str2rdf_selector(&rdf, str);
359 		break;
360 	case LDNS_RDF_TYPE_MATCHING_TYPE:
361 		status = ldns_str2rdf_matching_type(&rdf, str);
362 		break;
363 	case LDNS_RDF_TYPE_AMTRELAY:
364 		status = ldns_str2rdf_amtrelay(&rdf, str);
365 		break;
366 	case LDNS_RDF_TYPE_NONE:
367 	default:
368 		/* default default ??? */
369 		status = LDNS_STATUS_ERR;
370 		break;
371 	}
372 	if (LDNS_STATUS_OK == status) {
373 		ldns_rdf_set_type(rdf, type);
374 		return rdf;
375 	}
376 	if (rdf) {
377 		LDNS_FREE(rdf);
378 	}
379 	return NULL;
380 }
381 
382 ldns_status
383 ldns_rdf_new_frm_fp(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp)
384 {
385 	return ldns_rdf_new_frm_fp_l(rdf, type, fp, NULL);
386 }
387 
388 ldns_status
389 ldns_rdf_new_frm_fp_l(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp, int *line_nr)
390 {
391 	char *line;
392 	ldns_rdf *r;
393 	ssize_t t;
394 
395 	line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
396 	if (!line) {
397 		return LDNS_STATUS_MEM_ERR;
398 	}
399 
400 	/* read an entire line in from the file */
401 	if ((t = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, 0, line_nr)) == -1 || t == 0) {
402 		LDNS_FREE(line);
403 		return LDNS_STATUS_SYNTAX_RDATA_ERR;
404 	}
405 	r =  ldns_rdf_new_frm_str(type, (const char*) line);
406 	LDNS_FREE(line);
407 	if (rdf) {
408 		*rdf = r;
409 		return LDNS_STATUS_OK;
410 	} else {
411 		return LDNS_STATUS_NULL;
412 	}
413 }
414 
415 ldns_rdf *
416 ldns_rdf_address_reverse(const ldns_rdf *rd)
417 {
418 	uint8_t buf_4[LDNS_IP4ADDRLEN];
419 	uint8_t buf_6[LDNS_IP6ADDRLEN * 2];
420 	ldns_rdf *rev;
421 	ldns_rdf *in_addr;
422 	ldns_rdf *ret_dname;
423 	uint8_t octet;
424 	uint8_t nnibble;
425 	uint8_t nibble;
426 	uint8_t i, j;
427 
428 	char *char_dname;
429 	int nbit;
430 
431 	if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_A &&
432 			ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_AAAA) {
433 		return NULL;
434 	}
435 
436 	in_addr = NULL;
437 	ret_dname = NULL;
438 
439 	switch(ldns_rdf_get_type(rd)) {
440 		case LDNS_RDF_TYPE_A:
441 			/* the length of the buffer is 4 */
442 			buf_4[3] = ldns_rdf_data(rd)[0];
443 			buf_4[2] = ldns_rdf_data(rd)[1];
444 			buf_4[1] = ldns_rdf_data(rd)[2];
445 			buf_4[0] = ldns_rdf_data(rd)[3];
446 			in_addr = ldns_dname_new_frm_str("in-addr.arpa.");
447 			if (!in_addr) {
448 				return NULL;
449 			}
450 			/* make a new rdf and convert that back  */
451 			rev = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_A,
452 				LDNS_IP4ADDRLEN, (void*)&buf_4);
453 			if (!rev) {
454 				LDNS_FREE(in_addr);
455 				return NULL;
456 			}
457 
458 			/* convert rev to a string */
459 			char_dname = ldns_rdf2str(rev);
460 			if (!char_dname) {
461 				LDNS_FREE(in_addr);
462 				ldns_rdf_deep_free(rev);
463 				return NULL;
464 			}
465 			/* transform back to rdf with type dname */
466 			ret_dname = ldns_dname_new_frm_str(char_dname);
467 			if (!ret_dname) {
468 				LDNS_FREE(in_addr);
469 				ldns_rdf_deep_free(rev);
470 				LDNS_FREE(char_dname);
471 				return NULL;
472 			}
473 			/* not needed anymore */
474 			ldns_rdf_deep_free(rev);
475 			LDNS_FREE(char_dname);
476 			break;
477 		case LDNS_RDF_TYPE_AAAA:
478 			/* some foo magic to reverse the nibbles ... */
479 
480 			for (nbit = 127; nbit >= 0; nbit = nbit - 4) {
481 				/* calculate octet (8 bit) */
482 				octet = ( ((unsigned int) nbit) & 0x78) >> 3;
483 				/* calculate nibble */
484 				nnibble = ( ((unsigned int) nbit) & 0x04) >> 2;
485 				/* extract nibble */
486 				nibble = (ldns_rdf_data(rd)[octet] & ( 0xf << (4 * (1 -
487 						 nnibble)) ) ) >> ( 4 * (1 -
488 						nnibble));
489 
490 				buf_6[(LDNS_IP6ADDRLEN * 2 - 1) -
491 					(octet * 2 + nnibble)] =
492 						(uint8_t)ldns_int_to_hexdigit((int)nibble);
493 			}
494 
495 			char_dname = LDNS_XMALLOC(char, (LDNS_IP6ADDRLEN * 4));
496 			if (!char_dname) {
497 				return NULL;
498 			}
499 			char_dname[LDNS_IP6ADDRLEN * 4 - 1] = '\0'; /* closure */
500 
501 			/* walk the string and add . 's */
502 			for (i = 0, j = 0; i < LDNS_IP6ADDRLEN * 2; i++, j = j + 2) {
503 				char_dname[j] = (char)buf_6[i];
504 				if (i != LDNS_IP6ADDRLEN * 2 - 1) {
505 					char_dname[j + 1] = '.';
506 				}
507 			}
508 			in_addr = ldns_dname_new_frm_str("ip6.arpa.");
509 			if (!in_addr) {
510 				LDNS_FREE(char_dname);
511 				return NULL;
512 			}
513 
514 			/* convert rev to a string */
515 			ret_dname = ldns_dname_new_frm_str(char_dname);
516 			LDNS_FREE(char_dname);
517 			if (!ret_dname) {
518 				ldns_rdf_deep_free(in_addr);
519 				return NULL;
520 			}
521 			break;
522 		default:
523 			break;
524 	}
525 	/* add the suffix */
526 	rev = ldns_dname_cat_clone(ret_dname, in_addr);
527 
528 	ldns_rdf_deep_free(ret_dname);
529 	ldns_rdf_deep_free(in_addr);
530 	return rev;
531 }
532 
533 ldns_status
534 ldns_rdf_hip_get_alg_hit_pk(ldns_rdf *rdf, uint8_t* alg,
535                             uint8_t *hit_size, uint8_t** hit,
536                             uint16_t *pk_size, uint8_t** pk)
537 {
538 	uint8_t *data;
539 	size_t rdf_size;
540 
541 	if (! rdf || ! alg || ! hit || ! hit_size || ! pk || ! pk_size) {
542 		return LDNS_STATUS_INVALID_POINTER;
543 	} else if (ldns_rdf_get_type(rdf) != LDNS_RDF_TYPE_HIP) {
544 		return LDNS_STATUS_INVALID_RDF_TYPE;
545 	} else if ((rdf_size = ldns_rdf_size(rdf)) < 6) {
546 		return LDNS_STATUS_WIRE_RDATA_ERR;
547 	}
548 	data = ldns_rdf_data(rdf);
549 	*hit_size = data[0];
550 	*alg      = data[1];
551 	*pk_size  = ldns_read_uint16(data + 2);
552 	*hit      = data + 4;
553 	*pk       = data + 4 + *hit_size;
554 	if (*hit_size == 0 || *pk_size == 0 ||
555 			rdf_size < (size_t) *hit_size + *pk_size + 4) {
556 		return LDNS_STATUS_WIRE_RDATA_ERR;
557 	}
558 	return LDNS_STATUS_OK;
559 }
560 
561 ldns_status
562 ldns_rdf_hip_new_frm_alg_hit_pk(ldns_rdf** rdf, uint8_t alg,
563                                 uint8_t hit_size, uint8_t *hit,
564 				uint16_t pk_size, uint8_t *pk)
565 {
566 	uint8_t *data;
567 
568 	if (! rdf) {
569 		return LDNS_STATUS_INVALID_POINTER;
570 	}
571 	if (4 + hit_size + pk_size > LDNS_MAX_RDFLEN) {
572 		return LDNS_STATUS_RDATA_OVERFLOW;
573 	}
574 	data = LDNS_XMALLOC(uint8_t, 4 + hit_size + pk_size);
575 	if (data == NULL) {
576 		return LDNS_STATUS_MEM_ERR;
577 	}
578 	data[0] = hit_size;
579 	data[1] = alg;
580 	ldns_write_uint16(data + 2, pk_size);
581 	memcpy(data + 4, hit, hit_size);
582 	memcpy(data + 4 + hit_size, pk, pk_size);
583 	*rdf = ldns_rdf_new(LDNS_RDF_TYPE_HIP, 4 + hit_size + pk_size, data);
584 	if (! *rdf) {
585 		LDNS_FREE(data);
586 		return LDNS_STATUS_MEM_ERR;
587 	}
588 	return LDNS_STATUS_OK;
589 }
590 
591 ldns_status
592 ldns_octet(char *word, size_t *length)
593 {
594     char *s;
595     char *p;
596     *length = 0;
597 
598     for (s = p = word; *s != '\0'; s++,p++) {
599         switch (*s) {
600             case '.':
601                 if (s[1] == '.') {
602 		    return LDNS_STATUS_EMPTY_LABEL;
603                 }
604                 *p = *s;
605                 (*length)++;
606                 break;
607             case '\\':
608                 if ('0' <= s[1] && s[1] <= '9' &&
609                     '0' <= s[2] && s[2] <= '9' &&
610                     '0' <= s[3] && s[3] <= '9') {
611                     /* \DDD seen */
612                     int val = ((s[1] - '0') * 100 +
613                            (s[2] - '0') * 10 + (s[3] - '0'));
614 
615                     if (0 <= val && val <= 255) {
616                         /* this also handles \0 */
617                         s += 3;
618                         *p = val;
619                         (*length)++;
620                     } else {
621                         return LDNS_STATUS_DDD_OVERFLOW;
622                     }
623                 } else {
624                     /* an espaced character, like \<space> ?
625                     * remove the '\' keep the rest */
626                     *p = *++s;
627                     (*length)++;
628                 }
629                 break;
630             case '\"':
631                 /* non quoted " Is either first or the last character in
632                  * the string */
633 
634                 *p = *++s; /* skip it */
635                 (*length)++;
636 		/* I'm not sure if this is needed in libdns... MG */
637                 if ( *s == '\0' ) {
638                     /* ok, it was the last one */
639                     *p  = '\0';
640 		    return LDNS_STATUS_OK;
641                 }
642                 break;
643             default:
644                 *p = *s;
645                 (*length)++;
646                 break;
647         }
648     }
649     *p = '\0';
650     return LDNS_STATUS_OK;
651 }
652 
653 int
654 ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2)
655 {
656 	uint16_t i1, i2, i;
657 	uint8_t *d1, *d2;
658 
659 	/* only when both are not NULL we can say anything about them */
660 	if (!rd1 && !rd2) {
661 		return 0;
662 	}
663 	if (!rd1 || !rd2) {
664 		return -1;
665 	}
666 	i1 = ldns_rdf_size(rd1);
667 	i2 = ldns_rdf_size(rd2);
668 
669 	if (i1 < i2) {
670 		return -1;
671 	} else if (i1 > i2) {
672 		return +1;
673 	} else {
674 		d1 = (uint8_t*)ldns_rdf_data(rd1);
675 		d2 = (uint8_t*)ldns_rdf_data(rd2);
676 		for(i = 0; i < i1; i++) {
677 			if (d1[i] < d2[i]) {
678 				return -1;
679 			} else if (d1[i] > d2[i]) {
680 				return +1;
681 			}
682 		}
683 	}
684 	return 0;
685 }
686 
687 uint32_t
688 ldns_str2period(const char *nptr, const char **endptr)
689 {
690 	int sign = 0;
691 	uint32_t i = 0;
692 	uint32_t seconds = 0;
693 
694 	for(*endptr = nptr; **endptr; (*endptr)++) {
695 		switch (**endptr) {
696 			case ' ':
697 			case '\t':
698 				break;
699 			case '-':
700 				if(sign == 0) {
701 					sign = -1;
702 				} else {
703 					return seconds;
704 				}
705 				break;
706 			case '+':
707 				if(sign == 0) {
708 					sign = 1;
709 				} else {
710 					return seconds;
711 				}
712 				break;
713 			case 's':
714 			case 'S':
715 				seconds += i;
716 				i = 0;
717 				break;
718 			case 'm':
719 			case 'M':
720 				seconds += i * 60;
721 				i = 0;
722 				break;
723 			case 'h':
724 			case 'H':
725 				seconds += i * 60 * 60;
726 				i = 0;
727 				break;
728 			case 'd':
729 			case 'D':
730 				seconds += i * 60 * 60 * 24;
731 				i = 0;
732 				break;
733 			case 'w':
734 			case 'W':
735 				seconds += i * 60 * 60 * 24 * 7;
736 				i = 0;
737 				break;
738 			case '0':
739 			case '1':
740 			case '2':
741 			case '3':
742 			case '4':
743 			case '5':
744 			case '6':
745 			case '7':
746 			case '8':
747 			case '9':
748 				i *= 10;
749 				i += (**endptr - '0');
750 				break;
751 			default:
752 				seconds += i;
753 				/* disregard signedness */
754 				return seconds;
755 		}
756 	}
757 	seconds += i;
758 	/* disregard signedness */
759 	return seconds;
760 }
761