6 * a Net::DNS like library for C
8 * (c) NLnet Labs, 2004-2006
10 * See the file LICENSE for the license
13 #include <ldns/config.h>
15 #include <ldns/ldns.h>
19 * do this as functions to get type checking
24 ldns_rdf_size(const ldns_rdf *rd)
31 ldns_rdf_get_type(const ldns_rdf *rd)
38 ldns_rdf_data(const ldns_rdf *rd)
46 ldns_rdf_set_size(ldns_rdf *rd, size_t size)
53 ldns_rdf_set_type(ldns_rdf *rd, ldns_rdf_type type)
60 ldns_rdf_set_data(ldns_rdf *rd, void *data)
62 /* only copy the pointer */
67 /* for types that allow it, return
68 * the native/host order type */
70 ldns_rdf2native_int8(const ldns_rdf *rd)
74 /* only allow 8 bit rdfs */
75 if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_BYTE) {
79 memcpy(&data, ldns_rdf_data(rd), sizeof(data));
84 ldns_rdf2native_int16(const ldns_rdf *rd)
88 /* only allow 16 bit rdfs */
89 if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_WORD) {
93 memcpy(&data, ldns_rdf_data(rd), sizeof(data));
98 ldns_rdf2native_int32(const ldns_rdf *rd)
102 /* only allow 32 bit rdfs */
103 if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_DOUBLEWORD) {
107 memcpy(&data, ldns_rdf_data(rd), sizeof(data));
112 ldns_rdf2native_time_t(const ldns_rdf *rd)
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) {
121 memcpy(&data, ldns_rdf_data(rd), sizeof(data));
122 return (time_t)ntohl(data);
126 ldns_native2rdf_int8(ldns_rdf_type type, uint8_t value)
128 return ldns_rdf_new_frm_data(type, LDNS_RDF_SIZE_BYTE, &value);
132 ldns_native2rdf_int16(ldns_rdf_type type, uint16_t value)
134 uint16_t *rdf_data = LDNS_XMALLOC(uint16_t, 1);
139 ldns_write_uint16(rdf_data, value);
140 rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_WORD, rdf_data);
147 ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value)
149 uint32_t *rdf_data = LDNS_XMALLOC(uint32_t, 1);
154 ldns_write_uint32(rdf_data, value);
155 rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_DOUBLEWORD, rdf_data);
162 ldns_native2rdf_int16_data(size_t size, uint8_t *data)
164 uint8_t *rdf_data = LDNS_XMALLOC(uint8_t, size + 2);
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);
177 /* note: data must be allocated memory */
179 ldns_rdf_new(ldns_rdf_type type, size_t size, void *data)
182 rd = LDNS_MALLOC(ldns_rdf);
186 ldns_rdf_set_size(rd, size);
187 ldns_rdf_set_type(rd, type);
188 ldns_rdf_set_data(rd, data);
193 ldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data)
197 /* if the size is too big, fail */
198 if (size > LDNS_MAX_RDFLEN) {
203 rdf = LDNS_MALLOC(ldns_rdf);
207 rdf->_data = LDNS_XMALLOC(uint8_t, size);
214 ldns_rdf_set_type(rdf, type);
215 ldns_rdf_set_size(rdf, size);
216 memcpy(rdf->_data, data, size);
222 ldns_rdf_clone(const ldns_rdf *rd)
225 return (ldns_rdf_new_frm_data( ldns_rdf_get_type(rd),
226 ldns_rdf_size(rd), ldns_rdf_data(rd)));
230 ldns_rdf_deep_free(ldns_rdf *rd)
234 LDNS_FREE(rd->_data);
241 ldns_rdf_free(ldns_rdf *rd)
249 ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str)
251 ldns_rdf *rdf = NULL;
255 case LDNS_RDF_TYPE_DNAME:
256 status = ldns_str2rdf_dname(&rdf, str);
258 case LDNS_RDF_TYPE_INT8:
259 status = ldns_str2rdf_int8(&rdf, str);
261 case LDNS_RDF_TYPE_INT16:
262 status = ldns_str2rdf_int16(&rdf, str);
264 case LDNS_RDF_TYPE_INT32:
265 status = ldns_str2rdf_int32(&rdf, str);
267 case LDNS_RDF_TYPE_A:
268 status = ldns_str2rdf_a(&rdf, str);
270 case LDNS_RDF_TYPE_AAAA:
271 status = ldns_str2rdf_aaaa(&rdf, str);
273 case LDNS_RDF_TYPE_STR:
274 status = ldns_str2rdf_str(&rdf, str);
276 case LDNS_RDF_TYPE_APL:
277 status = ldns_str2rdf_apl(&rdf, str);
279 case LDNS_RDF_TYPE_B64:
280 status = ldns_str2rdf_b64(&rdf, str);
282 case LDNS_RDF_TYPE_B32_EXT:
283 status = ldns_str2rdf_b32_ext(&rdf, str);
285 case LDNS_RDF_TYPE_HEX:
286 status = ldns_str2rdf_hex(&rdf, str);
288 case LDNS_RDF_TYPE_NSEC:
289 status = ldns_str2rdf_nsec(&rdf, str);
291 case LDNS_RDF_TYPE_TYPE:
292 status = ldns_str2rdf_type(&rdf, str);
294 case LDNS_RDF_TYPE_CLASS:
295 status = ldns_str2rdf_class(&rdf, str);
297 case LDNS_RDF_TYPE_CERT_ALG:
298 status = ldns_str2rdf_cert_alg(&rdf, str);
300 case LDNS_RDF_TYPE_ALG:
301 status = ldns_str2rdf_alg(&rdf, str);
303 case LDNS_RDF_TYPE_UNKNOWN:
304 status = ldns_str2rdf_unknown(&rdf, str);
306 case LDNS_RDF_TYPE_TIME:
307 status = ldns_str2rdf_time(&rdf, str);
309 case LDNS_RDF_TYPE_PERIOD:
310 status = ldns_str2rdf_period(&rdf, str);
312 case LDNS_RDF_TYPE_HIP:
313 status = ldns_str2rdf_hip(&rdf, str);
315 case LDNS_RDF_TYPE_SERVICE:
316 status = ldns_str2rdf_service(&rdf, str);
318 case LDNS_RDF_TYPE_LOC:
319 status = ldns_str2rdf_loc(&rdf, str);
321 case LDNS_RDF_TYPE_WKS:
322 status = ldns_str2rdf_wks(&rdf, str);
324 case LDNS_RDF_TYPE_NSAP:
325 status = ldns_str2rdf_nsap(&rdf, str);
327 case LDNS_RDF_TYPE_ATMA:
328 status = ldns_str2rdf_atma(&rdf, str);
330 case LDNS_RDF_TYPE_IPSECKEY:
331 status = ldns_str2rdf_ipseckey(&rdf, str);
333 case LDNS_RDF_TYPE_NSEC3_SALT:
334 status = ldns_str2rdf_nsec3_salt(&rdf, str);
336 case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
337 status = ldns_str2rdf_b32_ext(&rdf, str);
339 case LDNS_RDF_TYPE_ILNP64:
340 status = ldns_str2rdf_ilnp64(&rdf, str);
342 case LDNS_RDF_TYPE_EUI48:
343 status = ldns_str2rdf_eui48(&rdf, str);
345 case LDNS_RDF_TYPE_EUI64:
346 status = ldns_str2rdf_eui64(&rdf, str);
348 case LDNS_RDF_TYPE_TAG:
349 status = ldns_str2rdf_tag(&rdf, str);
351 case LDNS_RDF_TYPE_LONG_STR:
352 status = ldns_str2rdf_long_str(&rdf, str);
354 case LDNS_RDF_TYPE_CERTIFICATE_USAGE:
355 status = ldns_str2rdf_certificate_usage(&rdf, str);
357 case LDNS_RDF_TYPE_SELECTOR:
358 status = ldns_str2rdf_selector(&rdf, str);
360 case LDNS_RDF_TYPE_MATCHING_TYPE:
361 status = ldns_str2rdf_matching_type(&rdf, str);
363 case LDNS_RDF_TYPE_NONE:
365 /* default default ??? */
366 status = LDNS_STATUS_ERR;
369 if (LDNS_STATUS_OK == status) {
370 ldns_rdf_set_type(rdf, type);
380 ldns_rdf_new_frm_fp(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp)
382 return ldns_rdf_new_frm_fp_l(rdf, type, fp, NULL);
386 ldns_rdf_new_frm_fp_l(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp, int *line_nr)
392 line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
394 return LDNS_STATUS_MEM_ERR;
397 /* read an entire line in from the file */
398 if ((t = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, 0, line_nr)) == -1 || t == 0) {
400 return LDNS_STATUS_SYNTAX_RDATA_ERR;
402 r = ldns_rdf_new_frm_str(type, (const char*) line);
406 return LDNS_STATUS_OK;
408 return LDNS_STATUS_NULL;
413 ldns_rdf_address_reverse(const ldns_rdf *rd)
415 uint8_t buf_4[LDNS_IP4ADDRLEN];
416 uint8_t buf_6[LDNS_IP6ADDRLEN * 2];
428 if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_A &&
429 ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_AAAA) {
436 switch(ldns_rdf_get_type(rd)) {
437 case LDNS_RDF_TYPE_A:
438 /* the length of the buffer is 4 */
439 buf_4[3] = ldns_rdf_data(rd)[0];
440 buf_4[2] = ldns_rdf_data(rd)[1];
441 buf_4[1] = ldns_rdf_data(rd)[2];
442 buf_4[0] = ldns_rdf_data(rd)[3];
443 in_addr = ldns_dname_new_frm_str("in-addr.arpa.");
447 /* make a new rdf and convert that back */
448 rev = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_A,
449 LDNS_IP4ADDRLEN, (void*)&buf_4);
455 /* convert rev to a string */
456 char_dname = ldns_rdf2str(rev);
459 ldns_rdf_deep_free(rev);
462 /* transform back to rdf with type dname */
463 ret_dname = ldns_dname_new_frm_str(char_dname);
466 ldns_rdf_deep_free(rev);
467 LDNS_FREE(char_dname);
470 /* not needed anymore */
471 ldns_rdf_deep_free(rev);
472 LDNS_FREE(char_dname);
474 case LDNS_RDF_TYPE_AAAA:
475 /* some foo magic to reverse the nibbles ... */
477 for (nbit = 127; nbit >= 0; nbit = nbit - 4) {
478 /* calculate octet (8 bit) */
479 octet = ( ((unsigned int) nbit) & 0x78) >> 3;
480 /* calculate nibble */
481 nnibble = ( ((unsigned int) nbit) & 0x04) >> 2;
483 nibble = (ldns_rdf_data(rd)[octet] & ( 0xf << (4 * (1 -
484 nnibble)) ) ) >> ( 4 * (1 -
487 buf_6[(LDNS_IP6ADDRLEN * 2 - 1) -
488 (octet * 2 + nnibble)] =
489 (uint8_t)ldns_int_to_hexdigit((int)nibble);
492 char_dname = LDNS_XMALLOC(char, (LDNS_IP6ADDRLEN * 4));
496 char_dname[LDNS_IP6ADDRLEN * 4 - 1] = '\0'; /* closure */
498 /* walk the string and add . 's */
499 for (i = 0, j = 0; i < LDNS_IP6ADDRLEN * 2; i++, j = j + 2) {
500 char_dname[j] = (char)buf_6[i];
501 if (i != LDNS_IP6ADDRLEN * 2 - 1) {
502 char_dname[j + 1] = '.';
505 in_addr = ldns_dname_new_frm_str("ip6.arpa.");
507 LDNS_FREE(char_dname);
511 /* convert rev to a string */
512 ret_dname = ldns_dname_new_frm_str(char_dname);
513 LDNS_FREE(char_dname);
515 ldns_rdf_deep_free(in_addr);
523 rev = ldns_dname_cat_clone(ret_dname, in_addr);
525 ldns_rdf_deep_free(ret_dname);
526 ldns_rdf_deep_free(in_addr);
531 ldns_rdf_hip_get_alg_hit_pk(ldns_rdf *rdf, uint8_t* alg,
532 uint8_t *hit_size, uint8_t** hit,
533 uint16_t *pk_size, uint8_t** pk)
538 if (! rdf || ! alg || ! hit || ! hit_size || ! pk || ! pk_size) {
539 return LDNS_STATUS_INVALID_POINTER;
540 } else if (ldns_rdf_get_type(rdf) != LDNS_RDF_TYPE_HIP) {
541 return LDNS_STATUS_INVALID_RDF_TYPE;
542 } else if ((rdf_size = ldns_rdf_size(rdf)) < 6) {
543 return LDNS_STATUS_WIRE_RDATA_ERR;
545 data = ldns_rdf_data(rdf);
548 *pk_size = ldns_read_uint16(data + 2);
550 *pk = data + 4 + *hit_size;
551 if (*hit_size == 0 || *pk_size == 0 ||
552 rdf_size < (size_t) *hit_size + *pk_size + 4) {
553 return LDNS_STATUS_WIRE_RDATA_ERR;
555 return LDNS_STATUS_OK;
559 ldns_rdf_hip_new_frm_alg_hit_pk(ldns_rdf** rdf, uint8_t alg,
560 uint8_t hit_size, uint8_t *hit,
561 uint16_t pk_size, uint8_t *pk)
566 return LDNS_STATUS_INVALID_POINTER;
568 if (4 + hit_size + pk_size > LDNS_MAX_RDFLEN) {
569 return LDNS_STATUS_RDATA_OVERFLOW;
571 data = LDNS_XMALLOC(uint8_t, 4 + hit_size + pk_size);
573 return LDNS_STATUS_MEM_ERR;
577 ldns_write_uint16(data + 2, pk_size);
578 memcpy(data + 4, hit, hit_size);
579 memcpy(data + 4 + hit_size, pk, pk_size);
580 *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HIP, 4 + hit_size + pk_size, data);
583 return LDNS_STATUS_MEM_ERR;
585 return LDNS_STATUS_OK;
589 ldns_octet(char *word, size_t *length)
595 for (s = p = word; *s != '\0'; s++,p++) {
599 return LDNS_STATUS_EMPTY_LABEL;
605 if ('0' <= s[1] && s[1] <= '9' &&
606 '0' <= s[2] && s[2] <= '9' &&
607 '0' <= s[3] && s[3] <= '9') {
609 int val = ((s[1] - '0') * 100 +
610 (s[2] - '0') * 10 + (s[3] - '0'));
612 if (0 <= val && val <= 255) {
613 /* this also handles \0 */
618 return LDNS_STATUS_DDD_OVERFLOW;
621 /* an espaced character, like \<space> ?
622 * remove the '\' keep the rest */
628 /* non quoted " Is either first or the last character in
631 *p = *++s; /* skip it */
633 /* I'm not sure if this is needed in libdns... MG */
635 /* ok, it was the last one */
637 return LDNS_STATUS_OK;
647 return LDNS_STATUS_OK;
651 ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2)
656 /* only when both are not NULL we can say anything about them */
663 i1 = ldns_rdf_size(rd1);
664 i2 = ldns_rdf_size(rd2);
668 } else if (i1 > i2) {
671 d1 = (uint8_t*)ldns_rdf_data(rd1);
672 d2 = (uint8_t*)ldns_rdf_data(rd2);
673 for(i = 0; i < i1; i++) {
676 } else if (d1[i] > d2[i]) {
685 ldns_str2period(const char *nptr, const char **endptr)
689 uint32_t seconds = 0;
691 for(*endptr = nptr; **endptr; (*endptr)++) {
722 seconds += i * 60 * 60;
727 seconds += i * 60 * 60 * 24;
732 seconds += i * 60 * 60 * 24 * 7;
746 i += (**endptr - '0');
750 /* disregard signedness */
755 /* disregard signedness */