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 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
);
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_TSIG
:
313 status
= ldns_str2rdf_tsig(&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_NONE
:
341 /* default default ??? */
342 status
= LDNS_STATUS_ERR
;
345 if (LDNS_STATUS_OK
== status
) {
346 ldns_rdf_set_type(rdf
, type
);
356 ldns_rdf_new_frm_fp(ldns_rdf
**rdf
, ldns_rdf_type type
, FILE *fp
)
358 return ldns_rdf_new_frm_fp_l(rdf
, type
, fp
, NULL
);
362 ldns_rdf_new_frm_fp_l(ldns_rdf
**rdf
, ldns_rdf_type type
, FILE *fp
, int *line_nr
)
368 line
= LDNS_XMALLOC(char, LDNS_MAX_LINELEN
+ 1);
370 return LDNS_STATUS_MEM_ERR
;
373 /* read an entire line in from the file */
374 if ((t
= ldns_fget_token_l(fp
, line
, LDNS_PARSE_SKIP_SPACE
, 0, line_nr
)) == -1 || t
== 0) {
376 return LDNS_STATUS_SYNTAX_RDATA_ERR
;
378 r
= ldns_rdf_new_frm_str(type
, (const char*) line
);
382 return LDNS_STATUS_OK
;
384 return LDNS_STATUS_NULL
;
389 ldns_rdf_address_reverse(ldns_rdf
*rd
)
391 uint8_t buf_4
[LDNS_IP4ADDRLEN
];
392 uint8_t buf_6
[LDNS_IP6ADDRLEN
* 2];
404 if (ldns_rdf_get_type(rd
) != LDNS_RDF_TYPE_A
&&
405 ldns_rdf_get_type(rd
) != LDNS_RDF_TYPE_AAAA
) {
412 switch(ldns_rdf_get_type(rd
)) {
413 case LDNS_RDF_TYPE_A
:
414 /* the length of the buffer is 4 */
415 buf_4
[3] = ldns_rdf_data(rd
)[0];
416 buf_4
[2] = ldns_rdf_data(rd
)[1];
417 buf_4
[1] = ldns_rdf_data(rd
)[2];
418 buf_4
[0] = ldns_rdf_data(rd
)[3];
419 in_addr
= ldns_dname_new_frm_str("in-addr.arpa.");
423 /* make a new rdf and convert that back */
424 rev
= ldns_rdf_new_frm_data( LDNS_RDF_TYPE_A
,
425 LDNS_IP4ADDRLEN
, (void*)&buf_4
);
431 /* convert rev to a string */
432 char_dname
= ldns_rdf2str(rev
);
435 ldns_rdf_deep_free(rev
);
438 /* transform back to rdf with type dname */
439 ret_dname
= ldns_dname_new_frm_str(char_dname
);
442 ldns_rdf_deep_free(rev
);
443 LDNS_FREE(char_dname
);
446 /* not needed anymore */
447 ldns_rdf_deep_free(rev
);
448 LDNS_FREE(char_dname
);
450 case LDNS_RDF_TYPE_AAAA
:
451 /* some foo magic to reverse the nibbles ... */
453 for (nbit
= 127; nbit
>= 0; nbit
= nbit
- 4) {
454 /* calculate octett (8 bit) */
455 octet
= ( ((unsigned int) nbit
) & 0x78) >> 3;
456 /* calculate nibble */
457 nnibble
= ( ((unsigned int) nbit
) & 0x04) >> 2;
459 nibble
= (ldns_rdf_data(rd
)[octet
] & ( 0xf << (4 * (1 -
460 nnibble
)) ) ) >> ( 4 * (1 -
463 buf_6
[(LDNS_IP6ADDRLEN
* 2 - 1) -
464 (octet
* 2 + nnibble
)] =
465 (uint8_t)ldns_int_to_hexdigit((int)nibble
);
468 char_dname
= LDNS_XMALLOC(char, (LDNS_IP6ADDRLEN
* 4));
472 char_dname
[LDNS_IP6ADDRLEN
* 4 - 1] = '\0'; /* closure */
474 /* walk the string and add . 's */
475 for (i
= 0, j
= 0; i
< LDNS_IP6ADDRLEN
* 2; i
++, j
= j
+ 2) {
476 char_dname
[j
] = (char)buf_6
[i
];
477 if (i
!= LDNS_IP6ADDRLEN
* 2 - 1) {
478 char_dname
[j
+ 1] = '.';
481 in_addr
= ldns_dname_new_frm_str("ip6.arpa.");
483 LDNS_FREE(char_dname
);
487 /* convert rev to a string */
488 ret_dname
= ldns_dname_new_frm_str(char_dname
);
489 LDNS_FREE(char_dname
);
491 ldns_rdf_deep_free(in_addr
);
499 rev
= ldns_dname_cat_clone(ret_dname
, in_addr
);
501 ldns_rdf_deep_free(ret_dname
);
502 ldns_rdf_deep_free(in_addr
);
507 ldns_octet(char *word
, size_t *length
)
513 for (s
= p
= word
; *s
!= '\0'; s
++,p
++) {
517 return LDNS_STATUS_EMPTY_LABEL
;
523 if ('0' <= s
[1] && s
[1] <= '9' &&
524 '0' <= s
[2] && s
[2] <= '9' &&
525 '0' <= s
[3] && s
[3] <= '9') {
527 int val
= ((s
[1] - '0') * 100 +
528 (s
[2] - '0') * 10 + (s
[3] - '0'));
530 if (0 <= val
&& val
<= 255) {
531 /* this also handles \0 */
536 return LDNS_STATUS_DDD_OVERFLOW
;
539 /* an espaced character, like \<space> ?
540 * remove the '\' keep the rest */
546 /* non quoted " Is either first or the last character in
549 *p
= *++s
; /* skip it */
551 /* I'm not sure if this is needed in libdns... MG */
553 /* ok, it was the last one */
555 return LDNS_STATUS_OK
;
565 return LDNS_STATUS_OK
;
569 ldns_rdf_compare(const ldns_rdf
*rd1
, const ldns_rdf
*rd2
)
574 /* only when both are not NULL we can say anything about them */
581 i1
= ldns_rdf_size(rd1
);
582 i2
= ldns_rdf_size(rd2
);
586 } else if (i1
> i2
) {
589 d1
= (uint8_t*)ldns_rdf_data(rd1
);
590 d2
= (uint8_t*)ldns_rdf_data(rd2
);
591 for(i
= 0; i
< i1
; i
++) {
594 } else if (d1
[i
] > d2
[i
]) {
603 ldns_str2period(const char *nptr
, const char **endptr
)
607 uint32_t seconds
= 0;
609 for(*endptr
= nptr
; **endptr
; (*endptr
)++) {
640 seconds
+= i
* 60 * 60;
645 seconds
+= i
* 60 * 60 * 24;
650 seconds
+= i
* 60 * 60 * 24 * 7;
664 i
+= (**endptr
- '0');
668 /* disregard signedness */
673 /* disregard signedness */