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