str2host.c
Go to the documentation of this file.
1/*
2 * str2host.c
3 *
4 * conversion routines from the presentation format
5 * to the host format
6 *
7 * a Net::DNS like library for C
8 *
9 * (c) NLnet Labs, 2004-2006
10 *
11 * See the file LICENSE for the license
12 */
13#include <ldns/config.h>
14
15#include <ldns/ldns.h>
16
17#ifdef HAVE_SYS_SOCKET_H
18#include <sys/socket.h>
19#endif
20#ifdef HAVE_ARPA_INET_H
21#include <arpa/inet.h>
22#endif
23#include <time.h>
24
25#include <errno.h>
26#ifdef HAVE_NETDB_H
27#include <netdb.h>
28#endif
29
30#include <limits.h>
31#ifdef HAVE_SYS_PARAM_H
32#include <sys/param.h>
33#endif
34
36ldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr)
37{
38 char *end = NULL;
39 uint16_t *r;
40 r = LDNS_MALLOC(uint16_t);
41 if(!r) return LDNS_STATUS_MEM_ERR;
42
43 *r = htons((uint16_t)strtol((char *)shortstr, &end, 10));
44
45 if(*end != 0) {
46 LDNS_FREE(r);
48 } else {
50 LDNS_RDF_TYPE_INT16, sizeof(uint16_t), r);
51 LDNS_FREE(r);
53 }
54}
55
57ldns_str2rdf_time(ldns_rdf **rd, const char *time)
58{
59 /* convert a time YYYYDDMMHHMMSS to wireformat */
60 uint32_t *r = NULL;
61 struct tm tm;
62 uint32_t l;
63 char *end;
64
65 /* Try to scan the time... */
66 r = (uint32_t *)LDNS_MALLOC(uint32_t);
67 if(!r) return LDNS_STATUS_MEM_ERR;
68
69 memset(&tm, 0, sizeof(tm));
70
71 if (strlen(time) == 14 &&
72 sscanf(time, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6
73 ) {
74 tm.tm_year -= 1900;
75 tm.tm_mon--;
76 /* Check values */
77 if (tm.tm_year < 70) {
78 goto bad_format;
79 }
80 if (tm.tm_mon < 0 || tm.tm_mon > 11) {
81 goto bad_format;
82 }
83 if (tm.tm_mday < 1 || tm.tm_mday > 31) {
84 goto bad_format;
85 }
86
87 if (tm.tm_hour < 0 || tm.tm_hour > 23) {
88 goto bad_format;
89 }
90
91 if (tm.tm_min < 0 || tm.tm_min > 59) {
92 goto bad_format;
93 }
94
95 if (tm.tm_sec < 0 || tm.tm_sec > 59) {
96 goto bad_format;
97 }
98
99 l = htonl(ldns_mktime_from_utc(&tm));
100 memcpy(r, &l, sizeof(uint32_t));
102 LDNS_RDF_TYPE_TIME, sizeof(uint32_t), r);
103 LDNS_FREE(r);
105 } else {
106 /* handle it as 32 bits timestamp */
107 l = htonl((uint32_t)strtol((char*)time, &end, 10));
108 if(*end != 0) {
109 LDNS_FREE(r);
110 return LDNS_STATUS_ERR;
111 } else {
112 memcpy(r, &l, sizeof(uint32_t));
114 LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r);
115 LDNS_FREE(r);
117 }
118 }
119
120 bad_format:
121 LDNS_FREE(r);
123}
124
126ldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *salt_str)
127{
128 uint8_t salt_length;
129 int c;
130 int salt_length_str;
131
132 uint8_t *salt;
133 uint8_t *data;
134 if(rd == NULL) {
135 return LDNS_STATUS_NULL;
136 }
137
138 salt_length_str = (int)strlen(salt_str);
139 if (salt_length_str == 1 && salt_str[0] == '-') {
140 salt_length_str = 0;
141 } else if (salt_length_str % 2 != 0) {
143 }
144 if (salt_length_str > 512) {
146 }
147
148 salt = LDNS_XMALLOC(uint8_t, salt_length_str / 2);
149 if(!salt) {
150 return LDNS_STATUS_MEM_ERR;
151 }
152 for (c = 0; c < salt_length_str; c += 2) {
153 if (isxdigit((int) salt_str[c]) && isxdigit((int) salt_str[c+1])) {
154 salt[c/2] = (uint8_t) ldns_hexdigit_to_int(salt_str[c]) * 16 +
155 ldns_hexdigit_to_int(salt_str[c+1]);
156 } else {
157 LDNS_FREE(salt);
159 }
160 }
161 salt_length = (uint8_t) (salt_length_str / 2);
162
163 data = LDNS_XMALLOC(uint8_t, 1 + salt_length);
164 if(!data) {
165 LDNS_FREE(salt);
166 return LDNS_STATUS_MEM_ERR;
167 }
168 data[0] = salt_length;
169 memcpy(&data[1], salt, salt_length);
170 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT, 1 + salt_length, data);
171 LDNS_FREE(data);
172 LDNS_FREE(salt);
173
175}
176
178ldns_str2rdf_period(ldns_rdf **rd,const char *period)
179{
180 uint32_t p;
181 const char *end;
182
183 /* Allocate required space... */
184 p = ldns_str2period(period, &end);
185
186 if (*end != 0) {
187 return LDNS_STATUS_ERR;
188 } else {
189 p = (uint32_t) htonl(p);
191 LDNS_RDF_TYPE_PERIOD, sizeof(uint32_t), &p);
192 }
194}
195
197ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr)
198{
199 char *end;
200 uint32_t *r = NULL;
201 uint32_t l;
202
203 r = (uint32_t*)LDNS_MALLOC(uint32_t);
204 if(!r) return LDNS_STATUS_MEM_ERR;
205 errno = 0; /* must set to zero before call,
206 note race condition on errno */
207 if(*longstr == '-')
208 l = htonl((uint32_t)strtol((char*)longstr, &end, 10));
209 else l = htonl((uint32_t)strtoul((char*)longstr, &end, 10));
210
211 if(*end != 0) {
212 LDNS_FREE(r);
213 return LDNS_STATUS_ERR;
214 } else {
215 if (errno == ERANGE) {
216 LDNS_FREE(r);
218 }
219 memcpy(r, &l, sizeof(uint32_t));
221 LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r);
222 LDNS_FREE(r);
224 }
225}
226
227#ifdef __BYTE_ORDER__
228# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
229# define htonll(x) (x)
230# define ntohll(x) (x)
231# else
232# define htonll(x) (((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
233# define ntohll(x) (((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
234# endif
235#else
236# define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
237# define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
238#endif
239
241ldns_str2rdf_ipn(ldns_rdf **rd, const char *ipnstr)
242{
243 char *end;
244 uint8_t r[sizeof(uint64_t)];
245 char left[21], *right;
246
247 if(strlen(ipnstr) > 21)
249 errno = 0; /* must set to zero before call,
250 note race condition on errno */
251 if((right = strchr(ipnstr, '.'))) {
252 uint32_t u32 = strtoul(right + 1, &end, 10);
253
254 if(*end != 0)
255 return LDNS_STATUS_ERR;
256
257 if(errno == ERANGE)
259
260 u32 = htonl(u32);
261 memcpy(r + sizeof(uint32_t), &u32, sizeof(uint32_t));
262 memcpy(left, ipnstr, right - ipnstr);
263 left[right - ipnstr] = 0;
264
265 u32 = strtoul(left, &end, 10);
266 if(*end != 0)
267 return LDNS_STATUS_ERR;
268
269 if(errno == ERANGE)
271
272 u32 = htonl(u32);
273 memcpy(r, &u32, sizeof(uint32_t));
274 } else {
275 uint64_t u64 = strtoull(ipnstr, &end, 10);
276
277 if(*end != 0)
278 return LDNS_STATUS_ERR;
279
280 if(u64 == ULLONG_MAX && errno == ERANGE)
282
283 u64 = htonll(u64);
284 memcpy(r, &u64, sizeof(uint64_t));
285 }
286 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_IPN, sizeof(r), r);
287 return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
288}
289
291ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr)
292{
293 char *end;
294 uint8_t *r = NULL;
295
296 r = LDNS_MALLOC(uint8_t);
297 if(!r) return LDNS_STATUS_MEM_ERR;
298
299 *r = (uint8_t)strtol((char*)bytestr, &end, 10);
300
301 if(*end != 0) {
302 LDNS_FREE(r);
303 return LDNS_STATUS_ERR;
304 } else {
306 LDNS_RDF_TYPE_INT8, sizeof(uint8_t), r);
307 LDNS_FREE(r);
309 }
310}
311
312
313/*
314 * Checks whether the escaped value at **s is an decimal value or
315 * a 'normally' escaped character (and not eos)
316 *
317 * The string pointer at *s is increased by either 0 (on error), 1 (on
318 * normal escapes), or 3 (on decimals)
319 *
320 * Returns the number of bytes read from the escaped string, or
321 * 0 on error
322 */
323INLINE bool
324parse_escape(uint8_t *ch_p, const char** str_p)
325{
326 uint16_t val;
327
328 if ((*str_p)[0] && isdigit((unsigned char)(*str_p)[0]) &&
329 (*str_p)[1] && isdigit((unsigned char)(*str_p)[1]) &&
330 (*str_p)[2] && isdigit((unsigned char)(*str_p)[2])) {
331
332 val = (uint16_t)(((*str_p)[0] - '0') * 100 +
333 ((*str_p)[1] - '0') * 10 +
334 ((*str_p)[2] - '0'));
335
336 if (val > 255) {
337 goto error;
338 }
339 *ch_p = (uint8_t)val;
340 *str_p += 3;
341 return true;
342
343 } else if ((*str_p)[0] && !isdigit((unsigned char)(*str_p)[0])) {
344
345 *ch_p = (uint8_t)*(*str_p)++;
346 return true;
347 }
348error:
349 *str_p = NULL;
350 return false; /* LDNS_STATUS_SYNTAX_BAD_ESCAPE */
351}
352
353INLINE bool
354parse_char(uint8_t *ch_p, const char** str_p)
355{
356 switch (**str_p) {
357
358 case '\0': return false;
359
360 case '\\': *str_p += 1;
361 return parse_escape(ch_p, str_p);
362
363 default: *ch_p = (uint8_t)*(*str_p)++;
364 return true;
365 }
366}
367
368/*
369 * No special care is taken, all dots are translated into
370 * label separators.
371 * Could be made more efficient....we do 3 memcpy's in total...
372 */
374ldns_str2rdf_dname(ldns_rdf **d, const char *str)
375{
376 size_t len;
377
378 const char *s;
379 uint8_t *q, *pq, label_len;
380 uint8_t buf[LDNS_MAX_DOMAINLEN + 1];
381 *d = NULL;
382
383 len = strlen((char*)str);
384 /* octet representation can make strings a lot longer than actual length */
385 if (len > LDNS_MAX_DOMAINLEN * 4) {
387 }
388 if (0 == len) {
390 }
391
392 /* root label */
393 if (1 == len && *str == '.') {
395 return LDNS_STATUS_OK;
396 }
397
398 /* get on with the rest */
399
400 /* s is on the current character in the string
401 * pq points to where the labellength is going to go
402 * label_len keeps track of the current label's length
403 * q builds the dname inside the buf array
404 */
405 len = 0;
406 q = buf+1;
407 pq = buf;
408 label_len = 0;
409 for (s = str; *s; s++, q++) {
410 if (q >= buf + LDNS_MAX_DOMAINLEN) {
412 }
413 *q = 0;
414 switch (*s) {
415 case '.':
416 if (label_len > LDNS_MAX_LABELLEN) {
418 }
419 if (label_len == 0) {
421 }
422 len += label_len + 1;
423 *pq = label_len;
424 label_len = 0;
425 pq = q;
426 break;
427 case '\\':
428 /* octet value or literal char */
429 s += 1;
430 if (! parse_escape(q, &s)) {
432 }
433 s -= 1;
434 label_len++;
435 break;
436 default:
437 *q = (uint8_t)*s;
438 label_len++;
439 }
440 }
441
442 /* add root label if last char was not '.' */
443 if (!ldns_dname_str_absolute(str)) {
444 if (q >= buf + LDNS_MAX_DOMAINLEN) {
446 }
447 if (label_len > LDNS_MAX_LABELLEN) {
449 }
450 if (label_len == 0) { /* label_len 0 but not . at end? */
452 }
453 len += label_len + 1;
454 *pq = label_len;
455 *q = 0;
456 }
457 len++;
458
460 return LDNS_STATUS_OK;
461}
462
464ldns_str2rdf_a(ldns_rdf **rd, const char *str)
465{
466 in_addr_t address;
467 if (inet_pton(AF_INET, (char*)str, &address) != 1) {
469 } else {
471 LDNS_RDF_TYPE_A, sizeof(address), &address);
472 }
474}
475
477ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str)
478{
479 uint8_t address[LDNS_IP6ADDRLEN + 1];
480
481 if (inet_pton(AF_INET6, (char*)str, address) != 1) {
483 } else {
485 LDNS_RDF_TYPE_AAAA, sizeof(address) - 1, &address);
486 }
488}
489
491ldns_str2rdf_str(ldns_rdf **rd, const char *str)
492{
493 uint8_t *data, *dp, ch = 0;
494 size_t length;
495
496 /* Worst case space requirement. We'll realloc to actual size later. */
497 dp = data = LDNS_XMALLOC(uint8_t, strlen(str) > 255 ? 256 : (strlen(str) + 1));
498 if (! data) {
499 return LDNS_STATUS_MEM_ERR;
500 }
501
502 /* Fill data (up to 255 characters) */
503 while (parse_char(&ch, &str)) {
504 if (dp - data >= 255) {
505 LDNS_FREE(data);
507 }
508 *++dp = ch;
509 }
510 if (! str) {
511 LDNS_FREE(data);
513 }
514 length = (size_t)(dp - data);
515 /* Fix last length byte */
516 data[0] = (uint8_t)length;
517
518 /* Lose the overmeasure */
519 data = LDNS_XREALLOC(dp = data, uint8_t, length + 1);
520 if (! data) {
521 LDNS_FREE(dp);
522 return LDNS_STATUS_MEM_ERR;
523 }
524
525 /* Create rdf */
526 *rd = ldns_rdf_new(LDNS_RDF_TYPE_STR, length + 1, data);
527 if (! *rd) {
528 LDNS_FREE(data);
529 return LDNS_STATUS_MEM_ERR;
530 }
531 return LDNS_STATUS_OK;
532}
533
535ldns_str2rdf_apl(ldns_rdf **rd, const char *str)
536{
537 const char *my_str = str;
538
539 char *my_ip_str;
540 size_t ip_str_len;
541
542 uint16_t family;
543 bool negation;
544 uint8_t afdlength = 0;
545 uint8_t *afdpart;
546 uint8_t prefix;
547
548 uint8_t *data;
549
550 size_t i = 0;
551
552 /* [!]afi:address/prefix */
553 if (strlen(my_str) < 2
554 || strchr(my_str, ':') == NULL
555 || strchr(my_str, '/') == NULL
556 || strchr(my_str, ':') > strchr(my_str, '/')) {
558 }
559
560 if (my_str[0] == '!') {
561 negation = true;
562 my_str += 1;
563 } else {
564 negation = false;
565 }
566
567 family = (uint16_t) atoi(my_str);
568
569 my_str = strchr(my_str, ':') + 1;
570
571 /* need ip addr and only ip addr for inet_pton */
572 ip_str_len = (size_t) (strchr(my_str, '/') - my_str);
573 my_ip_str = LDNS_XMALLOC(char, ip_str_len + 1);
574 if(!my_ip_str) return LDNS_STATUS_MEM_ERR;
575 strncpy(my_ip_str, my_str, ip_str_len + 1);
576 my_ip_str[ip_str_len] = '\0';
577
578 if (family == 1) {
579 /* ipv4 */
580 afdpart = LDNS_XMALLOC(uint8_t, 4);
581 if(!afdpart) {
582 LDNS_FREE(my_ip_str);
583 return LDNS_STATUS_MEM_ERR;
584 }
585 if (inet_pton(AF_INET, my_ip_str, afdpart) == 0) {
586 LDNS_FREE(my_ip_str);
587 LDNS_FREE(afdpart);
589 }
590 for (i = 0; i < 4; i++) {
591 if (afdpart[i] != 0) {
592 afdlength = i + 1;
593 }
594 }
595 } else if (family == 2) {
596 /* ipv6 */
597 afdpart = LDNS_XMALLOC(uint8_t, 16);
598 if(!afdpart) {
599 LDNS_FREE(my_ip_str);
600 return LDNS_STATUS_MEM_ERR;
601 }
602 if (inet_pton(AF_INET6, my_ip_str, afdpart) == 0) {
603 LDNS_FREE(my_ip_str);
604 LDNS_FREE(afdpart);
606 }
607 for (i = 0; i < 16; i++) {
608 if (afdpart[i] != 0) {
609 afdlength = i + 1;
610 }
611 }
612 } else {
613 /* unknown family */
614 LDNS_FREE(my_ip_str);
616 }
617
618 my_str = strchr(my_str, '/') + 1;
619 prefix = (uint8_t) atoi(my_str);
620
621 data = LDNS_XMALLOC(uint8_t, 4 + afdlength);
622 if(!data) {
623 LDNS_FREE(afdpart);
624 LDNS_FREE(my_ip_str);
626 }
627 ldns_write_uint16(data, family);
628 data[2] = prefix;
629 data[3] = afdlength;
630 if (negation) {
631 /* set bit 1 of byte 3 */
632 data[3] = data[3] | 0x80;
633 }
634
635 memcpy(data + 4, afdpart, afdlength);
636
637 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_APL, afdlength + 4, data);
638 LDNS_FREE(afdpart);
639 LDNS_FREE(data);
640 LDNS_FREE(my_ip_str);
641
643}
644
646ldns_str2rdf_b64(ldns_rdf **rd, const char *str)
647{
648 uint8_t *buffer;
649 int16_t i;
650
651 if ((*str == '-' || *str == '0') && str[1] == '\0') {
653 return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
654 }
655
656 buffer = LDNS_XMALLOC(uint8_t, ldns_b64_ntop_calculate_size(strlen(str)));
657 if(!buffer) {
658 return LDNS_STATUS_MEM_ERR;
659 }
660
661 i = (uint16_t)ldns_b64_pton((const char*)str, buffer,
662 ldns_b64_ntop_calculate_size(strlen(str)));
663 if (-1 == i) {
664 LDNS_FREE(buffer);
666 } else {
668 LDNS_RDF_TYPE_B64, (uint16_t) i, buffer);
669 }
670 LDNS_FREE(buffer);
671
673}
674
676ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str)
677{
678 uint8_t *buffer;
679 int i;
680 /* first byte contains length of actual b32 data */
681 size_t slen = strlen(str);
682 size_t len = ldns_b32_pton_calculate_size(slen);
683 if (len > 255) {
685 }
686 buffer = LDNS_XMALLOC(uint8_t, len + 1);
687 if(!buffer) {
688 return LDNS_STATUS_MEM_ERR;
689 }
690 buffer[0] = len;
691
692 i = ldns_b32_pton_extended_hex((const char*)str, slen, buffer + 1,
693 ldns_b32_ntop_calculate_size(slen));
694 if (i < 0) {
695 LDNS_FREE(buffer);
697 } else {
699 LDNS_RDF_TYPE_B32_EXT, (uint16_t) i + 1, buffer);
700 }
701 LDNS_FREE(buffer);
702
704}
705
707ldns_str2rdf_hex(ldns_rdf **rd, const char *str)
708{
709 uint8_t *t, *t_orig;
710 int i;
711 size_t len;
712
713 len = strlen(str);
714
715 if (len > LDNS_MAX_RDFLEN * 2) {
717 } else {
718 t = LDNS_XMALLOC(uint8_t, (len / 2) + 1);
719 if(!t) {
720 return LDNS_STATUS_MEM_ERR;
721 }
722 t_orig = t;
723 /* Now process octet by octet... */
724 while (*str) {
725 *t = 0;
726 if (isspace((int) *str)) {
727 str++;
728 } else {
729 for (i = 16; i >= 1; i -= 15) {
730 while (*str && isspace((int) *str)) { str++; }
731 if (*str) {
732 if (isxdigit((int) *str)) {
733 *t += ldns_hexdigit_to_int(*str) * i;
734 } else {
735 LDNS_FREE(t_orig);
736 return LDNS_STATUS_ERR;
737 }
738 ++str;
739 }
740 }
741 ++t;
742 }
743 }
745 (size_t) (t - t_orig),
746 t_orig);
747 LDNS_FREE(t_orig);
748 }
750}
751
753ldns_str2rdf_nsec(ldns_rdf **rd, const char *str)
754{
755 const char *delimiters = "\n\t ";
756 char *token = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN);
757 ldns_buffer *str_buf;
758 ssize_t c;
759 uint16_t cur_type;
760 size_t type_count = 0;
761 ldns_rr_type type_list[65536];
762 if(!token) return LDNS_STATUS_MEM_ERR;
763 if(rd == NULL) {
764 LDNS_FREE(token);
765 return LDNS_STATUS_NULL;
766 }
767
768 str_buf = LDNS_MALLOC(ldns_buffer);
769 if(!str_buf) {
770 LDNS_FREE(token);
771 return LDNS_STATUS_MEM_ERR;
772 }
773 ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
774 if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) {
775 LDNS_FREE(str_buf);
776 LDNS_FREE(token);
777 return LDNS_STATUS_MEM_ERR;
778 }
779
780 while ((c = ldns_bget_token(str_buf, token, delimiters, LDNS_MAX_RDFLEN)) != -1 && c != 0) {
781 if(type_count >= sizeof(type_list)) {
782 LDNS_FREE(str_buf);
783 LDNS_FREE(token);
784 return LDNS_STATUS_ERR;
785 }
786 cur_type = ldns_get_rr_type_by_name(token);
787 type_list[type_count] = cur_type;
788 type_count++;
789 }
790
791 *rd = ldns_dnssec_create_nsec_bitmap(type_list,
792 type_count,
794
795 LDNS_FREE(token);
796 ldns_buffer_free(str_buf);
798}
799
801ldns_str2rdf_type(ldns_rdf **rd, const char *str)
802{
803 uint16_t type;
804 type = htons(ldns_get_rr_type_by_name(str));
805 /* ldns_rr_type is a 16 bit value */
807 LDNS_RDF_TYPE_TYPE, sizeof(uint16_t), &type);
809}
810
812ldns_str2rdf_class(ldns_rdf **rd, const char *str)
813{
814 uint16_t klass;
815 klass = htons(ldns_get_rr_class_by_name(str));
816 /* class is 16 bit */
818 LDNS_RDF_TYPE_CLASS, sizeof(uint16_t), &klass);
820}
821
822/* An certificate alg field can either be specified as a 8 bits number
823 * or by its symbolic name. Handle both
824 */
826ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str)
827{
829 ldns_status st;
830 uint8_t idd[2];
832 st = LDNS_STATUS_OK;
833
834 if (lt) {
835 ldns_write_uint16(idd, (uint16_t) lt->id);
837 LDNS_RDF_TYPE_INT16, sizeof(uint16_t), idd);
838 if (!*rd) {
839 st = LDNS_STATUS_ERR;
840 }
841 } else {
842 /* try as-is (a number) */
843 st = ldns_str2rdf_int16(rd, str);
844 if (st == LDNS_STATUS_OK &&
845 ldns_rdf2native_int16(*rd) == 0) {
847 }
848 }
849
850 return st;
851}
852
853static ldns_lookup_table ldns_tlsa_certificate_usages[] = {
854 { LDNS_TLSA_USAGE_PKIX_TA , "PKIX-TA" },
855 { LDNS_TLSA_USAGE_PKIX_EE , "PKIX-EE" },
856 { LDNS_TLSA_USAGE_DANE_TA , "DANE-TA" },
857 { LDNS_TLSA_USAGE_DANE_EE , "DANE-EE" },
858 { LDNS_TLSA_USAGE_PRIVCERT , "PrivCert" },
859 { 0, NULL }
860};
861
862static ldns_lookup_table ldns_tlsa_selectors[] = {
863 { LDNS_TLSA_SELECTOR_CERT , "Cert" },
864 { LDNS_TLSA_SELECTOR_SPKI , "SPKI" },
865 { LDNS_TLSA_SELECTOR_PRIVSEL , "PrivSel" },
866 { 0, NULL }
867};
868
869static ldns_lookup_table ldns_tlsa_matching_types[] = {
870 { LDNS_TLSA_MATCHING_TYPE_FULL , "Full" },
871 { LDNS_TLSA_MATCHING_TYPE_SHA2_256 , "SHA2-256" },
872 { LDNS_TLSA_MATCHING_TYPE_SHA2_512 , "SHA2-512" },
873 { LDNS_TLSA_MATCHING_TYPE_PRIVMATCH , "PrivMatch" },
874 { 0, NULL }
875};
876
877static ldns_status
878ldns_str2rdf_mnemonic4int8(ldns_lookup_table *lt,
879 ldns_rdf **rd, const char *str)
880{
881 if ((lt = ldns_lookup_by_name(lt, str))) {
882 /* it was given as a integer */
883 *rd = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t) lt->id);
884 if (!*rd)
885 return LDNS_STATUS_ERR;
886 else
887 return LDNS_STATUS_OK;
888 }
889 return ldns_str2rdf_int8(rd, str);
890}
891
892/* An alg field can either be specified as a 8 bits number
893 * or by its symbolic name. Handle both
894 */
896ldns_str2rdf_alg(ldns_rdf **rd, const char *str)
897{
898 return ldns_str2rdf_mnemonic4int8(ldns_algorithms, rd, str);
899}
900
903{
904 return ldns_str2rdf_mnemonic4int8(
905 ldns_tlsa_certificate_usages, rd, str);
906}
907
909ldns_str2rdf_selector(ldns_rdf **rd, const char *str)
910{
911 return ldns_str2rdf_mnemonic4int8(ldns_tlsa_selectors, rd, str);
912}
913
916{
917 return ldns_str2rdf_mnemonic4int8(ldns_tlsa_matching_types, rd, str);
918}
919
922 , ATTR_UNUSED(const char *str)
923 )
924{
925 /* this should be caught in an earlier time (general str2host for
926 rr's */
928}
929
932 , ATTR_UNUSED(const char *str)
933 )
934{
935 /* is this used? is this actually WKS? or SRV? */
937}
938
939static int
940loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e)
941{
942 /* read <digits>[.<digits>][mM] */
943 /* into mantissa exponent format for LOC type */
944 uint32_t meters = 0, cm = 0, val;
945 char* cm_endstr;
946 while (isblank((unsigned char)*my_str)) {
947 my_str++;
948 }
949 meters = (uint32_t)strtol(my_str, &my_str, 10);
950 if (*my_str == '.') {
951 my_str++;
952 cm = (uint32_t)strtol(my_str, &cm_endstr, 10);
953 if (cm_endstr - my_str == 1) cm *= 10;
954 my_str = cm_endstr;
955 }
956 if (meters >= 1) {
957 *e = 2;
958 val = meters;
959 } else {
960 *e = 0;
961 val = cm;
962 }
963 while(val >= 10) {
964 (*e)++;
965 val /= 10;
966 }
967 *m = (uint8_t)val;
968
969 if (*e > 9)
970 return 0;
971 if (*my_str == 'm' || *my_str == 'M') {
972 my_str++;
973 }
974 *endstr = my_str;
975 return 1;
976}
977
979ldns_str2rdf_loc(ldns_rdf **rd, const char *str)
980{
981 uint32_t latitude = 0;
982 uint32_t longitude = 0;
983 uint32_t altitude = 0;
984
985 uint8_t *data;
986 uint32_t equator = (uint32_t) ldns_power(2, 31);
987
988 uint32_t h = 0;
989 uint32_t m = 0;
990 uint8_t size_b = 1, size_e = 2;
991 uint8_t horiz_pre_b = 1, horiz_pre_e = 6;
992 uint8_t vert_pre_b = 1, vert_pre_e = 3;
993
994 double s = 0.0;
995 bool northern_hemisphere;
996 bool eastern_hemisphere;
997
998 char *my_str = (char *) str;
999
1000 /* only support version 0 */
1001 if (isdigit((int) *my_str)) {
1002 h = (uint32_t) strtol(my_str, &my_str, 10);
1003 } else {
1005 }
1006
1007 while (isblank((int) *my_str)) {
1008 my_str++;
1009 }
1010
1011 if (isdigit((int) *my_str)) {
1012 m = (uint32_t) strtol(my_str, &my_str, 10);
1013 } else if (*my_str == 'N' || *my_str == 'S') {
1014 goto north;
1015 } else {
1017 }
1018
1019 while (isblank((int) *my_str)) {
1020 my_str++;
1021 }
1022
1023 if (isdigit((int) *my_str)) {
1024 s = strtod(my_str, &my_str);
1025 }
1026north:
1027 while (isblank((int) *my_str)) {
1028 my_str++;
1029 }
1030
1031 if (*my_str == 'N') {
1032 northern_hemisphere = true;
1033 } else if (*my_str == 'S') {
1034 northern_hemisphere = false;
1035 } else {
1037 }
1038
1039 my_str++;
1040
1041 /* store number */
1042 s = 1000.0 * s;
1043 /* add a little to make floor in conversion a round */
1044 s += 0.0005;
1045 latitude = (uint32_t) s;
1046 latitude += 1000 * 60 * m;
1047 latitude += 1000 * 60 * 60 * h;
1048 if (northern_hemisphere) {
1049 latitude = equator + latitude;
1050 } else {
1051 latitude = equator - latitude;
1052 }
1053 while (isblank((unsigned char)*my_str)) {
1054 my_str++;
1055 }
1056
1057 if (isdigit((int) *my_str)) {
1058 h = (uint32_t) strtol(my_str, &my_str, 10);
1059 } else {
1061 }
1062
1063 while (isblank((int) *my_str)) {
1064 my_str++;
1065 }
1066
1067 if (isdigit((int) *my_str)) {
1068 m = (uint32_t) strtol(my_str, &my_str, 10);
1069 } else if (*my_str == 'E' || *my_str == 'W') {
1070 goto east;
1071 } else {
1073 }
1074
1075 while (isblank((unsigned char)*my_str)) {
1076 my_str++;
1077 }
1078
1079 if (isdigit((int) *my_str)) {
1080 s = strtod(my_str, &my_str);
1081 }
1082
1083east:
1084 while (isblank((unsigned char)*my_str)) {
1085 my_str++;
1086 }
1087
1088 if (*my_str == 'E') {
1089 eastern_hemisphere = true;
1090 } else if (*my_str == 'W') {
1091 eastern_hemisphere = false;
1092 } else {
1094 }
1095
1096 my_str++;
1097
1098 /* store number */
1099 s *= 1000.0;
1100 /* add a little to make floor in conversion a round */
1101 s += 0.0005;
1102 longitude = (uint32_t) s;
1103 longitude += 1000 * 60 * m;
1104 longitude += 1000 * 60 * 60 * h;
1105
1106 if (eastern_hemisphere) {
1107 longitude += equator;
1108 } else {
1109 longitude = equator - longitude;
1110 }
1111
1112 altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 +
1113 10000000.0 + 0.5);
1114 if (*my_str == 'm' || *my_str == 'M') {
1115 my_str++;
1116 }
1117
1118 if (strlen(my_str) > 0) {
1119 if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e))
1121 }
1122
1123 if (strlen(my_str) > 0) {
1124 if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e))
1126 }
1127
1128 if (strlen(my_str) > 0) {
1129 if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e))
1131 }
1132
1133 data = LDNS_XMALLOC(uint8_t, 16);
1134 if(!data) {
1135 return LDNS_STATUS_MEM_ERR;
1136 }
1137 data[0] = 0;
1138 data[1] = 0;
1139 data[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f);
1140 data[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f);
1141 data[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f);
1142 ldns_write_uint32(data + 4, latitude);
1143 ldns_write_uint32(data + 8, longitude);
1144 ldns_write_uint32(data + 12, altitude);
1145
1147 LDNS_RDF_TYPE_LOC, 16, data);
1148
1149 LDNS_FREE(data);
1151}
1152
1154ldns_str2rdf_wks(ldns_rdf **rd, const char *str)
1155{
1156 uint8_t *bitmap = NULL;
1157 uint8_t *data;
1158 int bm_len = 0;
1159
1160 struct protoent *proto = NULL;
1161 struct servent *serv = NULL;
1162 int serv_port;
1163
1164 ldns_buffer *str_buf;
1165
1166 char *proto_str = NULL;
1167 char *lc_proto_str = NULL;
1168 char *token;
1169 char *lc_token;
1170 char *c;
1171 if(strlen(str) == 0)
1172 token = LDNS_XMALLOC(char, 50);
1173 else token = LDNS_XMALLOC(char, strlen(str)+2);
1174 if(!token) return LDNS_STATUS_MEM_ERR;
1175
1176 str_buf = LDNS_MALLOC(ldns_buffer);
1177 if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;}
1178 ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
1179 if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) {
1180 LDNS_FREE(str_buf);
1181 LDNS_FREE(token);
1182 return LDNS_STATUS_MEM_ERR;
1183 }
1184
1185 while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) {
1186 if (!proto_str) {
1187 proto_str = strdup(token);
1188 lc_proto_str = strdup(token);
1189 for (c = lc_proto_str; *c; c++) {
1190 *c = tolower((unsigned char)*c);
1191 }
1192 if (!proto_str || !lc_proto_str) {
1193 free(proto_str);
1194 free(lc_proto_str);
1195 LDNS_FREE(bitmap);
1196 LDNS_FREE(token);
1197 ldns_buffer_free(str_buf);
1199 }
1200 } else {
1201 serv = getservbyname(token, proto_str);
1202 if (!serv) {
1203 serv = getservbyname(token, lc_proto_str);
1204 }
1205 if (!serv && (lc_token = strdup(token))) {
1206 for (c = lc_token; *c; c++) {
1207 *c = tolower((unsigned char)*c);
1208 }
1209 serv = getservbyname(lc_token, proto_str);
1210 if (!serv) {
1211 serv = getservbyname(lc_token, lc_proto_str);
1212 }
1213 free(lc_token);
1214 }
1215 if (serv) {
1216 serv_port = (int) ntohs((uint16_t) serv->s_port);
1217 } else {
1218 serv_port = atoi(token);
1219 }
1220 if (serv_port < 0 || serv_port > 65535) {
1221 LDNS_FREE(bitmap);
1222 LDNS_FREE(token);
1223 ldns_buffer_free(str_buf);
1224 free(proto_str);
1225 free(lc_proto_str);
1227 }
1228 if (serv_port / 8 >= bm_len) {
1229 uint8_t *b2 = LDNS_XREALLOC(bitmap, uint8_t, (serv_port / 8) + 1);
1230 if(!b2) {
1231 LDNS_FREE(bitmap);
1232 LDNS_FREE(token);
1233 ldns_buffer_free(str_buf);
1234 free(proto_str);
1235 free(lc_proto_str);
1237 }
1238 bitmap = b2;
1239 /* set to zero to be sure */
1240 for (; bm_len <= serv_port / 8; bm_len++) {
1241 bitmap[bm_len] = 0;
1242 }
1243 }
1244 ldns_set_bit(bitmap + (serv_port / 8), 7 - (serv_port % 8), true);
1245 }
1246 }
1247
1248 if (!proto_str || !bitmap) {
1249 LDNS_FREE(bitmap);
1250 LDNS_FREE(token);
1251 ldns_buffer_free(str_buf);
1252 free(proto_str);
1253 free(lc_proto_str);
1255 }
1256
1257 data = LDNS_XMALLOC(uint8_t, bm_len + 1);
1258 if(!data) {
1259 LDNS_FREE(token);
1260 ldns_buffer_free(str_buf);
1261 LDNS_FREE(bitmap);
1262 free(proto_str);
1263 free(lc_proto_str);
1265 }
1266 if (proto_str)
1267 proto = getprotobyname(proto_str);
1268 if (!proto) {
1269 proto = getprotobyname(lc_proto_str);
1270 }
1271 if (proto) {
1272 data[0] = (uint8_t) proto->p_proto;
1273 } else if (proto_str) {
1274 data[0] = (uint8_t) atoi(proto_str);
1275 }
1276 memcpy(data + 1, bitmap, (size_t) bm_len);
1277
1278 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_WKS, (uint16_t) (bm_len + 1), data);
1279
1280 LDNS_FREE(data);
1281 LDNS_FREE(token);
1282 ldns_buffer_free(str_buf);
1283 LDNS_FREE(bitmap);
1284 free(proto_str);
1285 free(lc_proto_str);
1286#ifdef HAVE_ENDSERVENT
1287 endservent();
1288#endif
1289#ifdef HAVE_ENDPROTOENT
1290 endprotoent();
1291#endif
1292
1293 if(!*rd) return LDNS_STATUS_MEM_ERR;
1294
1295 return LDNS_STATUS_OK;
1296}
1297
1299ldns_str2rdf_nsap(ldns_rdf **rd, const char *str)
1300{
1301 size_t len, i;
1302 char* nsap_str = (char*) str;
1303
1304 /* just a hex string with optional dots? */
1305 if (str[0] != '0' || str[1] != 'x') {
1307 } else {
1308 len = strlen(str);
1309 for (i=0; i < len; i++) {
1310 if (nsap_str[i] == '.')
1311 nsap_str[i] = ' ';
1312 }
1313 return ldns_str2rdf_hex(rd, str+2);
1314 }
1315}
1316
1318ldns_str2rdf_atma(ldns_rdf **rd, const char *str)
1319{
1320 size_t len, i;
1321 char* atma_str = (char*) str;
1322 ldns_status status;
1323
1324 /* just a hex string with optional dots? */
1325 len = strlen(str);
1326 for (i=0; i < len; i++) {
1327 if (atma_str[i] == '.')
1328 atma_str[i] = ' ';
1329 }
1330 status = ldns_str2rdf_hex(rd, str);
1331 if (status != LDNS_STATUS_OK) {
1332 ; /* probably in e.164 format than */
1333 }
1334 return status;
1335}
1336
1338ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str)
1339{
1340 uint8_t precedence = 0;
1341 uint8_t gateway_type = 0;
1342 uint8_t algorithm = 0;
1343 char* gateway = NULL;
1344 char* publickey = NULL;
1345 uint8_t *data;
1346 ldns_buffer *str_buf;
1347 char *token;
1348 int token_count = 0;
1349 int ipseckey_len = 0;
1350 ldns_rdf* gateway_rdf = NULL;
1351 ldns_rdf* publickey_rdf = NULL;
1352 ldns_status status = LDNS_STATUS_OK;
1353
1354 if(strlen(str) == 0)
1355 token = LDNS_XMALLOC(char, 256);
1356 else token = LDNS_XMALLOC(char, strlen(str)+2);
1357 if(!token) return LDNS_STATUS_MEM_ERR;
1358
1359 str_buf = LDNS_MALLOC(ldns_buffer);
1360 if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;}
1361 ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
1362 if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) {
1363 LDNS_FREE(str_buf);
1364 LDNS_FREE(token);
1365 return LDNS_STATUS_MEM_ERR;
1366 }
1367 while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) {
1368 switch (token_count) {
1369 case 0:
1370 precedence = (uint8_t)atoi(token);
1371 break;
1372 case 1:
1373 gateway_type = (uint8_t)atoi(token);
1374 break;
1375 case 2:
1376 algorithm = (uint8_t)atoi(token);
1377 break;
1378 case 3:
1379 gateway = strdup(token);
1380 if (!gateway || (gateway_type == 0 &&
1381 (token[0] != '.' || token[1] != '\0'))) {
1382 LDNS_FREE(gateway);
1383 LDNS_FREE(token);
1384 ldns_buffer_free(str_buf);
1386 }
1387 break;
1388 case 4:
1389 publickey = strdup(token);
1390 break;
1391 default:
1392 LDNS_FREE(token);
1393 ldns_buffer_free(str_buf);
1395 break;
1396 }
1397 token_count++;
1398 }
1399
1400 if (!gateway || !publickey) {
1401 if (gateway)
1402 LDNS_FREE(gateway);
1403 if (publickey)
1404 LDNS_FREE(publickey);
1405 LDNS_FREE(token);
1406 ldns_buffer_free(str_buf);
1408 }
1409
1410 if (gateway_type == 1) {
1411 status = ldns_str2rdf_a(&gateway_rdf, gateway);
1412 } else if (gateway_type == 2) {
1413 status = ldns_str2rdf_aaaa(&gateway_rdf, gateway);
1414 } else if (gateway_type == 3) {
1415 status = ldns_str2rdf_dname(&gateway_rdf, gateway);
1416 } else if (gateway_type > 3) {
1417 status = LDNS_STATUS_INVALID_STR;
1418 }
1419
1420 if (status != LDNS_STATUS_OK) {
1421 if (gateway)
1422 LDNS_FREE(gateway);
1423 if (publickey)
1424 LDNS_FREE(publickey);
1425 LDNS_FREE(token);
1426 ldns_buffer_free(str_buf);
1428 }
1429
1430 status = ldns_str2rdf_b64(&publickey_rdf, publickey);
1431
1432 if (status != LDNS_STATUS_OK) {
1433 if (gateway)
1434 LDNS_FREE(gateway);
1435 if (publickey)
1436 LDNS_FREE(publickey);
1437 LDNS_FREE(token);
1438 ldns_buffer_free(str_buf);
1439 if (gateway_rdf) ldns_rdf_free(gateway_rdf);
1441 }
1442
1443 /* now copy all into one ipseckey rdf */
1444 if (gateway_type)
1445 ipseckey_len = 3 + (int)ldns_rdf_size(gateway_rdf) + (int)ldns_rdf_size(publickey_rdf);
1446 else
1447 ipseckey_len = 3 + (int)ldns_rdf_size(publickey_rdf);
1448
1449 data = LDNS_XMALLOC(uint8_t, ipseckey_len);
1450 if(!data) {
1451 if (gateway)
1452 LDNS_FREE(gateway);
1453 if (publickey)
1454 LDNS_FREE(publickey);
1455 LDNS_FREE(token);
1456 ldns_buffer_free(str_buf);
1457 if (gateway_rdf) ldns_rdf_free(gateway_rdf);
1458 if (publickey_rdf) ldns_rdf_free(publickey_rdf);
1459 return LDNS_STATUS_MEM_ERR;
1460 }
1461
1462 data[0] = precedence;
1463 data[1] = gateway_type;
1464 data[2] = algorithm;
1465
1466 if (gateway_type) {
1467 memcpy(data + 3,
1468 ldns_rdf_data(gateway_rdf), ldns_rdf_size(gateway_rdf));
1469 memcpy(data + 3 + ldns_rdf_size(gateway_rdf),
1470 ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf));
1471 } else {
1472 memcpy(data + 3,
1473 ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf));
1474 }
1475
1476 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_IPSECKEY, (uint16_t) ipseckey_len, data);
1477
1478 if (gateway)
1479 LDNS_FREE(gateway);
1480 if (publickey)
1481 LDNS_FREE(publickey);
1482 LDNS_FREE(token);
1483 ldns_buffer_free(str_buf);
1484 ldns_rdf_deep_free(gateway_rdf);
1485 ldns_rdf_deep_free(publickey_rdf);
1486 LDNS_FREE(data);
1487 if(!*rd) return LDNS_STATUS_MEM_ERR;
1488 return LDNS_STATUS_OK;
1489}
1490
1492ldns_str2rdf_ilnp64(ldns_rdf **rd, const char *str)
1493{
1494 unsigned int a, b, c, d;
1495 uint16_t shorts[4];
1496 int l;
1497
1498 if (sscanf(str, "%4x:%4x:%4x:%4x%n", &a, &b, &c, &d, &l) != 4 ||
1499 l != (int)strlen(str) || /* more data to read */
1500 strpbrk(str, "+-") /* signed hexes */
1501 ) {
1503 } else {
1504 shorts[0] = htons(a);
1505 shorts[1] = htons(b);
1506 shorts[2] = htons(c);
1507 shorts[3] = htons(d);
1509 LDNS_RDF_TYPE_ILNP64, 4 * sizeof(uint16_t), &shorts);
1510 }
1511 return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
1512}
1513
1515ldns_str2rdf_eui48(ldns_rdf **rd, const char *str)
1516{
1517 unsigned int a, b, c, d, e, f;
1518 uint8_t bytes[6];
1519 int l;
1520
1521 if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x%n",
1522 &a, &b, &c, &d, &e, &f, &l) != 6 ||
1523 l != (int)strlen(str)) {
1525 } else {
1526 bytes[0] = a;
1527 bytes[1] = b;
1528 bytes[2] = c;
1529 bytes[3] = d;
1530 bytes[4] = e;
1531 bytes[5] = f;
1533 }
1534 return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
1535}
1536
1538ldns_str2rdf_eui64(ldns_rdf **rd, const char *str)
1539{
1540 unsigned int a, b, c, d, e, f, g, h;
1541 uint8_t bytes[8];
1542 int l;
1543
1544 if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x%n",
1545 &a, &b, &c, &d, &e, &f, &g, &h, &l) != 8 ||
1546 l != (int)strlen(str)) {
1548 } else {
1549 bytes[0] = a;
1550 bytes[1] = b;
1551 bytes[2] = c;
1552 bytes[3] = d;
1553 bytes[4] = e;
1554 bytes[5] = f;
1555 bytes[6] = g;
1556 bytes[7] = h;
1558 }
1559 return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
1560}
1561
1563ldns_str2rdf_tag(ldns_rdf **rd, const char *str)
1564{
1565 uint8_t *data;
1566 const char* ptr;
1567
1568 if (strlen(str) > 255) {
1570 }
1571 for (ptr = str; *ptr; ptr++) {
1572 if (! isalnum((unsigned char)*ptr)) {
1574 }
1575 }
1576 data = LDNS_XMALLOC(uint8_t, strlen(str) + 1);
1577 if (!data) {
1578 return LDNS_STATUS_MEM_ERR;
1579 }
1580 data[0] = strlen(str);
1581 memcpy(data + 1, str, strlen(str));
1582
1583 *rd = ldns_rdf_new(LDNS_RDF_TYPE_TAG, strlen(str) + 1, data);
1584 if (!*rd) {
1585 LDNS_FREE(data);
1586 return LDNS_STATUS_MEM_ERR;
1587 }
1588 return LDNS_STATUS_OK;
1589}
1590
1592ldns_str2rdf_long_str(ldns_rdf **rd, const char *str)
1593{
1594 uint8_t *data, *dp, ch = 0;
1595 size_t length;
1596
1597 /* Worst case space requirement. We'll realloc to actual size later. */
1598 dp = data = LDNS_XMALLOC(uint8_t, strlen(str));
1599 if (! data) {
1600 return LDNS_STATUS_MEM_ERR;
1601 }
1602
1603 /* Fill data with parsed bytes */
1604 while (parse_char(&ch, &str)) {
1605 *dp++ = ch;
1606 if (dp - data > LDNS_MAX_RDFLEN) {
1607 LDNS_FREE(data);
1609 }
1610 }
1611 if (! str) {
1612 LDNS_FREE(data);
1614 }
1615 if (!(length = (size_t)(dp - data))) {
1616 /* An empty string is a data buffer of 0 bytes. The rdf for
1617 * this long string has to have length 0 and point to NULL.
1618 */
1619 LDNS_FREE(data);
1620 data = NULL;
1621 } else {
1622 /* Lose the overmeasure */
1623 data = LDNS_XREALLOC(dp = data, uint8_t, length);
1624 if (! data) {
1625 LDNS_FREE(dp);
1626 return LDNS_STATUS_MEM_ERR;
1627 }
1628 }
1629 /* Create rdf */
1630 *rd = ldns_rdf_new(LDNS_RDF_TYPE_LONG_STR, length, data);
1631 if (! *rd) {
1632 LDNS_FREE(data);
1633 return LDNS_STATUS_MEM_ERR;
1634 }
1635 return LDNS_STATUS_OK;
1636}
1637
1639ldns_str2rdf_hip(ldns_rdf **rd, const char *str)
1640{
1641 const char *hit = str == NULL ? NULL : strchr(str, ' ');
1642 const char *pk = hit == NULL ? NULL : strchr(hit + 1, ' ');
1643 size_t hit_size = hit == NULL ? 0
1644 : pk == NULL ? strlen(hit + 1) : (size_t) (pk - hit) - 1;
1645 size_t pk_size = pk == NULL ? 0 : strlen(pk + 1);
1646 size_t hit_wire_size = (hit_size + 1) / 2;
1647 size_t pk_wire_size = ldns_b64_pton_calculate_size(pk_size);
1648 size_t rdf_size = 4 + hit_wire_size + pk_wire_size;
1649
1650 char *endptr; /* utility var for strtol usage */
1651 int algorithm = str == NULL ? 0 : strtol(str, &endptr, 10);
1652
1653 uint8_t *data, *dp;
1654 int hi, lo, written;
1655
1656 if (hit_size == 0 || pk_size == 0 || (hit_size + 1) / 2 > 255
1657 || rdf_size > LDNS_MAX_RDFLEN
1658 || algorithm < 0 || algorithm > 255
1659 || (errno != 0 && algorithm == 0) /* out of range */
1660 || endptr == str /* no digits */) {
1661
1663 }
1664 hit += 1;
1665 pk += 1;
1666 if ((data = LDNS_XMALLOC(uint8_t, rdf_size)) == NULL) {
1667
1668 return LDNS_STATUS_MEM_ERR;
1669 }
1670 /* From RFC 5205 section 5. HIP RR Storage Format:
1671 *************************************************
1672
1673 0 1 2 3
1674 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1675 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1676 | HIT length | PK algorithm | PK length |
1677 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1678 | |
1679 ~ HIT ~
1680 | |
1681 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1682 | | |
1683 +-+-+-+-+-+-+-+-+-+-+-+ +
1684 | Public Key |
1685 ~ ~
1686 | |
1687 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1688 | | |
1689 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
1690 | |
1691 ~ Rendezvous Servers ~
1692 | |
1693 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1694 | |
1695 +-+-+-+-+-+-+-+ */
1696
1697 data[0] = (uint8_t) hit_wire_size;
1698 data[1] = (uint8_t) algorithm;
1699
1700 for (dp = data + 4; *hit && *hit != ' '; dp++) {
1701
1702 if ((hi = ldns_hexdigit_to_int(*hit++)) == -1 ||
1703 (lo = ldns_hexdigit_to_int(*hit++)) == -1) {
1704
1705 LDNS_FREE(data);
1707 }
1708 *dp = (uint8_t) hi << 4 | lo;
1709 }
1710 if ((written = ldns_b64_pton(pk, dp, pk_wire_size)) <= 0) {
1711
1712 LDNS_FREE(data);
1714 }
1715
1716 /* Because ldns_b64_pton_calculate_size isn't always correct:
1717 * (we have to fix it at some point)
1718 */
1719 pk_wire_size = (uint16_t) written;
1720 ldns_write_uint16(data + 2, pk_wire_size);
1721 rdf_size = 4 + hit_wire_size + pk_wire_size;
1722
1723 /* Create rdf */
1724 if (! (*rd = ldns_rdf_new(LDNS_RDF_TYPE_HIP, rdf_size, data))) {
1725
1726 LDNS_FREE(data);
1727 return LDNS_STATUS_MEM_ERR;
1728 }
1729 return LDNS_STATUS_OK;
1730}
1731
1732
1733/* Implementation mimics ldns_str2rdf_ipseckey */
1735ldns_str2rdf_amtrelay(ldns_rdf **rd, const char *str)
1736{
1737 /* From draft-ietf-mboned-driad-amt-discovery
1738 * Section 4.2. AMTRELAY RData Format
1739 *************************************************
1740
1741 0 1 2 3
1742 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1743 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1744 | precedence |D| type | |
1745 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
1746 ~ relay ~
1747 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
1748
1749 uint8_t precedence = 0;
1750 uint8_t relay_type = 0;
1751 uint8_t discovery_optional = 0;
1752 char* relay = NULL;
1753 uint8_t *data;
1754 ldns_buffer *str_buf;
1755 char *token;
1756 int token_count = 0;
1757 int amtrelay_len = 0;
1758 ldns_rdf* relay_rdf = NULL;
1759 ldns_status status = LDNS_STATUS_OK;
1760
1761 if(strlen(str) == 0)
1762 token = LDNS_XMALLOC(char, 256);
1763 else token = LDNS_XMALLOC(char, strlen(str)+2);
1764 if(!token) return LDNS_STATUS_MEM_ERR;
1765
1766 str_buf = LDNS_MALLOC(ldns_buffer);
1767 if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;}
1768 ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
1769 if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) {
1770 LDNS_FREE(str_buf);
1771 LDNS_FREE(token);
1772 return LDNS_STATUS_MEM_ERR;
1773 }
1774 while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) {
1775 switch (token_count) {
1776 case 0:
1777 precedence = (uint8_t)atoi(token);
1778 break;
1779 case 1:
1780 discovery_optional = (uint8_t)atoi(token);
1781 if (discovery_optional != 0 &&
1782 discovery_optional != 1) {
1783 LDNS_FREE(relay);
1784 LDNS_FREE(token);
1785 ldns_buffer_free(str_buf);
1787 }
1788 break;
1789 case 2:
1790 relay_type = (uint8_t)atoi(token);
1791 break;
1792 case 3:
1793 relay = strdup(token);
1794 if (!relay || (relay_type == 0 &&
1795 (token[0] != '.' || token[1] != '\0'))) {
1796 LDNS_FREE(relay);
1797 LDNS_FREE(token);
1798 ldns_buffer_free(str_buf);
1800 }
1801 break;
1802 default:
1803 LDNS_FREE(token);
1804 ldns_buffer_free(str_buf);
1806 break;
1807 }
1808 token_count++;
1809 }
1810 if (!relay && relay_type > 0) {
1811 if (relay)
1812 LDNS_FREE(relay);
1813 LDNS_FREE(token);
1814 ldns_buffer_free(str_buf);
1816 }
1817
1818 if (relay_type == 1) {
1819 status = ldns_str2rdf_a(&relay_rdf, relay);
1820 } else if (relay_type == 2) {
1821 status = ldns_str2rdf_aaaa(&relay_rdf, relay);
1822 } else if (relay_type == 3) {
1823 status = ldns_str2rdf_dname(&relay_rdf, relay);
1824 } else if (relay_type > 3) {
1825 status = LDNS_STATUS_INVALID_STR;
1826 }
1827
1828 if (status != LDNS_STATUS_OK) {
1829 if (relay)
1830 LDNS_FREE(relay);
1831 LDNS_FREE(token);
1832 ldns_buffer_free(str_buf);
1833 ldns_rdf_deep_free(relay_rdf);
1835 }
1836
1837 /* now copy all into one amtrelay rdf */
1838 if (relay_type)
1839 amtrelay_len = 2 + (int)ldns_rdf_size(relay_rdf);
1840 else
1841 amtrelay_len = 2;
1842
1843 data = LDNS_XMALLOC(uint8_t, amtrelay_len);
1844 if(!data) {
1845 if (relay)
1846 LDNS_FREE(relay);
1847 LDNS_FREE(token);
1848 ldns_buffer_free(str_buf);
1849 ldns_rdf_deep_free(relay_rdf);
1850 return LDNS_STATUS_MEM_ERR;
1851 }
1852
1853 data[0] = precedence;
1854 data[1] = relay_type;
1855 data[1] |= (discovery_optional << 7);
1856
1857 if (relay_type) {
1858 memcpy(data + 2,
1859 ldns_rdf_data(relay_rdf), ldns_rdf_size(relay_rdf));
1860 }
1862 , (uint16_t) amtrelay_len, data);
1863
1864 if (relay)
1865 LDNS_FREE(relay);
1866 LDNS_FREE(token);
1867 ldns_buffer_free(str_buf);
1868 ldns_rdf_deep_free(relay_rdf);
1869 LDNS_FREE(data);
1870 if(!*rd) return LDNS_STATUS_MEM_ERR;
1871 return LDNS_STATUS_OK;
1872}
1873
1874#ifdef RRTYPE_SVCB_HTTPS
1875static int
1876network_uint16_cmp(const void *a, const void *b)
1877{
1878 return ((int)ldns_read_uint16(a)) - ((int)ldns_read_uint16(b));
1879}
1880
1881static ldns_status parse_svcparam_key(const char **s, ldns_svcparam_key *key);
1882static ldns_status
1883parse_svcparam_mandatory(const char **s, uint8_t **dp, uint8_t *eod)
1884{
1885 bool quoted = false;
1886 uint8_t *keys = *dp;
1887 int prev_key;
1888
1889 if (**s == '"') {
1890 *s += 1;
1891 quoted = true;
1892 }
1893 for (;;) {
1894 ldns_status st;
1896
1897 if ((st = parse_svcparam_key(s, &key)))
1898 return st;
1899
1900 if (*dp + 2 > eod)
1902
1903 ldns_write_uint16(*dp, key);
1904 *dp += 2;
1905
1906 if (**s == ',')
1907 *s += 1;
1908 else
1909 break;
1910 }
1911 if (quoted) {
1912 if (**s != '"')
1914 *s += 1;
1915 }
1916 if (*dp - keys == 0)
1918
1919 if (**s && !isspace((unsigned char)**s))
1921
1922 /* In draft-ietf-dnsop-svcb-https-02 Section 7:
1923 *
1924 * In wire format, the keys are represented by their numeric
1925 * values in network byte order, concatenated in ascending order.
1926 */
1927 qsort(keys, (*dp - keys) / 2, 2, network_uint16_cmp);
1928
1929 /* In draft-ietf-dnsop-svcb-https-02 Section 7:
1930 *
1931 * Keys ...<snip>... MUST NOT appear more than once.
1932 */
1933 prev_key = -1;
1934 while (keys < *dp) {
1935 uint16_t key = ldns_read_uint16(keys);
1936
1937 if (key == prev_key) {
1938 /* "Be conservative in what you send,
1939 * be liberal in what you accept"
1940 *
1941 * Instead of
1942 * `return LDNS_STATUS_SVCPARAM_KEY_MORE_THAN_ONCE;`,
1943 *
1944 * we eliminate the double occurrence.
1945 */
1946 memmove(keys - 2, keys, *dp - keys);
1947 *dp -= 2;
1948 } else {
1949 prev_key = key;
1950 keys += 2;
1951 }
1952 }
1953 return LDNS_STATUS_OK;
1954}
1955
1956INLINE bool parse_escape2(uint8_t *ch_p, const char** str_p)
1957{ *str_p += 1; return parse_escape(ch_p, str_p); }
1958
1959static ldns_status
1960parse_svcparam_alpn(const char **s, uint8_t **dp, uint8_t *eod)
1961{
1962 uint8_t *val;
1963 size_t len;
1964
1965 if (*dp + 1 > eod)
1967 *dp += 1;
1968 val = *dp;
1969 if (**s == '"') {
1970 *s += 1;
1971 while (**s != '"') {
1972 if (**s == 0)
1974
1975 else if (**s == ',') {
1976 len = *dp - val;
1977 if (len == 0 || len > 255)
1979 val[-1] = len;
1980 if (*dp + 1 > eod)
1982 *dp += 1;
1983 val = *dp;
1984 *s += 1;
1985
1986 } else if (*dp + 1 > eod)
1988
1989 else if (**s != '\\')
1990 *(*dp)++ = (uint8_t)*(*s)++;
1991
1992 else if (!parse_escape2(*dp, s))
1994 else
1995 *dp += 1;
1996 }
1997 *s += 1;
1998
1999 } else while (**s && !isspace((unsigned char)**s)) {
2000 if (**s == ',') {
2001 len = *dp - val;
2002 if (len == 0 || len > 255)
2004 val[-1] = len;
2005 if (*dp + 1 > eod)
2007 *dp += 1;
2008 val = *dp;
2009 *s += 1;
2010
2011 } else if (*dp + 1 > eod)
2013
2014 else if (**s != '\\')
2015 *(*dp)++ = (uint8_t)*(*s)++;
2016
2017 else if (!parse_escape2(*dp, s))
2019 else
2020 *dp += 1;
2021 }
2022 len = *dp - val;
2023 if (len == 0 || len > 255)
2025 val[-1] = len;
2026 return **s && !isspace((unsigned char)**s)
2029}
2030
2031static ldns_status
2032parse_svcparam_value(const char **s, uint8_t **dp, uint8_t *eod)
2033{
2034 if (**s == '"') {
2035 *s += 1;
2036 while (**s != '"') {
2037 if (**s == 0)
2039
2040 else if (*dp + 1 > eod)
2042
2043 else if (**s != '\\')
2044 *(*dp)++ = (uint8_t)*(*s)++;
2045
2046 else if (!parse_escape2(*dp, s))
2048 else
2049 *dp += 1;
2050 }
2051 *s += 1;
2052
2053 } else while (**s && !isspace((unsigned char)**s)) {
2054 if (*dp + 1 > eod)
2056
2057 else if (**s != '\\')
2058 *(*dp)++ = (uint8_t)*(*s)++;
2059
2060 else if (!parse_escape2(*dp, s))
2062 else
2063 *dp += 1;
2064 }
2065 return **s && !isspace((unsigned char)**s)
2068}
2069
2070static ldns_status
2071parse_svcparam_port(const char **s, uint8_t **dp, uint8_t *eod)
2072{
2073 uint8_t *val = *dp;
2074 ldns_status st;
2075 size_t len;
2076 char num_str[6];
2077 char *endptr;
2078 unsigned long int num;
2079
2080 if ((st = parse_svcparam_value(s, dp, eod)))
2081 return st;
2082 len = *dp - val;
2083 if (len == 0 || len > 5)
2085
2086 memcpy(num_str, val, len);
2087 num_str[len] = 0;
2088 num = strtoul(num_str, &endptr, 10);
2089 if (*endptr)
2091
2092 ldns_write_uint16(val, num);
2093 *dp = val + 2;
2094 return LDNS_STATUS_OK;
2095}
2096
2097static ldns_status
2098parse_svcparam_ipv4hint(const char **s, uint8_t **dp, uint8_t *eod)
2099{
2100 bool quoted = false;
2101
2102 if (**s == '"') {
2103 *s += 1;
2104 quoted = true;
2105 }
2106 for (;;) {
2107 const char *ipv4_start = *s;
2108 char ipv4_str[16];
2109 size_t len;
2110
2111 while (isdigit((unsigned char)**s) || **s == '.')
2112 *s += 1;
2113
2114 len = *s - ipv4_start;
2115 if (len == 0 || len > 15)
2117
2118 if (*dp + 4 > eod)
2120
2121 memcpy(ipv4_str, ipv4_start, len);
2122 ipv4_str[len] = 0;
2123 if (inet_pton(AF_INET, ipv4_str, *dp) != 1)
2125
2126 *dp += 4;
2127 if (**s == ',')
2128 *s += 1;
2129 else
2130 break;
2131 }
2132 if (quoted) {
2133 if (**s != '"')
2135 *s += 1;
2136 }
2137 return **s && !isspace((unsigned char)**s)
2140}
2141
2142static ldns_status
2143parse_svcparam_ech(const char **s, uint8_t **dp, uint8_t *eod)
2144{
2145 bool quoted = false;
2146 const char *b64_str;
2147 size_t len, pad, out_len;
2148 char in_buf[4096];
2149 char *in = in_buf;
2150 int out;
2151
2152 if (**s == '"') {
2153 *s += 1;
2154 quoted = true;
2155 }
2156 b64_str = *s;
2157 while (isalnum((unsigned char)**s) || **s == '+'
2158 || **s == '/'
2159 || **s == '=')
2160 *s += 1;
2161
2162 len = *s - b64_str;
2163 pad = len % 4;
2164 pad = pad ? 4 - pad : 0;
2165 if (len == 0 || pad == 3)
2167
2168 if (quoted) {
2169 if (**s != '"')
2171 *s += 1;
2172 }
2173 if (**s && !isspace((unsigned char)**s))
2175
2176 out_len = ldns_b64_pton_calculate_size(len);
2177 if (*dp + out_len > eod)
2179
2180 if (len + pad > sizeof(in_buf) - 1
2181 && !(in = LDNS_XMALLOC(char, len + pad + 1)))
2182 return LDNS_STATUS_MEM_ERR;
2183
2184 memcpy(in, b64_str, len);
2185 while (pad--)
2186 in[len++] = '=';
2187 in[len] = 0;
2188 out = ldns_b64_pton(in, *dp, out_len);
2189 if (in != in_buf)
2190 LDNS_FREE(in);
2191
2192 if (out <= 0)
2194
2195 *dp += out;
2196 return LDNS_STATUS_OK;
2197}
2198
2199static ldns_status
2200parse_svcparam_ipv6hint(const char **s, uint8_t **dp, uint8_t *eod)
2201{
2202 bool quoted = false;
2203
2204 if (**s == '"') {
2205 *s += 1;
2206 quoted = true;
2207 }
2208 for (;;) {
2209 const char *ipv6_start = *s;
2210 char ipv6_str[INET6_ADDRSTRLEN];
2211 size_t len;
2212
2213 while (isxdigit((unsigned char)**s) || **s == ':' || **s == '.')
2214 *s += 1;
2215
2216 len = *s - ipv6_start;
2217 if (len == 0 || len > INET6_ADDRSTRLEN)
2219
2220 if (*dp + 16 > eod)
2222
2223 memcpy(ipv6_str, ipv6_start, len);
2224 ipv6_str[len] = 0;
2225 if (inet_pton(AF_INET6, ipv6_str, *dp) != 1)
2227
2228 *dp += 16;
2229 if (**s == ',')
2230 *s += 1;
2231 else
2232 break;
2233 }
2234 if (quoted) {
2235 if (**s != '"')
2237 *s += 1;
2238 }
2239 return **s && !isspace((unsigned char)**s)
2242}
2243
2245 const char *str;
2246 size_t len;
2247};
2249
2250static svcparam_key_def svcparam_key_defs[] = { { "mandatory" , 9 }
2251 , { "alpn" , 4 }
2252 , { "no-default-alpn", 15 }
2253 , { "port" , 4 }
2254 , { "ipv4hint" , 8 }
2255 , { "ech" , 3 }
2256 , { "ipv6hint" , 8 }
2257 , { "dohpath" , 7 } };
2258
2259static const size_t svcparam_key_defs_len = sizeof(svcparam_key_defs)
2260 / sizeof(svcparam_key_def);
2261
2262/* svcparam_key2buffer_str() should actually be in host2str.c, but we need the
2263 * svcparam_key_defs for it and it is not an exposed symbol anyway.
2264 */
2266{
2267 if (key <= LDNS_SVCPARAM_KEY_LAST_KEY)
2268 ldns_buffer_write_string(output, svcparam_key_defs[key].str);
2269 else
2270 ldns_buffer_printf(output, "key%d", (int)key);
2271 return ldns_buffer_status(output);
2272}
2273
2274static ldns_status
2275parse_svcparam_key(const char **s, ldns_svcparam_key *key)
2276{
2277 size_t i, len;
2278 const char *key_str = *s;
2279 char num_str[6];
2280 char *endptr;
2281 unsigned long int num;
2282
2283 /* parse key */
2284 while (islower((unsigned char)**s) || isdigit((unsigned char)**s)
2285 || **s == '-')
2286 *s += 1;
2287
2288 len = *s - key_str;
2289 for (i = 0; i < svcparam_key_defs_len; i++) {
2290 if (len == svcparam_key_defs[i].len
2291 && !strncmp(key_str, svcparam_key_defs[i].str, len)) {
2292 *key = i;
2293 return LDNS_STATUS_OK;
2294 }
2295 }
2296 /* Also allow "echconfig" from earlier draft versions. */
2297 if (len == 9 && !strncmp(key_str, "echconfig", 9)) {
2298 *key = LDNS_SVCPARAM_KEY_ECH;
2299 return LDNS_STATUS_OK;
2300 }
2301 if (len < 4 || len > 8 || strncmp(key_str, "key", 3))
2303
2304 memcpy(num_str, key_str + 3, len - 3);
2305 num_str[len - 3] = 0;
2306 num = strtoul(num_str, &endptr, 10);
2307 if (*endptr || num > 65535)
2309
2310 /* key65535 is Reserved to be an ("Invalid key"), though there is no
2311 * physiological reason to deny usage. We restrict ourselves to the
2312 * anatomical limitations only to maximize serviceability.
2313 * ```
2314 * if (num == 65535)
2315 * return LDNS_STATUS_RESERVED_SVCPARAM_KEY;
2316 * ```
2317 */
2318 *key = num;
2319 return LDNS_STATUS_OK;
2320}
2321
2322static ldns_status
2323parse_svcparam(const char **s, uint8_t **dp, uint8_t *eod)
2324{
2326 ldns_status st;
2327 uint8_t *val;
2328
2329 if (*dp + 4 > eod)
2331
2332 if ((st = parse_svcparam_key(s, &key)))
2333 return st;
2334
2335 ldns_write_uint16(*dp, key);
2336 ldns_write_uint16(*dp + 2, 0);
2337 *dp += 4;
2338 if (isspace((unsigned char)**s) || !**s)
2339 return LDNS_STATUS_OK;
2340
2341 else if (**s != '=')
2343 *s += 1;
2344 val = *dp;
2345 switch(key) {
2347 st = parse_svcparam_mandatory(s, dp, eod);
2348 break;
2350 st = parse_svcparam_alpn(s, dp, eod);
2351 break;
2355 st = parse_svcparam_port(s, dp, eod);
2356 break;
2358 st = parse_svcparam_ipv4hint(s, dp, eod);
2359 break;
2361 st = parse_svcparam_ech(s, dp, eod);
2362 break;
2364 st = parse_svcparam_ipv6hint(s, dp, eod);
2365 break;
2366 default:
2367 st = parse_svcparam_value(s, dp, eod);
2368 break;
2369 }
2370 if (st)
2371 return st;
2372 ldns_write_uint16(val - 2, *dp - val);
2373 return LDNS_STATUS_OK;
2374}
2375
2376static int
2377svcparam_ptr_cmp(const void *a, const void *b)
2378{
2379 uint8_t *x = *(uint8_t **)a , *y = *(uint8_t **)b;
2380 uint16_t x_type = ldns_read_uint16(x), y_type = ldns_read_uint16(y);
2381 uint16_t x_len , y_len;
2382
2383 if (x_type != y_type)
2384 return x_type > y_type ? 1 : -1;
2385
2386 x_len = ldns_read_uint16(x + 2);
2387 y_len = ldns_read_uint16(y + 2);
2388
2389 return x_len != y_len
2390 ? (x_len > y_len ? 1 : -1)
2391 : (x_len == 0 ? 0 : memcmp(x + 4, y + 4, x_len));
2392}
2393
2396{
2397 uint8_t *data, *dp, *eod, *p, *new_data;
2399 size_t length, i;
2400 size_t nparams = 0;
2401 uint8_t **svcparams;
2402 int prev_key;
2403
2404 if (!rd || !str)
2405 return LDNS_STATUS_NULL;
2406
2407 length = strlen(str);
2408 /* Worst case space requirement. We'll realloc to actual size later. */
2409 if (!(dp = data = LDNS_XMALLOC(uint8_t, length * 4)))
2410 return LDNS_STATUS_MEM_ERR;
2411 eod = data + length * 4;
2412
2413 /* Fill data with parsed bytes */
2414 for (;;) {
2415 while (isspace((unsigned char)*str))
2416 str += 1;
2417 if(!*str)
2418 break;
2419 if ((st = parse_svcparam(&str, &dp, eod))) {
2420 LDNS_FREE(data);
2421 return st;
2422 }
2423 nparams += 1;
2424 }
2425
2426 /* draft-ietf-dnsop-svcb-https-02 in Section 2.2:
2427 *
2428 * SvcParamKeys SHALL appear in increasing numeric order
2429 *
2430 * A svcparams array (with pointers to the individual key, value pairs)
2431 * is created to qsort the pairs in increasing numeric order.
2432 */
2433 if (!(svcparams = LDNS_XMALLOC(uint8_t *, nparams))) {
2434 LDNS_FREE(data);
2435 return LDNS_STATUS_MEM_ERR;
2436 }
2437 for ( p = data, i = 0
2438 ; p < dp && i < nparams
2439 ; p += 4 + ldns_read_uint16(p + 2))
2440 svcparams[i++] = p;
2441
2442 qsort(svcparams, i, sizeof(uint8_t *), svcparam_ptr_cmp);
2443
2444 /* Write out the (key, value) pairs to a newly allocated data in
2445 * sorted order.
2446 */
2447 length = dp - data;
2448 if (!(new_data = LDNS_XMALLOC(uint8_t, length))) {
2449 LDNS_FREE(data);
2450 LDNS_FREE(svcparams);
2451 return LDNS_STATUS_MEM_ERR;
2452 }
2453 prev_key = -1;
2454 for ( p = new_data, i = 0
2455 ; p < new_data + length && i < nparams
2456 ; p += 4 + ldns_read_uint16(p + 2), i += 1) {
2457 uint16_t key = ldns_read_uint16(svcparams[i]);
2458
2459 /* In draft-ietf-dnsop-svcb-https-02 Section 2.1:
2460 *
2461 * SvcParams ...<snip>... keys MUST NOT be repeated.
2462 *
2463 * ldns will not impose this limitation on the library user,
2464 * but we can merge completely equal repetitions into one.
2465 * So, not doing
2466 * ```
2467 * if (key == prev_key)
2468 * return LDNS_STATUS_SVCPARAM_KEY_MORE_THAN_ONCE;
2469 * ```
2470 * but instead:
2471 */
2472 if (key == prev_key && ldns_read_uint16(svcparams[i] + 2)
2473 == ldns_read_uint16(svcparams[i - 1] + 2)
2474 && 0 == memcmp( svcparams[i ] + 4
2475 , svcparams[i - 1] + 4
2476 , ldns_read_uint16(svcparams[i] + 2))) {
2477 p -= 4 + ldns_read_uint16(svcparams[i] + 2);
2478 continue;
2479 }
2480 memcpy(p, svcparams[i], 4 + ldns_read_uint16(svcparams[i] + 2));
2481 prev_key = key;
2482 }
2483 LDNS_FREE(data);
2484 LDNS_FREE(svcparams);
2485
2486 /* Create rdf */
2487 *rd = ldns_rdf_new(LDNS_RDF_TYPE_SVCPARAMS, p - new_data, new_data);
2488 if (! *rd) {
2489 LDNS_FREE(new_data);
2490 return LDNS_STATUS_MEM_ERR;
2491 }
2492 return LDNS_STATUS_OK;
2493}
2494#else /* #ifdef RRTYPE_SVCB_HTTPS */
2496ldns_str2rdf_svcparams(ldns_rdf **rd, const char *str)
2497{
2498 (void)rd; (void)str;
2499 return LDNS_STATUS_NOT_IMPL;
2500}
2501#endif /* #ifdef RRTYPE_SVCB_HTTPS */
void ldns_buffer_free(ldns_buffer *buffer)
frees the buffer.
Definition buffer.c:137
int ldns_buffer_printf(ldns_buffer *buffer, const char *format,...)
prints to the buffer, increasing the capacity if required using buffer_reserve().
Definition buffer.c:99
void ldns_buffer_new_frm_data(ldns_buffer *buffer, const void *data, size_t size)
creates a buffer with the specified data.
Definition buffer.c:41
#define ATTR_UNUSED(x)
Definition common.h:72
int ldns_b64_pton(char const *src, uint8_t *target, size_t targsize)
@ LDNS_TLSA_SELECTOR_PRIVSEL
Reserved for Private Use.
Definition dane.h:80
@ LDNS_TLSA_SELECTOR_SPKI
SubjectPublicKeyInfo: DER-encoded binary structure as defined in [RFC5280].
Definition dane.h:76
@ LDNS_TLSA_SELECTOR_CERT
Full certificate: the Certificate binary structure as defined in [RFC5280].
Definition dane.h:69
@ LDNS_TLSA_USAGE_PRIVCERT
Reserved for Private Use.
Definition dane.h:56
@ LDNS_TLSA_USAGE_DANE_EE
Domain issued certificate.
Definition dane.h:53
@ LDNS_TLSA_USAGE_PKIX_EE
Service certificate constraint.
Definition dane.h:47
@ LDNS_TLSA_USAGE_PKIX_TA
CA constraint.
Definition dane.h:44
@ LDNS_TLSA_USAGE_DANE_TA
Trust anchor assertion.
Definition dane.h:50
@ LDNS_TLSA_MATCHING_TYPE_FULL
Exact match on selected content.
Definition dane.h:90
@ LDNS_TLSA_MATCHING_TYPE_SHA2_512
SHA-512 hash of selected content [RFC6234].
Definition dane.h:96
@ LDNS_TLSA_MATCHING_TYPE_SHA2_256
SHA-256 hash of selected content [RFC6234].
Definition dane.h:93
@ LDNS_TLSA_MATCHING_TYPE_PRIVMATCH
Reserved for Private Use.
Definition dane.h:99
signed char ldns_dname_str_absolute(const char *dname_str)
Checks whether the given dname string is absolute (i.e.
Definition dname.c:518
ldns_rdf * ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[], size_t size, ldns_rr_type nsec_type)
Create the type bitmap for an NSEC(3) record.
Definition dnssec.c:721
@ LDNS_STATUS_INVALID_STR
Definition error.h:41
@ LDNS_STATUS_DOMAINNAME_UNDERFLOW
Definition error.h:30
@ LDNS_STATUS_INVALID_EUI48
Definition error.h:123
@ LDNS_STATUS_INVALID_IP4
Definition error.h:39
@ LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW
Definition error.h:94
@ LDNS_STATUS_SYNTAX_ERR
Definition error.h:97
@ LDNS_STATUS_SYNTAX_SVCPARAM_KEY_ERR
Definition error.h:139
@ LDNS_STATUS_INVALID_TIME
Definition error.h:45
@ LDNS_STATUS_INVALID_EUI64
Definition error.h:124
@ LDNS_STATUS_INVALID_B32_EXT
Definition error.h:42
@ LDNS_STATUS_LABEL_OVERFLOW
Definition error.h:28
@ LDNS_STATUS_NO_SVCPARAM_VALUE_EXPECTED
Definition error.h:142
@ LDNS_STATUS_NULL
Definition error.h:51
@ LDNS_STATUS_INVALID_IP6
Definition error.h:40
@ LDNS_STATUS_ERR
Definition error.h:37
@ LDNS_STATUS_MEM_ERR
Definition error.h:34
@ LDNS_STATUS_INVALID_ILNP64
Definition error.h:122
@ LDNS_STATUS_INVALID_HEX
Definition error.h:44
@ LDNS_STATUS_SYNTAX_BAD_ESCAPE
Definition error.h:95
@ LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR
Definition error.h:140
@ LDNS_STATUS_INVALID_INT
Definition error.h:38
@ LDNS_STATUS_OK
Definition error.h:26
@ LDNS_STATUS_EMPTY_LABEL
Definition error.h:27
@ LDNS_STATUS_DOMAINNAME_OVERFLOW
Definition error.h:29
@ LDNS_STATUS_INVALID_B64
Definition error.h:43
@ LDNS_STATUS_INVALID_TAG
Definition error.h:126
@ LDNS_STATUS_RDATA_OVERFLOW
Definition error.h:129
@ LDNS_STATUS_CERT_BAD_ALGORITHM
Definition error.h:78
@ LDNS_STATUS_NOT_IMPL
Definition error.h:50
enum ldns_enum_status ldns_status
Definition error.h:149
#define INET6_ADDRSTRLEN
Definition host2str.c:43
Including this file will include all ldns files, and define some lookup tables.
ldns_lookup_table ldns_algorithms[]
Taken from RFC 2535, section 7.
Definition host2str.c:53
#define LDNS_IP6ADDRLEN
Definition ldns.h:133
ldns_lookup_table ldns_cert_algorithms[]
Taken from RFC 2538.
Definition host2str.c:84
ssize_t ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit)
returns a token/char from the buffer b.
Definition parse.c:301
uint32_t ldns_str2period(const char *nptr, const char **endptr)
converts a ttl value (like 5d2h) to a long.
Definition rdata.c:697
uint8_t * ldns_rdf_data(const ldns_rdf *rd)
returns the data of the rdf.
Definition rdata.c:38
ldns_rdf * ldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data)
allocates a new rdf structure and fills it.
Definition rdata.c:193
void ldns_rdf_deep_free(ldns_rdf *rd)
frees a rdf structure and frees the data.
Definition rdata.c:230
#define LDNS_MAX_RDFLEN
Definition rdata.h:31
uint16_t ldns_rdf2native_int16(const ldns_rdf *rd)
returns the native uint16_t representation from the rdf.
Definition rdata.c:84
enum ldns_enum_svcparam_key ldns_svcparam_key
Definition rdata.h:193
ldns_rdf * ldns_native2rdf_int8(ldns_rdf_type type, uint8_t value)
returns the rdf containing the native uint8_t repr.
Definition rdata.c:126
@ LDNS_RDF_TYPE_INT32
32 bits
Definition rdata.h:56
@ LDNS_RDF_TYPE_TAG
A non-zero sequence of US-ASCII letters and numbers in lower case.
Definition rdata.h:132
@ LDNS_RDF_TYPE_HIP
Represents the Public Key Algorithm, HIT and Public Key fields for the HIP RR types.
Definition rdata.h:95
@ LDNS_RDF_TYPE_IPN
draft-johnson-dns-ipn-cla-07
Definition rdata.h:155
@ LDNS_RDF_TYPE_B32_EXT
b32 string
Definition rdata.h:68
@ LDNS_RDF_TYPE_EUI48
6 * 8 bit hex numbers separated by dashes.
Definition rdata.h:122
@ LDNS_RDF_TYPE_EUI64
8 * 8 bit hex numbers separated by dashes.
Definition rdata.h:124
@ LDNS_RDF_TYPE_PERIOD
period
Definition rdata.h:89
@ LDNS_RDF_TYPE_B64
b64 string
Definition rdata.h:70
@ LDNS_RDF_TYPE_AAAA
AAAA record.
Definition rdata.h:62
@ LDNS_RDF_TYPE_WKS
well known services
Definition rdata.h:104
@ LDNS_RDF_TYPE_DNAME
domain name
Definition rdata.h:50
@ LDNS_RDF_TYPE_TIME
time (32 bits)
Definition rdata.h:87
@ LDNS_RDF_TYPE_SVCPARAMS
draft-ietf-dnsop-svcb-https
Definition rdata.h:152
@ LDNS_RDF_TYPE_NSEC3_SALT
nsec3 hash salt
Definition rdata.h:112
@ LDNS_RDF_TYPE_APL
apl data
Definition rdata.h:66
@ LDNS_RDF_TYPE_A
A record.
Definition rdata.h:60
@ LDNS_RDF_TYPE_LONG_STR
A <character-string> encoding of the value field as specified [RFC1035], Section 5....
Definition rdata.h:138
@ LDNS_RDF_TYPE_LOC
location data
Definition rdata.h:102
@ LDNS_RDF_TYPE_ILNP64
4 shorts represented as 4 * 16 bit hex numbers separated by colons.
Definition rdata.h:119
@ LDNS_RDF_TYPE_HEX
hex string
Definition rdata.h:72
@ LDNS_RDF_TYPE_CLASS
a class
Definition rdata.h:79
@ LDNS_RDF_TYPE_INT8
8 bits
Definition rdata.h:52
@ LDNS_RDF_TYPE_IPSECKEY
IPSECKEY.
Definition rdata.h:110
@ LDNS_RDF_TYPE_STR
txt string
Definition rdata.h:64
@ LDNS_RDF_TYPE_INT16
16 bits
Definition rdata.h:54
@ LDNS_RDF_TYPE_AMTRELAY
draft-ietf-mboned-driad-amt-discovery
Definition rdata.h:149
@ LDNS_RDF_TYPE_TYPE
a RR type
Definition rdata.h:77
size_t ldns_rdf_size(const ldns_rdf *rd)
returns the size of the rdf.
Definition rdata.c:24
ldns_rdf * ldns_rdf_new(ldns_rdf_type type, size_t size, void *data)
allocates a new rdf structure and fills it.
Definition rdata.c:179
void ldns_rdf_free(ldns_rdf *rd)
frees a rdf structure, leaving the data pointer intact.
Definition rdata.c:241
@ LDNS_SVCPARAM_KEY_PORT
Definition rdata.h:185
@ LDNS_SVCPARAM_KEY_ALPN
Definition rdata.h:183
@ LDNS_SVCPARAM_KEY_ECH
Definition rdata.h:187
@ LDNS_SVCPARAM_KEY_MANDATORY
Definition rdata.h:182
@ LDNS_SVCPARAM_KEY_IPV4HINT
Definition rdata.h:186
@ LDNS_SVCPARAM_KEY_IPV6HINT
Definition rdata.h:188
@ LDNS_SVCPARAM_KEY_LAST_KEY
Definition rdata.h:190
@ LDNS_SVCPARAM_KEY_NO_DEFAULT_ALPN
Definition rdata.h:184
ldns_rr_class ldns_get_rr_class_by_name(const char *name)
retrieves a class by looking up its name.
Definition rr.c:2835
#define LDNS_MAX_LABELLEN
Maximum length of a dname label.
Definition rr.h:31
enum ldns_enum_rr_type ldns_rr_type
Definition rr.h:260
@ LDNS_RR_TYPE_NSEC
Definition rr.h:171
#define LDNS_MAX_DOMAINLEN
Maximum length of a complete dname.
Definition rr.h:33
ldns_rr_type ldns_get_rr_type_by_name(const char *name)
retrieves a rrtype by looking up its name.
Definition rr.c:2795
ldns_status ldns_str2rdf_hex(ldns_rdf **rd, const char *str)
convert a hex value into wireformat
Definition str2host.c:707
ldns_status ldns_str2rdf_amtrelay(ldns_rdf **rd, const char *str)
Convert a "<precedence> <D-bit> <type> <relay>" encoding of the value field as specified in Section 4...
Definition str2host.c:1735
ldns_status ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr)
convert a byte into wireformat
Definition str2host.c:291
ldns_status ldns_str2rdf_certificate_usage(ldns_rdf **rd, const char *str)
convert a tlsa certificate usage value into wireformat
Definition str2host.c:902
ldns_status ldns_str2rdf_hip(ldns_rdf **rd, const char *str)
Convert a "<algorithm> <hit> <pk>" encoding of the value field as specified in Section 6.
Definition str2host.c:1639
ldns_status ldns_str2rdf_atma(ldns_rdf **rd, const char *str)
convert a str with a ATMA RR into wireformat
Definition str2host.c:1318
ldns_status ldns_str2rdf_type(ldns_rdf **rd, const char *str)
convert a rrtype into wireformat
Definition str2host.c:801
ldns_status ldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *salt_str)
Definition str2host.c:126
ldns_status ldns_str2rdf_svcparams(ldns_rdf **rd, const char *str)
Convert a series of "key[=<value>]" encodings to wireformat as described in [draft-ietf-dnsop-svcb-ht...
Definition str2host.c:2395
ldns_status ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str)
convert the str with an AAAA record into wireformat
Definition str2host.c:477
ldns_status ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str)
convert the string with the b32 ext hex data into wireformat
Definition str2host.c:676
ldns_status ldns_str2rdf_period(ldns_rdf **rd, const char *period)
Definition str2host.c:178
ldns_status ldns_str2rdf_long_str(ldns_rdf **rd, const char *str)
Convert a <character-string> encoding of the value field as specified [RFC1035], Section 5....
Definition str2host.c:1592
ldns_status ldns_str2rdf_class(ldns_rdf **rd, const char *str)
convert string with a classname into wireformat
Definition str2host.c:812
ldns_status svcparam_key2buffer_str(ldns_buffer *output, uint16_t key)
Definition str2host.c:2265
ldns_status ldns_str2rdf_dname(ldns_rdf **d, const char *str)
convert a dname string into wireformat
Definition str2host.c:374
ldns_status ldns_str2rdf_alg(ldns_rdf **rd, const char *str)
convert an algorithm value into wireformat
Definition str2host.c:896
ldns_status ldns_str2rdf_nsec(ldns_rdf **rd, const char *str)
convert string with nsec into wireformat
Definition str2host.c:753
ldns_status ldns_str2rdf_a(ldns_rdf **rd, const char *str)
convert str with an A record into wireformat
Definition str2host.c:464
ldns_status ldns_str2rdf_matching_type(ldns_rdf **rd, const char *str)
convert a tlsa matching type value into wireformat
Definition str2host.c:915
ldns_status ldns_str2rdf_wks(ldns_rdf **rd, const char *str)
convert string with a WKS RR into wireformat
Definition str2host.c:1154
#define htonll(x)
Definition str2host.c:236
ldns_status ldns_str2rdf_ilnp64(ldns_rdf **rd, const char *str)
convert 4 * 16bit hex separated by colons into wireformat
Definition str2host.c:1492
ldns_status ldns_str2rdf_unknown(ldns_rdf **rd __attribute__((unused)), const char *str __attribute__((unused)))
Definition str2host.c:921
ldns_status ldns_str2rdf_service(ldns_rdf **rd __attribute__((unused)), const char *str __attribute__((unused)))
Definition str2host.c:931
ldns_status ldns_str2rdf_time(ldns_rdf **rd, const char *time)
convert a time string to a time value in wireformat
Definition str2host.c:57
ldns_status ldns_str2rdf_nsap(ldns_rdf **rd, const char *str)
convert a str with a NSAP RR into wireformat
Definition str2host.c:1299
ldns_status ldns_str2rdf_eui64(ldns_rdf **rd, const char *str)
convert 8 hex bytes separated by dashes into wireformat
Definition str2host.c:1538
ldns_status ldns_str2rdf_loc(ldns_rdf **rd, const char *str)
convert a string with a LOC RR into wireformat
Definition str2host.c:979
ldns_status ldns_str2rdf_str(ldns_rdf **rd, const char *str)
convert a string into wireformat (think txt record)
Definition str2host.c:491
ldns_status ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str)
convert a str with a IPSECKEY RR into wireformat
Definition str2host.c:1338
ldns_status ldns_str2rdf_selector(ldns_rdf **rd, const char *str)
convert a tlsa selector value into wireformat
Definition str2host.c:909
ldns_status ldns_str2rdf_tag(ldns_rdf **rd, const char *str)
Convert a non-zero sequence of US-ASCII letters and numbers into wireformat.
Definition str2host.c:1563
ldns_status ldns_str2rdf_apl(ldns_rdf **rd, const char *str)
convert str with the apl record into wireformat
Definition str2host.c:535
ldns_status ldns_str2rdf_b64(ldns_rdf **rd, const char *str)
convert the string with the b64 data into wireformat
Definition str2host.c:646
ldns_status ldns_str2rdf_ipn(ldns_rdf **rd, const char *ipnstr)
Convert either two unsigned 32 bit decimal numbers seperated by a '.
Definition str2host.c:241
ldns_status ldns_str2rdf_eui48(ldns_rdf **rd, const char *str)
convert 6 hex bytes separated by dashes into wireformat
Definition str2host.c:1515
ldns_status ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr)
convert a strings into a 4 byte int in wireformat
Definition str2host.c:197
ldns_status ldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr)
convert a string to a int16 in wireformat
Definition str2host.c:36
ldns_status ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str)
convert an certificate algorithm value into wireformat
Definition str2host.c:826
implementation of buffers to ease operations
Definition buffer.h:51
A general purpose lookup table.
Definition util.h:178
Resource record data field.
Definition rdata.h:203
int ldns_hexdigit_to_int(char ch)
Returns the int value of the given (hex) digit.
Definition util.c:88
int ldns_b32_pton_extended_hex(const char *src_text, size_t src_text_length, uint8_t *target_data_buffer, size_t target_data_buffer_size)
Definition util.c:777
time_t ldns_mktime_from_utc(const struct tm *tm)
Convert TM to seconds since epoch (midnight, January 1st, 1970).
Definition util.c:194
ldns_lookup_table * ldns_lookup_by_name(ldns_lookup_table table[], const char *name)
Looks up the table entry by name, returns NULL if not found.
#define INLINE
splint static inline workaround
Definition util.h:42
#define LDNS_FREE(ptr)
Definition util.h:60
#define LDNS_MALLOC(type)
Memory management macros.
Definition util.h:49
void ldns_set_bit(uint8_t *byte, int bit_nr, signed char value)
sets the specified bit in the specified byte to 1 if value is true, 0 if false The bits are counted f...
Definition util.c:72
#define LDNS_XMALLOC(type, count)
Definition util.h:51
#define LDNS_XREALLOC(ptr, type, count)
Definition util.h:57