corepower: Fix identify method for multi-cpu-package systems
[dragonfly.git] / contrib / ldns / rdata.c
blob8af16a13a1c2e85d59a60f99e534590742d85068
1 /*
2 * rdata.c
4 * rdata implementation
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>
18 * Access functions
19 * do this as functions to get type checking
22 /* read */
23 size_t
24 ldns_rdf_size(const ldns_rdf *rd)
26 assert(rd != NULL);
27 return rd->_size;
30 ldns_rdf_type
31 ldns_rdf_get_type(const ldns_rdf *rd)
33 assert(rd != NULL);
34 return rd->_type;
37 uint8_t *
38 ldns_rdf_data(const ldns_rdf *rd)
40 assert(rd != NULL);
41 return rd->_data;
44 /* write */
45 void
46 ldns_rdf_set_size(ldns_rdf *rd, size_t size)
48 assert(rd != NULL);
49 rd->_size = size;
52 void
53 ldns_rdf_set_type(ldns_rdf *rd, ldns_rdf_type type)
55 assert(rd != NULL);
56 rd->_type = type;
59 void
60 ldns_rdf_set_data(ldns_rdf *rd, void *data)
62 /* only copy the pointer */
63 assert(rd != NULL);
64 rd->_data = data;
67 /* for types that allow it, return
68 * the native/host order type */
69 uint8_t
70 ldns_rdf2native_int8(const ldns_rdf *rd)
72 uint8_t data;
74 /* only allow 8 bit rdfs */
75 if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_BYTE) {
76 return 0;
79 memcpy(&data, ldns_rdf_data(rd), sizeof(data));
80 return data;
83 uint16_t
84 ldns_rdf2native_int16(const ldns_rdf *rd)
86 uint16_t data;
88 /* only allow 16 bit rdfs */
89 if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_WORD) {
90 return 0;
93 memcpy(&data, ldns_rdf_data(rd), sizeof(data));
94 return ntohs(data);
97 uint32_t
98 ldns_rdf2native_int32(const ldns_rdf *rd)
100 uint32_t data;
102 /* only allow 32 bit rdfs */
103 if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_DOUBLEWORD) {
104 return 0;
107 memcpy(&data, ldns_rdf_data(rd), sizeof(data));
108 return ntohl(data);
111 time_t
112 ldns_rdf2native_time_t(const ldns_rdf *rd)
114 uint32_t data;
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;
125 ldns_rdf *
126 ldns_native2rdf_int8(ldns_rdf_type type, uint8_t value)
128 return ldns_rdf_new_frm_data(type, LDNS_RDF_SIZE_BYTE, &value);
131 ldns_rdf *
132 ldns_native2rdf_int16(ldns_rdf_type type, uint16_t value)
134 uint16_t *rdf_data = LDNS_XMALLOC(uint16_t, 1);
135 ldns_rdf* rdf;
136 if (!rdf_data) {
137 return NULL;
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;
146 ldns_rdf *
147 ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value)
149 uint32_t *rdf_data = LDNS_XMALLOC(uint32_t, 1);
150 ldns_rdf* rdf;
151 if (!rdf_data) {
152 return NULL;
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;
161 ldns_rdf *
162 ldns_native2rdf_int16_data(size_t size, uint8_t *data)
164 uint8_t *rdf_data = LDNS_XMALLOC(uint8_t, size + 2);
165 ldns_rdf* rdf;
166 if (!rdf_data) {
167 return NULL;
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;
177 /* note: data must be allocated memory */
178 ldns_rdf *
179 ldns_rdf_new(ldns_rdf_type type, size_t size, void *data)
181 ldns_rdf *rd;
182 rd = LDNS_MALLOC(ldns_rdf);
183 if (!rd) {
184 return NULL;
186 ldns_rdf_set_size(rd, size);
187 ldns_rdf_set_type(rd, type);
188 ldns_rdf_set_data(rd, data);
189 return rd;
192 ldns_rdf *
193 ldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data)
195 ldns_rdf *rdf;
197 /* if the size is too big, fail */
198 if (size > LDNS_MAX_RDFLEN) {
199 return NULL;
202 /* allocate space */
203 rdf = LDNS_MALLOC(ldns_rdf);
204 if (!rdf) {
205 return NULL;
207 rdf->_data = LDNS_XMALLOC(uint8_t, size);
208 if (!rdf->_data) {
209 LDNS_FREE(rdf);
210 return NULL;
213 /* set the values */
214 ldns_rdf_set_type(rdf, type);
215 ldns_rdf_set_size(rdf, size);
216 memcpy(rdf->_data, data, size);
218 return rdf;
221 ldns_rdf *
222 ldns_rdf_clone(const ldns_rdf *rd)
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)));
229 void
230 ldns_rdf_deep_free(ldns_rdf *rd)
232 if (rd) {
233 if (rd->_data) {
234 LDNS_FREE(rd->_data);
236 LDNS_FREE(rd);
240 void
241 ldns_rdf_free(ldns_rdf *rd)
243 if (rd) {
244 LDNS_FREE(rd);
248 ldns_rdf *
249 ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str)
251 ldns_rdf *rdf = NULL;
252 ldns_status status;
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_TSIG:
313 status = ldns_str2rdf_tsig(&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_NONE:
340 default:
341 /* default default ??? */
342 status = LDNS_STATUS_ERR;
343 break;
345 if (LDNS_STATUS_OK == status) {
346 ldns_rdf_set_type(rdf, type);
347 return rdf;
349 if (rdf) {
350 LDNS_FREE(rdf);
352 return NULL;
355 ldns_status
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);
361 ldns_status
362 ldns_rdf_new_frm_fp_l(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp, int *line_nr)
364 char *line;
365 ldns_rdf *r;
366 ssize_t t;
368 line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
369 if (!line) {
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) {
375 LDNS_FREE(line);
376 return LDNS_STATUS_SYNTAX_RDATA_ERR;
378 r = ldns_rdf_new_frm_str(type, (const char*) line);
379 LDNS_FREE(line);
380 if (rdf) {
381 *rdf = r;
382 return LDNS_STATUS_OK;
383 } else {
384 return LDNS_STATUS_NULL;
388 ldns_rdf *
389 ldns_rdf_address_reverse(ldns_rdf *rd)
391 uint8_t buf_4[LDNS_IP4ADDRLEN];
392 uint8_t buf_6[LDNS_IP6ADDRLEN * 2];
393 ldns_rdf *rev;
394 ldns_rdf *in_addr;
395 ldns_rdf *ret_dname;
396 uint8_t octet;
397 uint8_t nnibble;
398 uint8_t nibble;
399 uint8_t i, j;
401 char *char_dname;
402 int nbit;
404 if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_A &&
405 ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_AAAA) {
406 return NULL;
409 in_addr = NULL;
410 ret_dname = NULL;
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.");
420 if (!in_addr) {
421 return NULL;
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);
426 if (!rev) {
427 LDNS_FREE(in_addr);
428 return NULL;
431 /* convert rev to a string */
432 char_dname = ldns_rdf2str(rev);
433 if (!char_dname) {
434 LDNS_FREE(in_addr);
435 ldns_rdf_deep_free(rev);
436 return NULL;
438 /* transform back to rdf with type dname */
439 ret_dname = ldns_dname_new_frm_str(char_dname);
440 if (!ret_dname) {
441 LDNS_FREE(in_addr);
442 ldns_rdf_deep_free(rev);
443 LDNS_FREE(char_dname);
444 return NULL;
446 /* not needed anymore */
447 ldns_rdf_deep_free(rev);
448 LDNS_FREE(char_dname);
449 break;
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;
458 /* extract nibble */
459 nibble = (ldns_rdf_data(rd)[octet] & ( 0xf << (4 * (1 -
460 nnibble)) ) ) >> ( 4 * (1 -
461 nnibble));
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));
469 if (!char_dname) {
470 return NULL;
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.");
482 if (!in_addr) {
483 LDNS_FREE(char_dname);
484 return NULL;
487 /* convert rev to a string */
488 ret_dname = ldns_dname_new_frm_str(char_dname);
489 LDNS_FREE(char_dname);
490 if (!ret_dname) {
491 ldns_rdf_deep_free(in_addr);
492 return NULL;
494 break;
495 default:
496 break;
498 /* add the suffix */
499 rev = ldns_dname_cat_clone(ret_dname, in_addr);
501 ldns_rdf_deep_free(ret_dname);
502 ldns_rdf_deep_free(in_addr);
503 return rev;
506 ldns_status
507 ldns_octet(char *word, size_t *length)
509 char *s;
510 char *p;
511 *length = 0;
513 for (s = p = word; *s != '\0'; s++,p++) {
514 switch (*s) {
515 case '.':
516 if (s[1] == '.') {
517 return LDNS_STATUS_EMPTY_LABEL;
519 *p = *s;
520 (*length)++;
521 break;
522 case '\\':
523 if ('0' <= s[1] && s[1] <= '9' &&
524 '0' <= s[2] && s[2] <= '9' &&
525 '0' <= s[3] && s[3] <= '9') {
526 /* \DDD seen */
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 */
532 s += 3;
533 *p = val;
534 (*length)++;
535 } else {
536 return LDNS_STATUS_DDD_OVERFLOW;
538 } else {
539 /* an espaced character, like \<space> ?
540 * remove the '\' keep the rest */
541 *p = *++s;
542 (*length)++;
544 break;
545 case '\"':
546 /* non quoted " Is either first or the last character in
547 * the string */
549 *p = *++s; /* skip it */
550 (*length)++;
551 /* I'm not sure if this is needed in libdns... MG */
552 if ( *s == '\0' ) {
553 /* ok, it was the last one */
554 *p = '\0';
555 return LDNS_STATUS_OK;
557 break;
558 default:
559 *p = *s;
560 (*length)++;
561 break;
564 *p = '\0';
565 return LDNS_STATUS_OK;
569 ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2)
571 uint16_t i1, i2, i;
572 uint8_t *d1, *d2;
574 /* only when both are not NULL we can say anything about them */
575 if (!rd1 && !rd2) {
576 return 0;
578 if (!rd1 || !rd2) {
579 return -1;
581 i1 = ldns_rdf_size(rd1);
582 i2 = ldns_rdf_size(rd2);
584 if (i1 < i2) {
585 return -1;
586 } else if (i1 > i2) {
587 return +1;
588 } else {
589 d1 = (uint8_t*)ldns_rdf_data(rd1);
590 d2 = (uint8_t*)ldns_rdf_data(rd2);
591 for(i = 0; i < i1; i++) {
592 if (d1[i] < d2[i]) {
593 return -1;
594 } else if (d1[i] > d2[i]) {
595 return +1;
599 return 0;
602 uint32_t
603 ldns_str2period(const char *nptr, const char **endptr)
605 int sign = 0;
606 uint32_t i = 0;
607 uint32_t seconds = 0;
609 for(*endptr = nptr; **endptr; (*endptr)++) {
610 switch (**endptr) {
611 case ' ':
612 case '\t':
613 break;
614 case '-':
615 if(sign == 0) {
616 sign = -1;
617 } else {
618 return seconds;
620 break;
621 case '+':
622 if(sign == 0) {
623 sign = 1;
624 } else {
625 return seconds;
627 break;
628 case 's':
629 case 'S':
630 seconds += i;
631 i = 0;
632 break;
633 case 'm':
634 case 'M':
635 seconds += i * 60;
636 i = 0;
637 break;
638 case 'h':
639 case 'H':
640 seconds += i * 60 * 60;
641 i = 0;
642 break;
643 case 'd':
644 case 'D':
645 seconds += i * 60 * 60 * 24;
646 i = 0;
647 break;
648 case 'w':
649 case 'W':
650 seconds += i * 60 * 60 * 24 * 7;
651 i = 0;
652 break;
653 case '0':
654 case '1':
655 case '2':
656 case '3':
657 case '4':
658 case '5':
659 case '6':
660 case '7':
661 case '8':
662 case '9':
663 i *= 10;
664 i += (**endptr - '0');
665 break;
666 default:
667 seconds += i;
668 /* disregard signedness */
669 return seconds;
672 seconds += i;
673 /* disregard signedness */
674 return seconds;