]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ldns/str2host.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / ldns / str2host.c
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
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
57 ldns_str2rdf_time(ldns_rdf **rd, const char *time)
58 {
59         /* convert a time YYYYDDMMHHMMSS to wireformat */
60         uint16_t *r = NULL;
61         struct tm tm;
62         uint32_t l;
63         char *end;
64
65         /* Try to scan the time... */
66         r = (uint16_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
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
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
197 ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr)
198 {
199         char *end;
200         uint16_t *r = NULL;
201         uint32_t l;
202
203         r = (uint16_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
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 octal 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 octals)
256  *
257  * Returns the number of bytes read from the escaped string, or
258  * 0 on error
259  */
260 INLINE bool
261 parse_escape(uint8_t *ch_p, const char** str_p)
262 {
263         uint16_t val;
264
265         if ((*str_p)[0] && isdigit((*str_p)[0])  &&
266             (*str_p)[1] && isdigit((*str_p)[1])  &&
267             (*str_p)[2] && isdigit((*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((*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
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 seperators.
308  * Could be made more efficient....we do 3 memcpy's in total...
309  */
310 ldns_status
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
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
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
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                 return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
449         }
450         length = (size_t)(dp - data);
451         /* Fix last length byte */
452         data[0] = (uint8_t)length;
453
454         /* Lose the overmeasure */
455         data = LDNS_XREALLOC(dp = data, uint8_t, length + 1);
456         if (! data) {
457                 LDNS_FREE(dp);
458                 return LDNS_STATUS_MEM_ERR;
459         }
460
461         /* Create rdf */
462         *rd = ldns_rdf_new(LDNS_RDF_TYPE_STR, length + 1, data);
463         if (! *rd) {
464                 LDNS_FREE(data);
465                 return LDNS_STATUS_MEM_ERR;
466         }
467         return LDNS_STATUS_OK;
468 }
469
470 ldns_status
471 ldns_str2rdf_apl(ldns_rdf **rd, const char *str)
472 {
473         const char *my_str = str;
474
475         char *my_ip_str;
476         size_t ip_str_len;
477
478         uint16_t family;
479         bool negation;
480         uint8_t afdlength = 0;
481         uint8_t *afdpart;
482         uint8_t prefix;
483
484         uint8_t *data;
485
486         size_t i = 0;
487
488         /* [!]afi:address/prefix */
489         if (strlen(my_str) < 2
490                         || strchr(my_str, ':') == NULL
491                         || strchr(my_str, '/') == NULL
492                         || strchr(my_str, ':') > strchr(my_str, '/')) {
493                 return LDNS_STATUS_INVALID_STR;
494         }
495
496         if (my_str[0] == '!') {
497                 negation = true;
498                 my_str += 1;
499         } else {
500                 negation = false;
501         }
502
503         family = (uint16_t) atoi(my_str);
504
505         my_str = strchr(my_str, ':') + 1;
506
507         /* need ip addr and only ip addr for inet_pton */
508         ip_str_len = (size_t) (strchr(my_str, '/') - my_str);
509         my_ip_str = LDNS_XMALLOC(char, ip_str_len + 1);
510         if(!my_ip_str) return LDNS_STATUS_MEM_ERR;
511         strncpy(my_ip_str, my_str, ip_str_len + 1);
512         my_ip_str[ip_str_len] = '\0';
513
514         if (family == 1) {
515                 /* ipv4 */
516                 afdpart = LDNS_XMALLOC(uint8_t, 4);
517                 if(!afdpart) {
518                         LDNS_FREE(my_ip_str);
519                         return LDNS_STATUS_MEM_ERR;
520                 }
521                 if (inet_pton(AF_INET, my_ip_str, afdpart) == 0) {
522                         LDNS_FREE(my_ip_str);
523                         LDNS_FREE(afdpart);
524                         return LDNS_STATUS_INVALID_STR;
525                 }
526                 for (i = 0; i < 4; i++) {
527                         if (afdpart[i] != 0) {
528                                 afdlength = i + 1;
529                         }
530                 }
531         } else if (family == 2) {
532                 /* ipv6 */
533                 afdpart = LDNS_XMALLOC(uint8_t, 16);
534                 if(!afdpart) {
535                         LDNS_FREE(my_ip_str);
536                         return LDNS_STATUS_MEM_ERR;
537                 }
538                 if (inet_pton(AF_INET6, my_ip_str, afdpart) == 0) {
539                         LDNS_FREE(my_ip_str);
540                         LDNS_FREE(afdpart);
541                         return LDNS_STATUS_INVALID_STR;
542                 }
543                 for (i = 0; i < 16; i++) {
544                         if (afdpart[i] != 0) {
545                                 afdlength = i + 1;
546                         }
547                 }
548         } else {
549                 /* unknown family */
550                 LDNS_FREE(my_ip_str);
551                 return LDNS_STATUS_INVALID_STR;
552         }
553
554         my_str = strchr(my_str, '/') + 1;
555         prefix = (uint8_t) atoi(my_str);
556
557         data = LDNS_XMALLOC(uint8_t, 4 + afdlength);
558         if(!data) {
559                 LDNS_FREE(afdpart);
560                 LDNS_FREE(my_ip_str);
561                 return LDNS_STATUS_INVALID_STR;
562         }
563         ldns_write_uint16(data, family);
564         data[2] = prefix;
565         data[3] = afdlength;
566         if (negation) {
567                 /* set bit 1 of byte 3 */
568                 data[3] = data[3] | 0x80;
569         }
570
571         memcpy(data + 4, afdpart, afdlength);
572
573         *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_APL, afdlength + 4, data);
574         LDNS_FREE(afdpart);
575         LDNS_FREE(data);
576         LDNS_FREE(my_ip_str);
577
578         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
579 }
580
581 ldns_status
582 ldns_str2rdf_b64(ldns_rdf **rd, const char *str)
583 {
584         uint8_t *buffer;
585         int16_t i;
586
587         buffer = LDNS_XMALLOC(uint8_t, ldns_b64_ntop_calculate_size(strlen(str)));
588         if(!buffer) {
589                 return LDNS_STATUS_MEM_ERR;
590         }
591
592         i = (uint16_t)ldns_b64_pton((const char*)str, buffer,
593                                                    ldns_b64_ntop_calculate_size(strlen(str)));
594         if (-1 == i) {
595                 LDNS_FREE(buffer);
596                 return LDNS_STATUS_INVALID_B64;
597         } else {
598                 *rd = ldns_rdf_new_frm_data(
599                         LDNS_RDF_TYPE_B64, (uint16_t) i, buffer);
600         }
601         LDNS_FREE(buffer);
602
603         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
604 }
605
606 ldns_status
607 ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str)
608 {
609         uint8_t *buffer;
610         int i;
611         /* first byte contains length of actual b32 data */
612         uint8_t len = ldns_b32_pton_calculate_size(strlen(str));
613         buffer = LDNS_XMALLOC(uint8_t, len + 1);
614         if(!buffer) {
615                 return LDNS_STATUS_MEM_ERR;
616         }
617         buffer[0] = len;
618
619         i = ldns_b32_pton_extended_hex((const char*)str, strlen(str), buffer + 1,
620                                                          ldns_b32_ntop_calculate_size(strlen(str)));
621         if (i < 0) {
622                 LDNS_FREE(buffer);
623                 return LDNS_STATUS_INVALID_B32_EXT;
624         } else {
625                 *rd = ldns_rdf_new_frm_data(
626                         LDNS_RDF_TYPE_B32_EXT, (uint16_t) i + 1, buffer);
627         }
628         LDNS_FREE(buffer);
629
630         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
631 }
632
633 ldns_status
634 ldns_str2rdf_hex(ldns_rdf **rd, const char *str)
635 {
636         uint8_t *t, *t_orig;
637         int i;
638         size_t len;
639
640         len = strlen(str);
641
642         if (len > LDNS_MAX_RDFLEN * 2) {
643                 return LDNS_STATUS_LABEL_OVERFLOW;
644         } else {
645                 t = LDNS_XMALLOC(uint8_t, (len / 2) + 1);
646                 if(!t) {
647                         return LDNS_STATUS_MEM_ERR;
648                 }
649                 t_orig = t;
650                 /* Now process octet by octet... */
651                 while (*str) {
652                         *t = 0;
653                         if (isspace((int) *str)) {
654                                 str++;
655                         } else {
656                                 for (i = 16; i >= 1; i -= 15) {
657                                         while (*str && isspace((int) *str)) { str++; }
658                                         if (*str) {
659                                                 if (isxdigit((int) *str)) {
660                                                         *t += ldns_hexdigit_to_int(*str) * i;
661                                                 } else {
662                                                         LDNS_FREE(t_orig);
663                                                         return LDNS_STATUS_ERR;
664                                                 }
665                                                 ++str;
666                                         }
667                                 }
668                                 ++t;
669                         }
670                 }
671                 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX,
672                                             (size_t) (t - t_orig),
673                                             t_orig);
674                 LDNS_FREE(t_orig);
675         }
676         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
677 }
678
679 ldns_status
680 ldns_str2rdf_nsec(ldns_rdf **rd, const char *str)
681 {
682         const char *delimiters = "\n\t ";
683         char *token = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN);
684         ldns_buffer *str_buf;
685         ssize_t c;
686         uint16_t cur_type;
687         size_t type_count = 0;
688         ldns_rr_type type_list[65536];
689         if(!token) return LDNS_STATUS_MEM_ERR;
690         if(rd == NULL) {
691                 LDNS_FREE(token);
692                 return LDNS_STATUS_NULL;
693         }
694
695         str_buf = LDNS_MALLOC(ldns_buffer);
696         if(!str_buf) {
697                 LDNS_FREE(token);
698                 return LDNS_STATUS_MEM_ERR;
699         }
700         ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
701         if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) {
702                 LDNS_FREE(str_buf);
703                 LDNS_FREE(token);
704                 return LDNS_STATUS_MEM_ERR;
705         }
706
707         while ((c = ldns_bget_token(str_buf, token, delimiters, LDNS_MAX_RDFLEN)) != -1 && c != 0) {
708                 if(type_count >= sizeof(type_list)) {
709                         LDNS_FREE(str_buf);
710                         LDNS_FREE(token);
711                         return LDNS_STATUS_ERR;
712                 }
713                 cur_type = ldns_get_rr_type_by_name(token);
714                 type_list[type_count] = cur_type;
715                 type_count++;
716         }
717
718         *rd = ldns_dnssec_create_nsec_bitmap(type_list,
719                                              type_count,
720                                              LDNS_RR_TYPE_NSEC);
721
722         LDNS_FREE(token);
723         ldns_buffer_free(str_buf);
724         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
725 }
726
727 ldns_status
728 ldns_str2rdf_type(ldns_rdf **rd, const char *str)
729 {
730         uint16_t type;
731         type = htons(ldns_get_rr_type_by_name(str));
732         /* ldns_rr_type is a 16 bit value */
733         *rd = ldns_rdf_new_frm_data(
734                 LDNS_RDF_TYPE_TYPE, sizeof(uint16_t), &type);
735         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
736 }
737
738 ldns_status
739 ldns_str2rdf_class(ldns_rdf **rd, const char *str)
740 {
741         uint16_t klass;
742         klass = htons(ldns_get_rr_class_by_name(str));
743         /* class is 16 bit */
744         *rd = ldns_rdf_new_frm_data(
745                 LDNS_RDF_TYPE_CLASS, sizeof(uint16_t), &klass);
746         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
747 }
748
749 /* An certificate alg field can either be specified as a 8 bits number
750  * or by its symbolic name. Handle both
751  */
752 ldns_status
753 ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str)
754 {
755         ldns_lookup_table *lt;
756         ldns_status st;
757         uint8_t idd[2];
758         lt = ldns_lookup_by_name(ldns_cert_algorithms, str);
759         st = LDNS_STATUS_OK;
760
761         if (lt) {
762                 ldns_write_uint16(idd, (uint16_t) lt->id);
763                 *rd = ldns_rdf_new_frm_data(
764                         LDNS_RDF_TYPE_INT16, sizeof(uint16_t), idd);
765                 if (!*rd) {
766                         st = LDNS_STATUS_ERR;
767                 }
768         } else {
769                 /* try as-is (a number) */
770                 st = ldns_str2rdf_int16(rd, str);
771                 if (st == LDNS_STATUS_OK &&
772                     ldns_rdf2native_int16(*rd) == 0) {
773                         st = LDNS_STATUS_CERT_BAD_ALGORITHM;
774                 }
775         }
776
777         return st;
778 }
779
780 /* An alg field can either be specified as a 8 bits number
781  * or by its symbolic name. Handle both
782  */
783 ldns_status
784 ldns_str2rdf_alg(ldns_rdf **rd, const char *str)
785 {
786         ldns_lookup_table *lt;
787         ldns_status st;
788
789         lt = ldns_lookup_by_name(ldns_algorithms, str);
790         st = LDNS_STATUS_OK;
791
792         if (lt) {
793                 /* it was given as a integer */
794                 *rd = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t) lt->id);
795                 if (!*rd) {
796                         st = LDNS_STATUS_ERR;
797                 }
798         } else {
799                 /* try as-is (a number) */
800                 st = ldns_str2rdf_int8(rd, str);
801         }
802         return st;
803 }
804
805 ldns_status
806 ldns_str2rdf_unknown( ATTR_UNUSED(ldns_rdf **rd)
807                     , ATTR_UNUSED(const char *str)
808                     )
809 {
810         /* this should be caught in an earlier time (general str2host for
811            rr's */
812         return LDNS_STATUS_NOT_IMPL;
813 }
814
815 ldns_status
816 ldns_str2rdf_service( ATTR_UNUSED(ldns_rdf **rd)
817                     , ATTR_UNUSED(const char *str)
818                     )
819 {
820         /* is this used? is this actually WKS? or SRV? */
821         return LDNS_STATUS_NOT_IMPL;
822 }
823
824 static int
825 loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e)
826 {
827         /* read <digits>[.<digits>][mM] */
828         /* into mantissa exponent format for LOC type */
829         uint32_t meters = 0, cm = 0, val;
830         while (isblank(*my_str)) {
831                 my_str++;
832         }
833         meters = (uint32_t)strtol(my_str, &my_str, 10);
834         if (*my_str == '.') {
835                 my_str++;
836                 cm = (uint32_t)strtol(my_str, &my_str, 10);
837         }
838         if (meters >= 1) {
839                 *e = 2;
840                 val = meters;
841         } else  {
842                 *e = 0;
843                 val = cm;
844         }
845         while(val >= 10) {
846                 (*e)++;
847                 val /= 10;
848         }
849         *m = (uint8_t)val;
850
851         if (*e > 9)
852                 return 0;
853         if (*my_str == 'm' || *my_str == 'M') {
854                 my_str++;
855         }
856         *endstr = my_str;
857         return 1;
858 }
859
860 ldns_status
861 ldns_str2rdf_loc(ldns_rdf **rd, const char *str)
862 {
863         uint32_t latitude = 0;
864         uint32_t longitude = 0;
865         uint32_t altitude = 0;
866
867         uint8_t *data;
868         uint32_t equator = (uint32_t) ldns_power(2, 31);
869
870         uint32_t h = 0;
871         uint32_t m = 0;
872         uint8_t size_b = 1, size_e = 2;
873         uint8_t horiz_pre_b = 1, horiz_pre_e = 6;
874         uint8_t vert_pre_b = 1, vert_pre_e = 3;
875
876         double s = 0.0;
877         bool northerness;
878         bool easterness;
879
880         char *my_str = (char *) str;
881
882         /* only support version 0 */
883         if (isdigit((int) *my_str)) {
884                 h = (uint32_t) strtol(my_str, &my_str, 10);
885         } else {
886                 return LDNS_STATUS_INVALID_STR;
887         }
888
889         while (isblank((int) *my_str)) {
890                 my_str++;
891         }
892
893         if (isdigit((int) *my_str)) {
894                 m = (uint32_t) strtol(my_str, &my_str, 10);
895         } else if (*my_str == 'N' || *my_str == 'S') {
896                 goto north;
897         } else {
898                 return LDNS_STATUS_INVALID_STR;
899         }
900
901         while (isblank((int) *my_str)) {
902                 my_str++;
903         }
904
905         if (isdigit((int) *my_str)) {
906                 s = strtod(my_str, &my_str);
907         }
908 north:
909         while (isblank((int) *my_str)) {
910                 my_str++;
911         }
912
913         if (*my_str == 'N') {
914                 northerness = true;
915         } else if (*my_str == 'S') {
916                 northerness = false;
917         } else {
918                 return LDNS_STATUS_INVALID_STR;
919         }
920
921         my_str++;
922
923         /* store number */
924         s = 1000.0 * s;
925         /* add a little to make floor in conversion a round */
926         s += 0.0005;
927         latitude = (uint32_t) s;
928         latitude += 1000 * 60 * m;
929         latitude += 1000 * 60 * 60 * h;
930         if (northerness) {
931                 latitude = equator + latitude;
932         } else {
933                 latitude = equator - latitude;
934         }
935         while (isblank(*my_str)) {
936                 my_str++;
937         }
938
939         if (isdigit((int) *my_str)) {
940                 h = (uint32_t) strtol(my_str, &my_str, 10);
941         } else {
942                 return LDNS_STATUS_INVALID_STR;
943         }
944
945         while (isblank((int) *my_str)) {
946                 my_str++;
947         }
948
949         if (isdigit((int) *my_str)) {
950                 m = (uint32_t) strtol(my_str, &my_str, 10);
951         } else if (*my_str == 'E' || *my_str == 'W') {
952                 goto east;
953         } else {
954                 return LDNS_STATUS_INVALID_STR;
955         }
956
957         while (isblank(*my_str)) {
958                 my_str++;
959         }
960
961         if (isdigit((int) *my_str)) {
962                 s = strtod(my_str, &my_str);
963         }
964
965 east:
966         while (isblank(*my_str)) {
967                 my_str++;
968         }
969
970         if (*my_str == 'E') {
971                 easterness = true;
972         } else if (*my_str == 'W') {
973                 easterness = false;
974         } else {
975                 return LDNS_STATUS_INVALID_STR;
976         }
977
978         my_str++;
979
980         /* store number */
981         s *= 1000.0;
982         /* add a little to make floor in conversion a round */
983         s += 0.0005;
984         longitude = (uint32_t) s;
985         longitude += 1000 * 60 * m;
986         longitude += 1000 * 60 * 60 * h;
987
988         if (easterness) {
989                 longitude += equator;
990         } else {
991                 longitude = equator - longitude;
992         }
993
994         altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 +
995                 10000000.0 + 0.5);
996         if (*my_str == 'm' || *my_str == 'M') {
997                 my_str++;
998         }
999
1000         if (strlen(my_str) > 0) {
1001                 if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e))
1002                         return LDNS_STATUS_INVALID_STR;
1003         }
1004
1005         if (strlen(my_str) > 0) {
1006                 if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e))
1007                         return LDNS_STATUS_INVALID_STR;
1008         }
1009
1010         if (strlen(my_str) > 0) {
1011                 if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e))
1012                         return LDNS_STATUS_INVALID_STR;
1013         }
1014
1015         data = LDNS_XMALLOC(uint8_t, 16);
1016         if(!data) {
1017                 return LDNS_STATUS_MEM_ERR;
1018         }
1019         data[0] = 0;
1020         data[1] = 0;
1021         data[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f);
1022         data[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f);
1023         data[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f);
1024         ldns_write_uint32(data + 4, latitude);
1025         ldns_write_uint32(data + 8, longitude);
1026         ldns_write_uint32(data + 12, altitude);
1027
1028         *rd = ldns_rdf_new_frm_data(
1029                 LDNS_RDF_TYPE_LOC, 16, data);
1030
1031         LDNS_FREE(data);
1032         return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
1033 }
1034
1035 ldns_status
1036 ldns_str2rdf_wks(ldns_rdf **rd, const char *str)
1037 {
1038         uint8_t *bitmap = NULL;
1039         uint8_t *data;
1040         int bm_len = 0;
1041
1042         struct protoent *proto = NULL;
1043         struct servent *serv = NULL;
1044         int serv_port;
1045
1046         ldns_buffer *str_buf;
1047
1048         char *proto_str = NULL;
1049         char *token;
1050         if(strlen(str) == 0)
1051                 token = LDNS_XMALLOC(char, 50);
1052         else    token = LDNS_XMALLOC(char, strlen(str)+2);
1053         if(!token) return LDNS_STATUS_MEM_ERR;
1054
1055         str_buf = LDNS_MALLOC(ldns_buffer);
1056         if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;}
1057         ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
1058         if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) {
1059                 LDNS_FREE(str_buf);
1060                 LDNS_FREE(token);
1061                 return LDNS_STATUS_MEM_ERR;
1062         }
1063
1064         while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) {
1065                 if (!proto_str) {
1066                         proto_str = strdup(token);
1067                         if (!proto_str) {
1068                                 LDNS_FREE(bitmap);
1069                                 LDNS_FREE(token);
1070                                 ldns_buffer_free(str_buf);
1071                                 return LDNS_STATUS_INVALID_STR;
1072                         }
1073                 } else {
1074                         serv = getservbyname(token, proto_str);
1075                         if (serv) {
1076                                 serv_port = (int) ntohs((uint16_t) serv->s_port);
1077                         } else {
1078                                 serv_port = atoi(token);
1079                         }
1080                         if (serv_port / 8 >= bm_len) {
1081                                 uint8_t *b2 = LDNS_XREALLOC(bitmap, uint8_t, (serv_port / 8) + 1);
1082                                 if(!b2) {
1083                                         LDNS_FREE(bitmap);
1084                                         LDNS_FREE(token);
1085                                         ldns_buffer_free(str_buf);
1086                                         free(proto_str);
1087                                         return LDNS_STATUS_INVALID_STR;
1088                                 }
1089                                 bitmap = b2;
1090                                 /* set to zero to be sure */
1091                                 for (; bm_len <= serv_port / 8; bm_len++) {
1092                                         bitmap[bm_len] = 0;
1093                                 }
1094                         }
1095                         ldns_set_bit(bitmap + (serv_port / 8), 7 - (serv_port % 8), true);
1096                 }
1097         }
1098
1099         if (!proto_str || !bitmap) {
1100                 LDNS_FREE(bitmap);
1101                 LDNS_FREE(token);
1102                 ldns_buffer_free(str_buf);
1103                 free(proto_str);
1104                 return LDNS_STATUS_INVALID_STR;
1105         }
1106
1107         data = LDNS_XMALLOC(uint8_t, bm_len + 1);
1108         if(!data) {
1109                 LDNS_FREE(token);
1110                 ldns_buffer_free(str_buf);
1111                 LDNS_FREE(bitmap);
1112                 free(proto_str);
1113                 return LDNS_STATUS_INVALID_STR;
1114         }
1115     if (proto_str)
1116                 proto = getprotobyname(proto_str);
1117         if (proto) {
1118                 data[0] = (uint8_t) proto->p_proto;
1119         } else if (proto_str) {
1120                 data[0] = (uint8_t) atoi(proto_str);
1121         }
1122         memcpy(data + 1, bitmap, (size_t) bm_len);
1123
1124         *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_WKS, (uint16_t) (bm_len + 1), data);
1125
1126         LDNS_FREE(data);
1127         LDNS_FREE(token);
1128         ldns_buffer_free(str_buf);
1129         LDNS_FREE(bitmap);
1130         free(proto_str);
1131 #ifdef HAVE_ENDSERVENT
1132         endservent();
1133 #endif
1134 #ifdef HAVE_ENDPROTOENT
1135         endprotoent();
1136 #endif
1137
1138         if(!*rd) return LDNS_STATUS_MEM_ERR;
1139
1140         return LDNS_STATUS_OK;
1141 }
1142
1143 ldns_status
1144 ldns_str2rdf_nsap(ldns_rdf **rd, const char *str)
1145 {
1146     size_t len, i;
1147     char* nsap_str = (char*) str;
1148
1149         /* just a hex string with optional dots? */
1150         if (str[0] != '0' || str[1] != 'x') {
1151                 return LDNS_STATUS_INVALID_STR;
1152         } else {
1153                 len = strlen(str);
1154                 for (i=0; i < len; i++) {
1155                         if (nsap_str[i] == '.')
1156                                 nsap_str[i] = ' ';
1157         }
1158                 return ldns_str2rdf_hex(rd, str+2);
1159         }
1160 }
1161
1162 ldns_status
1163 ldns_str2rdf_atma(ldns_rdf **rd, const char *str)
1164 {
1165     size_t len, i;
1166     char* atma_str = (char*) str;
1167         ldns_status status;
1168
1169         /* just a hex string with optional dots? */
1170         len = strlen(str);
1171         for (i=0; i < len; i++) {
1172                 if (atma_str[i] == '.')
1173                         atma_str[i] = ' ';
1174         }
1175         status = ldns_str2rdf_hex(rd, str);
1176     if (status != LDNS_STATUS_OK) {
1177                 ; /* probably in e.164 format than */
1178         }
1179         return status;
1180 }
1181
1182 ldns_status
1183 ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str)
1184 {
1185         uint8_t precedence = 0;
1186         uint8_t gateway_type = 0;
1187         uint8_t algorithm = 0;
1188         char* gateway = NULL;
1189         char* publickey = NULL;
1190         uint8_t *data;
1191         ldns_buffer *str_buf;
1192         char *token;
1193         int token_count = 0;
1194         int ipseckey_len = 0;
1195         ldns_rdf* gateway_rdf = NULL;
1196         ldns_rdf* publickey_rdf = NULL;
1197         ldns_status status = LDNS_STATUS_OK;
1198         
1199         if(strlen(str) == 0)
1200                 token = LDNS_XMALLOC(char, 256);
1201         else    token = LDNS_XMALLOC(char, strlen(str)+2);
1202         if(!token) return LDNS_STATUS_MEM_ERR;
1203
1204         str_buf = LDNS_MALLOC(ldns_buffer);
1205         if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;}
1206         ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
1207         if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) {
1208                 LDNS_FREE(str_buf);
1209                 LDNS_FREE(token);
1210                 return LDNS_STATUS_MEM_ERR;
1211         }
1212         while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) {
1213                 switch (token_count) {
1214                                 case 0:
1215                                         precedence = (uint8_t)atoi(token);
1216                                         break;
1217                                 case 1:
1218                                         gateway_type = (uint8_t)atoi(token);
1219                                         break;
1220                                 case 2:
1221                                         algorithm = (uint8_t)atoi(token);
1222                                         break;
1223                                 case 3:
1224                                         gateway = strdup(token);
1225                                         if (!gateway || (gateway_type == 0 &&
1226                                                         (token[0] != '.' || token[1] != '\0'))) {
1227                                                 LDNS_FREE(gateway);
1228                                                 LDNS_FREE(token);
1229                                                 ldns_buffer_free(str_buf);
1230                                                 return LDNS_STATUS_INVALID_STR;
1231                                         }
1232                                         break;
1233                                 case 4:
1234                                         publickey = strdup(token);
1235                                         break;
1236                                 default:
1237                                         LDNS_FREE(token);
1238                                         ldns_buffer_free(str_buf);
1239                                         return LDNS_STATUS_INVALID_STR;
1240                                         break;
1241                 }
1242                 token_count++;
1243         }
1244
1245         if (!gateway || !publickey) {
1246                 if (gateway)
1247                         LDNS_FREE(gateway);
1248                 if (publickey)
1249                         LDNS_FREE(publickey);
1250                 LDNS_FREE(token);
1251                 ldns_buffer_free(str_buf);
1252                 return LDNS_STATUS_INVALID_STR;
1253         }
1254
1255         if (gateway_type == 1) {
1256                 status = ldns_str2rdf_a(&gateway_rdf, gateway);
1257         } else if (gateway_type == 2) {
1258                 status = ldns_str2rdf_aaaa(&gateway_rdf, gateway);
1259         } else if (gateway_type == 3) {
1260                 status = ldns_str2rdf_dname(&gateway_rdf, gateway);
1261         }
1262
1263         if (status != LDNS_STATUS_OK) {
1264                 if (gateway)
1265                         LDNS_FREE(gateway);
1266                 if (publickey)
1267                         LDNS_FREE(publickey);
1268                 LDNS_FREE(token);
1269                 ldns_buffer_free(str_buf);
1270                 return LDNS_STATUS_INVALID_STR;
1271         }
1272
1273         status = ldns_str2rdf_b64(&publickey_rdf, publickey);
1274
1275         if (status != LDNS_STATUS_OK) {
1276                 if (gateway)
1277                         LDNS_FREE(gateway);
1278                 if (publickey)
1279                         LDNS_FREE(publickey);
1280                 LDNS_FREE(token);
1281                 ldns_buffer_free(str_buf);
1282                 if (gateway_rdf) ldns_rdf_free(gateway_rdf);
1283                 return LDNS_STATUS_INVALID_STR;
1284         }
1285
1286         /* now copy all into one ipseckey rdf */
1287         if (gateway_type)
1288                 ipseckey_len = 3 + (int)ldns_rdf_size(gateway_rdf) + (int)ldns_rdf_size(publickey_rdf);
1289         else
1290                 ipseckey_len = 3 + (int)ldns_rdf_size(publickey_rdf);
1291
1292         data = LDNS_XMALLOC(uint8_t, ipseckey_len);
1293         if(!data) {
1294                 if (gateway)
1295                         LDNS_FREE(gateway);
1296                 if (publickey)
1297                         LDNS_FREE(publickey);
1298                 LDNS_FREE(token);
1299                 ldns_buffer_free(str_buf);
1300                 if (gateway_rdf) ldns_rdf_free(gateway_rdf);
1301                 if (publickey_rdf) ldns_rdf_free(publickey_rdf);
1302                 return LDNS_STATUS_MEM_ERR;
1303         }
1304
1305         data[0] = precedence;
1306         data[1] = gateway_type;
1307         data[2] = algorithm;
1308
1309         if (gateway_type) {
1310                 memcpy(data + 3,
1311                         ldns_rdf_data(gateway_rdf), ldns_rdf_size(gateway_rdf));
1312                 memcpy(data + 3 + ldns_rdf_size(gateway_rdf),
1313                         ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf));
1314         } else {
1315                 memcpy(data + 3,
1316                         ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf));
1317         }
1318
1319         *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_IPSECKEY, (uint16_t) ipseckey_len, data);
1320
1321         if (gateway)
1322                 LDNS_FREE(gateway);
1323         if (publickey)
1324                 LDNS_FREE(publickey);
1325         LDNS_FREE(token);
1326         ldns_buffer_free(str_buf);
1327         ldns_rdf_free(gateway_rdf);
1328         ldns_rdf_free(publickey_rdf);
1329         LDNS_FREE(data);
1330         if(!*rd) return LDNS_STATUS_MEM_ERR;
1331         return LDNS_STATUS_OK;
1332 }
1333
1334 ldns_status
1335 ldns_str2rdf_ilnp64(ldns_rdf **rd, const char *str)
1336 {
1337         unsigned int a, b, c, d;
1338         uint16_t shorts[4];
1339         int l;
1340
1341         if (sscanf(str, "%4x:%4x:%4x:%4x%n", &a, &b, &c, &d, &l) != 4 ||
1342                         l != (int)strlen(str) || /* more data to read */
1343                         strpbrk(str, "+-")       /* signed hexes */
1344                         ) {
1345                 return LDNS_STATUS_INVALID_ILNP64;
1346         } else {
1347                 shorts[0] = htons(a);
1348                 shorts[1] = htons(b);
1349                 shorts[2] = htons(c);
1350                 shorts[3] = htons(d);
1351                 *rd = ldns_rdf_new_frm_data(
1352                         LDNS_RDF_TYPE_ILNP64, 4 * sizeof(uint16_t), &shorts);
1353         }
1354         return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
1355 }
1356
1357 ldns_status
1358 ldns_str2rdf_eui48(ldns_rdf **rd, const char *str)
1359 {
1360         unsigned int a, b, c, d, e, f;
1361         uint8_t bytes[6];
1362         int l;
1363
1364         if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x%n",
1365                         &a, &b, &c, &d, &e, &f, &l) != 6 ||
1366                         l != (int)strlen(str) || /* more data to read */
1367                         strpbrk(str, "+-")       /* signed hexes */
1368                         ) {
1369                 return LDNS_STATUS_INVALID_EUI48;
1370         } else {
1371                 bytes[0] = a;
1372                 bytes[1] = b;
1373                 bytes[2] = c;
1374                 bytes[3] = d;
1375                 bytes[4] = e;
1376                 bytes[5] = f;
1377                 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_EUI48, 6, &bytes);
1378         }
1379         return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
1380 }
1381
1382 ldns_status
1383 ldns_str2rdf_eui64(ldns_rdf **rd, const char *str)
1384 {
1385         unsigned int a, b, c, d, e, f, g, h;
1386         uint8_t bytes[8];
1387         int l;
1388
1389         if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x%n",
1390                         &a, &b, &c, &d, &e, &f, &g, &h, &l) != 8 ||
1391                         l != (int)strlen(str) || /* more data to read */
1392                         strpbrk(str, "+-")       /* signed hexes */
1393                         ) {
1394                 return LDNS_STATUS_INVALID_EUI64;
1395         } else {
1396                 bytes[0] = a;
1397                 bytes[1] = b;
1398                 bytes[2] = c;
1399                 bytes[3] = d;
1400                 bytes[4] = e;
1401                 bytes[5] = f;
1402                 bytes[6] = g;
1403                 bytes[7] = h;
1404                 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_EUI64, 8, &bytes);
1405         }
1406         return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
1407 }
1408
1409 ldns_status
1410 ldns_str2rdf_tag(ldns_rdf **rd, const char *str)
1411 {
1412         uint8_t *data;
1413         const char* ptr;
1414
1415         if (strlen(str) > 255) {
1416                 return LDNS_STATUS_INVALID_TAG;
1417         }
1418         for (ptr = str; *ptr; ptr++) {
1419                 if (! isalnum(*ptr)) {
1420                         return LDNS_STATUS_INVALID_TAG;
1421                 }
1422         }
1423         data = LDNS_XMALLOC(uint8_t, strlen(str) + 1);
1424         if (!data) {
1425                 return LDNS_STATUS_MEM_ERR;
1426         }
1427         data[0] = strlen(str);
1428         memcpy(data + 1, str, strlen(str));
1429
1430         *rd = ldns_rdf_new(LDNS_RDF_TYPE_TAG, strlen(str) + 1, data);
1431         if (!*rd) {
1432                 LDNS_FREE(data);
1433                 return LDNS_STATUS_MEM_ERR;
1434         }
1435         return LDNS_STATUS_OK;
1436 }
1437
1438 ldns_status
1439 ldns_str2rdf_long_str(ldns_rdf **rd, const char *str)
1440 {
1441         uint8_t *data, *dp, ch = 0;
1442         size_t length;
1443
1444         /* Worst case space requirement. We'll realloc to actual size later. */
1445         dp = data = LDNS_XMALLOC(uint8_t, strlen(str));
1446         if (! data) {
1447                 return LDNS_STATUS_MEM_ERR;
1448         }
1449
1450         /* Fill data with parsed bytes */
1451         while (parse_char(&ch, &str)) {
1452                 *dp++ = ch;
1453                 if (dp - data > LDNS_MAX_RDFLEN) {
1454                         LDNS_FREE(data);
1455                         return LDNS_STATUS_INVALID_STR;
1456                 }
1457         }
1458         if (! str) {
1459                 return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
1460         }
1461         length = (size_t)(dp - data);
1462
1463         /* Lose the overmeasure */
1464         data = LDNS_XREALLOC(dp = data, uint8_t, length);
1465         if (! data) {
1466                 LDNS_FREE(dp);
1467                 return LDNS_STATUS_MEM_ERR;
1468         }
1469
1470         /* Create rdf */
1471         *rd = ldns_rdf_new(LDNS_RDF_TYPE_LONG_STR, length, data);
1472         if (! *rd) {
1473                 LDNS_FREE(data);
1474                 return LDNS_STATUS_MEM_ERR;
1475         }
1476         return LDNS_STATUS_OK;
1477 }
1478
1479 ldns_status
1480 ldns_str2rdf_hip(ldns_rdf **rd, const char *str)
1481 {
1482         const char *hit = strchr(str, ' ') + 1;
1483         const char *pk  = hit == NULL ? NULL : strchr(hit, ' ') + 1;
1484         size_t hit_size = hit == NULL ? 0
1485                         : pk  == NULL ? strlen(hit) : (size_t) (pk - hit) - 1;
1486         size_t  pk_size = pk  == NULL ? 0 : strlen(pk);
1487         size_t hit_wire_size = (hit_size + 1) / 2;
1488         size_t  pk_wire_size = ldns_b64_pton_calculate_size(pk_size);
1489         size_t rdf_size = 4 + hit_wire_size + pk_wire_size;
1490
1491         char *endptr; /* utility var for strtol usage */
1492         int algorithm = strtol(str, &endptr, 10);
1493
1494         uint8_t *data, *dp;
1495         int hi, lo, written;
1496
1497         if (hit_size == 0 || pk_size == 0 || (hit_size + 1) / 2 > 255
1498                         || rdf_size > LDNS_MAX_RDFLEN
1499                         || algorithm < 0 || algorithm > 255
1500                         || (errno != 0 && algorithm == 0) /* out of range */
1501                         || endptr == str                  /* no digits    */) {
1502
1503                 return LDNS_STATUS_SYNTAX_ERR;
1504         }
1505         if ((data = LDNS_XMALLOC(uint8_t, rdf_size)) == NULL) {
1506
1507                 return LDNS_STATUS_MEM_ERR;
1508         }
1509         /* From RFC 5205 section 5. HIP RR Storage Format:
1510          *************************************************
1511
1512         0                   1                   2                   3
1513         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
1514         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1515         |  HIT length   | PK algorithm  |          PK length            |
1516         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1517         |                                                               |
1518         ~                           HIT                                 ~
1519         |                                                               |
1520         +                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1521         |                     |                                         |
1522         +-+-+-+-+-+-+-+-+-+-+-+                                         +
1523         |                           Public Key                          |
1524         ~                                                               ~
1525         |                                                               |
1526         +                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1527         |                               |                               |
1528         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
1529         |                                                               |
1530         ~                       Rendezvous Servers                      ~
1531         |                                                               |
1532         +             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1533         |             |
1534         +-+-+-+-+-+-+-+                                                    */
1535
1536         data[0] = (uint8_t) hit_wire_size;
1537         data[1] = (uint8_t) algorithm;
1538
1539         for (dp = data + 4; *hit && *hit != ' '; dp++) {
1540
1541                 if ((hi = ldns_hexdigit_to_int(*hit++)) == -1 ||
1542                     (lo = ldns_hexdigit_to_int(*hit++)) == -1) {
1543
1544                         LDNS_FREE(data);
1545                         return LDNS_STATUS_INVALID_HEX;
1546                 }
1547                 *dp = (uint8_t) hi << 4 | lo;
1548         }
1549         if ((written = ldns_b64_pton(pk, dp, pk_wire_size)) <= 0) {
1550
1551                 LDNS_FREE(data);
1552                 return LDNS_STATUS_INVALID_B64;
1553         }
1554
1555         /* Because ldns_b64_pton_calculate_size isn't always correct:
1556          * (we have to fix it at some point)
1557          */
1558         pk_wire_size = (uint16_t) written;
1559         ldns_write_uint16(data + 2, pk_wire_size);
1560         rdf_size = 4 + hit_wire_size + pk_wire_size;
1561
1562         /* Create rdf */
1563         if (! (*rd = ldns_rdf_new(LDNS_RDF_TYPE_HIP, rdf_size, data))) {
1564
1565                 LDNS_FREE(data);
1566                 return LDNS_STATUS_MEM_ERR;
1567         }
1568         return LDNS_STATUS_OK;
1569 }