4 * conversion routines from the presentation format
7 * a Net::DNS like library for C
9 * (c) NLnet Labs, 2004-2006
11 * See the file LICENSE for the license
13 #include <ldns/config.h>
15 #include <ldns/ldns.h>
17 #ifdef HAVE_SYS_SOCKET_H
18 #include <sys/socket.h>
20 #ifdef HAVE_ARPA_INET_H
21 #include <arpa/inet.h>
31 #ifdef HAVE_SYS_PARAM_H
32 #include <sys/param.h>
36 ldns_str2rdf_int16(ldns_rdf
**rd
, const char *shortstr
)
40 r
= LDNS_MALLOC(uint16_t);
41 if(!r
) return LDNS_STATUS_MEM_ERR
;
43 *r
= htons((uint16_t)strtol((char *)shortstr
, &end
, 10));
47 return LDNS_STATUS_INVALID_INT
;
49 *rd
= ldns_rdf_new_frm_data(
50 LDNS_RDF_TYPE_INT16
, sizeof(uint16_t), r
);
52 return *rd
?LDNS_STATUS_OK
:LDNS_STATUS_MEM_ERR
;
57 ldns_str2rdf_time(ldns_rdf
**rd
, const char *time
)
59 /* convert a time YYYYDDMMHHMMSS to wireformat */
65 /* Try to scan the time... */
66 r
= (uint16_t*)LDNS_MALLOC(uint32_t);
67 if(!r
) return LDNS_STATUS_MEM_ERR
;
69 memset(&tm
, 0, sizeof(tm
));
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
77 if (tm
.tm_year
< 70) {
80 if (tm
.tm_mon
< 0 || tm
.tm_mon
> 11) {
83 if (tm
.tm_mday
< 1 || tm
.tm_mday
> 31) {
87 if (tm
.tm_hour
< 0 || tm
.tm_hour
> 23) {
91 if (tm
.tm_min
< 0 || tm
.tm_min
> 59) {
95 if (tm
.tm_sec
< 0 || tm
.tm_sec
> 59) {
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
);
104 return *rd
?LDNS_STATUS_OK
:LDNS_STATUS_MEM_ERR
;
106 /* handle it as 32 bits timestamp */
107 l
= htonl((uint32_t)strtol((char*)time
, &end
, 10));
110 return LDNS_STATUS_ERR
;
112 memcpy(r
, &l
, sizeof(uint32_t));
113 *rd
= ldns_rdf_new_frm_data(
114 LDNS_RDF_TYPE_INT32
, sizeof(uint32_t), r
);
116 return *rd
?LDNS_STATUS_OK
:LDNS_STATUS_MEM_ERR
;
122 return LDNS_STATUS_INVALID_TIME
;
126 ldns_str2rdf_nsec3_salt(ldns_rdf
**rd
, const char *salt_str
)
135 return LDNS_STATUS_NULL
;
138 salt_length_str
= (int)strlen(salt_str
);
139 if (salt_length_str
== 1 && salt_str
[0] == '-') {
141 } else if (salt_length_str
% 2 != 0) {
142 return LDNS_STATUS_INVALID_HEX
;
144 if (salt_length_str
> 512) {
145 return LDNS_STATUS_INVALID_HEX
;
148 salt
= LDNS_XMALLOC(uint8_t, salt_length_str
/ 2);
150 return LDNS_STATUS_MEM_ERR
;
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]);
158 return LDNS_STATUS_INVALID_HEX
;
161 salt_length
= (uint8_t) (salt_length_str
/ 2);
163 data
= LDNS_XMALLOC(uint8_t, 1 + salt_length
);
166 return LDNS_STATUS_MEM_ERR
;
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
);
174 return *rd
?LDNS_STATUS_OK
:LDNS_STATUS_MEM_ERR
;
178 ldns_str2rdf_period(ldns_rdf
**rd
,const char *period
)
183 /* Allocate required space... */
184 p
= ldns_str2period(period
, &end
);
187 return LDNS_STATUS_ERR
;
189 p
= (uint32_t) htonl(p
);
190 *rd
= ldns_rdf_new_frm_data(
191 LDNS_RDF_TYPE_PERIOD
, sizeof(uint32_t), &p
);
193 return *rd
?LDNS_STATUS_OK
:LDNS_STATUS_MEM_ERR
;
197 ldns_str2rdf_int32(ldns_rdf
**rd
, const char *longstr
)
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 */
208 l
= htonl((uint32_t)strtol((char*)longstr
, &end
, 10));
209 else l
= htonl((uint32_t)strtoul((char*)longstr
, &end
, 10));
213 return LDNS_STATUS_ERR
;
215 if (errno
== ERANGE
) {
217 return LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW
;
219 memcpy(r
, &l
, sizeof(uint32_t));
220 *rd
= ldns_rdf_new_frm_data(
221 LDNS_RDF_TYPE_INT32
, sizeof(uint32_t), r
);
223 return *rd
?LDNS_STATUS_OK
:LDNS_STATUS_MEM_ERR
;
228 ldns_str2rdf_int8(ldns_rdf
**rd
, const char *bytestr
)
233 r
= LDNS_MALLOC(uint8_t);
234 if(!r
) return LDNS_STATUS_MEM_ERR
;
236 *r
= (uint8_t)strtol((char*)bytestr
, &end
, 10);
240 return LDNS_STATUS_ERR
;
242 *rd
= ldns_rdf_new_frm_data(
243 LDNS_RDF_TYPE_INT8
, sizeof(uint8_t), r
);
245 return *rd
?LDNS_STATUS_OK
:LDNS_STATUS_MEM_ERR
;
251 * Checks whether the escaped value at **s is an decimal value or
252 * a 'normally' escaped character (and not eos)
254 * The string pointer at *s is increased by either 0 (on error), 1 (on
255 * normal escapes), or 3 (on decimals)
257 * Returns the number of bytes read from the escaped string, or
261 parse_escape(uint8_t *ch_p
, const char** str_p
)
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])) {
269 val
= (uint16_t)(((*str_p
)[0] - '0') * 100 +
270 ((*str_p
)[1] - '0') * 10 +
271 ((*str_p
)[2] - '0'));
276 *ch_p
= (uint8_t)val
;
280 } else if ((*str_p
)[0] && !isdigit((unsigned char)(*str_p
)[0])) {
282 *ch_p
= (uint8_t)*(*str_p
)++;
287 return false; /* LDNS_STATUS_SYNTAX_BAD_ESCAPE */
291 parse_char(uint8_t *ch_p
, const char** str_p
)
295 case '\0': return false;
297 case '\\': *str_p
+= 1;
298 return parse_escape(ch_p
, str_p
);
300 default: *ch_p
= (uint8_t)*(*str_p
)++;
306 * No special care is taken, all dots are translated into
308 * Could be made more efficient....we do 3 memcpy's in total...
311 ldns_str2rdf_dname(ldns_rdf
**d
, const char *str
)
316 uint8_t *q
, *pq
, label_len
;
317 uint8_t buf
[LDNS_MAX_DOMAINLEN
+ 1];
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
;
326 return LDNS_STATUS_DOMAINNAME_UNDERFLOW
;
330 if (1 == len
&& *str
== '.') {
331 *d
= ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME
, 1, "\0");
332 return LDNS_STATUS_OK
;
335 /* get on with the rest */
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
346 for (s
= str
; *s
; s
++, q
++) {
347 if (q
> buf
+ LDNS_MAX_DOMAINLEN
) {
348 return LDNS_STATUS_DOMAINNAME_OVERFLOW
;
353 if (label_len
> LDNS_MAX_LABELLEN
) {
354 return LDNS_STATUS_LABEL_OVERFLOW
;
356 if (label_len
== 0) {
357 return LDNS_STATUS_EMPTY_LABEL
;
359 len
+= label_len
+ 1;
365 /* octet value or literal char */
367 if (! parse_escape(q
, &s
)) {
368 return LDNS_STATUS_SYNTAX_BAD_ESCAPE
;
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
;
384 if (label_len
> LDNS_MAX_LABELLEN
) {
385 return LDNS_STATUS_LABEL_OVERFLOW
;
387 if (label_len
== 0) { /* label_len 0 but not . at end? */
388 return LDNS_STATUS_EMPTY_LABEL
;
390 len
+= label_len
+ 1;
396 *d
= ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME
, len
, buf
);
397 return LDNS_STATUS_OK
;
401 ldns_str2rdf_a(ldns_rdf
**rd
, const char *str
)
404 if (inet_pton(AF_INET
, (char*)str
, &address
) != 1) {
405 return LDNS_STATUS_INVALID_IP4
;
407 *rd
= ldns_rdf_new_frm_data(
408 LDNS_RDF_TYPE_A
, sizeof(address
), &address
);
410 return *rd
?LDNS_STATUS_OK
:LDNS_STATUS_MEM_ERR
;
414 ldns_str2rdf_aaaa(ldns_rdf
**rd
, const char *str
)
416 uint8_t address
[LDNS_IP6ADDRLEN
+ 1];
418 if (inet_pton(AF_INET6
, (char*)str
, address
) != 1) {
419 return LDNS_STATUS_INVALID_IP6
;
421 *rd
= ldns_rdf_new_frm_data(
422 LDNS_RDF_TYPE_AAAA
, sizeof(address
) - 1, &address
);
424 return *rd
?LDNS_STATUS_OK
:LDNS_STATUS_MEM_ERR
;
428 ldns_str2rdf_str(ldns_rdf
**rd
, const char *str
)
430 uint8_t *data
, *dp
, ch
= 0;
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));
436 return LDNS_STATUS_MEM_ERR
;
439 /* Fill data (up to 255 characters) */
440 while (parse_char(&ch
, &str
)) {
441 if (dp
- data
>= 255) {
443 return LDNS_STATUS_INVALID_STR
;
448 return LDNS_STATUS_SYNTAX_BAD_ESCAPE
;
450 length
= (size_t)(dp
- data
);
451 /* Fix last length byte */
452 data
[0] = (uint8_t)length
;
454 /* Lose the overmeasure */
455 data
= LDNS_XREALLOC(dp
= data
, uint8_t, length
+ 1);
458 return LDNS_STATUS_MEM_ERR
;
462 *rd
= ldns_rdf_new(LDNS_RDF_TYPE_STR
, length
+ 1, data
);
465 return LDNS_STATUS_MEM_ERR
;
467 return LDNS_STATUS_OK
;
471 ldns_str2rdf_apl(ldns_rdf
**rd
, const char *str
)
473 const char *my_str
= str
;
480 uint8_t afdlength
= 0;
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
;
496 if (my_str
[0] == '!') {
503 family
= (uint16_t) atoi(my_str
);
505 my_str
= strchr(my_str
, ':') + 1;
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';
516 afdpart
= LDNS_XMALLOC(uint8_t, 4);
518 LDNS_FREE(my_ip_str
);
519 return LDNS_STATUS_MEM_ERR
;
521 if (inet_pton(AF_INET
, my_ip_str
, afdpart
) == 0) {
522 LDNS_FREE(my_ip_str
);
524 return LDNS_STATUS_INVALID_STR
;
526 for (i
= 0; i
< 4; i
++) {
527 if (afdpart
[i
] != 0) {
531 } else if (family
== 2) {
533 afdpart
= LDNS_XMALLOC(uint8_t, 16);
535 LDNS_FREE(my_ip_str
);
536 return LDNS_STATUS_MEM_ERR
;
538 if (inet_pton(AF_INET6
, my_ip_str
, afdpart
) == 0) {
539 LDNS_FREE(my_ip_str
);
541 return LDNS_STATUS_INVALID_STR
;
543 for (i
= 0; i
< 16; i
++) {
544 if (afdpart
[i
] != 0) {
550 LDNS_FREE(my_ip_str
);
551 return LDNS_STATUS_INVALID_STR
;
554 my_str
= strchr(my_str
, '/') + 1;
555 prefix
= (uint8_t) atoi(my_str
);
557 data
= LDNS_XMALLOC(uint8_t, 4 + afdlength
);
560 LDNS_FREE(my_ip_str
);
561 return LDNS_STATUS_INVALID_STR
;
563 ldns_write_uint16(data
, family
);
567 /* set bit 1 of byte 3 */
568 data
[3] = data
[3] | 0x80;
571 memcpy(data
+ 4, afdpart
, afdlength
);
573 *rd
= ldns_rdf_new_frm_data(LDNS_RDF_TYPE_APL
, afdlength
+ 4, data
);
576 LDNS_FREE(my_ip_str
);
578 return *rd
?LDNS_STATUS_OK
:LDNS_STATUS_MEM_ERR
;
582 ldns_str2rdf_b64(ldns_rdf
**rd
, const char *str
)
587 buffer
= LDNS_XMALLOC(uint8_t, ldns_b64_ntop_calculate_size(strlen(str
)));
589 return LDNS_STATUS_MEM_ERR
;
592 i
= (uint16_t)ldns_b64_pton((const char*)str
, buffer
,
593 ldns_b64_ntop_calculate_size(strlen(str
)));
596 return LDNS_STATUS_INVALID_B64
;
598 *rd
= ldns_rdf_new_frm_data(
599 LDNS_RDF_TYPE_B64
, (uint16_t) i
, buffer
);
603 return *rd
?LDNS_STATUS_OK
:LDNS_STATUS_MEM_ERR
;
607 ldns_str2rdf_b32_ext(ldns_rdf
**rd
, const char *str
)
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);
615 return LDNS_STATUS_MEM_ERR
;
619 i
= ldns_b32_pton_extended_hex((const char*)str
, strlen(str
), buffer
+ 1,
620 ldns_b32_ntop_calculate_size(strlen(str
)));
623 return LDNS_STATUS_INVALID_B32_EXT
;
625 *rd
= ldns_rdf_new_frm_data(
626 LDNS_RDF_TYPE_B32_EXT
, (uint16_t) i
+ 1, buffer
);
630 return *rd
?LDNS_STATUS_OK
:LDNS_STATUS_MEM_ERR
;
634 ldns_str2rdf_hex(ldns_rdf
**rd
, const char *str
)
642 if (len
> LDNS_MAX_RDFLEN
* 2) {
643 return LDNS_STATUS_LABEL_OVERFLOW
;
645 t
= LDNS_XMALLOC(uint8_t, (len
/ 2) + 1);
647 return LDNS_STATUS_MEM_ERR
;
650 /* Now process octet by octet... */
653 if (isspace((int) *str
)) {
656 for (i
= 16; i
>= 1; i
-= 15) {
657 while (*str
&& isspace((int) *str
)) { str
++; }
659 if (isxdigit((int) *str
)) {
660 *t
+= ldns_hexdigit_to_int(*str
) * i
;
663 return LDNS_STATUS_ERR
;
671 *rd
= ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX
,
672 (size_t) (t
- t_orig
),
676 return *rd
?LDNS_STATUS_OK
:LDNS_STATUS_MEM_ERR
;
680 ldns_str2rdf_nsec(ldns_rdf
**rd
, const char *str
)
682 const char *delimiters
= "\n\t ";
683 char *token
= LDNS_XMALLOC(char, LDNS_MAX_RDFLEN
);
684 ldns_buffer
*str_buf
;
687 size_t type_count
= 0;
688 ldns_rr_type type_list
[65536];
689 if(!token
) return LDNS_STATUS_MEM_ERR
;
692 return LDNS_STATUS_NULL
;
695 str_buf
= LDNS_MALLOC(ldns_buffer
);
698 return LDNS_STATUS_MEM_ERR
;
700 ldns_buffer_new_frm_data(str_buf
, (char *)str
, strlen(str
));
701 if(ldns_buffer_status(str_buf
) != LDNS_STATUS_OK
) {
704 return LDNS_STATUS_MEM_ERR
;
707 while ((c
= ldns_bget_token(str_buf
, token
, delimiters
, LDNS_MAX_RDFLEN
)) != -1 && c
!= 0) {
708 if(type_count
>= sizeof(type_list
)) {
711 return LDNS_STATUS_ERR
;
713 cur_type
= ldns_get_rr_type_by_name(token
);
714 type_list
[type_count
] = cur_type
;
718 *rd
= ldns_dnssec_create_nsec_bitmap(type_list
,
723 ldns_buffer_free(str_buf
);
724 return *rd
?LDNS_STATUS_OK
:LDNS_STATUS_MEM_ERR
;
728 ldns_str2rdf_type(ldns_rdf
**rd
, const char *str
)
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
;
739 ldns_str2rdf_class(ldns_rdf
**rd
, const char *str
)
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
;
749 /* An certificate alg field can either be specified as a 8 bits number
750 * or by its symbolic name. Handle both
753 ldns_str2rdf_cert_alg(ldns_rdf
**rd
, const char *str
)
755 ldns_lookup_table
*lt
;
758 lt
= ldns_lookup_by_name(ldns_cert_algorithms
, str
);
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
);
766 st
= LDNS_STATUS_ERR
;
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
;
780 static ldns_lookup_table ldns_tlsa_certificate_usages
[] = {
781 { LDNS_TLSA_USAGE_PKIX_TA
, "PKIX-TA" },
782 { LDNS_TLSA_USAGE_PKIX_EE
, "PKIX-EE" },
783 { LDNS_TLSA_USAGE_DANE_TA
, "DANE-TA" },
784 { LDNS_TLSA_USAGE_DANE_EE
, "DANE-EE" },
785 { LDNS_TLSA_USAGE_PRIVCERT
, "PrivCert" },
789 static ldns_lookup_table ldns_tlsa_selectors
[] = {
790 { LDNS_TLSA_SELECTOR_CERT
, "Cert" },
791 { LDNS_TLSA_SELECTOR_SPKI
, "SPKI" },
792 { LDNS_TLSA_SELECTOR_PRIVSEL
, "PrivSel" },
796 static ldns_lookup_table ldns_tlsa_matching_types
[] = {
797 { LDNS_TLSA_MATCHING_TYPE_FULL
, "Full" },
798 { LDNS_TLSA_MATCHING_TYPE_SHA2_256
, "SHA2-256" },
799 { LDNS_TLSA_MATCHING_TYPE_SHA2_512
, "SHA2-512" },
800 { LDNS_TLSA_MATCHING_TYPE_PRIVMATCH
, "PrivMatch" },
805 ldns_str2rdf_mnemonic4int8(ldns_lookup_table
*lt
,
806 ldns_rdf
**rd
, const char *str
)
808 if ((lt
= ldns_lookup_by_name(lt
, str
))) {
809 /* it was given as a integer */
810 *rd
= ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8
, (uint8_t) lt
->id
);
812 return LDNS_STATUS_ERR
;
814 return LDNS_STATUS_OK
;
816 return ldns_str2rdf_int8(rd
, str
);
819 /* An alg field can either be specified as a 8 bits number
820 * or by its symbolic name. Handle both
823 ldns_str2rdf_alg(ldns_rdf
**rd
, const char *str
)
825 return ldns_str2rdf_mnemonic4int8(ldns_algorithms
, rd
, str
);
829 ldns_str2rdf_certificate_usage(ldns_rdf
**rd
, const char *str
)
831 return ldns_str2rdf_mnemonic4int8(
832 ldns_tlsa_certificate_usages
, rd
, str
);
836 ldns_str2rdf_selector(ldns_rdf
**rd
, const char *str
)
838 return ldns_str2rdf_mnemonic4int8(ldns_tlsa_selectors
, rd
, str
);
842 ldns_str2rdf_matching_type(ldns_rdf
**rd
, const char *str
)
844 return ldns_str2rdf_mnemonic4int8(ldns_tlsa_matching_types
, rd
, str
);
848 ldns_str2rdf_unknown( ATTR_UNUSED(ldns_rdf
**rd
)
849 , ATTR_UNUSED(const char *str
)
852 /* this should be caught in an earlier time (general str2host for
854 return LDNS_STATUS_NOT_IMPL
;
858 ldns_str2rdf_service( ATTR_UNUSED(ldns_rdf
**rd
)
859 , ATTR_UNUSED(const char *str
)
862 /* is this used? is this actually WKS? or SRV? */
863 return LDNS_STATUS_NOT_IMPL
;
867 loc_parse_cm(char* my_str
, char** endstr
, uint8_t* m
, uint8_t* e
)
869 /* read <digits>[.<digits>][mM] */
870 /* into mantissa exponent format for LOC type */
871 uint32_t meters
= 0, cm
= 0, val
;
872 while (isblank((unsigned char)*my_str
)) {
875 meters
= (uint32_t)strtol(my_str
, &my_str
, 10);
876 if (*my_str
== '.') {
878 cm
= (uint32_t)strtol(my_str
, &my_str
, 10);
895 if (*my_str
== 'm' || *my_str
== 'M') {
903 ldns_str2rdf_loc(ldns_rdf
**rd
, const char *str
)
905 uint32_t latitude
= 0;
906 uint32_t longitude
= 0;
907 uint32_t altitude
= 0;
910 uint32_t equator
= (uint32_t) ldns_power(2, 31);
914 uint8_t size_b
= 1, size_e
= 2;
915 uint8_t horiz_pre_b
= 1, horiz_pre_e
= 6;
916 uint8_t vert_pre_b
= 1, vert_pre_e
= 3;
922 char *my_str
= (char *) str
;
924 /* only support version 0 */
925 if (isdigit((int) *my_str
)) {
926 h
= (uint32_t) strtol(my_str
, &my_str
, 10);
928 return LDNS_STATUS_INVALID_STR
;
931 while (isblank((int) *my_str
)) {
935 if (isdigit((int) *my_str
)) {
936 m
= (uint32_t) strtol(my_str
, &my_str
, 10);
937 } else if (*my_str
== 'N' || *my_str
== 'S') {
940 return LDNS_STATUS_INVALID_STR
;
943 while (isblank((int) *my_str
)) {
947 if (isdigit((int) *my_str
)) {
948 s
= strtod(my_str
, &my_str
);
951 while (isblank((int) *my_str
)) {
955 if (*my_str
== 'N') {
957 } else if (*my_str
== 'S') {
960 return LDNS_STATUS_INVALID_STR
;
967 /* add a little to make floor in conversion a round */
969 latitude
= (uint32_t) s
;
970 latitude
+= 1000 * 60 * m
;
971 latitude
+= 1000 * 60 * 60 * h
;
973 latitude
= equator
+ latitude
;
975 latitude
= equator
- latitude
;
977 while (isblank((unsigned char)*my_str
)) {
981 if (isdigit((int) *my_str
)) {
982 h
= (uint32_t) strtol(my_str
, &my_str
, 10);
984 return LDNS_STATUS_INVALID_STR
;
987 while (isblank((int) *my_str
)) {
991 if (isdigit((int) *my_str
)) {
992 m
= (uint32_t) strtol(my_str
, &my_str
, 10);
993 } else if (*my_str
== 'E' || *my_str
== 'W') {
996 return LDNS_STATUS_INVALID_STR
;
999 while (isblank((unsigned char)*my_str
)) {
1003 if (isdigit((int) *my_str
)) {
1004 s
= strtod(my_str
, &my_str
);
1008 while (isblank((unsigned char)*my_str
)) {
1012 if (*my_str
== 'E') {
1014 } else if (*my_str
== 'W') {
1017 return LDNS_STATUS_INVALID_STR
;
1024 /* add a little to make floor in conversion a round */
1026 longitude
= (uint32_t) s
;
1027 longitude
+= 1000 * 60 * m
;
1028 longitude
+= 1000 * 60 * 60 * h
;
1031 longitude
+= equator
;
1033 longitude
= equator
- longitude
;
1036 altitude
= (uint32_t)(strtod(my_str
, &my_str
)*100.0 +
1038 if (*my_str
== 'm' || *my_str
== 'M') {
1042 if (strlen(my_str
) > 0) {
1043 if(!loc_parse_cm(my_str
, &my_str
, &size_b
, &size_e
))
1044 return LDNS_STATUS_INVALID_STR
;
1047 if (strlen(my_str
) > 0) {
1048 if(!loc_parse_cm(my_str
, &my_str
, &horiz_pre_b
, &horiz_pre_e
))
1049 return LDNS_STATUS_INVALID_STR
;
1052 if (strlen(my_str
) > 0) {
1053 if(!loc_parse_cm(my_str
, &my_str
, &vert_pre_b
, &vert_pre_e
))
1054 return LDNS_STATUS_INVALID_STR
;
1057 data
= LDNS_XMALLOC(uint8_t, 16);
1059 return LDNS_STATUS_MEM_ERR
;
1063 data
[1] = ((size_b
<< 4) & 0xf0) | (size_e
& 0x0f);
1064 data
[2] = ((horiz_pre_b
<< 4) & 0xf0) | (horiz_pre_e
& 0x0f);
1065 data
[3] = ((vert_pre_b
<< 4) & 0xf0) | (vert_pre_e
& 0x0f);
1066 ldns_write_uint32(data
+ 4, latitude
);
1067 ldns_write_uint32(data
+ 8, longitude
);
1068 ldns_write_uint32(data
+ 12, altitude
);
1070 *rd
= ldns_rdf_new_frm_data(
1071 LDNS_RDF_TYPE_LOC
, 16, data
);
1074 return *rd
?LDNS_STATUS_OK
:LDNS_STATUS_MEM_ERR
;
1078 ldns_str2rdf_wks(ldns_rdf
**rd
, const char *str
)
1080 uint8_t *bitmap
= NULL
;
1084 struct protoent
*proto
= NULL
;
1085 struct servent
*serv
= NULL
;
1088 ldns_buffer
*str_buf
;
1090 char *proto_str
= NULL
;
1092 if(strlen(str
) == 0)
1093 token
= LDNS_XMALLOC(char, 50);
1094 else token
= LDNS_XMALLOC(char, strlen(str
)+2);
1095 if(!token
) return LDNS_STATUS_MEM_ERR
;
1097 str_buf
= LDNS_MALLOC(ldns_buffer
);
1098 if(!str_buf
) {LDNS_FREE(token
); return LDNS_STATUS_MEM_ERR
;}
1099 ldns_buffer_new_frm_data(str_buf
, (char *)str
, strlen(str
));
1100 if(ldns_buffer_status(str_buf
) != LDNS_STATUS_OK
) {
1103 return LDNS_STATUS_MEM_ERR
;
1106 while(ldns_bget_token(str_buf
, token
, "\t\n ", strlen(str
)) > 0) {
1108 proto_str
= strdup(token
);
1112 ldns_buffer_free(str_buf
);
1113 return LDNS_STATUS_INVALID_STR
;
1116 serv
= getservbyname(token
, proto_str
);
1118 serv_port
= (int) ntohs((uint16_t) serv
->s_port
);
1120 serv_port
= atoi(token
);
1122 if (serv_port
/ 8 >= bm_len
) {
1123 uint8_t *b2
= LDNS_XREALLOC(bitmap
, uint8_t, (serv_port
/ 8) + 1);
1127 ldns_buffer_free(str_buf
);
1129 return LDNS_STATUS_INVALID_STR
;
1132 /* set to zero to be sure */
1133 for (; bm_len
<= serv_port
/ 8; bm_len
++) {
1137 ldns_set_bit(bitmap
+ (serv_port
/ 8), 7 - (serv_port
% 8), true);
1141 if (!proto_str
|| !bitmap
) {
1144 ldns_buffer_free(str_buf
);
1146 return LDNS_STATUS_INVALID_STR
;
1149 data
= LDNS_XMALLOC(uint8_t, bm_len
+ 1);
1152 ldns_buffer_free(str_buf
);
1155 return LDNS_STATUS_INVALID_STR
;
1158 proto
= getprotobyname(proto_str
);
1160 data
[0] = (uint8_t) proto
->p_proto
;
1161 } else if (proto_str
) {
1162 data
[0] = (uint8_t) atoi(proto_str
);
1164 memcpy(data
+ 1, bitmap
, (size_t) bm_len
);
1166 *rd
= ldns_rdf_new_frm_data(LDNS_RDF_TYPE_WKS
, (uint16_t) (bm_len
+ 1), data
);
1170 ldns_buffer_free(str_buf
);
1173 #ifdef HAVE_ENDSERVENT
1176 #ifdef HAVE_ENDPROTOENT
1180 if(!*rd
) return LDNS_STATUS_MEM_ERR
;
1182 return LDNS_STATUS_OK
;
1186 ldns_str2rdf_nsap(ldns_rdf
**rd
, const char *str
)
1189 char* nsap_str
= (char*) str
;
1191 /* just a hex string with optional dots? */
1192 if (str
[0] != '0' || str
[1] != 'x') {
1193 return LDNS_STATUS_INVALID_STR
;
1196 for (i
=0; i
< len
; i
++) {
1197 if (nsap_str
[i
] == '.')
1200 return ldns_str2rdf_hex(rd
, str
+2);
1205 ldns_str2rdf_atma(ldns_rdf
**rd
, const char *str
)
1208 char* atma_str
= (char*) str
;
1211 /* just a hex string with optional dots? */
1213 for (i
=0; i
< len
; i
++) {
1214 if (atma_str
[i
] == '.')
1217 status
= ldns_str2rdf_hex(rd
, str
);
1218 if (status
!= LDNS_STATUS_OK
) {
1219 ; /* probably in e.164 format than */
1225 ldns_str2rdf_ipseckey(ldns_rdf
**rd
, const char *str
)
1227 uint8_t precedence
= 0;
1228 uint8_t gateway_type
= 0;
1229 uint8_t algorithm
= 0;
1230 char* gateway
= NULL
;
1231 char* publickey
= NULL
;
1233 ldns_buffer
*str_buf
;
1235 int token_count
= 0;
1236 int ipseckey_len
= 0;
1237 ldns_rdf
* gateway_rdf
= NULL
;
1238 ldns_rdf
* publickey_rdf
= NULL
;
1239 ldns_status status
= LDNS_STATUS_OK
;
1241 if(strlen(str
) == 0)
1242 token
= LDNS_XMALLOC(char, 256);
1243 else token
= LDNS_XMALLOC(char, strlen(str
)+2);
1244 if(!token
) return LDNS_STATUS_MEM_ERR
;
1246 str_buf
= LDNS_MALLOC(ldns_buffer
);
1247 if(!str_buf
) {LDNS_FREE(token
); return LDNS_STATUS_MEM_ERR
;}
1248 ldns_buffer_new_frm_data(str_buf
, (char *)str
, strlen(str
));
1249 if(ldns_buffer_status(str_buf
) != LDNS_STATUS_OK
) {
1252 return LDNS_STATUS_MEM_ERR
;
1254 while(ldns_bget_token(str_buf
, token
, "\t\n ", strlen(str
)) > 0) {
1255 switch (token_count
) {
1257 precedence
= (uint8_t)atoi(token
);
1260 gateway_type
= (uint8_t)atoi(token
);
1263 algorithm
= (uint8_t)atoi(token
);
1266 gateway
= strdup(token
);
1267 if (!gateway
|| (gateway_type
== 0 &&
1268 (token
[0] != '.' || token
[1] != '\0'))) {
1271 ldns_buffer_free(str_buf
);
1272 return LDNS_STATUS_INVALID_STR
;
1276 publickey
= strdup(token
);
1280 ldns_buffer_free(str_buf
);
1281 return LDNS_STATUS_INVALID_STR
;
1287 if (!gateway
|| !publickey
) {
1291 LDNS_FREE(publickey
);
1293 ldns_buffer_free(str_buf
);
1294 return LDNS_STATUS_INVALID_STR
;
1297 if (gateway_type
== 1) {
1298 status
= ldns_str2rdf_a(&gateway_rdf
, gateway
);
1299 } else if (gateway_type
== 2) {
1300 status
= ldns_str2rdf_aaaa(&gateway_rdf
, gateway
);
1301 } else if (gateway_type
== 3) {
1302 status
= ldns_str2rdf_dname(&gateway_rdf
, gateway
);
1305 if (status
!= LDNS_STATUS_OK
) {
1309 LDNS_FREE(publickey
);
1311 ldns_buffer_free(str_buf
);
1312 return LDNS_STATUS_INVALID_STR
;
1315 status
= ldns_str2rdf_b64(&publickey_rdf
, publickey
);
1317 if (status
!= LDNS_STATUS_OK
) {
1321 LDNS_FREE(publickey
);
1323 ldns_buffer_free(str_buf
);
1324 if (gateway_rdf
) ldns_rdf_free(gateway_rdf
);
1325 return LDNS_STATUS_INVALID_STR
;
1328 /* now copy all into one ipseckey rdf */
1330 ipseckey_len
= 3 + (int)ldns_rdf_size(gateway_rdf
) + (int)ldns_rdf_size(publickey_rdf
);
1332 ipseckey_len
= 3 + (int)ldns_rdf_size(publickey_rdf
);
1334 data
= LDNS_XMALLOC(uint8_t, ipseckey_len
);
1339 LDNS_FREE(publickey
);
1341 ldns_buffer_free(str_buf
);
1342 if (gateway_rdf
) ldns_rdf_free(gateway_rdf
);
1343 if (publickey_rdf
) ldns_rdf_free(publickey_rdf
);
1344 return LDNS_STATUS_MEM_ERR
;
1347 data
[0] = precedence
;
1348 data
[1] = gateway_type
;
1349 data
[2] = algorithm
;
1353 ldns_rdf_data(gateway_rdf
), ldns_rdf_size(gateway_rdf
));
1354 memcpy(data
+ 3 + ldns_rdf_size(gateway_rdf
),
1355 ldns_rdf_data(publickey_rdf
), ldns_rdf_size(publickey_rdf
));
1358 ldns_rdf_data(publickey_rdf
), ldns_rdf_size(publickey_rdf
));
1361 *rd
= ldns_rdf_new_frm_data(LDNS_RDF_TYPE_IPSECKEY
, (uint16_t) ipseckey_len
, data
);
1366 LDNS_FREE(publickey
);
1368 ldns_buffer_free(str_buf
);
1369 ldns_rdf_free(gateway_rdf
);
1370 ldns_rdf_free(publickey_rdf
);
1372 if(!*rd
) return LDNS_STATUS_MEM_ERR
;
1373 return LDNS_STATUS_OK
;
1377 ldns_str2rdf_ilnp64(ldns_rdf
**rd
, const char *str
)
1379 unsigned int a
, b
, c
, d
;
1383 if (sscanf(str
, "%4x:%4x:%4x:%4x%n", &a
, &b
, &c
, &d
, &l
) != 4 ||
1384 l
!= (int)strlen(str
) || /* more data to read */
1385 strpbrk(str
, "+-") /* signed hexes */
1387 return LDNS_STATUS_INVALID_ILNP64
;
1389 shorts
[0] = htons(a
);
1390 shorts
[1] = htons(b
);
1391 shorts
[2] = htons(c
);
1392 shorts
[3] = htons(d
);
1393 *rd
= ldns_rdf_new_frm_data(
1394 LDNS_RDF_TYPE_ILNP64
, 4 * sizeof(uint16_t), &shorts
);
1396 return *rd
? LDNS_STATUS_OK
: LDNS_STATUS_MEM_ERR
;
1400 ldns_str2rdf_eui48(ldns_rdf
**rd
, const char *str
)
1402 unsigned int a
, b
, c
, d
, e
, f
;
1406 if (sscanf(str
, "%2x-%2x-%2x-%2x-%2x-%2x%n",
1407 &a
, &b
, &c
, &d
, &e
, &f
, &l
) != 6 ||
1408 l
!= (int)strlen(str
)) {
1409 return LDNS_STATUS_INVALID_EUI48
;
1417 *rd
= ldns_rdf_new_frm_data(LDNS_RDF_TYPE_EUI48
, 6, &bytes
);
1419 return *rd
? LDNS_STATUS_OK
: LDNS_STATUS_MEM_ERR
;
1423 ldns_str2rdf_eui64(ldns_rdf
**rd
, const char *str
)
1425 unsigned int a
, b
, c
, d
, e
, f
, g
, h
;
1429 if (sscanf(str
, "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x%n",
1430 &a
, &b
, &c
, &d
, &e
, &f
, &g
, &h
, &l
) != 8 ||
1431 l
!= (int)strlen(str
)) {
1432 return LDNS_STATUS_INVALID_EUI64
;
1442 *rd
= ldns_rdf_new_frm_data(LDNS_RDF_TYPE_EUI64
, 8, &bytes
);
1444 return *rd
? LDNS_STATUS_OK
: LDNS_STATUS_MEM_ERR
;
1448 ldns_str2rdf_tag(ldns_rdf
**rd
, const char *str
)
1453 if (strlen(str
) > 255) {
1454 return LDNS_STATUS_INVALID_TAG
;
1456 for (ptr
= str
; *ptr
; ptr
++) {
1457 if (! isalnum((unsigned char)*ptr
)) {
1458 return LDNS_STATUS_INVALID_TAG
;
1461 data
= LDNS_XMALLOC(uint8_t, strlen(str
) + 1);
1463 return LDNS_STATUS_MEM_ERR
;
1465 data
[0] = strlen(str
);
1466 memcpy(data
+ 1, str
, strlen(str
));
1468 *rd
= ldns_rdf_new(LDNS_RDF_TYPE_TAG
, strlen(str
) + 1, data
);
1471 return LDNS_STATUS_MEM_ERR
;
1473 return LDNS_STATUS_OK
;
1477 ldns_str2rdf_long_str(ldns_rdf
**rd
, const char *str
)
1479 uint8_t *data
, *dp
, ch
= 0;
1482 /* Worst case space requirement. We'll realloc to actual size later. */
1483 dp
= data
= LDNS_XMALLOC(uint8_t, strlen(str
));
1485 return LDNS_STATUS_MEM_ERR
;
1488 /* Fill data with parsed bytes */
1489 while (parse_char(&ch
, &str
)) {
1491 if (dp
- data
> LDNS_MAX_RDFLEN
) {
1493 return LDNS_STATUS_INVALID_STR
;
1497 return LDNS_STATUS_SYNTAX_BAD_ESCAPE
;
1499 length
= (size_t)(dp
- data
);
1501 /* Lose the overmeasure */
1502 data
= LDNS_XREALLOC(dp
= data
, uint8_t, length
);
1505 return LDNS_STATUS_MEM_ERR
;
1509 *rd
= ldns_rdf_new(LDNS_RDF_TYPE_LONG_STR
, length
, data
);
1512 return LDNS_STATUS_MEM_ERR
;
1514 return LDNS_STATUS_OK
;
1518 ldns_str2rdf_hip(ldns_rdf
**rd
, const char *str
)
1520 const char *hit
= strchr(str
, ' ') + 1;
1521 const char *pk
= hit
== NULL
? NULL
: strchr(hit
, ' ') + 1;
1522 size_t hit_size
= hit
== NULL
? 0
1523 : pk
== NULL
? strlen(hit
) : (size_t) (pk
- hit
) - 1;
1524 size_t pk_size
= pk
== NULL
? 0 : strlen(pk
);
1525 size_t hit_wire_size
= (hit_size
+ 1) / 2;
1526 size_t pk_wire_size
= ldns_b64_pton_calculate_size(pk_size
);
1527 size_t rdf_size
= 4 + hit_wire_size
+ pk_wire_size
;
1529 char *endptr
; /* utility var for strtol usage */
1530 int algorithm
= strtol(str
, &endptr
, 10);
1533 int hi
, lo
, written
;
1535 if (hit_size
== 0 || pk_size
== 0 || (hit_size
+ 1) / 2 > 255
1536 || rdf_size
> LDNS_MAX_RDFLEN
1537 || algorithm
< 0 || algorithm
> 255
1538 || (errno
!= 0 && algorithm
== 0) /* out of range */
1539 || endptr
== str
/* no digits */) {
1541 return LDNS_STATUS_SYNTAX_ERR
;
1543 if ((data
= LDNS_XMALLOC(uint8_t, rdf_size
)) == NULL
) {
1545 return LDNS_STATUS_MEM_ERR
;
1547 /* From RFC 5205 section 5. HIP RR Storage Format:
1548 *************************************************
1551 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
1552 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1553 | HIT length | PK algorithm | PK length |
1554 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1558 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1560 +-+-+-+-+-+-+-+-+-+-+-+ +
1564 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1566 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
1568 ~ Rendezvous Servers ~
1570 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1574 data
[0] = (uint8_t) hit_wire_size
;
1575 data
[1] = (uint8_t) algorithm
;
1577 for (dp
= data
+ 4; *hit
&& *hit
!= ' '; dp
++) {
1579 if ((hi
= ldns_hexdigit_to_int(*hit
++)) == -1 ||
1580 (lo
= ldns_hexdigit_to_int(*hit
++)) == -1) {
1583 return LDNS_STATUS_INVALID_HEX
;
1585 *dp
= (uint8_t) hi
<< 4 | lo
;
1587 if ((written
= ldns_b64_pton(pk
, dp
, pk_wire_size
)) <= 0) {
1590 return LDNS_STATUS_INVALID_B64
;
1593 /* Because ldns_b64_pton_calculate_size isn't always correct:
1594 * (we have to fix it at some point)
1596 pk_wire_size
= (uint16_t) written
;
1597 ldns_write_uint16(data
+ 2, pk_wire_size
);
1598 rdf_size
= 4 + hit_wire_size
+ pk_wire_size
;
1601 if (! (*rd
= ldns_rdf_new(LDNS_RDF_TYPE_HIP
, rdf_size
, data
))) {
1604 return LDNS_STATUS_MEM_ERR
;
1606 return LDNS_STATUS_OK
;