17b5038d7SDag-Erling Smørgrav /*
27b5038d7SDag-Erling Smørgrav * str2host.c
37b5038d7SDag-Erling Smørgrav *
47b5038d7SDag-Erling Smørgrav * conversion routines from the presentation format
57b5038d7SDag-Erling Smørgrav * to the host format
67b5038d7SDag-Erling Smørgrav *
77b5038d7SDag-Erling Smørgrav * a Net::DNS like library for C
87b5038d7SDag-Erling Smørgrav *
97b5038d7SDag-Erling Smørgrav * (c) NLnet Labs, 2004-2006
107b5038d7SDag-Erling Smørgrav *
117b5038d7SDag-Erling Smørgrav * See the file LICENSE for the license
127b5038d7SDag-Erling Smørgrav */
137b5038d7SDag-Erling Smørgrav #include <ldns/config.h>
147b5038d7SDag-Erling Smørgrav
157b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h>
16*5afab0e5SDag-Erling Smørgrav #include <ldns/internal.h>
177b5038d7SDag-Erling Smørgrav
187b5038d7SDag-Erling Smørgrav #ifdef HAVE_SYS_SOCKET_H
197b5038d7SDag-Erling Smørgrav #include <sys/socket.h>
207b5038d7SDag-Erling Smørgrav #endif
217b5038d7SDag-Erling Smørgrav #ifdef HAVE_ARPA_INET_H
227b5038d7SDag-Erling Smørgrav #include <arpa/inet.h>
237b5038d7SDag-Erling Smørgrav #endif
247b5038d7SDag-Erling Smørgrav #include <time.h>
257b5038d7SDag-Erling Smørgrav
267b5038d7SDag-Erling Smørgrav #include <errno.h>
277b5038d7SDag-Erling Smørgrav #ifdef HAVE_NETDB_H
287b5038d7SDag-Erling Smørgrav #include <netdb.h>
297b5038d7SDag-Erling Smørgrav #endif
307b5038d7SDag-Erling Smørgrav
317b5038d7SDag-Erling Smørgrav #include <limits.h>
327b5038d7SDag-Erling Smørgrav #ifdef HAVE_SYS_PARAM_H
337b5038d7SDag-Erling Smørgrav #include <sys/param.h>
347b5038d7SDag-Erling Smørgrav #endif
357b5038d7SDag-Erling Smørgrav
367b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_int16(ldns_rdf ** rd,const char * shortstr)377b5038d7SDag-Erling Smørgrav ldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr)
387b5038d7SDag-Erling Smørgrav {
397b5038d7SDag-Erling Smørgrav char *end = NULL;
407b5038d7SDag-Erling Smørgrav uint16_t *r;
417b5038d7SDag-Erling Smørgrav r = LDNS_MALLOC(uint16_t);
427b5038d7SDag-Erling Smørgrav if(!r) return LDNS_STATUS_MEM_ERR;
437b5038d7SDag-Erling Smørgrav
447b5038d7SDag-Erling Smørgrav *r = htons((uint16_t)strtol((char *)shortstr, &end, 10));
457b5038d7SDag-Erling Smørgrav
467b5038d7SDag-Erling Smørgrav if(*end != 0) {
477b5038d7SDag-Erling Smørgrav LDNS_FREE(r);
487b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_INT;
497b5038d7SDag-Erling Smørgrav } else {
507b5038d7SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(
517b5038d7SDag-Erling Smørgrav LDNS_RDF_TYPE_INT16, sizeof(uint16_t), r);
527b5038d7SDag-Erling Smørgrav LDNS_FREE(r);
537b5038d7SDag-Erling Smørgrav return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
547b5038d7SDag-Erling Smørgrav }
557b5038d7SDag-Erling Smørgrav }
567b5038d7SDag-Erling Smørgrav
577b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_time(ldns_rdf ** rd,const char * time)587b5038d7SDag-Erling Smørgrav ldns_str2rdf_time(ldns_rdf **rd, const char *time)
597b5038d7SDag-Erling Smørgrav {
607b5038d7SDag-Erling Smørgrav /* convert a time YYYYDDMMHHMMSS to wireformat */
61*5afab0e5SDag-Erling Smørgrav uint32_t *r = NULL;
627b5038d7SDag-Erling Smørgrav struct tm tm;
637b5038d7SDag-Erling Smørgrav uint32_t l;
647b5038d7SDag-Erling Smørgrav char *end;
657b5038d7SDag-Erling Smørgrav
667b5038d7SDag-Erling Smørgrav /* Try to scan the time... */
67*5afab0e5SDag-Erling Smørgrav r = (uint32_t *)LDNS_MALLOC(uint32_t);
687b5038d7SDag-Erling Smørgrav if(!r) return LDNS_STATUS_MEM_ERR;
697b5038d7SDag-Erling Smørgrav
707b5038d7SDag-Erling Smørgrav memset(&tm, 0, sizeof(tm));
717b5038d7SDag-Erling Smørgrav
727b5038d7SDag-Erling Smørgrav if (strlen(time) == 14 &&
737b5038d7SDag-Erling Smørgrav 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
747b5038d7SDag-Erling Smørgrav ) {
757b5038d7SDag-Erling Smørgrav tm.tm_year -= 1900;
767b5038d7SDag-Erling Smørgrav tm.tm_mon--;
777b5038d7SDag-Erling Smørgrav /* Check values */
787b5038d7SDag-Erling Smørgrav if (tm.tm_year < 70) {
797b5038d7SDag-Erling Smørgrav goto bad_format;
807b5038d7SDag-Erling Smørgrav }
817b5038d7SDag-Erling Smørgrav if (tm.tm_mon < 0 || tm.tm_mon > 11) {
827b5038d7SDag-Erling Smørgrav goto bad_format;
837b5038d7SDag-Erling Smørgrav }
847b5038d7SDag-Erling Smørgrav if (tm.tm_mday < 1 || tm.tm_mday > 31) {
857b5038d7SDag-Erling Smørgrav goto bad_format;
867b5038d7SDag-Erling Smørgrav }
877b5038d7SDag-Erling Smørgrav
887b5038d7SDag-Erling Smørgrav if (tm.tm_hour < 0 || tm.tm_hour > 23) {
897b5038d7SDag-Erling Smørgrav goto bad_format;
907b5038d7SDag-Erling Smørgrav }
917b5038d7SDag-Erling Smørgrav
927b5038d7SDag-Erling Smørgrav if (tm.tm_min < 0 || tm.tm_min > 59) {
937b5038d7SDag-Erling Smørgrav goto bad_format;
947b5038d7SDag-Erling Smørgrav }
957b5038d7SDag-Erling Smørgrav
967b5038d7SDag-Erling Smørgrav if (tm.tm_sec < 0 || tm.tm_sec > 59) {
977b5038d7SDag-Erling Smørgrav goto bad_format;
987b5038d7SDag-Erling Smørgrav }
997b5038d7SDag-Erling Smørgrav
1002787e39aSDag-Erling Smørgrav l = htonl(ldns_mktime_from_utc(&tm));
1017b5038d7SDag-Erling Smørgrav memcpy(r, &l, sizeof(uint32_t));
1027b5038d7SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(
1037b5038d7SDag-Erling Smørgrav LDNS_RDF_TYPE_TIME, sizeof(uint32_t), r);
1047b5038d7SDag-Erling Smørgrav LDNS_FREE(r);
1057b5038d7SDag-Erling Smørgrav return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
1067b5038d7SDag-Erling Smørgrav } else {
1077b5038d7SDag-Erling Smørgrav /* handle it as 32 bits timestamp */
1087b5038d7SDag-Erling Smørgrav l = htonl((uint32_t)strtol((char*)time, &end, 10));
1097b5038d7SDag-Erling Smørgrav if(*end != 0) {
1107b5038d7SDag-Erling Smørgrav LDNS_FREE(r);
1117b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR;
1127b5038d7SDag-Erling Smørgrav } else {
1137b5038d7SDag-Erling Smørgrav memcpy(r, &l, sizeof(uint32_t));
1147b5038d7SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(
1157b5038d7SDag-Erling Smørgrav LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r);
1167b5038d7SDag-Erling Smørgrav LDNS_FREE(r);
1177b5038d7SDag-Erling Smørgrav return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
1187b5038d7SDag-Erling Smørgrav }
1197b5038d7SDag-Erling Smørgrav }
1207b5038d7SDag-Erling Smørgrav
1217b5038d7SDag-Erling Smørgrav bad_format:
1227b5038d7SDag-Erling Smørgrav LDNS_FREE(r);
1237b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_TIME;
1247b5038d7SDag-Erling Smørgrav }
1257b5038d7SDag-Erling Smørgrav
1267b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_nsec3_salt(ldns_rdf ** rd,const char * salt_str)1277b5038d7SDag-Erling Smørgrav ldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *salt_str)
1287b5038d7SDag-Erling Smørgrav {
1297b5038d7SDag-Erling Smørgrav uint8_t salt_length;
1307b5038d7SDag-Erling Smørgrav int c;
1317b5038d7SDag-Erling Smørgrav int salt_length_str;
1327b5038d7SDag-Erling Smørgrav
1337b5038d7SDag-Erling Smørgrav uint8_t *salt;
1347b5038d7SDag-Erling Smørgrav uint8_t *data;
1357b5038d7SDag-Erling Smørgrav if(rd == NULL) {
1367b5038d7SDag-Erling Smørgrav return LDNS_STATUS_NULL;
1377b5038d7SDag-Erling Smørgrav }
1387b5038d7SDag-Erling Smørgrav
1397b5038d7SDag-Erling Smørgrav salt_length_str = (int)strlen(salt_str);
1407b5038d7SDag-Erling Smørgrav if (salt_length_str == 1 && salt_str[0] == '-') {
1417b5038d7SDag-Erling Smørgrav salt_length_str = 0;
1427b5038d7SDag-Erling Smørgrav } else if (salt_length_str % 2 != 0) {
1437b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_HEX;
1447b5038d7SDag-Erling Smørgrav }
1457b5038d7SDag-Erling Smørgrav if (salt_length_str > 512) {
1467b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_HEX;
1477b5038d7SDag-Erling Smørgrav }
1487b5038d7SDag-Erling Smørgrav
1497b5038d7SDag-Erling Smørgrav salt = LDNS_XMALLOC(uint8_t, salt_length_str / 2);
1507b5038d7SDag-Erling Smørgrav if(!salt) {
1517b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
1527b5038d7SDag-Erling Smørgrav }
1537b5038d7SDag-Erling Smørgrav for (c = 0; c < salt_length_str; c += 2) {
1547b5038d7SDag-Erling Smørgrav if (isxdigit((int) salt_str[c]) && isxdigit((int) salt_str[c+1])) {
1557b5038d7SDag-Erling Smørgrav salt[c/2] = (uint8_t) ldns_hexdigit_to_int(salt_str[c]) * 16 +
1567b5038d7SDag-Erling Smørgrav ldns_hexdigit_to_int(salt_str[c+1]);
1577b5038d7SDag-Erling Smørgrav } else {
1587b5038d7SDag-Erling Smørgrav LDNS_FREE(salt);
1597b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_HEX;
1607b5038d7SDag-Erling Smørgrav }
1617b5038d7SDag-Erling Smørgrav }
1627b5038d7SDag-Erling Smørgrav salt_length = (uint8_t) (salt_length_str / 2);
1637b5038d7SDag-Erling Smørgrav
1647b5038d7SDag-Erling Smørgrav data = LDNS_XMALLOC(uint8_t, 1 + salt_length);
1657b5038d7SDag-Erling Smørgrav if(!data) {
1667b5038d7SDag-Erling Smørgrav LDNS_FREE(salt);
1677b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
1687b5038d7SDag-Erling Smørgrav }
1697b5038d7SDag-Erling Smørgrav data[0] = salt_length;
1707b5038d7SDag-Erling Smørgrav memcpy(&data[1], salt, salt_length);
1717b5038d7SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT, 1 + salt_length, data);
1727b5038d7SDag-Erling Smørgrav LDNS_FREE(data);
1737b5038d7SDag-Erling Smørgrav LDNS_FREE(salt);
1747b5038d7SDag-Erling Smørgrav
1757b5038d7SDag-Erling Smørgrav return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
1767b5038d7SDag-Erling Smørgrav }
1777b5038d7SDag-Erling Smørgrav
1787b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_period(ldns_rdf ** rd,const char * period)1797b5038d7SDag-Erling Smørgrav ldns_str2rdf_period(ldns_rdf **rd,const char *period)
1807b5038d7SDag-Erling Smørgrav {
1817b5038d7SDag-Erling Smørgrav uint32_t p;
1827b5038d7SDag-Erling Smørgrav const char *end;
1837b5038d7SDag-Erling Smørgrav
1847b5038d7SDag-Erling Smørgrav /* Allocate required space... */
1857b5038d7SDag-Erling Smørgrav p = ldns_str2period(period, &end);
1867b5038d7SDag-Erling Smørgrav
1877b5038d7SDag-Erling Smørgrav if (*end != 0) {
1887b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR;
1897b5038d7SDag-Erling Smørgrav } else {
1907b5038d7SDag-Erling Smørgrav p = (uint32_t) htonl(p);
1917b5038d7SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(
1927b5038d7SDag-Erling Smørgrav LDNS_RDF_TYPE_PERIOD, sizeof(uint32_t), &p);
1937b5038d7SDag-Erling Smørgrav }
1947b5038d7SDag-Erling Smørgrav return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
1957b5038d7SDag-Erling Smørgrav }
1967b5038d7SDag-Erling Smørgrav
1977b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_int32(ldns_rdf ** rd,const char * longstr)1987b5038d7SDag-Erling Smørgrav ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr)
1997b5038d7SDag-Erling Smørgrav {
2007b5038d7SDag-Erling Smørgrav char *end;
201*5afab0e5SDag-Erling Smørgrav uint32_t *r = NULL;
2027b5038d7SDag-Erling Smørgrav uint32_t l;
2037b5038d7SDag-Erling Smørgrav
204*5afab0e5SDag-Erling Smørgrav r = (uint32_t*)LDNS_MALLOC(uint32_t);
2057b5038d7SDag-Erling Smørgrav if(!r) return LDNS_STATUS_MEM_ERR;
2067b5038d7SDag-Erling Smørgrav errno = 0; /* must set to zero before call,
2077b5038d7SDag-Erling Smørgrav note race condition on errno */
2087b5038d7SDag-Erling Smørgrav if(*longstr == '-')
2097b5038d7SDag-Erling Smørgrav l = htonl((uint32_t)strtol((char*)longstr, &end, 10));
2107b5038d7SDag-Erling Smørgrav else l = htonl((uint32_t)strtoul((char*)longstr, &end, 10));
2117b5038d7SDag-Erling Smørgrav
2127b5038d7SDag-Erling Smørgrav if(*end != 0) {
2137b5038d7SDag-Erling Smørgrav LDNS_FREE(r);
2147b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR;
2157b5038d7SDag-Erling Smørgrav } else {
2167b5038d7SDag-Erling Smørgrav if (errno == ERANGE) {
2177b5038d7SDag-Erling Smørgrav LDNS_FREE(r);
2187b5038d7SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW;
2197b5038d7SDag-Erling Smørgrav }
2207b5038d7SDag-Erling Smørgrav memcpy(r, &l, sizeof(uint32_t));
2217b5038d7SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(
2227b5038d7SDag-Erling Smørgrav LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r);
2237b5038d7SDag-Erling Smørgrav LDNS_FREE(r);
2247b5038d7SDag-Erling Smørgrav return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
2257b5038d7SDag-Erling Smørgrav }
2267b5038d7SDag-Erling Smørgrav }
2277b5038d7SDag-Erling Smørgrav
2287b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_int8(ldns_rdf ** rd,const char * bytestr)2297b5038d7SDag-Erling Smørgrav ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr)
2307b5038d7SDag-Erling Smørgrav {
2317b5038d7SDag-Erling Smørgrav char *end;
2327b5038d7SDag-Erling Smørgrav uint8_t *r = NULL;
2337b5038d7SDag-Erling Smørgrav
2347b5038d7SDag-Erling Smørgrav r = LDNS_MALLOC(uint8_t);
2357b5038d7SDag-Erling Smørgrav if(!r) return LDNS_STATUS_MEM_ERR;
2367b5038d7SDag-Erling Smørgrav
2377b5038d7SDag-Erling Smørgrav *r = (uint8_t)strtol((char*)bytestr, &end, 10);
2387b5038d7SDag-Erling Smørgrav
2397b5038d7SDag-Erling Smørgrav if(*end != 0) {
2407b5038d7SDag-Erling Smørgrav LDNS_FREE(r);
2417b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR;
2427b5038d7SDag-Erling Smørgrav } else {
2437b5038d7SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(
2447b5038d7SDag-Erling Smørgrav LDNS_RDF_TYPE_INT8, sizeof(uint8_t), r);
2457b5038d7SDag-Erling Smørgrav LDNS_FREE(r);
2467b5038d7SDag-Erling Smørgrav return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
2477b5038d7SDag-Erling Smørgrav }
2487b5038d7SDag-Erling Smørgrav }
2497b5038d7SDag-Erling Smørgrav
2507b5038d7SDag-Erling Smørgrav
2517b5038d7SDag-Erling Smørgrav /*
252986ba33cSDag-Erling Smørgrav * Checks whether the escaped value at **s is an decimal value or
2537b5038d7SDag-Erling Smørgrav * a 'normally' escaped character (and not eos)
2547b5038d7SDag-Erling Smørgrav *
2557b5038d7SDag-Erling Smørgrav * The string pointer at *s is increased by either 0 (on error), 1 (on
256986ba33cSDag-Erling Smørgrav * normal escapes), or 3 (on decimals)
2577b5038d7SDag-Erling Smørgrav *
2587b5038d7SDag-Erling Smørgrav * Returns the number of bytes read from the escaped string, or
2597b5038d7SDag-Erling Smørgrav * 0 on error
2607b5038d7SDag-Erling Smørgrav */
26117d15b25SDag-Erling Smørgrav INLINE bool
parse_escape(uint8_t * ch_p,const char ** str_p)26217d15b25SDag-Erling Smørgrav parse_escape(uint8_t *ch_p, const char** str_p)
26317d15b25SDag-Erling Smørgrav {
2647b5038d7SDag-Erling Smørgrav uint16_t val;
26517d15b25SDag-Erling Smørgrav
266986ba33cSDag-Erling Smørgrav if ((*str_p)[0] && isdigit((unsigned char)(*str_p)[0]) &&
267986ba33cSDag-Erling Smørgrav (*str_p)[1] && isdigit((unsigned char)(*str_p)[1]) &&
268986ba33cSDag-Erling Smørgrav (*str_p)[2] && isdigit((unsigned char)(*str_p)[2])) {
26917d15b25SDag-Erling Smørgrav
27017d15b25SDag-Erling Smørgrav val = (uint16_t)(((*str_p)[0] - '0') * 100 +
27117d15b25SDag-Erling Smørgrav ((*str_p)[1] - '0') * 10 +
27217d15b25SDag-Erling Smørgrav ((*str_p)[2] - '0'));
27317d15b25SDag-Erling Smørgrav
2747b5038d7SDag-Erling Smørgrav if (val > 255) {
27517d15b25SDag-Erling Smørgrav goto error;
2767b5038d7SDag-Erling Smørgrav }
27717d15b25SDag-Erling Smørgrav *ch_p = (uint8_t)val;
27817d15b25SDag-Erling Smørgrav *str_p += 3;
27917d15b25SDag-Erling Smørgrav return true;
28017d15b25SDag-Erling Smørgrav
281986ba33cSDag-Erling Smørgrav } else if ((*str_p)[0] && !isdigit((unsigned char)(*str_p)[0])) {
28217d15b25SDag-Erling Smørgrav
28317d15b25SDag-Erling Smørgrav *ch_p = (uint8_t)*(*str_p)++;
28417d15b25SDag-Erling Smørgrav return true;
2857b5038d7SDag-Erling Smørgrav }
28617d15b25SDag-Erling Smørgrav error:
28717d15b25SDag-Erling Smørgrav *str_p = NULL;
28817d15b25SDag-Erling Smørgrav return false; /* LDNS_STATUS_SYNTAX_BAD_ESCAPE */
28917d15b25SDag-Erling Smørgrav }
29017d15b25SDag-Erling Smørgrav
29117d15b25SDag-Erling Smørgrav INLINE bool
parse_char(uint8_t * ch_p,const char ** str_p)29217d15b25SDag-Erling Smørgrav parse_char(uint8_t *ch_p, const char** str_p)
29317d15b25SDag-Erling Smørgrav {
29417d15b25SDag-Erling Smørgrav switch (**str_p) {
29517d15b25SDag-Erling Smørgrav
29617d15b25SDag-Erling Smørgrav case '\0': return false;
29717d15b25SDag-Erling Smørgrav
29817d15b25SDag-Erling Smørgrav case '\\': *str_p += 1;
29917d15b25SDag-Erling Smørgrav return parse_escape(ch_p, str_p);
30017d15b25SDag-Erling Smørgrav
30117d15b25SDag-Erling Smørgrav default: *ch_p = (uint8_t)*(*str_p)++;
30217d15b25SDag-Erling Smørgrav return true;
3037b5038d7SDag-Erling Smørgrav }
3047b5038d7SDag-Erling Smørgrav }
3057b5038d7SDag-Erling Smørgrav
3067b5038d7SDag-Erling Smørgrav /*
3077b5038d7SDag-Erling Smørgrav * No special care is taken, all dots are translated into
308*5afab0e5SDag-Erling Smørgrav * label separators.
3097b5038d7SDag-Erling Smørgrav * Could be made more efficient....we do 3 memcpy's in total...
3107b5038d7SDag-Erling Smørgrav */
3117b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_dname(ldns_rdf ** d,const char * str)3127b5038d7SDag-Erling Smørgrav ldns_str2rdf_dname(ldns_rdf **d, const char *str)
3137b5038d7SDag-Erling Smørgrav {
3147b5038d7SDag-Erling Smørgrav size_t len;
3157b5038d7SDag-Erling Smørgrav
31617d15b25SDag-Erling Smørgrav const char *s;
31717d15b25SDag-Erling Smørgrav uint8_t *q, *pq, label_len;
3187b5038d7SDag-Erling Smørgrav uint8_t buf[LDNS_MAX_DOMAINLEN + 1];
3197b5038d7SDag-Erling Smørgrav *d = NULL;
3207b5038d7SDag-Erling Smørgrav
3217b5038d7SDag-Erling Smørgrav len = strlen((char*)str);
3227b5038d7SDag-Erling Smørgrav /* octet representation can make strings a lot longer than actual length */
3237b5038d7SDag-Erling Smørgrav if (len > LDNS_MAX_DOMAINLEN * 4) {
3247b5038d7SDag-Erling Smørgrav return LDNS_STATUS_DOMAINNAME_OVERFLOW;
3257b5038d7SDag-Erling Smørgrav }
3267b5038d7SDag-Erling Smørgrav if (0 == len) {
3277b5038d7SDag-Erling Smørgrav return LDNS_STATUS_DOMAINNAME_UNDERFLOW;
3287b5038d7SDag-Erling Smørgrav }
3297b5038d7SDag-Erling Smørgrav
3307b5038d7SDag-Erling Smørgrav /* root label */
3317b5038d7SDag-Erling Smørgrav if (1 == len && *str == '.') {
3327b5038d7SDag-Erling Smørgrav *d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, 1, "\0");
3337b5038d7SDag-Erling Smørgrav return LDNS_STATUS_OK;
3347b5038d7SDag-Erling Smørgrav }
3357b5038d7SDag-Erling Smørgrav
3367b5038d7SDag-Erling Smørgrav /* get on with the rest */
3377b5038d7SDag-Erling Smørgrav
3387b5038d7SDag-Erling Smørgrav /* s is on the current character in the string
3397b5038d7SDag-Erling Smørgrav * pq points to where the labellength is going to go
3407b5038d7SDag-Erling Smørgrav * label_len keeps track of the current label's length
3417b5038d7SDag-Erling Smørgrav * q builds the dname inside the buf array
3427b5038d7SDag-Erling Smørgrav */
3437b5038d7SDag-Erling Smørgrav len = 0;
3447b5038d7SDag-Erling Smørgrav q = buf+1;
3457b5038d7SDag-Erling Smørgrav pq = buf;
3467b5038d7SDag-Erling Smørgrav label_len = 0;
34717d15b25SDag-Erling Smørgrav for (s = str; *s; s++, q++) {
348*5afab0e5SDag-Erling Smørgrav if (q >= buf + LDNS_MAX_DOMAINLEN) {
3497b5038d7SDag-Erling Smørgrav return LDNS_STATUS_DOMAINNAME_OVERFLOW;
3507b5038d7SDag-Erling Smørgrav }
3517b5038d7SDag-Erling Smørgrav *q = 0;
3527b5038d7SDag-Erling Smørgrav switch (*s) {
3537b5038d7SDag-Erling Smørgrav case '.':
3547b5038d7SDag-Erling Smørgrav if (label_len > LDNS_MAX_LABELLEN) {
3557b5038d7SDag-Erling Smørgrav return LDNS_STATUS_LABEL_OVERFLOW;
3567b5038d7SDag-Erling Smørgrav }
3577b5038d7SDag-Erling Smørgrav if (label_len == 0) {
3587b5038d7SDag-Erling Smørgrav return LDNS_STATUS_EMPTY_LABEL;
3597b5038d7SDag-Erling Smørgrav }
3607b5038d7SDag-Erling Smørgrav len += label_len + 1;
3617b5038d7SDag-Erling Smørgrav *pq = label_len;
3627b5038d7SDag-Erling Smørgrav label_len = 0;
3637b5038d7SDag-Erling Smørgrav pq = q;
3647b5038d7SDag-Erling Smørgrav break;
3657b5038d7SDag-Erling Smørgrav case '\\':
3667b5038d7SDag-Erling Smørgrav /* octet value or literal char */
36717d15b25SDag-Erling Smørgrav s += 1;
36817d15b25SDag-Erling Smørgrav if (! parse_escape(q, &s)) {
3697b5038d7SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
3707b5038d7SDag-Erling Smørgrav }
37117d15b25SDag-Erling Smørgrav s -= 1;
37217d15b25SDag-Erling Smørgrav label_len++;
3737b5038d7SDag-Erling Smørgrav break;
3747b5038d7SDag-Erling Smørgrav default:
37517d15b25SDag-Erling Smørgrav *q = (uint8_t)*s;
3767b5038d7SDag-Erling Smørgrav label_len++;
3777b5038d7SDag-Erling Smørgrav }
3787b5038d7SDag-Erling Smørgrav }
3797b5038d7SDag-Erling Smørgrav
3807b5038d7SDag-Erling Smørgrav /* add root label if last char was not '.' */
3817b5038d7SDag-Erling Smørgrav if (!ldns_dname_str_absolute(str)) {
382*5afab0e5SDag-Erling Smørgrav if (q >= buf + LDNS_MAX_DOMAINLEN) {
3837b5038d7SDag-Erling Smørgrav return LDNS_STATUS_DOMAINNAME_OVERFLOW;
3847b5038d7SDag-Erling Smørgrav }
3857b5038d7SDag-Erling Smørgrav if (label_len > LDNS_MAX_LABELLEN) {
3867b5038d7SDag-Erling Smørgrav return LDNS_STATUS_LABEL_OVERFLOW;
3877b5038d7SDag-Erling Smørgrav }
3887b5038d7SDag-Erling Smørgrav if (label_len == 0) { /* label_len 0 but not . at end? */
3897b5038d7SDag-Erling Smørgrav return LDNS_STATUS_EMPTY_LABEL;
3907b5038d7SDag-Erling Smørgrav }
3917b5038d7SDag-Erling Smørgrav len += label_len + 1;
3927b5038d7SDag-Erling Smørgrav *pq = label_len;
3937b5038d7SDag-Erling Smørgrav *q = 0;
3947b5038d7SDag-Erling Smørgrav }
3957b5038d7SDag-Erling Smørgrav len++;
3967b5038d7SDag-Erling Smørgrav
3977b5038d7SDag-Erling Smørgrav *d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, len, buf);
3987b5038d7SDag-Erling Smørgrav return LDNS_STATUS_OK;
3997b5038d7SDag-Erling Smørgrav }
4007b5038d7SDag-Erling Smørgrav
4017b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_a(ldns_rdf ** rd,const char * str)4027b5038d7SDag-Erling Smørgrav ldns_str2rdf_a(ldns_rdf **rd, const char *str)
4037b5038d7SDag-Erling Smørgrav {
4047b5038d7SDag-Erling Smørgrav in_addr_t address;
4057b5038d7SDag-Erling Smørgrav if (inet_pton(AF_INET, (char*)str, &address) != 1) {
4067b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_IP4;
4077b5038d7SDag-Erling Smørgrav } else {
4087b5038d7SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(
4097b5038d7SDag-Erling Smørgrav LDNS_RDF_TYPE_A, sizeof(address), &address);
4107b5038d7SDag-Erling Smørgrav }
4117b5038d7SDag-Erling Smørgrav return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
4127b5038d7SDag-Erling Smørgrav }
4137b5038d7SDag-Erling Smørgrav
4147b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_aaaa(ldns_rdf ** rd,const char * str)4157b5038d7SDag-Erling Smørgrav ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str)
4167b5038d7SDag-Erling Smørgrav {
4177b5038d7SDag-Erling Smørgrav uint8_t address[LDNS_IP6ADDRLEN + 1];
4187b5038d7SDag-Erling Smørgrav
4197b5038d7SDag-Erling Smørgrav if (inet_pton(AF_INET6, (char*)str, address) != 1) {
4207b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_IP6;
4217b5038d7SDag-Erling Smørgrav } else {
4227b5038d7SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(
4237b5038d7SDag-Erling Smørgrav LDNS_RDF_TYPE_AAAA, sizeof(address) - 1, &address);
4247b5038d7SDag-Erling Smørgrav }
4257b5038d7SDag-Erling Smørgrav return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
4267b5038d7SDag-Erling Smørgrav }
4277b5038d7SDag-Erling Smørgrav
4287b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_str(ldns_rdf ** rd,const char * str)4297b5038d7SDag-Erling Smørgrav ldns_str2rdf_str(ldns_rdf **rd, const char *str)
4307b5038d7SDag-Erling Smørgrav {
43117d15b25SDag-Erling Smørgrav uint8_t *data, *dp, ch = 0;
43217d15b25SDag-Erling Smørgrav size_t length;
4337b5038d7SDag-Erling Smørgrav
43417d15b25SDag-Erling Smørgrav /* Worst case space requirement. We'll realloc to actual size later. */
43517d15b25SDag-Erling Smørgrav dp = data = LDNS_XMALLOC(uint8_t, strlen(str) > 255 ? 256 : (strlen(str) + 1));
43617d15b25SDag-Erling Smørgrav if (! data) {
43717d15b25SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
43817d15b25SDag-Erling Smørgrav }
43917d15b25SDag-Erling Smørgrav
44017d15b25SDag-Erling Smørgrav /* Fill data (up to 255 characters) */
44117d15b25SDag-Erling Smørgrav while (parse_char(&ch, &str)) {
44217d15b25SDag-Erling Smørgrav if (dp - data >= 255) {
44317d15b25SDag-Erling Smørgrav LDNS_FREE(data);
4447b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
4457b5038d7SDag-Erling Smørgrav }
44617d15b25SDag-Erling Smørgrav *++dp = ch;
44717d15b25SDag-Erling Smørgrav }
44817d15b25SDag-Erling Smørgrav if (! str) {
449*5afab0e5SDag-Erling Smørgrav LDNS_FREE(data);
4507b5038d7SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
4517b5038d7SDag-Erling Smørgrav }
45217d15b25SDag-Erling Smørgrav length = (size_t)(dp - data);
45317d15b25SDag-Erling Smørgrav /* Fix last length byte */
45417d15b25SDag-Erling Smørgrav data[0] = (uint8_t)length;
4557b5038d7SDag-Erling Smørgrav
45617d15b25SDag-Erling Smørgrav /* Lose the overmeasure */
45717d15b25SDag-Erling Smørgrav data = LDNS_XREALLOC(dp = data, uint8_t, length + 1);
45817d15b25SDag-Erling Smørgrav if (! data) {
45917d15b25SDag-Erling Smørgrav LDNS_FREE(dp);
46017d15b25SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
46117d15b25SDag-Erling Smørgrav }
46217d15b25SDag-Erling Smørgrav
46317d15b25SDag-Erling Smørgrav /* Create rdf */
46417d15b25SDag-Erling Smørgrav *rd = ldns_rdf_new(LDNS_RDF_TYPE_STR, length + 1, data);
46517d15b25SDag-Erling Smørgrav if (! *rd) {
4667b5038d7SDag-Erling Smørgrav LDNS_FREE(data);
46717d15b25SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
46817d15b25SDag-Erling Smørgrav }
46917d15b25SDag-Erling Smørgrav return LDNS_STATUS_OK;
4707b5038d7SDag-Erling Smørgrav }
4717b5038d7SDag-Erling Smørgrav
4727b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_apl(ldns_rdf ** rd,const char * str)4737b5038d7SDag-Erling Smørgrav ldns_str2rdf_apl(ldns_rdf **rd, const char *str)
4747b5038d7SDag-Erling Smørgrav {
4757b5038d7SDag-Erling Smørgrav const char *my_str = str;
4767b5038d7SDag-Erling Smørgrav
4777b5038d7SDag-Erling Smørgrav char *my_ip_str;
4787b5038d7SDag-Erling Smørgrav size_t ip_str_len;
4797b5038d7SDag-Erling Smørgrav
4807b5038d7SDag-Erling Smørgrav uint16_t family;
4817b5038d7SDag-Erling Smørgrav bool negation;
4827b5038d7SDag-Erling Smørgrav uint8_t afdlength = 0;
4837b5038d7SDag-Erling Smørgrav uint8_t *afdpart;
4847b5038d7SDag-Erling Smørgrav uint8_t prefix;
4857b5038d7SDag-Erling Smørgrav
4867b5038d7SDag-Erling Smørgrav uint8_t *data;
4877b5038d7SDag-Erling Smørgrav
4887b5038d7SDag-Erling Smørgrav size_t i = 0;
4897b5038d7SDag-Erling Smørgrav
4907b5038d7SDag-Erling Smørgrav /* [!]afi:address/prefix */
4917b5038d7SDag-Erling Smørgrav if (strlen(my_str) < 2
4927b5038d7SDag-Erling Smørgrav || strchr(my_str, ':') == NULL
4937b5038d7SDag-Erling Smørgrav || strchr(my_str, '/') == NULL
4947b5038d7SDag-Erling Smørgrav || strchr(my_str, ':') > strchr(my_str, '/')) {
4957b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
4967b5038d7SDag-Erling Smørgrav }
4977b5038d7SDag-Erling Smørgrav
4987b5038d7SDag-Erling Smørgrav if (my_str[0] == '!') {
4997b5038d7SDag-Erling Smørgrav negation = true;
5007b5038d7SDag-Erling Smørgrav my_str += 1;
5017b5038d7SDag-Erling Smørgrav } else {
5027b5038d7SDag-Erling Smørgrav negation = false;
5037b5038d7SDag-Erling Smørgrav }
5047b5038d7SDag-Erling Smørgrav
5057b5038d7SDag-Erling Smørgrav family = (uint16_t) atoi(my_str);
5067b5038d7SDag-Erling Smørgrav
5077b5038d7SDag-Erling Smørgrav my_str = strchr(my_str, ':') + 1;
5087b5038d7SDag-Erling Smørgrav
5097b5038d7SDag-Erling Smørgrav /* need ip addr and only ip addr for inet_pton */
5107b5038d7SDag-Erling Smørgrav ip_str_len = (size_t) (strchr(my_str, '/') - my_str);
5117b5038d7SDag-Erling Smørgrav my_ip_str = LDNS_XMALLOC(char, ip_str_len + 1);
5127b5038d7SDag-Erling Smørgrav if(!my_ip_str) return LDNS_STATUS_MEM_ERR;
5137b5038d7SDag-Erling Smørgrav strncpy(my_ip_str, my_str, ip_str_len + 1);
5147b5038d7SDag-Erling Smørgrav my_ip_str[ip_str_len] = '\0';
5157b5038d7SDag-Erling Smørgrav
5167b5038d7SDag-Erling Smørgrav if (family == 1) {
5177b5038d7SDag-Erling Smørgrav /* ipv4 */
5187b5038d7SDag-Erling Smørgrav afdpart = LDNS_XMALLOC(uint8_t, 4);
5197b5038d7SDag-Erling Smørgrav if(!afdpart) {
5207b5038d7SDag-Erling Smørgrav LDNS_FREE(my_ip_str);
5217b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
5227b5038d7SDag-Erling Smørgrav }
5237b5038d7SDag-Erling Smørgrav if (inet_pton(AF_INET, my_ip_str, afdpart) == 0) {
5247b5038d7SDag-Erling Smørgrav LDNS_FREE(my_ip_str);
5257b5038d7SDag-Erling Smørgrav LDNS_FREE(afdpart);
5267b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
5277b5038d7SDag-Erling Smørgrav }
5287b5038d7SDag-Erling Smørgrav for (i = 0; i < 4; i++) {
5297b5038d7SDag-Erling Smørgrav if (afdpart[i] != 0) {
5307b5038d7SDag-Erling Smørgrav afdlength = i + 1;
5317b5038d7SDag-Erling Smørgrav }
5327b5038d7SDag-Erling Smørgrav }
5337b5038d7SDag-Erling Smørgrav } else if (family == 2) {
5347b5038d7SDag-Erling Smørgrav /* ipv6 */
5357b5038d7SDag-Erling Smørgrav afdpart = LDNS_XMALLOC(uint8_t, 16);
5367b5038d7SDag-Erling Smørgrav if(!afdpart) {
5377b5038d7SDag-Erling Smørgrav LDNS_FREE(my_ip_str);
5387b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
5397b5038d7SDag-Erling Smørgrav }
5407b5038d7SDag-Erling Smørgrav if (inet_pton(AF_INET6, my_ip_str, afdpart) == 0) {
5417b5038d7SDag-Erling Smørgrav LDNS_FREE(my_ip_str);
5427b5038d7SDag-Erling Smørgrav LDNS_FREE(afdpart);
5437b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
5447b5038d7SDag-Erling Smørgrav }
5457b5038d7SDag-Erling Smørgrav for (i = 0; i < 16; i++) {
5467b5038d7SDag-Erling Smørgrav if (afdpart[i] != 0) {
5477b5038d7SDag-Erling Smørgrav afdlength = i + 1;
5487b5038d7SDag-Erling Smørgrav }
5497b5038d7SDag-Erling Smørgrav }
5507b5038d7SDag-Erling Smørgrav } else {
5517b5038d7SDag-Erling Smørgrav /* unknown family */
5527b5038d7SDag-Erling Smørgrav LDNS_FREE(my_ip_str);
5537b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
5547b5038d7SDag-Erling Smørgrav }
5557b5038d7SDag-Erling Smørgrav
5567b5038d7SDag-Erling Smørgrav my_str = strchr(my_str, '/') + 1;
5577b5038d7SDag-Erling Smørgrav prefix = (uint8_t) atoi(my_str);
5587b5038d7SDag-Erling Smørgrav
5597b5038d7SDag-Erling Smørgrav data = LDNS_XMALLOC(uint8_t, 4 + afdlength);
5607b5038d7SDag-Erling Smørgrav if(!data) {
5612787e39aSDag-Erling Smørgrav LDNS_FREE(afdpart);
5627b5038d7SDag-Erling Smørgrav LDNS_FREE(my_ip_str);
5637b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
5647b5038d7SDag-Erling Smørgrav }
5657b5038d7SDag-Erling Smørgrav ldns_write_uint16(data, family);
5667b5038d7SDag-Erling Smørgrav data[2] = prefix;
5677b5038d7SDag-Erling Smørgrav data[3] = afdlength;
5687b5038d7SDag-Erling Smørgrav if (negation) {
5697b5038d7SDag-Erling Smørgrav /* set bit 1 of byte 3 */
5707b5038d7SDag-Erling Smørgrav data[3] = data[3] | 0x80;
5717b5038d7SDag-Erling Smørgrav }
5727b5038d7SDag-Erling Smørgrav
5737b5038d7SDag-Erling Smørgrav memcpy(data + 4, afdpart, afdlength);
5747b5038d7SDag-Erling Smørgrav
5757b5038d7SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_APL, afdlength + 4, data);
5767b5038d7SDag-Erling Smørgrav LDNS_FREE(afdpart);
5777b5038d7SDag-Erling Smørgrav LDNS_FREE(data);
5787b5038d7SDag-Erling Smørgrav LDNS_FREE(my_ip_str);
5797b5038d7SDag-Erling Smørgrav
5807b5038d7SDag-Erling Smørgrav return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
5817b5038d7SDag-Erling Smørgrav }
5827b5038d7SDag-Erling Smørgrav
5837b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_b64(ldns_rdf ** rd,const char * str)5847b5038d7SDag-Erling Smørgrav ldns_str2rdf_b64(ldns_rdf **rd, const char *str)
5857b5038d7SDag-Erling Smørgrav {
5867b5038d7SDag-Erling Smørgrav uint8_t *buffer;
5877b5038d7SDag-Erling Smørgrav int16_t i;
5887b5038d7SDag-Erling Smørgrav
589*5afab0e5SDag-Erling Smørgrav if ((*str == '-' || *str == '0') && str[1] == '\0') {
590*5afab0e5SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, 0, NULL);
591*5afab0e5SDag-Erling Smørgrav return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
592*5afab0e5SDag-Erling Smørgrav }
593*5afab0e5SDag-Erling Smørgrav
5947b5038d7SDag-Erling Smørgrav buffer = LDNS_XMALLOC(uint8_t, ldns_b64_ntop_calculate_size(strlen(str)));
5957b5038d7SDag-Erling Smørgrav if(!buffer) {
5967b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
5977b5038d7SDag-Erling Smørgrav }
5987b5038d7SDag-Erling Smørgrav
5997b5038d7SDag-Erling Smørgrav i = (uint16_t)ldns_b64_pton((const char*)str, buffer,
6007b5038d7SDag-Erling Smørgrav ldns_b64_ntop_calculate_size(strlen(str)));
6017b5038d7SDag-Erling Smørgrav if (-1 == i) {
6027b5038d7SDag-Erling Smørgrav LDNS_FREE(buffer);
6037b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_B64;
6047b5038d7SDag-Erling Smørgrav } else {
6057b5038d7SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(
6067b5038d7SDag-Erling Smørgrav LDNS_RDF_TYPE_B64, (uint16_t) i, buffer);
6077b5038d7SDag-Erling Smørgrav }
6087b5038d7SDag-Erling Smørgrav LDNS_FREE(buffer);
6097b5038d7SDag-Erling Smørgrav
6107b5038d7SDag-Erling Smørgrav return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
6117b5038d7SDag-Erling Smørgrav }
6127b5038d7SDag-Erling Smørgrav
6137b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_b32_ext(ldns_rdf ** rd,const char * str)6147b5038d7SDag-Erling Smørgrav ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str)
6157b5038d7SDag-Erling Smørgrav {
6167b5038d7SDag-Erling Smørgrav uint8_t *buffer;
6177b5038d7SDag-Erling Smørgrav int i;
6187b5038d7SDag-Erling Smørgrav /* first byte contains length of actual b32 data */
619*5afab0e5SDag-Erling Smørgrav size_t slen = strlen(str);
620*5afab0e5SDag-Erling Smørgrav size_t len = ldns_b32_pton_calculate_size(slen);
621*5afab0e5SDag-Erling Smørgrav if (len > 255) {
622*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_INVALID_B32_EXT;
623*5afab0e5SDag-Erling Smørgrav }
6247b5038d7SDag-Erling Smørgrav buffer = LDNS_XMALLOC(uint8_t, len + 1);
6257b5038d7SDag-Erling Smørgrav if(!buffer) {
6267b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
6277b5038d7SDag-Erling Smørgrav }
6287b5038d7SDag-Erling Smørgrav buffer[0] = len;
6297b5038d7SDag-Erling Smørgrav
630*5afab0e5SDag-Erling Smørgrav i = ldns_b32_pton_extended_hex((const char*)str, slen, buffer + 1,
631*5afab0e5SDag-Erling Smørgrav ldns_b32_ntop_calculate_size(slen));
6327b5038d7SDag-Erling Smørgrav if (i < 0) {
6337b5038d7SDag-Erling Smørgrav LDNS_FREE(buffer);
6347b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_B32_EXT;
6357b5038d7SDag-Erling Smørgrav } else {
6367b5038d7SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(
6377b5038d7SDag-Erling Smørgrav LDNS_RDF_TYPE_B32_EXT, (uint16_t) i + 1, buffer);
6387b5038d7SDag-Erling Smørgrav }
6397b5038d7SDag-Erling Smørgrav LDNS_FREE(buffer);
6407b5038d7SDag-Erling Smørgrav
6417b5038d7SDag-Erling Smørgrav return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
6427b5038d7SDag-Erling Smørgrav }
6437b5038d7SDag-Erling Smørgrav
6447b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_hex(ldns_rdf ** rd,const char * str)6457b5038d7SDag-Erling Smørgrav ldns_str2rdf_hex(ldns_rdf **rd, const char *str)
6467b5038d7SDag-Erling Smørgrav {
6477b5038d7SDag-Erling Smørgrav uint8_t *t, *t_orig;
6487b5038d7SDag-Erling Smørgrav int i;
6497b5038d7SDag-Erling Smørgrav size_t len;
6507b5038d7SDag-Erling Smørgrav
6517b5038d7SDag-Erling Smørgrav len = strlen(str);
6527b5038d7SDag-Erling Smørgrav
6537b5038d7SDag-Erling Smørgrav if (len > LDNS_MAX_RDFLEN * 2) {
6547b5038d7SDag-Erling Smørgrav return LDNS_STATUS_LABEL_OVERFLOW;
6557b5038d7SDag-Erling Smørgrav } else {
6567b5038d7SDag-Erling Smørgrav t = LDNS_XMALLOC(uint8_t, (len / 2) + 1);
6577b5038d7SDag-Erling Smørgrav if(!t) {
6587b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
6597b5038d7SDag-Erling Smørgrav }
6607b5038d7SDag-Erling Smørgrav t_orig = t;
6617b5038d7SDag-Erling Smørgrav /* Now process octet by octet... */
6627b5038d7SDag-Erling Smørgrav while (*str) {
6637b5038d7SDag-Erling Smørgrav *t = 0;
6647b5038d7SDag-Erling Smørgrav if (isspace((int) *str)) {
6657b5038d7SDag-Erling Smørgrav str++;
6667b5038d7SDag-Erling Smørgrav } else {
6677b5038d7SDag-Erling Smørgrav for (i = 16; i >= 1; i -= 15) {
6687b5038d7SDag-Erling Smørgrav while (*str && isspace((int) *str)) { str++; }
6697b5038d7SDag-Erling Smørgrav if (*str) {
6707b5038d7SDag-Erling Smørgrav if (isxdigit((int) *str)) {
6717b5038d7SDag-Erling Smørgrav *t += ldns_hexdigit_to_int(*str) * i;
6727b5038d7SDag-Erling Smørgrav } else {
6737b5038d7SDag-Erling Smørgrav LDNS_FREE(t_orig);
6747b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR;
6757b5038d7SDag-Erling Smørgrav }
6767b5038d7SDag-Erling Smørgrav ++str;
6777b5038d7SDag-Erling Smørgrav }
6787b5038d7SDag-Erling Smørgrav }
6797b5038d7SDag-Erling Smørgrav ++t;
6807b5038d7SDag-Erling Smørgrav }
6817b5038d7SDag-Erling Smørgrav }
6827b5038d7SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX,
6837b5038d7SDag-Erling Smørgrav (size_t) (t - t_orig),
6847b5038d7SDag-Erling Smørgrav t_orig);
6857b5038d7SDag-Erling Smørgrav LDNS_FREE(t_orig);
6867b5038d7SDag-Erling Smørgrav }
6877b5038d7SDag-Erling Smørgrav return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
6887b5038d7SDag-Erling Smørgrav }
6897b5038d7SDag-Erling Smørgrav
6907b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_nsec(ldns_rdf ** rd,const char * str)6917b5038d7SDag-Erling Smørgrav ldns_str2rdf_nsec(ldns_rdf **rd, const char *str)
6927b5038d7SDag-Erling Smørgrav {
6937b5038d7SDag-Erling Smørgrav const char *delimiters = "\n\t ";
6947b5038d7SDag-Erling Smørgrav char *token = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN);
6957b5038d7SDag-Erling Smørgrav ldns_buffer *str_buf;
6967b5038d7SDag-Erling Smørgrav ssize_t c;
6977b5038d7SDag-Erling Smørgrav uint16_t cur_type;
6987b5038d7SDag-Erling Smørgrav size_t type_count = 0;
6997b5038d7SDag-Erling Smørgrav ldns_rr_type type_list[65536];
7007b5038d7SDag-Erling Smørgrav if(!token) return LDNS_STATUS_MEM_ERR;
7017b5038d7SDag-Erling Smørgrav if(rd == NULL) {
7027b5038d7SDag-Erling Smørgrav LDNS_FREE(token);
7037b5038d7SDag-Erling Smørgrav return LDNS_STATUS_NULL;
7047b5038d7SDag-Erling Smørgrav }
7057b5038d7SDag-Erling Smørgrav
7067b5038d7SDag-Erling Smørgrav str_buf = LDNS_MALLOC(ldns_buffer);
7077b5038d7SDag-Erling Smørgrav if(!str_buf) {
7087b5038d7SDag-Erling Smørgrav LDNS_FREE(token);
7097b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
7107b5038d7SDag-Erling Smørgrav }
7117b5038d7SDag-Erling Smørgrav ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
7127b5038d7SDag-Erling Smørgrav if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) {
7137b5038d7SDag-Erling Smørgrav LDNS_FREE(str_buf);
7147b5038d7SDag-Erling Smørgrav LDNS_FREE(token);
7157b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
7167b5038d7SDag-Erling Smørgrav }
7177b5038d7SDag-Erling Smørgrav
7187b5038d7SDag-Erling Smørgrav while ((c = ldns_bget_token(str_buf, token, delimiters, LDNS_MAX_RDFLEN)) != -1 && c != 0) {
7197b5038d7SDag-Erling Smørgrav if(type_count >= sizeof(type_list)) {
7207b5038d7SDag-Erling Smørgrav LDNS_FREE(str_buf);
7217b5038d7SDag-Erling Smørgrav LDNS_FREE(token);
7227b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR;
7237b5038d7SDag-Erling Smørgrav }
7247b5038d7SDag-Erling Smørgrav cur_type = ldns_get_rr_type_by_name(token);
7257b5038d7SDag-Erling Smørgrav type_list[type_count] = cur_type;
7267b5038d7SDag-Erling Smørgrav type_count++;
7277b5038d7SDag-Erling Smørgrav }
7287b5038d7SDag-Erling Smørgrav
7297b5038d7SDag-Erling Smørgrav *rd = ldns_dnssec_create_nsec_bitmap(type_list,
7307b5038d7SDag-Erling Smørgrav type_count,
7317b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_NSEC);
7327b5038d7SDag-Erling Smørgrav
7337b5038d7SDag-Erling Smørgrav LDNS_FREE(token);
7347b5038d7SDag-Erling Smørgrav ldns_buffer_free(str_buf);
7357b5038d7SDag-Erling Smørgrav return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
7367b5038d7SDag-Erling Smørgrav }
7377b5038d7SDag-Erling Smørgrav
7387b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_type(ldns_rdf ** rd,const char * str)7397b5038d7SDag-Erling Smørgrav ldns_str2rdf_type(ldns_rdf **rd, const char *str)
7407b5038d7SDag-Erling Smørgrav {
7417b5038d7SDag-Erling Smørgrav uint16_t type;
7427b5038d7SDag-Erling Smørgrav type = htons(ldns_get_rr_type_by_name(str));
7437b5038d7SDag-Erling Smørgrav /* ldns_rr_type is a 16 bit value */
7447b5038d7SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(
7457b5038d7SDag-Erling Smørgrav LDNS_RDF_TYPE_TYPE, sizeof(uint16_t), &type);
7467b5038d7SDag-Erling Smørgrav return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
7477b5038d7SDag-Erling Smørgrav }
7487b5038d7SDag-Erling Smørgrav
7497b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_class(ldns_rdf ** rd,const char * str)7507b5038d7SDag-Erling Smørgrav ldns_str2rdf_class(ldns_rdf **rd, const char *str)
7517b5038d7SDag-Erling Smørgrav {
7527b5038d7SDag-Erling Smørgrav uint16_t klass;
7537b5038d7SDag-Erling Smørgrav klass = htons(ldns_get_rr_class_by_name(str));
7547b5038d7SDag-Erling Smørgrav /* class is 16 bit */
7557b5038d7SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(
7567b5038d7SDag-Erling Smørgrav LDNS_RDF_TYPE_CLASS, sizeof(uint16_t), &klass);
7577b5038d7SDag-Erling Smørgrav return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
7587b5038d7SDag-Erling Smørgrav }
7597b5038d7SDag-Erling Smørgrav
7607b5038d7SDag-Erling Smørgrav /* An certificate alg field can either be specified as a 8 bits number
7617b5038d7SDag-Erling Smørgrav * or by its symbolic name. Handle both
7627b5038d7SDag-Erling Smørgrav */
7637b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_cert_alg(ldns_rdf ** rd,const char * str)7647b5038d7SDag-Erling Smørgrav ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str)
7657b5038d7SDag-Erling Smørgrav {
7667b5038d7SDag-Erling Smørgrav ldns_lookup_table *lt;
7677b5038d7SDag-Erling Smørgrav ldns_status st;
7687b5038d7SDag-Erling Smørgrav uint8_t idd[2];
7697b5038d7SDag-Erling Smørgrav lt = ldns_lookup_by_name(ldns_cert_algorithms, str);
7707b5038d7SDag-Erling Smørgrav st = LDNS_STATUS_OK;
7717b5038d7SDag-Erling Smørgrav
7727b5038d7SDag-Erling Smørgrav if (lt) {
7737b5038d7SDag-Erling Smørgrav ldns_write_uint16(idd, (uint16_t) lt->id);
7747b5038d7SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(
7757b5038d7SDag-Erling Smørgrav LDNS_RDF_TYPE_INT16, sizeof(uint16_t), idd);
7767b5038d7SDag-Erling Smørgrav if (!*rd) {
7777b5038d7SDag-Erling Smørgrav st = LDNS_STATUS_ERR;
7787b5038d7SDag-Erling Smørgrav }
7797b5038d7SDag-Erling Smørgrav } else {
7807b5038d7SDag-Erling Smørgrav /* try as-is (a number) */
7817b5038d7SDag-Erling Smørgrav st = ldns_str2rdf_int16(rd, str);
7827b5038d7SDag-Erling Smørgrav if (st == LDNS_STATUS_OK &&
7837b5038d7SDag-Erling Smørgrav ldns_rdf2native_int16(*rd) == 0) {
7847b5038d7SDag-Erling Smørgrav st = LDNS_STATUS_CERT_BAD_ALGORITHM;
7857b5038d7SDag-Erling Smørgrav }
7867b5038d7SDag-Erling Smørgrav }
7877b5038d7SDag-Erling Smørgrav
7887b5038d7SDag-Erling Smørgrav return st;
7897b5038d7SDag-Erling Smørgrav }
7907b5038d7SDag-Erling Smørgrav
791986ba33cSDag-Erling Smørgrav static ldns_lookup_table ldns_tlsa_certificate_usages[] = {
792986ba33cSDag-Erling Smørgrav { LDNS_TLSA_USAGE_PKIX_TA , "PKIX-TA" },
793986ba33cSDag-Erling Smørgrav { LDNS_TLSA_USAGE_PKIX_EE , "PKIX-EE" },
794986ba33cSDag-Erling Smørgrav { LDNS_TLSA_USAGE_DANE_TA , "DANE-TA" },
795986ba33cSDag-Erling Smørgrav { LDNS_TLSA_USAGE_DANE_EE , "DANE-EE" },
796986ba33cSDag-Erling Smørgrav { LDNS_TLSA_USAGE_PRIVCERT , "PrivCert" },
797986ba33cSDag-Erling Smørgrav { 0, NULL }
798986ba33cSDag-Erling Smørgrav };
799986ba33cSDag-Erling Smørgrav
800986ba33cSDag-Erling Smørgrav static ldns_lookup_table ldns_tlsa_selectors[] = {
801986ba33cSDag-Erling Smørgrav { LDNS_TLSA_SELECTOR_CERT , "Cert" },
802986ba33cSDag-Erling Smørgrav { LDNS_TLSA_SELECTOR_SPKI , "SPKI" },
803986ba33cSDag-Erling Smørgrav { LDNS_TLSA_SELECTOR_PRIVSEL , "PrivSel" },
804986ba33cSDag-Erling Smørgrav { 0, NULL }
805986ba33cSDag-Erling Smørgrav };
806986ba33cSDag-Erling Smørgrav
807986ba33cSDag-Erling Smørgrav static ldns_lookup_table ldns_tlsa_matching_types[] = {
808986ba33cSDag-Erling Smørgrav { LDNS_TLSA_MATCHING_TYPE_FULL , "Full" },
809986ba33cSDag-Erling Smørgrav { LDNS_TLSA_MATCHING_TYPE_SHA2_256 , "SHA2-256" },
810986ba33cSDag-Erling Smørgrav { LDNS_TLSA_MATCHING_TYPE_SHA2_512 , "SHA2-512" },
811986ba33cSDag-Erling Smørgrav { LDNS_TLSA_MATCHING_TYPE_PRIVMATCH , "PrivMatch" },
812986ba33cSDag-Erling Smørgrav { 0, NULL }
813986ba33cSDag-Erling Smørgrav };
814986ba33cSDag-Erling Smørgrav
815986ba33cSDag-Erling Smørgrav static ldns_status
ldns_str2rdf_mnemonic4int8(ldns_lookup_table * lt,ldns_rdf ** rd,const char * str)816986ba33cSDag-Erling Smørgrav ldns_str2rdf_mnemonic4int8(ldns_lookup_table *lt,
817986ba33cSDag-Erling Smørgrav ldns_rdf **rd, const char *str)
818986ba33cSDag-Erling Smørgrav {
819986ba33cSDag-Erling Smørgrav if ((lt = ldns_lookup_by_name(lt, str))) {
820986ba33cSDag-Erling Smørgrav /* it was given as a integer */
821986ba33cSDag-Erling Smørgrav *rd = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t) lt->id);
822986ba33cSDag-Erling Smørgrav if (!*rd)
823986ba33cSDag-Erling Smørgrav return LDNS_STATUS_ERR;
824986ba33cSDag-Erling Smørgrav else
825986ba33cSDag-Erling Smørgrav return LDNS_STATUS_OK;
826986ba33cSDag-Erling Smørgrav }
827986ba33cSDag-Erling Smørgrav return ldns_str2rdf_int8(rd, str);
828986ba33cSDag-Erling Smørgrav }
829986ba33cSDag-Erling Smørgrav
8307b5038d7SDag-Erling Smørgrav /* An alg field can either be specified as a 8 bits number
8317b5038d7SDag-Erling Smørgrav * or by its symbolic name. Handle both
8327b5038d7SDag-Erling Smørgrav */
8337b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_alg(ldns_rdf ** rd,const char * str)8347b5038d7SDag-Erling Smørgrav ldns_str2rdf_alg(ldns_rdf **rd, const char *str)
8357b5038d7SDag-Erling Smørgrav {
836986ba33cSDag-Erling Smørgrav return ldns_str2rdf_mnemonic4int8(ldns_algorithms, rd, str);
8377b5038d7SDag-Erling Smørgrav }
838986ba33cSDag-Erling Smørgrav
839986ba33cSDag-Erling Smørgrav ldns_status
ldns_str2rdf_certificate_usage(ldns_rdf ** rd,const char * str)840986ba33cSDag-Erling Smørgrav ldns_str2rdf_certificate_usage(ldns_rdf **rd, const char *str)
841986ba33cSDag-Erling Smørgrav {
842986ba33cSDag-Erling Smørgrav return ldns_str2rdf_mnemonic4int8(
843986ba33cSDag-Erling Smørgrav ldns_tlsa_certificate_usages, rd, str);
8447b5038d7SDag-Erling Smørgrav }
845986ba33cSDag-Erling Smørgrav
846986ba33cSDag-Erling Smørgrav ldns_status
ldns_str2rdf_selector(ldns_rdf ** rd,const char * str)847986ba33cSDag-Erling Smørgrav ldns_str2rdf_selector(ldns_rdf **rd, const char *str)
848986ba33cSDag-Erling Smørgrav {
849986ba33cSDag-Erling Smørgrav return ldns_str2rdf_mnemonic4int8(ldns_tlsa_selectors, rd, str);
850986ba33cSDag-Erling Smørgrav }
851986ba33cSDag-Erling Smørgrav
852986ba33cSDag-Erling Smørgrav ldns_status
ldns_str2rdf_matching_type(ldns_rdf ** rd,const char * str)853986ba33cSDag-Erling Smørgrav ldns_str2rdf_matching_type(ldns_rdf **rd, const char *str)
854986ba33cSDag-Erling Smørgrav {
855986ba33cSDag-Erling Smørgrav return ldns_str2rdf_mnemonic4int8(ldns_tlsa_matching_types, rd, str);
8567b5038d7SDag-Erling Smørgrav }
8577b5038d7SDag-Erling Smørgrav
8587b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_unknown(ATTR_UNUSED (ldns_rdf ** rd),ATTR_UNUSED (const char * str))8597b5038d7SDag-Erling Smørgrav ldns_str2rdf_unknown( ATTR_UNUSED(ldns_rdf **rd)
8607b5038d7SDag-Erling Smørgrav , ATTR_UNUSED(const char *str)
8617b5038d7SDag-Erling Smørgrav )
8627b5038d7SDag-Erling Smørgrav {
8637b5038d7SDag-Erling Smørgrav /* this should be caught in an earlier time (general str2host for
8647b5038d7SDag-Erling Smørgrav rr's */
8657b5038d7SDag-Erling Smørgrav return LDNS_STATUS_NOT_IMPL;
8667b5038d7SDag-Erling Smørgrav }
8677b5038d7SDag-Erling Smørgrav
8687b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_service(ATTR_UNUSED (ldns_rdf ** rd),ATTR_UNUSED (const char * str))8697b5038d7SDag-Erling Smørgrav ldns_str2rdf_service( ATTR_UNUSED(ldns_rdf **rd)
8707b5038d7SDag-Erling Smørgrav , ATTR_UNUSED(const char *str)
8717b5038d7SDag-Erling Smørgrav )
8727b5038d7SDag-Erling Smørgrav {
8737b5038d7SDag-Erling Smørgrav /* is this used? is this actually WKS? or SRV? */
8747b5038d7SDag-Erling Smørgrav return LDNS_STATUS_NOT_IMPL;
8757b5038d7SDag-Erling Smørgrav }
8767b5038d7SDag-Erling Smørgrav
8777b5038d7SDag-Erling Smørgrav static int
loc_parse_cm(char * my_str,char ** endstr,uint8_t * m,uint8_t * e)8787b5038d7SDag-Erling Smørgrav loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e)
8797b5038d7SDag-Erling Smørgrav {
8807b5038d7SDag-Erling Smørgrav /* read <digits>[.<digits>][mM] */
8817b5038d7SDag-Erling Smørgrav /* into mantissa exponent format for LOC type */
8827b5038d7SDag-Erling Smørgrav uint32_t meters = 0, cm = 0, val;
883*5afab0e5SDag-Erling Smørgrav char* cm_endstr;
884986ba33cSDag-Erling Smørgrav while (isblank((unsigned char)*my_str)) {
8857b5038d7SDag-Erling Smørgrav my_str++;
8867b5038d7SDag-Erling Smørgrav }
8877b5038d7SDag-Erling Smørgrav meters = (uint32_t)strtol(my_str, &my_str, 10);
8887b5038d7SDag-Erling Smørgrav if (*my_str == '.') {
8897b5038d7SDag-Erling Smørgrav my_str++;
890*5afab0e5SDag-Erling Smørgrav cm = (uint32_t)strtol(my_str, &cm_endstr, 10);
891*5afab0e5SDag-Erling Smørgrav if (cm_endstr - my_str == 1) cm *= 10;
892*5afab0e5SDag-Erling Smørgrav my_str = cm_endstr;
8937b5038d7SDag-Erling Smørgrav }
8947b5038d7SDag-Erling Smørgrav if (meters >= 1) {
8957b5038d7SDag-Erling Smørgrav *e = 2;
8967b5038d7SDag-Erling Smørgrav val = meters;
8977b5038d7SDag-Erling Smørgrav } else {
8987b5038d7SDag-Erling Smørgrav *e = 0;
8997b5038d7SDag-Erling Smørgrav val = cm;
9007b5038d7SDag-Erling Smørgrav }
9017b5038d7SDag-Erling Smørgrav while(val >= 10) {
9027b5038d7SDag-Erling Smørgrav (*e)++;
9037b5038d7SDag-Erling Smørgrav val /= 10;
9047b5038d7SDag-Erling Smørgrav }
9057b5038d7SDag-Erling Smørgrav *m = (uint8_t)val;
9067b5038d7SDag-Erling Smørgrav
9077b5038d7SDag-Erling Smørgrav if (*e > 9)
9087b5038d7SDag-Erling Smørgrav return 0;
9097b5038d7SDag-Erling Smørgrav if (*my_str == 'm' || *my_str == 'M') {
9107b5038d7SDag-Erling Smørgrav my_str++;
9117b5038d7SDag-Erling Smørgrav }
9127b5038d7SDag-Erling Smørgrav *endstr = my_str;
9137b5038d7SDag-Erling Smørgrav return 1;
9147b5038d7SDag-Erling Smørgrav }
9157b5038d7SDag-Erling Smørgrav
9167b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_loc(ldns_rdf ** rd,const char * str)9177b5038d7SDag-Erling Smørgrav ldns_str2rdf_loc(ldns_rdf **rd, const char *str)
9187b5038d7SDag-Erling Smørgrav {
9197b5038d7SDag-Erling Smørgrav uint32_t latitude = 0;
9207b5038d7SDag-Erling Smørgrav uint32_t longitude = 0;
9217b5038d7SDag-Erling Smørgrav uint32_t altitude = 0;
9227b5038d7SDag-Erling Smørgrav
9237b5038d7SDag-Erling Smørgrav uint8_t *data;
9247b5038d7SDag-Erling Smørgrav uint32_t equator = (uint32_t) ldns_power(2, 31);
9257b5038d7SDag-Erling Smørgrav
9267b5038d7SDag-Erling Smørgrav uint32_t h = 0;
9277b5038d7SDag-Erling Smørgrav uint32_t m = 0;
9287b5038d7SDag-Erling Smørgrav uint8_t size_b = 1, size_e = 2;
9297b5038d7SDag-Erling Smørgrav uint8_t horiz_pre_b = 1, horiz_pre_e = 6;
9307b5038d7SDag-Erling Smørgrav uint8_t vert_pre_b = 1, vert_pre_e = 3;
9317b5038d7SDag-Erling Smørgrav
9327b5038d7SDag-Erling Smørgrav double s = 0.0;
933*5afab0e5SDag-Erling Smørgrav bool northern_hemisphere;
934*5afab0e5SDag-Erling Smørgrav bool eastern_hemisphere;
9357b5038d7SDag-Erling Smørgrav
9367b5038d7SDag-Erling Smørgrav char *my_str = (char *) str;
9377b5038d7SDag-Erling Smørgrav
9387b5038d7SDag-Erling Smørgrav /* only support version 0 */
9397b5038d7SDag-Erling Smørgrav if (isdigit((int) *my_str)) {
9407b5038d7SDag-Erling Smørgrav h = (uint32_t) strtol(my_str, &my_str, 10);
9417b5038d7SDag-Erling Smørgrav } else {
9427b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
9437b5038d7SDag-Erling Smørgrav }
9447b5038d7SDag-Erling Smørgrav
9457b5038d7SDag-Erling Smørgrav while (isblank((int) *my_str)) {
9467b5038d7SDag-Erling Smørgrav my_str++;
9477b5038d7SDag-Erling Smørgrav }
9487b5038d7SDag-Erling Smørgrav
9497b5038d7SDag-Erling Smørgrav if (isdigit((int) *my_str)) {
9507b5038d7SDag-Erling Smørgrav m = (uint32_t) strtol(my_str, &my_str, 10);
9517b5038d7SDag-Erling Smørgrav } else if (*my_str == 'N' || *my_str == 'S') {
9527b5038d7SDag-Erling Smørgrav goto north;
9537b5038d7SDag-Erling Smørgrav } else {
9547b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
9557b5038d7SDag-Erling Smørgrav }
9567b5038d7SDag-Erling Smørgrav
9577b5038d7SDag-Erling Smørgrav while (isblank((int) *my_str)) {
9587b5038d7SDag-Erling Smørgrav my_str++;
9597b5038d7SDag-Erling Smørgrav }
9607b5038d7SDag-Erling Smørgrav
9617b5038d7SDag-Erling Smørgrav if (isdigit((int) *my_str)) {
9627b5038d7SDag-Erling Smørgrav s = strtod(my_str, &my_str);
9637b5038d7SDag-Erling Smørgrav }
9647b5038d7SDag-Erling Smørgrav north:
9657b5038d7SDag-Erling Smørgrav while (isblank((int) *my_str)) {
9667b5038d7SDag-Erling Smørgrav my_str++;
9677b5038d7SDag-Erling Smørgrav }
9687b5038d7SDag-Erling Smørgrav
9697b5038d7SDag-Erling Smørgrav if (*my_str == 'N') {
970*5afab0e5SDag-Erling Smørgrav northern_hemisphere = true;
9717b5038d7SDag-Erling Smørgrav } else if (*my_str == 'S') {
972*5afab0e5SDag-Erling Smørgrav northern_hemisphere = false;
9737b5038d7SDag-Erling Smørgrav } else {
9747b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
9757b5038d7SDag-Erling Smørgrav }
9767b5038d7SDag-Erling Smørgrav
9777b5038d7SDag-Erling Smørgrav my_str++;
9787b5038d7SDag-Erling Smørgrav
9797b5038d7SDag-Erling Smørgrav /* store number */
9807b5038d7SDag-Erling Smørgrav s = 1000.0 * s;
9817b5038d7SDag-Erling Smørgrav /* add a little to make floor in conversion a round */
9827b5038d7SDag-Erling Smørgrav s += 0.0005;
9837b5038d7SDag-Erling Smørgrav latitude = (uint32_t) s;
9847b5038d7SDag-Erling Smørgrav latitude += 1000 * 60 * m;
9857b5038d7SDag-Erling Smørgrav latitude += 1000 * 60 * 60 * h;
986*5afab0e5SDag-Erling Smørgrav if (northern_hemisphere) {
9877b5038d7SDag-Erling Smørgrav latitude = equator + latitude;
9887b5038d7SDag-Erling Smørgrav } else {
9897b5038d7SDag-Erling Smørgrav latitude = equator - latitude;
9907b5038d7SDag-Erling Smørgrav }
991986ba33cSDag-Erling Smørgrav while (isblank((unsigned char)*my_str)) {
9927b5038d7SDag-Erling Smørgrav my_str++;
9937b5038d7SDag-Erling Smørgrav }
9947b5038d7SDag-Erling Smørgrav
9957b5038d7SDag-Erling Smørgrav if (isdigit((int) *my_str)) {
9967b5038d7SDag-Erling Smørgrav h = (uint32_t) strtol(my_str, &my_str, 10);
9977b5038d7SDag-Erling Smørgrav } else {
9987b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
9997b5038d7SDag-Erling Smørgrav }
10007b5038d7SDag-Erling Smørgrav
10017b5038d7SDag-Erling Smørgrav while (isblank((int) *my_str)) {
10027b5038d7SDag-Erling Smørgrav my_str++;
10037b5038d7SDag-Erling Smørgrav }
10047b5038d7SDag-Erling Smørgrav
10057b5038d7SDag-Erling Smørgrav if (isdigit((int) *my_str)) {
10067b5038d7SDag-Erling Smørgrav m = (uint32_t) strtol(my_str, &my_str, 10);
10077b5038d7SDag-Erling Smørgrav } else if (*my_str == 'E' || *my_str == 'W') {
10087b5038d7SDag-Erling Smørgrav goto east;
10097b5038d7SDag-Erling Smørgrav } else {
10107b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
10117b5038d7SDag-Erling Smørgrav }
10127b5038d7SDag-Erling Smørgrav
1013986ba33cSDag-Erling Smørgrav while (isblank((unsigned char)*my_str)) {
10147b5038d7SDag-Erling Smørgrav my_str++;
10157b5038d7SDag-Erling Smørgrav }
10167b5038d7SDag-Erling Smørgrav
10177b5038d7SDag-Erling Smørgrav if (isdigit((int) *my_str)) {
10187b5038d7SDag-Erling Smørgrav s = strtod(my_str, &my_str);
10197b5038d7SDag-Erling Smørgrav }
10207b5038d7SDag-Erling Smørgrav
10217b5038d7SDag-Erling Smørgrav east:
1022986ba33cSDag-Erling Smørgrav while (isblank((unsigned char)*my_str)) {
10237b5038d7SDag-Erling Smørgrav my_str++;
10247b5038d7SDag-Erling Smørgrav }
10257b5038d7SDag-Erling Smørgrav
10267b5038d7SDag-Erling Smørgrav if (*my_str == 'E') {
1027*5afab0e5SDag-Erling Smørgrav eastern_hemisphere = true;
10287b5038d7SDag-Erling Smørgrav } else if (*my_str == 'W') {
1029*5afab0e5SDag-Erling Smørgrav eastern_hemisphere = false;
10307b5038d7SDag-Erling Smørgrav } else {
10317b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
10327b5038d7SDag-Erling Smørgrav }
10337b5038d7SDag-Erling Smørgrav
10347b5038d7SDag-Erling Smørgrav my_str++;
10357b5038d7SDag-Erling Smørgrav
10367b5038d7SDag-Erling Smørgrav /* store number */
10377b5038d7SDag-Erling Smørgrav s *= 1000.0;
10387b5038d7SDag-Erling Smørgrav /* add a little to make floor in conversion a round */
10397b5038d7SDag-Erling Smørgrav s += 0.0005;
10407b5038d7SDag-Erling Smørgrav longitude = (uint32_t) s;
10417b5038d7SDag-Erling Smørgrav longitude += 1000 * 60 * m;
10427b5038d7SDag-Erling Smørgrav longitude += 1000 * 60 * 60 * h;
10437b5038d7SDag-Erling Smørgrav
1044*5afab0e5SDag-Erling Smørgrav if (eastern_hemisphere) {
10457b5038d7SDag-Erling Smørgrav longitude += equator;
10467b5038d7SDag-Erling Smørgrav } else {
10477b5038d7SDag-Erling Smørgrav longitude = equator - longitude;
10487b5038d7SDag-Erling Smørgrav }
10497b5038d7SDag-Erling Smørgrav
10507b5038d7SDag-Erling Smørgrav altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 +
10517b5038d7SDag-Erling Smørgrav 10000000.0 + 0.5);
10527b5038d7SDag-Erling Smørgrav if (*my_str == 'm' || *my_str == 'M') {
10537b5038d7SDag-Erling Smørgrav my_str++;
10547b5038d7SDag-Erling Smørgrav }
10557b5038d7SDag-Erling Smørgrav
10567b5038d7SDag-Erling Smørgrav if (strlen(my_str) > 0) {
10577b5038d7SDag-Erling Smørgrav if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e))
10587b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
10597b5038d7SDag-Erling Smørgrav }
10607b5038d7SDag-Erling Smørgrav
10617b5038d7SDag-Erling Smørgrav if (strlen(my_str) > 0) {
10627b5038d7SDag-Erling Smørgrav if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e))
10637b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
10647b5038d7SDag-Erling Smørgrav }
10657b5038d7SDag-Erling Smørgrav
10667b5038d7SDag-Erling Smørgrav if (strlen(my_str) > 0) {
10677b5038d7SDag-Erling Smørgrav if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e))
10687b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
10697b5038d7SDag-Erling Smørgrav }
10707b5038d7SDag-Erling Smørgrav
10717b5038d7SDag-Erling Smørgrav data = LDNS_XMALLOC(uint8_t, 16);
10727b5038d7SDag-Erling Smørgrav if(!data) {
10737b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
10747b5038d7SDag-Erling Smørgrav }
10757b5038d7SDag-Erling Smørgrav data[0] = 0;
10767b5038d7SDag-Erling Smørgrav data[1] = 0;
10777b5038d7SDag-Erling Smørgrav data[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f);
10787b5038d7SDag-Erling Smørgrav data[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f);
10797b5038d7SDag-Erling Smørgrav data[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f);
10807b5038d7SDag-Erling Smørgrav ldns_write_uint32(data + 4, latitude);
10817b5038d7SDag-Erling Smørgrav ldns_write_uint32(data + 8, longitude);
10827b5038d7SDag-Erling Smørgrav ldns_write_uint32(data + 12, altitude);
10837b5038d7SDag-Erling Smørgrav
10847b5038d7SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(
10857b5038d7SDag-Erling Smørgrav LDNS_RDF_TYPE_LOC, 16, data);
10867b5038d7SDag-Erling Smørgrav
10877b5038d7SDag-Erling Smørgrav LDNS_FREE(data);
10887b5038d7SDag-Erling Smørgrav return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
10897b5038d7SDag-Erling Smørgrav }
10907b5038d7SDag-Erling Smørgrav
10917b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_wks(ldns_rdf ** rd,const char * str)10927b5038d7SDag-Erling Smørgrav ldns_str2rdf_wks(ldns_rdf **rd, const char *str)
10937b5038d7SDag-Erling Smørgrav {
10947b5038d7SDag-Erling Smørgrav uint8_t *bitmap = NULL;
10957b5038d7SDag-Erling Smørgrav uint8_t *data;
10967b5038d7SDag-Erling Smørgrav int bm_len = 0;
10977b5038d7SDag-Erling Smørgrav
10987b5038d7SDag-Erling Smørgrav struct protoent *proto = NULL;
10997b5038d7SDag-Erling Smørgrav struct servent *serv = NULL;
11007b5038d7SDag-Erling Smørgrav int serv_port;
11017b5038d7SDag-Erling Smørgrav
11027b5038d7SDag-Erling Smørgrav ldns_buffer *str_buf;
11037b5038d7SDag-Erling Smørgrav
11047b5038d7SDag-Erling Smørgrav char *proto_str = NULL;
1105*5afab0e5SDag-Erling Smørgrav char *lc_proto_str = NULL;
11067b5038d7SDag-Erling Smørgrav char *token;
1107*5afab0e5SDag-Erling Smørgrav char *lc_token;
1108*5afab0e5SDag-Erling Smørgrav char *c;
11097b5038d7SDag-Erling Smørgrav if(strlen(str) == 0)
11107b5038d7SDag-Erling Smørgrav token = LDNS_XMALLOC(char, 50);
11117b5038d7SDag-Erling Smørgrav else token = LDNS_XMALLOC(char, strlen(str)+2);
11127b5038d7SDag-Erling Smørgrav if(!token) return LDNS_STATUS_MEM_ERR;
11137b5038d7SDag-Erling Smørgrav
11147b5038d7SDag-Erling Smørgrav str_buf = LDNS_MALLOC(ldns_buffer);
11157b5038d7SDag-Erling Smørgrav if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;}
11167b5038d7SDag-Erling Smørgrav ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
11177b5038d7SDag-Erling Smørgrav if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) {
11187b5038d7SDag-Erling Smørgrav LDNS_FREE(str_buf);
11197b5038d7SDag-Erling Smørgrav LDNS_FREE(token);
11207b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
11217b5038d7SDag-Erling Smørgrav }
11227b5038d7SDag-Erling Smørgrav
11237b5038d7SDag-Erling Smørgrav while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) {
11247b5038d7SDag-Erling Smørgrav if (!proto_str) {
11257b5038d7SDag-Erling Smørgrav proto_str = strdup(token);
1126*5afab0e5SDag-Erling Smørgrav lc_proto_str = strdup(token);
1127*5afab0e5SDag-Erling Smørgrav for (c = lc_proto_str; *c; c++) {
1128*5afab0e5SDag-Erling Smørgrav *c = tolower((unsigned char)*c);
1129*5afab0e5SDag-Erling Smørgrav }
1130*5afab0e5SDag-Erling Smørgrav if (!proto_str || !lc_proto_str) {
1131*5afab0e5SDag-Erling Smørgrav free(proto_str);
1132*5afab0e5SDag-Erling Smørgrav free(lc_proto_str);
11337b5038d7SDag-Erling Smørgrav LDNS_FREE(bitmap);
11347b5038d7SDag-Erling Smørgrav LDNS_FREE(token);
11357b5038d7SDag-Erling Smørgrav ldns_buffer_free(str_buf);
11367b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
11377b5038d7SDag-Erling Smørgrav }
11387b5038d7SDag-Erling Smørgrav } else {
11397b5038d7SDag-Erling Smørgrav serv = getservbyname(token, proto_str);
1140*5afab0e5SDag-Erling Smørgrav if (!serv) {
1141*5afab0e5SDag-Erling Smørgrav serv = getservbyname(token, lc_proto_str);
1142*5afab0e5SDag-Erling Smørgrav }
1143*5afab0e5SDag-Erling Smørgrav if (!serv && (lc_token = strdup(token))) {
1144*5afab0e5SDag-Erling Smørgrav for (c = lc_token; *c; c++) {
1145*5afab0e5SDag-Erling Smørgrav *c = tolower((unsigned char)*c);
1146*5afab0e5SDag-Erling Smørgrav }
1147*5afab0e5SDag-Erling Smørgrav serv = getservbyname(lc_token, proto_str);
1148*5afab0e5SDag-Erling Smørgrav if (!serv) {
1149*5afab0e5SDag-Erling Smørgrav serv = getservbyname(lc_token, lc_proto_str);
1150*5afab0e5SDag-Erling Smørgrav }
1151*5afab0e5SDag-Erling Smørgrav free(lc_token);
1152*5afab0e5SDag-Erling Smørgrav }
11537b5038d7SDag-Erling Smørgrav if (serv) {
11547b5038d7SDag-Erling Smørgrav serv_port = (int) ntohs((uint16_t) serv->s_port);
11557b5038d7SDag-Erling Smørgrav } else {
11567b5038d7SDag-Erling Smørgrav serv_port = atoi(token);
11577b5038d7SDag-Erling Smørgrav }
1158*5afab0e5SDag-Erling Smørgrav if (serv_port < 0 || serv_port > 65535) {
1159*5afab0e5SDag-Erling Smørgrav LDNS_FREE(bitmap);
1160*5afab0e5SDag-Erling Smørgrav LDNS_FREE(token);
1161*5afab0e5SDag-Erling Smørgrav ldns_buffer_free(str_buf);
1162*5afab0e5SDag-Erling Smørgrav free(proto_str);
1163*5afab0e5SDag-Erling Smørgrav free(lc_proto_str);
1164*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
1165*5afab0e5SDag-Erling Smørgrav }
11667b5038d7SDag-Erling Smørgrav if (serv_port / 8 >= bm_len) {
11677b5038d7SDag-Erling Smørgrav uint8_t *b2 = LDNS_XREALLOC(bitmap, uint8_t, (serv_port / 8) + 1);
11687b5038d7SDag-Erling Smørgrav if(!b2) {
11697b5038d7SDag-Erling Smørgrav LDNS_FREE(bitmap);
11707b5038d7SDag-Erling Smørgrav LDNS_FREE(token);
11717b5038d7SDag-Erling Smørgrav ldns_buffer_free(str_buf);
11727b5038d7SDag-Erling Smørgrav free(proto_str);
1173*5afab0e5SDag-Erling Smørgrav free(lc_proto_str);
11747b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
11757b5038d7SDag-Erling Smørgrav }
11767b5038d7SDag-Erling Smørgrav bitmap = b2;
11777b5038d7SDag-Erling Smørgrav /* set to zero to be sure */
11787b5038d7SDag-Erling Smørgrav for (; bm_len <= serv_port / 8; bm_len++) {
11797b5038d7SDag-Erling Smørgrav bitmap[bm_len] = 0;
11807b5038d7SDag-Erling Smørgrav }
11817b5038d7SDag-Erling Smørgrav }
11827b5038d7SDag-Erling Smørgrav ldns_set_bit(bitmap + (serv_port / 8), 7 - (serv_port % 8), true);
11837b5038d7SDag-Erling Smørgrav }
11847b5038d7SDag-Erling Smørgrav }
11857b5038d7SDag-Erling Smørgrav
11867b5038d7SDag-Erling Smørgrav if (!proto_str || !bitmap) {
11877b5038d7SDag-Erling Smørgrav LDNS_FREE(bitmap);
11887b5038d7SDag-Erling Smørgrav LDNS_FREE(token);
11897b5038d7SDag-Erling Smørgrav ldns_buffer_free(str_buf);
11907b5038d7SDag-Erling Smørgrav free(proto_str);
1191*5afab0e5SDag-Erling Smørgrav free(lc_proto_str);
11927b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
11937b5038d7SDag-Erling Smørgrav }
11947b5038d7SDag-Erling Smørgrav
11957b5038d7SDag-Erling Smørgrav data = LDNS_XMALLOC(uint8_t, bm_len + 1);
11967b5038d7SDag-Erling Smørgrav if(!data) {
11977b5038d7SDag-Erling Smørgrav LDNS_FREE(token);
11987b5038d7SDag-Erling Smørgrav ldns_buffer_free(str_buf);
11997b5038d7SDag-Erling Smørgrav LDNS_FREE(bitmap);
12007b5038d7SDag-Erling Smørgrav free(proto_str);
1201*5afab0e5SDag-Erling Smørgrav free(lc_proto_str);
12027b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
12037b5038d7SDag-Erling Smørgrav }
12047b5038d7SDag-Erling Smørgrav if (proto_str)
12057b5038d7SDag-Erling Smørgrav proto = getprotobyname(proto_str);
1206*5afab0e5SDag-Erling Smørgrav if (!proto) {
1207*5afab0e5SDag-Erling Smørgrav proto = getprotobyname(lc_proto_str);
1208*5afab0e5SDag-Erling Smørgrav }
12097b5038d7SDag-Erling Smørgrav if (proto) {
12107b5038d7SDag-Erling Smørgrav data[0] = (uint8_t) proto->p_proto;
12117b5038d7SDag-Erling Smørgrav } else if (proto_str) {
12127b5038d7SDag-Erling Smørgrav data[0] = (uint8_t) atoi(proto_str);
12137b5038d7SDag-Erling Smørgrav }
12147b5038d7SDag-Erling Smørgrav memcpy(data + 1, bitmap, (size_t) bm_len);
12157b5038d7SDag-Erling Smørgrav
12167b5038d7SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_WKS, (uint16_t) (bm_len + 1), data);
12177b5038d7SDag-Erling Smørgrav
12187b5038d7SDag-Erling Smørgrav LDNS_FREE(data);
12197b5038d7SDag-Erling Smørgrav LDNS_FREE(token);
12207b5038d7SDag-Erling Smørgrav ldns_buffer_free(str_buf);
12217b5038d7SDag-Erling Smørgrav LDNS_FREE(bitmap);
12227b5038d7SDag-Erling Smørgrav free(proto_str);
1223*5afab0e5SDag-Erling Smørgrav free(lc_proto_str);
12247b5038d7SDag-Erling Smørgrav #ifdef HAVE_ENDSERVENT
12257b5038d7SDag-Erling Smørgrav endservent();
12267b5038d7SDag-Erling Smørgrav #endif
12277b5038d7SDag-Erling Smørgrav #ifdef HAVE_ENDPROTOENT
12287b5038d7SDag-Erling Smørgrav endprotoent();
12297b5038d7SDag-Erling Smørgrav #endif
12307b5038d7SDag-Erling Smørgrav
12317b5038d7SDag-Erling Smørgrav if(!*rd) return LDNS_STATUS_MEM_ERR;
12327b5038d7SDag-Erling Smørgrav
12337b5038d7SDag-Erling Smørgrav return LDNS_STATUS_OK;
12347b5038d7SDag-Erling Smørgrav }
12357b5038d7SDag-Erling Smørgrav
12367b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_nsap(ldns_rdf ** rd,const char * str)12377b5038d7SDag-Erling Smørgrav ldns_str2rdf_nsap(ldns_rdf **rd, const char *str)
12387b5038d7SDag-Erling Smørgrav {
12397b5038d7SDag-Erling Smørgrav size_t len, i;
12407b5038d7SDag-Erling Smørgrav char* nsap_str = (char*) str;
12417b5038d7SDag-Erling Smørgrav
12427b5038d7SDag-Erling Smørgrav /* just a hex string with optional dots? */
12437b5038d7SDag-Erling Smørgrav if (str[0] != '0' || str[1] != 'x') {
12447b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
12457b5038d7SDag-Erling Smørgrav } else {
12467b5038d7SDag-Erling Smørgrav len = strlen(str);
12477b5038d7SDag-Erling Smørgrav for (i=0; i < len; i++) {
12487b5038d7SDag-Erling Smørgrav if (nsap_str[i] == '.')
12497b5038d7SDag-Erling Smørgrav nsap_str[i] = ' ';
12507b5038d7SDag-Erling Smørgrav }
12517b5038d7SDag-Erling Smørgrav return ldns_str2rdf_hex(rd, str+2);
12527b5038d7SDag-Erling Smørgrav }
12537b5038d7SDag-Erling Smørgrav }
12547b5038d7SDag-Erling Smørgrav
12557b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_atma(ldns_rdf ** rd,const char * str)12567b5038d7SDag-Erling Smørgrav ldns_str2rdf_atma(ldns_rdf **rd, const char *str)
12577b5038d7SDag-Erling Smørgrav {
12587b5038d7SDag-Erling Smørgrav size_t len, i;
12597b5038d7SDag-Erling Smørgrav char* atma_str = (char*) str;
12607b5038d7SDag-Erling Smørgrav ldns_status status;
12617b5038d7SDag-Erling Smørgrav
12627b5038d7SDag-Erling Smørgrav /* just a hex string with optional dots? */
12637b5038d7SDag-Erling Smørgrav len = strlen(str);
12647b5038d7SDag-Erling Smørgrav for (i=0; i < len; i++) {
12657b5038d7SDag-Erling Smørgrav if (atma_str[i] == '.')
12667b5038d7SDag-Erling Smørgrav atma_str[i] = ' ';
12677b5038d7SDag-Erling Smørgrav }
12687b5038d7SDag-Erling Smørgrav status = ldns_str2rdf_hex(rd, str);
12697b5038d7SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) {
12707b5038d7SDag-Erling Smørgrav ; /* probably in e.164 format than */
12717b5038d7SDag-Erling Smørgrav }
12727b5038d7SDag-Erling Smørgrav return status;
12737b5038d7SDag-Erling Smørgrav }
12747b5038d7SDag-Erling Smørgrav
12757b5038d7SDag-Erling Smørgrav ldns_status
ldns_str2rdf_ipseckey(ldns_rdf ** rd,const char * str)12767b5038d7SDag-Erling Smørgrav ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str)
12777b5038d7SDag-Erling Smørgrav {
12787b5038d7SDag-Erling Smørgrav uint8_t precedence = 0;
12797b5038d7SDag-Erling Smørgrav uint8_t gateway_type = 0;
12807b5038d7SDag-Erling Smørgrav uint8_t algorithm = 0;
12817b5038d7SDag-Erling Smørgrav char* gateway = NULL;
12827b5038d7SDag-Erling Smørgrav char* publickey = NULL;
12837b5038d7SDag-Erling Smørgrav uint8_t *data;
12847b5038d7SDag-Erling Smørgrav ldns_buffer *str_buf;
12857b5038d7SDag-Erling Smørgrav char *token;
12867b5038d7SDag-Erling Smørgrav int token_count = 0;
12877b5038d7SDag-Erling Smørgrav int ipseckey_len = 0;
12887b5038d7SDag-Erling Smørgrav ldns_rdf* gateway_rdf = NULL;
12897b5038d7SDag-Erling Smørgrav ldns_rdf* publickey_rdf = NULL;
12907b5038d7SDag-Erling Smørgrav ldns_status status = LDNS_STATUS_OK;
12917b5038d7SDag-Erling Smørgrav
12927b5038d7SDag-Erling Smørgrav if(strlen(str) == 0)
12937b5038d7SDag-Erling Smørgrav token = LDNS_XMALLOC(char, 256);
12947b5038d7SDag-Erling Smørgrav else token = LDNS_XMALLOC(char, strlen(str)+2);
12957b5038d7SDag-Erling Smørgrav if(!token) return LDNS_STATUS_MEM_ERR;
12967b5038d7SDag-Erling Smørgrav
12977b5038d7SDag-Erling Smørgrav str_buf = LDNS_MALLOC(ldns_buffer);
12987b5038d7SDag-Erling Smørgrav if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;}
12997b5038d7SDag-Erling Smørgrav ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
13007b5038d7SDag-Erling Smørgrav if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) {
13017b5038d7SDag-Erling Smørgrav LDNS_FREE(str_buf);
13027b5038d7SDag-Erling Smørgrav LDNS_FREE(token);
13037b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
13047b5038d7SDag-Erling Smørgrav }
13057b5038d7SDag-Erling Smørgrav while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) {
13067b5038d7SDag-Erling Smørgrav switch (token_count) {
13077b5038d7SDag-Erling Smørgrav case 0:
13087b5038d7SDag-Erling Smørgrav precedence = (uint8_t)atoi(token);
13097b5038d7SDag-Erling Smørgrav break;
13107b5038d7SDag-Erling Smørgrav case 1:
13117b5038d7SDag-Erling Smørgrav gateway_type = (uint8_t)atoi(token);
13127b5038d7SDag-Erling Smørgrav break;
13137b5038d7SDag-Erling Smørgrav case 2:
13147b5038d7SDag-Erling Smørgrav algorithm = (uint8_t)atoi(token);
13157b5038d7SDag-Erling Smørgrav break;
13167b5038d7SDag-Erling Smørgrav case 3:
13177b5038d7SDag-Erling Smørgrav gateway = strdup(token);
13187b5038d7SDag-Erling Smørgrav if (!gateway || (gateway_type == 0 &&
13197b5038d7SDag-Erling Smørgrav (token[0] != '.' || token[1] != '\0'))) {
13207b5038d7SDag-Erling Smørgrav LDNS_FREE(gateway);
13217b5038d7SDag-Erling Smørgrav LDNS_FREE(token);
13227b5038d7SDag-Erling Smørgrav ldns_buffer_free(str_buf);
13237b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
13247b5038d7SDag-Erling Smørgrav }
13257b5038d7SDag-Erling Smørgrav break;
13267b5038d7SDag-Erling Smørgrav case 4:
13277b5038d7SDag-Erling Smørgrav publickey = strdup(token);
13287b5038d7SDag-Erling Smørgrav break;
13297b5038d7SDag-Erling Smørgrav default:
13307b5038d7SDag-Erling Smørgrav LDNS_FREE(token);
13317b5038d7SDag-Erling Smørgrav ldns_buffer_free(str_buf);
13327b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
13337b5038d7SDag-Erling Smørgrav break;
13347b5038d7SDag-Erling Smørgrav }
13357b5038d7SDag-Erling Smørgrav token_count++;
13367b5038d7SDag-Erling Smørgrav }
13377b5038d7SDag-Erling Smørgrav
13387b5038d7SDag-Erling Smørgrav if (!gateway || !publickey) {
13397b5038d7SDag-Erling Smørgrav if (gateway)
13407b5038d7SDag-Erling Smørgrav LDNS_FREE(gateway);
13417b5038d7SDag-Erling Smørgrav if (publickey)
13427b5038d7SDag-Erling Smørgrav LDNS_FREE(publickey);
13437b5038d7SDag-Erling Smørgrav LDNS_FREE(token);
13447b5038d7SDag-Erling Smørgrav ldns_buffer_free(str_buf);
13457b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
13467b5038d7SDag-Erling Smørgrav }
13477b5038d7SDag-Erling Smørgrav
13487b5038d7SDag-Erling Smørgrav if (gateway_type == 1) {
13497b5038d7SDag-Erling Smørgrav status = ldns_str2rdf_a(&gateway_rdf, gateway);
13507b5038d7SDag-Erling Smørgrav } else if (gateway_type == 2) {
13517b5038d7SDag-Erling Smørgrav status = ldns_str2rdf_aaaa(&gateway_rdf, gateway);
13527b5038d7SDag-Erling Smørgrav } else if (gateway_type == 3) {
13537b5038d7SDag-Erling Smørgrav status = ldns_str2rdf_dname(&gateway_rdf, gateway);
1354*5afab0e5SDag-Erling Smørgrav } else if (gateway_type > 3) {
1355*5afab0e5SDag-Erling Smørgrav status = LDNS_STATUS_INVALID_STR;
13567b5038d7SDag-Erling Smørgrav }
13577b5038d7SDag-Erling Smørgrav
13587b5038d7SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) {
13597b5038d7SDag-Erling Smørgrav if (gateway)
13607b5038d7SDag-Erling Smørgrav LDNS_FREE(gateway);
13617b5038d7SDag-Erling Smørgrav if (publickey)
13627b5038d7SDag-Erling Smørgrav LDNS_FREE(publickey);
13637b5038d7SDag-Erling Smørgrav LDNS_FREE(token);
13647b5038d7SDag-Erling Smørgrav ldns_buffer_free(str_buf);
13657b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
13667b5038d7SDag-Erling Smørgrav }
13677b5038d7SDag-Erling Smørgrav
13687b5038d7SDag-Erling Smørgrav status = ldns_str2rdf_b64(&publickey_rdf, publickey);
13697b5038d7SDag-Erling Smørgrav
13707b5038d7SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) {
13717b5038d7SDag-Erling Smørgrav if (gateway)
13727b5038d7SDag-Erling Smørgrav LDNS_FREE(gateway);
13737b5038d7SDag-Erling Smørgrav if (publickey)
13747b5038d7SDag-Erling Smørgrav LDNS_FREE(publickey);
13757b5038d7SDag-Erling Smørgrav LDNS_FREE(token);
13767b5038d7SDag-Erling Smørgrav ldns_buffer_free(str_buf);
13777b5038d7SDag-Erling Smørgrav if (gateway_rdf) ldns_rdf_free(gateway_rdf);
13787b5038d7SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
13797b5038d7SDag-Erling Smørgrav }
13807b5038d7SDag-Erling Smørgrav
13817b5038d7SDag-Erling Smørgrav /* now copy all into one ipseckey rdf */
13827b5038d7SDag-Erling Smørgrav if (gateway_type)
13837b5038d7SDag-Erling Smørgrav ipseckey_len = 3 + (int)ldns_rdf_size(gateway_rdf) + (int)ldns_rdf_size(publickey_rdf);
13847b5038d7SDag-Erling Smørgrav else
13857b5038d7SDag-Erling Smørgrav ipseckey_len = 3 + (int)ldns_rdf_size(publickey_rdf);
13867b5038d7SDag-Erling Smørgrav
13877b5038d7SDag-Erling Smørgrav data = LDNS_XMALLOC(uint8_t, ipseckey_len);
13887b5038d7SDag-Erling Smørgrav if(!data) {
13897b5038d7SDag-Erling Smørgrav if (gateway)
13907b5038d7SDag-Erling Smørgrav LDNS_FREE(gateway);
13917b5038d7SDag-Erling Smørgrav if (publickey)
13927b5038d7SDag-Erling Smørgrav LDNS_FREE(publickey);
13937b5038d7SDag-Erling Smørgrav LDNS_FREE(token);
13947b5038d7SDag-Erling Smørgrav ldns_buffer_free(str_buf);
13957b5038d7SDag-Erling Smørgrav if (gateway_rdf) ldns_rdf_free(gateway_rdf);
13967b5038d7SDag-Erling Smørgrav if (publickey_rdf) ldns_rdf_free(publickey_rdf);
13977b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
13987b5038d7SDag-Erling Smørgrav }
13997b5038d7SDag-Erling Smørgrav
14007b5038d7SDag-Erling Smørgrav data[0] = precedence;
14017b5038d7SDag-Erling Smørgrav data[1] = gateway_type;
14027b5038d7SDag-Erling Smørgrav data[2] = algorithm;
14037b5038d7SDag-Erling Smørgrav
14047b5038d7SDag-Erling Smørgrav if (gateway_type) {
14057b5038d7SDag-Erling Smørgrav memcpy(data + 3,
14067b5038d7SDag-Erling Smørgrav ldns_rdf_data(gateway_rdf), ldns_rdf_size(gateway_rdf));
14077b5038d7SDag-Erling Smørgrav memcpy(data + 3 + ldns_rdf_size(gateway_rdf),
14087b5038d7SDag-Erling Smørgrav ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf));
14097b5038d7SDag-Erling Smørgrav } else {
14107b5038d7SDag-Erling Smørgrav memcpy(data + 3,
14117b5038d7SDag-Erling Smørgrav ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf));
14127b5038d7SDag-Erling Smørgrav }
14137b5038d7SDag-Erling Smørgrav
14147b5038d7SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_IPSECKEY, (uint16_t) ipseckey_len, data);
14157b5038d7SDag-Erling Smørgrav
14167b5038d7SDag-Erling Smørgrav if (gateway)
14177b5038d7SDag-Erling Smørgrav LDNS_FREE(gateway);
14187b5038d7SDag-Erling Smørgrav if (publickey)
14197b5038d7SDag-Erling Smørgrav LDNS_FREE(publickey);
14207b5038d7SDag-Erling Smørgrav LDNS_FREE(token);
14217b5038d7SDag-Erling Smørgrav ldns_buffer_free(str_buf);
1422*5afab0e5SDag-Erling Smørgrav ldns_rdf_deep_free(gateway_rdf);
1423*5afab0e5SDag-Erling Smørgrav ldns_rdf_deep_free(publickey_rdf);
14247b5038d7SDag-Erling Smørgrav LDNS_FREE(data);
14257b5038d7SDag-Erling Smørgrav if(!*rd) return LDNS_STATUS_MEM_ERR;
14267b5038d7SDag-Erling Smørgrav return LDNS_STATUS_OK;
14277b5038d7SDag-Erling Smørgrav }
142817d15b25SDag-Erling Smørgrav
142917d15b25SDag-Erling Smørgrav ldns_status
ldns_str2rdf_ilnp64(ldns_rdf ** rd,const char * str)143017d15b25SDag-Erling Smørgrav ldns_str2rdf_ilnp64(ldns_rdf **rd, const char *str)
143117d15b25SDag-Erling Smørgrav {
143217d15b25SDag-Erling Smørgrav unsigned int a, b, c, d;
143317d15b25SDag-Erling Smørgrav uint16_t shorts[4];
143417d15b25SDag-Erling Smørgrav int l;
143517d15b25SDag-Erling Smørgrav
143617d15b25SDag-Erling Smørgrav if (sscanf(str, "%4x:%4x:%4x:%4x%n", &a, &b, &c, &d, &l) != 4 ||
143717d15b25SDag-Erling Smørgrav l != (int)strlen(str) || /* more data to read */
143817d15b25SDag-Erling Smørgrav strpbrk(str, "+-") /* signed hexes */
143917d15b25SDag-Erling Smørgrav ) {
144017d15b25SDag-Erling Smørgrav return LDNS_STATUS_INVALID_ILNP64;
144117d15b25SDag-Erling Smørgrav } else {
144217d15b25SDag-Erling Smørgrav shorts[0] = htons(a);
144317d15b25SDag-Erling Smørgrav shorts[1] = htons(b);
144417d15b25SDag-Erling Smørgrav shorts[2] = htons(c);
144517d15b25SDag-Erling Smørgrav shorts[3] = htons(d);
144617d15b25SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(
144717d15b25SDag-Erling Smørgrav LDNS_RDF_TYPE_ILNP64, 4 * sizeof(uint16_t), &shorts);
144817d15b25SDag-Erling Smørgrav }
144917d15b25SDag-Erling Smørgrav return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
145017d15b25SDag-Erling Smørgrav }
145117d15b25SDag-Erling Smørgrav
145217d15b25SDag-Erling Smørgrav ldns_status
ldns_str2rdf_eui48(ldns_rdf ** rd,const char * str)145317d15b25SDag-Erling Smørgrav ldns_str2rdf_eui48(ldns_rdf **rd, const char *str)
145417d15b25SDag-Erling Smørgrav {
145517d15b25SDag-Erling Smørgrav unsigned int a, b, c, d, e, f;
145617d15b25SDag-Erling Smørgrav uint8_t bytes[6];
145717d15b25SDag-Erling Smørgrav int l;
145817d15b25SDag-Erling Smørgrav
145917d15b25SDag-Erling Smørgrav if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x%n",
146017d15b25SDag-Erling Smørgrav &a, &b, &c, &d, &e, &f, &l) != 6 ||
1461986ba33cSDag-Erling Smørgrav l != (int)strlen(str)) {
146217d15b25SDag-Erling Smørgrav return LDNS_STATUS_INVALID_EUI48;
146317d15b25SDag-Erling Smørgrav } else {
146417d15b25SDag-Erling Smørgrav bytes[0] = a;
146517d15b25SDag-Erling Smørgrav bytes[1] = b;
146617d15b25SDag-Erling Smørgrav bytes[2] = c;
146717d15b25SDag-Erling Smørgrav bytes[3] = d;
146817d15b25SDag-Erling Smørgrav bytes[4] = e;
146917d15b25SDag-Erling Smørgrav bytes[5] = f;
147017d15b25SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_EUI48, 6, &bytes);
147117d15b25SDag-Erling Smørgrav }
147217d15b25SDag-Erling Smørgrav return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
147317d15b25SDag-Erling Smørgrav }
147417d15b25SDag-Erling Smørgrav
147517d15b25SDag-Erling Smørgrav ldns_status
ldns_str2rdf_eui64(ldns_rdf ** rd,const char * str)147617d15b25SDag-Erling Smørgrav ldns_str2rdf_eui64(ldns_rdf **rd, const char *str)
147717d15b25SDag-Erling Smørgrav {
147817d15b25SDag-Erling Smørgrav unsigned int a, b, c, d, e, f, g, h;
147917d15b25SDag-Erling Smørgrav uint8_t bytes[8];
148017d15b25SDag-Erling Smørgrav int l;
148117d15b25SDag-Erling Smørgrav
148217d15b25SDag-Erling Smørgrav if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x%n",
148317d15b25SDag-Erling Smørgrav &a, &b, &c, &d, &e, &f, &g, &h, &l) != 8 ||
1484986ba33cSDag-Erling Smørgrav l != (int)strlen(str)) {
148517d15b25SDag-Erling Smørgrav return LDNS_STATUS_INVALID_EUI64;
148617d15b25SDag-Erling Smørgrav } else {
148717d15b25SDag-Erling Smørgrav bytes[0] = a;
148817d15b25SDag-Erling Smørgrav bytes[1] = b;
148917d15b25SDag-Erling Smørgrav bytes[2] = c;
149017d15b25SDag-Erling Smørgrav bytes[3] = d;
149117d15b25SDag-Erling Smørgrav bytes[4] = e;
149217d15b25SDag-Erling Smørgrav bytes[5] = f;
149317d15b25SDag-Erling Smørgrav bytes[6] = g;
149417d15b25SDag-Erling Smørgrav bytes[7] = h;
149517d15b25SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_EUI64, 8, &bytes);
149617d15b25SDag-Erling Smørgrav }
149717d15b25SDag-Erling Smørgrav return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
149817d15b25SDag-Erling Smørgrav }
149917d15b25SDag-Erling Smørgrav
150017d15b25SDag-Erling Smørgrav ldns_status
ldns_str2rdf_tag(ldns_rdf ** rd,const char * str)150117d15b25SDag-Erling Smørgrav ldns_str2rdf_tag(ldns_rdf **rd, const char *str)
150217d15b25SDag-Erling Smørgrav {
150317d15b25SDag-Erling Smørgrav uint8_t *data;
150417d15b25SDag-Erling Smørgrav const char* ptr;
150517d15b25SDag-Erling Smørgrav
150617d15b25SDag-Erling Smørgrav if (strlen(str) > 255) {
150717d15b25SDag-Erling Smørgrav return LDNS_STATUS_INVALID_TAG;
150817d15b25SDag-Erling Smørgrav }
150917d15b25SDag-Erling Smørgrav for (ptr = str; *ptr; ptr++) {
1510986ba33cSDag-Erling Smørgrav if (! isalnum((unsigned char)*ptr)) {
151117d15b25SDag-Erling Smørgrav return LDNS_STATUS_INVALID_TAG;
151217d15b25SDag-Erling Smørgrav }
151317d15b25SDag-Erling Smørgrav }
151417d15b25SDag-Erling Smørgrav data = LDNS_XMALLOC(uint8_t, strlen(str) + 1);
151517d15b25SDag-Erling Smørgrav if (!data) {
151617d15b25SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
151717d15b25SDag-Erling Smørgrav }
151817d15b25SDag-Erling Smørgrav data[0] = strlen(str);
151917d15b25SDag-Erling Smørgrav memcpy(data + 1, str, strlen(str));
152017d15b25SDag-Erling Smørgrav
152117d15b25SDag-Erling Smørgrav *rd = ldns_rdf_new(LDNS_RDF_TYPE_TAG, strlen(str) + 1, data);
152217d15b25SDag-Erling Smørgrav if (!*rd) {
152317d15b25SDag-Erling Smørgrav LDNS_FREE(data);
152417d15b25SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
152517d15b25SDag-Erling Smørgrav }
152617d15b25SDag-Erling Smørgrav return LDNS_STATUS_OK;
152717d15b25SDag-Erling Smørgrav }
152817d15b25SDag-Erling Smørgrav
152917d15b25SDag-Erling Smørgrav ldns_status
ldns_str2rdf_long_str(ldns_rdf ** rd,const char * str)153017d15b25SDag-Erling Smørgrav ldns_str2rdf_long_str(ldns_rdf **rd, const char *str)
153117d15b25SDag-Erling Smørgrav {
153217d15b25SDag-Erling Smørgrav uint8_t *data, *dp, ch = 0;
153317d15b25SDag-Erling Smørgrav size_t length;
153417d15b25SDag-Erling Smørgrav
153517d15b25SDag-Erling Smørgrav /* Worst case space requirement. We'll realloc to actual size later. */
153617d15b25SDag-Erling Smørgrav dp = data = LDNS_XMALLOC(uint8_t, strlen(str));
153717d15b25SDag-Erling Smørgrav if (! data) {
153817d15b25SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
153917d15b25SDag-Erling Smørgrav }
154017d15b25SDag-Erling Smørgrav
154117d15b25SDag-Erling Smørgrav /* Fill data with parsed bytes */
154217d15b25SDag-Erling Smørgrav while (parse_char(&ch, &str)) {
154317d15b25SDag-Erling Smørgrav *dp++ = ch;
154417d15b25SDag-Erling Smørgrav if (dp - data > LDNS_MAX_RDFLEN) {
154517d15b25SDag-Erling Smørgrav LDNS_FREE(data);
154617d15b25SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
154717d15b25SDag-Erling Smørgrav }
154817d15b25SDag-Erling Smørgrav }
154917d15b25SDag-Erling Smørgrav if (! str) {
1550*5afab0e5SDag-Erling Smørgrav LDNS_FREE(data);
155117d15b25SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
155217d15b25SDag-Erling Smørgrav }
1553*5afab0e5SDag-Erling Smørgrav if (!(length = (size_t)(dp - data))) {
1554*5afab0e5SDag-Erling Smørgrav /* An empty string is a data buffer of 0 bytes. The rdf for
1555*5afab0e5SDag-Erling Smørgrav * this long string has to have length 0 and point to NULL.
1556*5afab0e5SDag-Erling Smørgrav */
1557*5afab0e5SDag-Erling Smørgrav LDNS_FREE(data);
1558*5afab0e5SDag-Erling Smørgrav data = NULL;
1559*5afab0e5SDag-Erling Smørgrav } else {
156017d15b25SDag-Erling Smørgrav /* Lose the overmeasure */
156117d15b25SDag-Erling Smørgrav data = LDNS_XREALLOC(dp = data, uint8_t, length);
156217d15b25SDag-Erling Smørgrav if (! data) {
156317d15b25SDag-Erling Smørgrav LDNS_FREE(dp);
156417d15b25SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
156517d15b25SDag-Erling Smørgrav }
1566*5afab0e5SDag-Erling Smørgrav }
156717d15b25SDag-Erling Smørgrav /* Create rdf */
156817d15b25SDag-Erling Smørgrav *rd = ldns_rdf_new(LDNS_RDF_TYPE_LONG_STR, length, data);
156917d15b25SDag-Erling Smørgrav if (! *rd) {
157017d15b25SDag-Erling Smørgrav LDNS_FREE(data);
157117d15b25SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
157217d15b25SDag-Erling Smørgrav }
157317d15b25SDag-Erling Smørgrav return LDNS_STATUS_OK;
157417d15b25SDag-Erling Smørgrav }
157517d15b25SDag-Erling Smørgrav
157617d15b25SDag-Erling Smørgrav ldns_status
ldns_str2rdf_hip(ldns_rdf ** rd,const char * str)157717d15b25SDag-Erling Smørgrav ldns_str2rdf_hip(ldns_rdf **rd, const char *str)
157817d15b25SDag-Erling Smørgrav {
1579*5afab0e5SDag-Erling Smørgrav const char *hit = str == NULL ? NULL : strchr(str, ' ');
1580*5afab0e5SDag-Erling Smørgrav const char *pk = hit == NULL ? NULL : strchr(hit + 1, ' ');
158117d15b25SDag-Erling Smørgrav size_t hit_size = hit == NULL ? 0
1582*5afab0e5SDag-Erling Smørgrav : pk == NULL ? strlen(hit + 1) : (size_t) (pk - hit) - 1;
1583*5afab0e5SDag-Erling Smørgrav size_t pk_size = pk == NULL ? 0 : strlen(pk + 1);
158417d15b25SDag-Erling Smørgrav size_t hit_wire_size = (hit_size + 1) / 2;
158517d15b25SDag-Erling Smørgrav size_t pk_wire_size = ldns_b64_pton_calculate_size(pk_size);
158617d15b25SDag-Erling Smørgrav size_t rdf_size = 4 + hit_wire_size + pk_wire_size;
158717d15b25SDag-Erling Smørgrav
158817d15b25SDag-Erling Smørgrav char *endptr; /* utility var for strtol usage */
1589*5afab0e5SDag-Erling Smørgrav int algorithm = str == NULL ? 0 : strtol(str, &endptr, 10);
159017d15b25SDag-Erling Smørgrav
159117d15b25SDag-Erling Smørgrav uint8_t *data, *dp;
159217d15b25SDag-Erling Smørgrav int hi, lo, written;
159317d15b25SDag-Erling Smørgrav
159417d15b25SDag-Erling Smørgrav if (hit_size == 0 || pk_size == 0 || (hit_size + 1) / 2 > 255
159517d15b25SDag-Erling Smørgrav || rdf_size > LDNS_MAX_RDFLEN
159617d15b25SDag-Erling Smørgrav || algorithm < 0 || algorithm > 255
159717d15b25SDag-Erling Smørgrav || (errno != 0 && algorithm == 0) /* out of range */
159817d15b25SDag-Erling Smørgrav || endptr == str /* no digits */) {
159917d15b25SDag-Erling Smørgrav
160017d15b25SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_ERR;
160117d15b25SDag-Erling Smørgrav }
1602*5afab0e5SDag-Erling Smørgrav hit += 1;
1603*5afab0e5SDag-Erling Smørgrav pk += 1;
160417d15b25SDag-Erling Smørgrav if ((data = LDNS_XMALLOC(uint8_t, rdf_size)) == NULL) {
160517d15b25SDag-Erling Smørgrav
160617d15b25SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
160717d15b25SDag-Erling Smørgrav }
160817d15b25SDag-Erling Smørgrav /* From RFC 5205 section 5. HIP RR Storage Format:
160917d15b25SDag-Erling Smørgrav *************************************************
161017d15b25SDag-Erling Smørgrav
161117d15b25SDag-Erling Smørgrav 0 1 2 3
161217d15b25SDag-Erling Smørgrav 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
161317d15b25SDag-Erling Smørgrav +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
161417d15b25SDag-Erling Smørgrav | HIT length | PK algorithm | PK length |
161517d15b25SDag-Erling Smørgrav +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
161617d15b25SDag-Erling Smørgrav | |
161717d15b25SDag-Erling Smørgrav ~ HIT ~
161817d15b25SDag-Erling Smørgrav | |
161917d15b25SDag-Erling Smørgrav + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
162017d15b25SDag-Erling Smørgrav | | |
162117d15b25SDag-Erling Smørgrav +-+-+-+-+-+-+-+-+-+-+-+ +
162217d15b25SDag-Erling Smørgrav | Public Key |
162317d15b25SDag-Erling Smørgrav ~ ~
162417d15b25SDag-Erling Smørgrav | |
162517d15b25SDag-Erling Smørgrav + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
162617d15b25SDag-Erling Smørgrav | | |
162717d15b25SDag-Erling Smørgrav +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
162817d15b25SDag-Erling Smørgrav | |
162917d15b25SDag-Erling Smørgrav ~ Rendezvous Servers ~
163017d15b25SDag-Erling Smørgrav | |
163117d15b25SDag-Erling Smørgrav + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
163217d15b25SDag-Erling Smørgrav | |
163317d15b25SDag-Erling Smørgrav +-+-+-+-+-+-+-+ */
163417d15b25SDag-Erling Smørgrav
163517d15b25SDag-Erling Smørgrav data[0] = (uint8_t) hit_wire_size;
163617d15b25SDag-Erling Smørgrav data[1] = (uint8_t) algorithm;
163717d15b25SDag-Erling Smørgrav
163817d15b25SDag-Erling Smørgrav for (dp = data + 4; *hit && *hit != ' '; dp++) {
163917d15b25SDag-Erling Smørgrav
164017d15b25SDag-Erling Smørgrav if ((hi = ldns_hexdigit_to_int(*hit++)) == -1 ||
164117d15b25SDag-Erling Smørgrav (lo = ldns_hexdigit_to_int(*hit++)) == -1) {
164217d15b25SDag-Erling Smørgrav
164317d15b25SDag-Erling Smørgrav LDNS_FREE(data);
164417d15b25SDag-Erling Smørgrav return LDNS_STATUS_INVALID_HEX;
164517d15b25SDag-Erling Smørgrav }
164617d15b25SDag-Erling Smørgrav *dp = (uint8_t) hi << 4 | lo;
164717d15b25SDag-Erling Smørgrav }
164817d15b25SDag-Erling Smørgrav if ((written = ldns_b64_pton(pk, dp, pk_wire_size)) <= 0) {
164917d15b25SDag-Erling Smørgrav
165017d15b25SDag-Erling Smørgrav LDNS_FREE(data);
165117d15b25SDag-Erling Smørgrav return LDNS_STATUS_INVALID_B64;
165217d15b25SDag-Erling Smørgrav }
165317d15b25SDag-Erling Smørgrav
165417d15b25SDag-Erling Smørgrav /* Because ldns_b64_pton_calculate_size isn't always correct:
165517d15b25SDag-Erling Smørgrav * (we have to fix it at some point)
165617d15b25SDag-Erling Smørgrav */
165717d15b25SDag-Erling Smørgrav pk_wire_size = (uint16_t) written;
165817d15b25SDag-Erling Smørgrav ldns_write_uint16(data + 2, pk_wire_size);
165917d15b25SDag-Erling Smørgrav rdf_size = 4 + hit_wire_size + pk_wire_size;
166017d15b25SDag-Erling Smørgrav
166117d15b25SDag-Erling Smørgrav /* Create rdf */
166217d15b25SDag-Erling Smørgrav if (! (*rd = ldns_rdf_new(LDNS_RDF_TYPE_HIP, rdf_size, data))) {
166317d15b25SDag-Erling Smørgrav
166417d15b25SDag-Erling Smørgrav LDNS_FREE(data);
166517d15b25SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
166617d15b25SDag-Erling Smørgrav }
166717d15b25SDag-Erling Smørgrav return LDNS_STATUS_OK;
166817d15b25SDag-Erling Smørgrav }
1669*5afab0e5SDag-Erling Smørgrav
1670*5afab0e5SDag-Erling Smørgrav
1671*5afab0e5SDag-Erling Smørgrav /* Implementation mimics ldns_str2rdf_ipseckey */
1672*5afab0e5SDag-Erling Smørgrav ldns_status
ldns_str2rdf_amtrelay(ldns_rdf ** rd,const char * str)1673*5afab0e5SDag-Erling Smørgrav ldns_str2rdf_amtrelay(ldns_rdf **rd, const char *str)
1674*5afab0e5SDag-Erling Smørgrav {
1675*5afab0e5SDag-Erling Smørgrav /* From draft-ietf-mboned-driad-amt-discovery
1676*5afab0e5SDag-Erling Smørgrav * Section 4.2. AMTRELAY RData Format
1677*5afab0e5SDag-Erling Smørgrav *************************************************
1678*5afab0e5SDag-Erling Smørgrav
1679*5afab0e5SDag-Erling Smørgrav 0 1 2 3
1680*5afab0e5SDag-Erling Smørgrav 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
1681*5afab0e5SDag-Erling Smørgrav +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1682*5afab0e5SDag-Erling Smørgrav | precedence |D| type | |
1683*5afab0e5SDag-Erling Smørgrav +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
1684*5afab0e5SDag-Erling Smørgrav ~ relay ~
1685*5afab0e5SDag-Erling Smørgrav +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
1686*5afab0e5SDag-Erling Smørgrav
1687*5afab0e5SDag-Erling Smørgrav uint8_t precedence = 0;
1688*5afab0e5SDag-Erling Smørgrav uint8_t relay_type = 0;
1689*5afab0e5SDag-Erling Smørgrav uint8_t discovery_optional = 0;
1690*5afab0e5SDag-Erling Smørgrav char* relay = NULL;
1691*5afab0e5SDag-Erling Smørgrav uint8_t *data;
1692*5afab0e5SDag-Erling Smørgrav ldns_buffer *str_buf;
1693*5afab0e5SDag-Erling Smørgrav char *token;
1694*5afab0e5SDag-Erling Smørgrav int token_count = 0;
1695*5afab0e5SDag-Erling Smørgrav int amtrelay_len = 0;
1696*5afab0e5SDag-Erling Smørgrav ldns_rdf* relay_rdf = NULL;
1697*5afab0e5SDag-Erling Smørgrav ldns_status status = LDNS_STATUS_OK;
1698*5afab0e5SDag-Erling Smørgrav
1699*5afab0e5SDag-Erling Smørgrav if(strlen(str) == 0)
1700*5afab0e5SDag-Erling Smørgrav token = LDNS_XMALLOC(char, 256);
1701*5afab0e5SDag-Erling Smørgrav else token = LDNS_XMALLOC(char, strlen(str)+2);
1702*5afab0e5SDag-Erling Smørgrav if(!token) return LDNS_STATUS_MEM_ERR;
1703*5afab0e5SDag-Erling Smørgrav
1704*5afab0e5SDag-Erling Smørgrav str_buf = LDNS_MALLOC(ldns_buffer);
1705*5afab0e5SDag-Erling Smørgrav if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;}
1706*5afab0e5SDag-Erling Smørgrav ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
1707*5afab0e5SDag-Erling Smørgrav if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) {
1708*5afab0e5SDag-Erling Smørgrav LDNS_FREE(str_buf);
1709*5afab0e5SDag-Erling Smørgrav LDNS_FREE(token);
1710*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
1711*5afab0e5SDag-Erling Smørgrav }
1712*5afab0e5SDag-Erling Smørgrav while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) {
1713*5afab0e5SDag-Erling Smørgrav switch (token_count) {
1714*5afab0e5SDag-Erling Smørgrav case 0:
1715*5afab0e5SDag-Erling Smørgrav precedence = (uint8_t)atoi(token);
1716*5afab0e5SDag-Erling Smørgrav break;
1717*5afab0e5SDag-Erling Smørgrav case 1:
1718*5afab0e5SDag-Erling Smørgrav discovery_optional = (uint8_t)atoi(token);
1719*5afab0e5SDag-Erling Smørgrav if (discovery_optional != 0 &&
1720*5afab0e5SDag-Erling Smørgrav discovery_optional != 1) {
1721*5afab0e5SDag-Erling Smørgrav LDNS_FREE(relay);
1722*5afab0e5SDag-Erling Smørgrav LDNS_FREE(token);
1723*5afab0e5SDag-Erling Smørgrav ldns_buffer_free(str_buf);
1724*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
1725*5afab0e5SDag-Erling Smørgrav }
1726*5afab0e5SDag-Erling Smørgrav break;
1727*5afab0e5SDag-Erling Smørgrav case 2:
1728*5afab0e5SDag-Erling Smørgrav relay_type = (uint8_t)atoi(token);
1729*5afab0e5SDag-Erling Smørgrav break;
1730*5afab0e5SDag-Erling Smørgrav case 3:
1731*5afab0e5SDag-Erling Smørgrav relay = strdup(token);
1732*5afab0e5SDag-Erling Smørgrav if (!relay || (relay_type == 0 &&
1733*5afab0e5SDag-Erling Smørgrav (token[0] != '.' || token[1] != '\0'))) {
1734*5afab0e5SDag-Erling Smørgrav LDNS_FREE(relay);
1735*5afab0e5SDag-Erling Smørgrav LDNS_FREE(token);
1736*5afab0e5SDag-Erling Smørgrav ldns_buffer_free(str_buf);
1737*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
1738*5afab0e5SDag-Erling Smørgrav }
1739*5afab0e5SDag-Erling Smørgrav break;
1740*5afab0e5SDag-Erling Smørgrav default:
1741*5afab0e5SDag-Erling Smørgrav LDNS_FREE(token);
1742*5afab0e5SDag-Erling Smørgrav ldns_buffer_free(str_buf);
1743*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
1744*5afab0e5SDag-Erling Smørgrav break;
1745*5afab0e5SDag-Erling Smørgrav }
1746*5afab0e5SDag-Erling Smørgrav token_count++;
1747*5afab0e5SDag-Erling Smørgrav }
1748*5afab0e5SDag-Erling Smørgrav if (!relay && relay_type > 0) {
1749*5afab0e5SDag-Erling Smørgrav if (relay)
1750*5afab0e5SDag-Erling Smørgrav LDNS_FREE(relay);
1751*5afab0e5SDag-Erling Smørgrav LDNS_FREE(token);
1752*5afab0e5SDag-Erling Smørgrav ldns_buffer_free(str_buf);
1753*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
1754*5afab0e5SDag-Erling Smørgrav }
1755*5afab0e5SDag-Erling Smørgrav
1756*5afab0e5SDag-Erling Smørgrav if (relay_type == 1) {
1757*5afab0e5SDag-Erling Smørgrav status = ldns_str2rdf_a(&relay_rdf, relay);
1758*5afab0e5SDag-Erling Smørgrav } else if (relay_type == 2) {
1759*5afab0e5SDag-Erling Smørgrav status = ldns_str2rdf_aaaa(&relay_rdf, relay);
1760*5afab0e5SDag-Erling Smørgrav } else if (relay_type == 3) {
1761*5afab0e5SDag-Erling Smørgrav status = ldns_str2rdf_dname(&relay_rdf, relay);
1762*5afab0e5SDag-Erling Smørgrav } else if (relay_type > 3) {
1763*5afab0e5SDag-Erling Smørgrav status = LDNS_STATUS_INVALID_STR;
1764*5afab0e5SDag-Erling Smørgrav }
1765*5afab0e5SDag-Erling Smørgrav
1766*5afab0e5SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) {
1767*5afab0e5SDag-Erling Smørgrav if (relay)
1768*5afab0e5SDag-Erling Smørgrav LDNS_FREE(relay);
1769*5afab0e5SDag-Erling Smørgrav LDNS_FREE(token);
1770*5afab0e5SDag-Erling Smørgrav ldns_buffer_free(str_buf);
1771*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
1772*5afab0e5SDag-Erling Smørgrav }
1773*5afab0e5SDag-Erling Smørgrav
1774*5afab0e5SDag-Erling Smørgrav /* now copy all into one amtrelay rdf */
1775*5afab0e5SDag-Erling Smørgrav if (relay_type)
1776*5afab0e5SDag-Erling Smørgrav amtrelay_len = 2 + (int)ldns_rdf_size(relay_rdf);
1777*5afab0e5SDag-Erling Smørgrav else
1778*5afab0e5SDag-Erling Smørgrav amtrelay_len = 2;
1779*5afab0e5SDag-Erling Smørgrav
1780*5afab0e5SDag-Erling Smørgrav data = LDNS_XMALLOC(uint8_t, amtrelay_len);
1781*5afab0e5SDag-Erling Smørgrav if(!data) {
1782*5afab0e5SDag-Erling Smørgrav if (relay)
1783*5afab0e5SDag-Erling Smørgrav LDNS_FREE(relay);
1784*5afab0e5SDag-Erling Smørgrav LDNS_FREE(token);
1785*5afab0e5SDag-Erling Smørgrav ldns_buffer_free(str_buf);
1786*5afab0e5SDag-Erling Smørgrav if (relay_rdf) ldns_rdf_free(relay_rdf);
1787*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
1788*5afab0e5SDag-Erling Smørgrav }
1789*5afab0e5SDag-Erling Smørgrav
1790*5afab0e5SDag-Erling Smørgrav data[0] = precedence;
1791*5afab0e5SDag-Erling Smørgrav data[1] = relay_type;
1792*5afab0e5SDag-Erling Smørgrav data[1] |= (discovery_optional << 7);
1793*5afab0e5SDag-Erling Smørgrav
1794*5afab0e5SDag-Erling Smørgrav if (relay_type) {
1795*5afab0e5SDag-Erling Smørgrav memcpy(data + 2,
1796*5afab0e5SDag-Erling Smørgrav ldns_rdf_data(relay_rdf), ldns_rdf_size(relay_rdf));
1797*5afab0e5SDag-Erling Smørgrav }
1798*5afab0e5SDag-Erling Smørgrav *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_AMTRELAY
1799*5afab0e5SDag-Erling Smørgrav , (uint16_t) amtrelay_len, data);
1800*5afab0e5SDag-Erling Smørgrav
1801*5afab0e5SDag-Erling Smørgrav if (relay)
1802*5afab0e5SDag-Erling Smørgrav LDNS_FREE(relay);
1803*5afab0e5SDag-Erling Smørgrav LDNS_FREE(token);
1804*5afab0e5SDag-Erling Smørgrav ldns_buffer_free(str_buf);
1805*5afab0e5SDag-Erling Smørgrav ldns_rdf_free(relay_rdf);
1806*5afab0e5SDag-Erling Smørgrav LDNS_FREE(data);
1807*5afab0e5SDag-Erling Smørgrav if(!*rd) return LDNS_STATUS_MEM_ERR;
1808*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_OK;
1809*5afab0e5SDag-Erling Smørgrav }
1810*5afab0e5SDag-Erling Smørgrav
1811*5afab0e5SDag-Erling Smørgrav #ifdef RRTYPE_SVCB_HTTPS
1812*5afab0e5SDag-Erling Smørgrav static int
network_uint16_cmp(const void * a,const void * b)1813*5afab0e5SDag-Erling Smørgrav network_uint16_cmp(const void *a, const void *b)
1814*5afab0e5SDag-Erling Smørgrav {
1815*5afab0e5SDag-Erling Smørgrav return ((int)ldns_read_uint16(a)) - ((int)ldns_read_uint16(b));
1816*5afab0e5SDag-Erling Smørgrav }
1817*5afab0e5SDag-Erling Smørgrav
1818*5afab0e5SDag-Erling Smørgrav static ldns_status parse_svcparam_key(const char **s, ldns_svcparam_key *key);
1819*5afab0e5SDag-Erling Smørgrav static ldns_status
parse_svcparam_mandatory(const char ** s,uint8_t ** dp,uint8_t * eod)1820*5afab0e5SDag-Erling Smørgrav parse_svcparam_mandatory(const char **s, uint8_t **dp, uint8_t *eod)
1821*5afab0e5SDag-Erling Smørgrav {
1822*5afab0e5SDag-Erling Smørgrav bool quoted = false;
1823*5afab0e5SDag-Erling Smørgrav uint8_t *keys = *dp;
1824*5afab0e5SDag-Erling Smørgrav int prev_key;
1825*5afab0e5SDag-Erling Smørgrav
1826*5afab0e5SDag-Erling Smørgrav if (**s == '"') {
1827*5afab0e5SDag-Erling Smørgrav *s += 1;
1828*5afab0e5SDag-Erling Smørgrav quoted = true;
1829*5afab0e5SDag-Erling Smørgrav }
1830*5afab0e5SDag-Erling Smørgrav for (;;) {
1831*5afab0e5SDag-Erling Smørgrav ldns_status st;
1832*5afab0e5SDag-Erling Smørgrav ldns_svcparam_key key;
1833*5afab0e5SDag-Erling Smørgrav
1834*5afab0e5SDag-Erling Smørgrav if ((st = parse_svcparam_key(s, &key)))
1835*5afab0e5SDag-Erling Smørgrav return st;
1836*5afab0e5SDag-Erling Smørgrav
1837*5afab0e5SDag-Erling Smørgrav if (*dp + 2 > eod)
1838*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_RDATA_OVERFLOW;
1839*5afab0e5SDag-Erling Smørgrav
1840*5afab0e5SDag-Erling Smørgrav ldns_write_uint16(*dp, key);
1841*5afab0e5SDag-Erling Smørgrav *dp += 2;
1842*5afab0e5SDag-Erling Smørgrav
1843*5afab0e5SDag-Erling Smørgrav if (**s == ',')
1844*5afab0e5SDag-Erling Smørgrav *s += 1;
1845*5afab0e5SDag-Erling Smørgrav else
1846*5afab0e5SDag-Erling Smørgrav break;
1847*5afab0e5SDag-Erling Smørgrav }
1848*5afab0e5SDag-Erling Smørgrav if (quoted) {
1849*5afab0e5SDag-Erling Smørgrav if (**s != '"')
1850*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
1851*5afab0e5SDag-Erling Smørgrav *s += 1;
1852*5afab0e5SDag-Erling Smørgrav }
1853*5afab0e5SDag-Erling Smørgrav if (*dp - keys == 0)
1854*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR;
1855*5afab0e5SDag-Erling Smørgrav
1856*5afab0e5SDag-Erling Smørgrav if (**s && !isspace((unsigned char)**s))
1857*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR;
1858*5afab0e5SDag-Erling Smørgrav
1859*5afab0e5SDag-Erling Smørgrav /* In draft-ietf-dnsop-svcb-https-02 Section 7:
1860*5afab0e5SDag-Erling Smørgrav *
1861*5afab0e5SDag-Erling Smørgrav * In wire format, the keys are represented by their numeric
1862*5afab0e5SDag-Erling Smørgrav * values in network byte order, concatenated in ascending order.
1863*5afab0e5SDag-Erling Smørgrav */
1864*5afab0e5SDag-Erling Smørgrav qsort(keys, (*dp - keys) / 2, 2, network_uint16_cmp);
1865*5afab0e5SDag-Erling Smørgrav
1866*5afab0e5SDag-Erling Smørgrav /* In draft-ietf-dnsop-svcb-https-02 Section 7:
1867*5afab0e5SDag-Erling Smørgrav *
1868*5afab0e5SDag-Erling Smørgrav * Keys ...<snip>... MUST NOT appear more than once.
1869*5afab0e5SDag-Erling Smørgrav */
1870*5afab0e5SDag-Erling Smørgrav prev_key = -1;
1871*5afab0e5SDag-Erling Smørgrav while (keys < *dp) {
1872*5afab0e5SDag-Erling Smørgrav uint16_t key = ldns_read_uint16(keys);
1873*5afab0e5SDag-Erling Smørgrav
1874*5afab0e5SDag-Erling Smørgrav if (key == prev_key) {
1875*5afab0e5SDag-Erling Smørgrav /* "Be conservative in what you send,
1876*5afab0e5SDag-Erling Smørgrav * be liberal in what you accept"
1877*5afab0e5SDag-Erling Smørgrav *
1878*5afab0e5SDag-Erling Smørgrav * Instead of
1879*5afab0e5SDag-Erling Smørgrav * `return LDNS_STATUS_SVCPARAM_KEY_MORE_THAN_ONCE;`,
1880*5afab0e5SDag-Erling Smørgrav *
1881*5afab0e5SDag-Erling Smørgrav * we eliminate the double occurrence.
1882*5afab0e5SDag-Erling Smørgrav */
1883*5afab0e5SDag-Erling Smørgrav memmove(keys - 2, keys, *dp - keys);
1884*5afab0e5SDag-Erling Smørgrav *dp -= 2;
1885*5afab0e5SDag-Erling Smørgrav } else {
1886*5afab0e5SDag-Erling Smørgrav prev_key = key;
1887*5afab0e5SDag-Erling Smørgrav keys += 2;
1888*5afab0e5SDag-Erling Smørgrav }
1889*5afab0e5SDag-Erling Smørgrav }
1890*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_OK;
1891*5afab0e5SDag-Erling Smørgrav }
1892*5afab0e5SDag-Erling Smørgrav
parse_escape2(uint8_t * ch_p,const char ** str_p)1893*5afab0e5SDag-Erling Smørgrav INLINE bool parse_escape2(uint8_t *ch_p, const char** str_p)
1894*5afab0e5SDag-Erling Smørgrav { *str_p += 1; return parse_escape(ch_p, str_p); }
1895*5afab0e5SDag-Erling Smørgrav
1896*5afab0e5SDag-Erling Smørgrav static ldns_status
parse_svcparam_alpn(const char ** s,uint8_t ** dp,uint8_t * eod)1897*5afab0e5SDag-Erling Smørgrav parse_svcparam_alpn(const char **s, uint8_t **dp, uint8_t *eod)
1898*5afab0e5SDag-Erling Smørgrav {
1899*5afab0e5SDag-Erling Smørgrav uint8_t *val;
1900*5afab0e5SDag-Erling Smørgrav size_t len;
1901*5afab0e5SDag-Erling Smørgrav
1902*5afab0e5SDag-Erling Smørgrav if (*dp + 1 > eod)
1903*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_RDATA_OVERFLOW;
1904*5afab0e5SDag-Erling Smørgrav *dp += 1;
1905*5afab0e5SDag-Erling Smørgrav val = *dp;
1906*5afab0e5SDag-Erling Smørgrav if (**s == '"') {
1907*5afab0e5SDag-Erling Smørgrav *s += 1;
1908*5afab0e5SDag-Erling Smørgrav while (**s != '"') {
1909*5afab0e5SDag-Erling Smørgrav if (**s == 0)
1910*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
1911*5afab0e5SDag-Erling Smørgrav
1912*5afab0e5SDag-Erling Smørgrav else if (**s == ',') {
1913*5afab0e5SDag-Erling Smørgrav len = *dp - val;
1914*5afab0e5SDag-Erling Smørgrav if (len == 0 || len > 255)
1915*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
1916*5afab0e5SDag-Erling Smørgrav val[-1] = len;
1917*5afab0e5SDag-Erling Smørgrav if (*dp + 1 > eod)
1918*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_RDATA_OVERFLOW;
1919*5afab0e5SDag-Erling Smørgrav *dp += 1;
1920*5afab0e5SDag-Erling Smørgrav val = *dp;
1921*5afab0e5SDag-Erling Smørgrav *s += 1;
1922*5afab0e5SDag-Erling Smørgrav
1923*5afab0e5SDag-Erling Smørgrav } else if (*dp + 1 > eod)
1924*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_RDATA_OVERFLOW;
1925*5afab0e5SDag-Erling Smørgrav
1926*5afab0e5SDag-Erling Smørgrav else if (**s != '\\')
1927*5afab0e5SDag-Erling Smørgrav *(*dp)++ = (uint8_t)*(*s)++;
1928*5afab0e5SDag-Erling Smørgrav
1929*5afab0e5SDag-Erling Smørgrav else if (!parse_escape2(*dp, s))
1930*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
1931*5afab0e5SDag-Erling Smørgrav else
1932*5afab0e5SDag-Erling Smørgrav *dp += 1;
1933*5afab0e5SDag-Erling Smørgrav }
1934*5afab0e5SDag-Erling Smørgrav *s += 1;
1935*5afab0e5SDag-Erling Smørgrav
1936*5afab0e5SDag-Erling Smørgrav } else while (**s && !isspace((unsigned char)**s)) {
1937*5afab0e5SDag-Erling Smørgrav if (**s == ',') {
1938*5afab0e5SDag-Erling Smørgrav len = *dp - val;
1939*5afab0e5SDag-Erling Smørgrav if (len == 0 || len > 255)
1940*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
1941*5afab0e5SDag-Erling Smørgrav val[-1] = len;
1942*5afab0e5SDag-Erling Smørgrav if (*dp + 1 > eod)
1943*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_RDATA_OVERFLOW;
1944*5afab0e5SDag-Erling Smørgrav *dp += 1;
1945*5afab0e5SDag-Erling Smørgrav val = *dp;
1946*5afab0e5SDag-Erling Smørgrav *s += 1;
1947*5afab0e5SDag-Erling Smørgrav
1948*5afab0e5SDag-Erling Smørgrav } else if (*dp + 1 > eod)
1949*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_RDATA_OVERFLOW;
1950*5afab0e5SDag-Erling Smørgrav
1951*5afab0e5SDag-Erling Smørgrav else if (**s != '\\')
1952*5afab0e5SDag-Erling Smørgrav *(*dp)++ = (uint8_t)*(*s)++;
1953*5afab0e5SDag-Erling Smørgrav
1954*5afab0e5SDag-Erling Smørgrav else if (!parse_escape2(*dp, s))
1955*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
1956*5afab0e5SDag-Erling Smørgrav else
1957*5afab0e5SDag-Erling Smørgrav *dp += 1;
1958*5afab0e5SDag-Erling Smørgrav }
1959*5afab0e5SDag-Erling Smørgrav len = *dp - val;
1960*5afab0e5SDag-Erling Smørgrav if (len == 0 || len > 255)
1961*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
1962*5afab0e5SDag-Erling Smørgrav val[-1] = len;
1963*5afab0e5SDag-Erling Smørgrav return **s && !isspace((unsigned char)**s)
1964*5afab0e5SDag-Erling Smørgrav ? LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR
1965*5afab0e5SDag-Erling Smørgrav : LDNS_STATUS_OK;
1966*5afab0e5SDag-Erling Smørgrav }
1967*5afab0e5SDag-Erling Smørgrav
1968*5afab0e5SDag-Erling Smørgrav static ldns_status
parse_svcparam_value(const char ** s,uint8_t ** dp,uint8_t * eod)1969*5afab0e5SDag-Erling Smørgrav parse_svcparam_value(const char **s, uint8_t **dp, uint8_t *eod)
1970*5afab0e5SDag-Erling Smørgrav {
1971*5afab0e5SDag-Erling Smørgrav if (**s == '"') {
1972*5afab0e5SDag-Erling Smørgrav *s += 1;
1973*5afab0e5SDag-Erling Smørgrav while (**s != '"') {
1974*5afab0e5SDag-Erling Smørgrav if (**s == 0)
1975*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
1976*5afab0e5SDag-Erling Smørgrav
1977*5afab0e5SDag-Erling Smørgrav else if (*dp + 1 > eod)
1978*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_RDATA_OVERFLOW;
1979*5afab0e5SDag-Erling Smørgrav
1980*5afab0e5SDag-Erling Smørgrav else if (**s != '\\')
1981*5afab0e5SDag-Erling Smørgrav *(*dp)++ = (uint8_t)*(*s)++;
1982*5afab0e5SDag-Erling Smørgrav
1983*5afab0e5SDag-Erling Smørgrav else if (!parse_escape2(*dp, s))
1984*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
1985*5afab0e5SDag-Erling Smørgrav else
1986*5afab0e5SDag-Erling Smørgrav *dp += 1;
1987*5afab0e5SDag-Erling Smørgrav }
1988*5afab0e5SDag-Erling Smørgrav *s += 1;
1989*5afab0e5SDag-Erling Smørgrav
1990*5afab0e5SDag-Erling Smørgrav } else while (**s && !isspace((unsigned char)**s)) {
1991*5afab0e5SDag-Erling Smørgrav if (*dp + 1 > eod)
1992*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_RDATA_OVERFLOW;
1993*5afab0e5SDag-Erling Smørgrav
1994*5afab0e5SDag-Erling Smørgrav else if (**s != '\\')
1995*5afab0e5SDag-Erling Smørgrav *(*dp)++ = (uint8_t)*(*s)++;
1996*5afab0e5SDag-Erling Smørgrav
1997*5afab0e5SDag-Erling Smørgrav else if (!parse_escape2(*dp, s))
1998*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
1999*5afab0e5SDag-Erling Smørgrav else
2000*5afab0e5SDag-Erling Smørgrav *dp += 1;
2001*5afab0e5SDag-Erling Smørgrav }
2002*5afab0e5SDag-Erling Smørgrav return **s && !isspace((unsigned char)**s)
2003*5afab0e5SDag-Erling Smørgrav ? LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR
2004*5afab0e5SDag-Erling Smørgrav : LDNS_STATUS_OK;
2005*5afab0e5SDag-Erling Smørgrav }
2006*5afab0e5SDag-Erling Smørgrav
2007*5afab0e5SDag-Erling Smørgrav static ldns_status
parse_svcparam_port(const char ** s,uint8_t ** dp,uint8_t * eod)2008*5afab0e5SDag-Erling Smørgrav parse_svcparam_port(const char **s, uint8_t **dp, uint8_t *eod)
2009*5afab0e5SDag-Erling Smørgrav {
2010*5afab0e5SDag-Erling Smørgrav uint8_t *val = *dp;
2011*5afab0e5SDag-Erling Smørgrav ldns_status st;
2012*5afab0e5SDag-Erling Smørgrav size_t len;
2013*5afab0e5SDag-Erling Smørgrav char num_str[6];
2014*5afab0e5SDag-Erling Smørgrav char *endptr;
2015*5afab0e5SDag-Erling Smørgrav unsigned long int num;
2016*5afab0e5SDag-Erling Smørgrav
2017*5afab0e5SDag-Erling Smørgrav if ((st = parse_svcparam_value(s, dp, eod)))
2018*5afab0e5SDag-Erling Smørgrav return st;
2019*5afab0e5SDag-Erling Smørgrav len = *dp - val;
2020*5afab0e5SDag-Erling Smørgrav if (len == 0 || len > 5)
2021*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR;
2022*5afab0e5SDag-Erling Smørgrav
2023*5afab0e5SDag-Erling Smørgrav memcpy(num_str, val, len);
2024*5afab0e5SDag-Erling Smørgrav num_str[len] = 0;
2025*5afab0e5SDag-Erling Smørgrav num = strtoul(num_str, &endptr, 10);
2026*5afab0e5SDag-Erling Smørgrav if (*endptr)
2027*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR;
2028*5afab0e5SDag-Erling Smørgrav
2029*5afab0e5SDag-Erling Smørgrav ldns_write_uint16(val, num);
2030*5afab0e5SDag-Erling Smørgrav *dp = val + 2;
2031*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_OK;
2032*5afab0e5SDag-Erling Smørgrav }
2033*5afab0e5SDag-Erling Smørgrav
2034*5afab0e5SDag-Erling Smørgrav static ldns_status
parse_svcparam_ipv4hint(const char ** s,uint8_t ** dp,uint8_t * eod)2035*5afab0e5SDag-Erling Smørgrav parse_svcparam_ipv4hint(const char **s, uint8_t **dp, uint8_t *eod)
2036*5afab0e5SDag-Erling Smørgrav {
2037*5afab0e5SDag-Erling Smørgrav bool quoted = false;
2038*5afab0e5SDag-Erling Smørgrav
2039*5afab0e5SDag-Erling Smørgrav if (**s == '"') {
2040*5afab0e5SDag-Erling Smørgrav *s += 1;
2041*5afab0e5SDag-Erling Smørgrav quoted = true;
2042*5afab0e5SDag-Erling Smørgrav }
2043*5afab0e5SDag-Erling Smørgrav for (;;) {
2044*5afab0e5SDag-Erling Smørgrav const char *ipv4_start = *s;
2045*5afab0e5SDag-Erling Smørgrav char ipv4_str[16];
2046*5afab0e5SDag-Erling Smørgrav size_t len;
2047*5afab0e5SDag-Erling Smørgrav
2048*5afab0e5SDag-Erling Smørgrav while (isdigit((unsigned char)**s) || **s == '.')
2049*5afab0e5SDag-Erling Smørgrav *s += 1;
2050*5afab0e5SDag-Erling Smørgrav
2051*5afab0e5SDag-Erling Smørgrav len = *s - ipv4_start;
2052*5afab0e5SDag-Erling Smørgrav if (len == 0 || len > 15)
2053*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR;
2054*5afab0e5SDag-Erling Smørgrav
2055*5afab0e5SDag-Erling Smørgrav if (*dp + 4 > eod)
2056*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_RDATA_OVERFLOW;
2057*5afab0e5SDag-Erling Smørgrav
2058*5afab0e5SDag-Erling Smørgrav memcpy(ipv4_str, ipv4_start, len);
2059*5afab0e5SDag-Erling Smørgrav ipv4_str[len] = 0;
2060*5afab0e5SDag-Erling Smørgrav if (inet_pton(AF_INET, ipv4_str, *dp) != 1)
2061*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR;
2062*5afab0e5SDag-Erling Smørgrav
2063*5afab0e5SDag-Erling Smørgrav *dp += 4;
2064*5afab0e5SDag-Erling Smørgrav if (**s == ',')
2065*5afab0e5SDag-Erling Smørgrav *s += 1;
2066*5afab0e5SDag-Erling Smørgrav else
2067*5afab0e5SDag-Erling Smørgrav break;
2068*5afab0e5SDag-Erling Smørgrav }
2069*5afab0e5SDag-Erling Smørgrav if (quoted) {
2070*5afab0e5SDag-Erling Smørgrav if (**s != '"')
2071*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
2072*5afab0e5SDag-Erling Smørgrav *s += 1;
2073*5afab0e5SDag-Erling Smørgrav }
2074*5afab0e5SDag-Erling Smørgrav return **s && !isspace((unsigned char)**s)
2075*5afab0e5SDag-Erling Smørgrav ? LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR
2076*5afab0e5SDag-Erling Smørgrav : LDNS_STATUS_OK;
2077*5afab0e5SDag-Erling Smørgrav }
2078*5afab0e5SDag-Erling Smørgrav
2079*5afab0e5SDag-Erling Smørgrav static ldns_status
parse_svcparam_ech(const char ** s,uint8_t ** dp,uint8_t * eod)2080*5afab0e5SDag-Erling Smørgrav parse_svcparam_ech(const char **s, uint8_t **dp, uint8_t *eod)
2081*5afab0e5SDag-Erling Smørgrav {
2082*5afab0e5SDag-Erling Smørgrav bool quoted = false;
2083*5afab0e5SDag-Erling Smørgrav const char *b64_str;
2084*5afab0e5SDag-Erling Smørgrav size_t len, pad, out_len;
2085*5afab0e5SDag-Erling Smørgrav char in_buf[4096];
2086*5afab0e5SDag-Erling Smørgrav char *in = in_buf;
2087*5afab0e5SDag-Erling Smørgrav int out;
2088*5afab0e5SDag-Erling Smørgrav
2089*5afab0e5SDag-Erling Smørgrav if (**s == '"') {
2090*5afab0e5SDag-Erling Smørgrav *s += 1;
2091*5afab0e5SDag-Erling Smørgrav quoted = true;
2092*5afab0e5SDag-Erling Smørgrav }
2093*5afab0e5SDag-Erling Smørgrav b64_str = *s;
2094*5afab0e5SDag-Erling Smørgrav while (isalnum((unsigned char)**s) || **s == '+'
2095*5afab0e5SDag-Erling Smørgrav || **s == '/'
2096*5afab0e5SDag-Erling Smørgrav || **s == '=')
2097*5afab0e5SDag-Erling Smørgrav *s += 1;
2098*5afab0e5SDag-Erling Smørgrav
2099*5afab0e5SDag-Erling Smørgrav len = *s - b64_str;
2100*5afab0e5SDag-Erling Smørgrav pad = len % 4;
2101*5afab0e5SDag-Erling Smørgrav pad = pad ? 4 - pad : 0;
2102*5afab0e5SDag-Erling Smørgrav if (len == 0 || pad == 3)
2103*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR;
2104*5afab0e5SDag-Erling Smørgrav
2105*5afab0e5SDag-Erling Smørgrav if (quoted) {
2106*5afab0e5SDag-Erling Smørgrav if (**s != '"')
2107*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
2108*5afab0e5SDag-Erling Smørgrav *s += 1;
2109*5afab0e5SDag-Erling Smørgrav }
2110*5afab0e5SDag-Erling Smørgrav if (**s && !isspace((unsigned char)**s))
2111*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR;
2112*5afab0e5SDag-Erling Smørgrav
2113*5afab0e5SDag-Erling Smørgrav out_len = ldns_b64_pton_calculate_size(len);
2114*5afab0e5SDag-Erling Smørgrav if (*dp + out_len > eod)
2115*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_RDATA_OVERFLOW;
2116*5afab0e5SDag-Erling Smørgrav
2117*5afab0e5SDag-Erling Smørgrav if (len + pad > sizeof(in_buf) - 1
2118*5afab0e5SDag-Erling Smørgrav && !(in = LDNS_XMALLOC(char, len + pad + 1)))
2119*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
2120*5afab0e5SDag-Erling Smørgrav
2121*5afab0e5SDag-Erling Smørgrav memcpy(in, b64_str, len);
2122*5afab0e5SDag-Erling Smørgrav while (pad--)
2123*5afab0e5SDag-Erling Smørgrav in[len++] = '=';
2124*5afab0e5SDag-Erling Smørgrav in[len] = 0;
2125*5afab0e5SDag-Erling Smørgrav out = ldns_b64_pton(in, *dp, out_len);
2126*5afab0e5SDag-Erling Smørgrav if (in != in_buf)
2127*5afab0e5SDag-Erling Smørgrav LDNS_FREE(in);
2128*5afab0e5SDag-Erling Smørgrav
2129*5afab0e5SDag-Erling Smørgrav if (out <= 0)
2130*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR;
2131*5afab0e5SDag-Erling Smørgrav
2132*5afab0e5SDag-Erling Smørgrav *dp += out;
2133*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_OK;
2134*5afab0e5SDag-Erling Smørgrav }
2135*5afab0e5SDag-Erling Smørgrav
2136*5afab0e5SDag-Erling Smørgrav static ldns_status
parse_svcparam_ipv6hint(const char ** s,uint8_t ** dp,uint8_t * eod)2137*5afab0e5SDag-Erling Smørgrav parse_svcparam_ipv6hint(const char **s, uint8_t **dp, uint8_t *eod)
2138*5afab0e5SDag-Erling Smørgrav {
2139*5afab0e5SDag-Erling Smørgrav bool quoted = false;
2140*5afab0e5SDag-Erling Smørgrav
2141*5afab0e5SDag-Erling Smørgrav if (**s == '"') {
2142*5afab0e5SDag-Erling Smørgrav *s += 1;
2143*5afab0e5SDag-Erling Smørgrav quoted = true;
2144*5afab0e5SDag-Erling Smørgrav }
2145*5afab0e5SDag-Erling Smørgrav for (;;) {
2146*5afab0e5SDag-Erling Smørgrav const char *ipv6_start = *s;
2147*5afab0e5SDag-Erling Smørgrav char ipv6_str[INET6_ADDRSTRLEN];
2148*5afab0e5SDag-Erling Smørgrav size_t len;
2149*5afab0e5SDag-Erling Smørgrav
2150*5afab0e5SDag-Erling Smørgrav while (isxdigit((unsigned char)**s) || **s == ':' || **s == '.')
2151*5afab0e5SDag-Erling Smørgrav *s += 1;
2152*5afab0e5SDag-Erling Smørgrav
2153*5afab0e5SDag-Erling Smørgrav len = *s - ipv6_start;
2154*5afab0e5SDag-Erling Smørgrav if (len == 0 || len > INET6_ADDRSTRLEN)
2155*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR;
2156*5afab0e5SDag-Erling Smørgrav
2157*5afab0e5SDag-Erling Smørgrav if (*dp + 16 > eod)
2158*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_RDATA_OVERFLOW;
2159*5afab0e5SDag-Erling Smørgrav
2160*5afab0e5SDag-Erling Smørgrav memcpy(ipv6_str, ipv6_start, len);
2161*5afab0e5SDag-Erling Smørgrav ipv6_str[len] = 0;
2162*5afab0e5SDag-Erling Smørgrav if (inet_pton(AF_INET6, ipv6_str, *dp) != 1)
2163*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR;
2164*5afab0e5SDag-Erling Smørgrav
2165*5afab0e5SDag-Erling Smørgrav *dp += 16;
2166*5afab0e5SDag-Erling Smørgrav if (**s == ',')
2167*5afab0e5SDag-Erling Smørgrav *s += 1;
2168*5afab0e5SDag-Erling Smørgrav else
2169*5afab0e5SDag-Erling Smørgrav break;
2170*5afab0e5SDag-Erling Smørgrav }
2171*5afab0e5SDag-Erling Smørgrav if (quoted) {
2172*5afab0e5SDag-Erling Smørgrav if (**s != '"')
2173*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_INVALID_STR;
2174*5afab0e5SDag-Erling Smørgrav *s += 1;
2175*5afab0e5SDag-Erling Smørgrav }
2176*5afab0e5SDag-Erling Smørgrav return **s && !isspace((unsigned char)**s)
2177*5afab0e5SDag-Erling Smørgrav ? LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR
2178*5afab0e5SDag-Erling Smørgrav : LDNS_STATUS_OK;
2179*5afab0e5SDag-Erling Smørgrav }
2180*5afab0e5SDag-Erling Smørgrav
2181*5afab0e5SDag-Erling Smørgrav struct struct_svcparam_key_def {
2182*5afab0e5SDag-Erling Smørgrav const char *str;
2183*5afab0e5SDag-Erling Smørgrav size_t len;
2184*5afab0e5SDag-Erling Smørgrav };
2185*5afab0e5SDag-Erling Smørgrav typedef struct struct_svcparam_key_def svcparam_key_def;
2186*5afab0e5SDag-Erling Smørgrav
2187*5afab0e5SDag-Erling Smørgrav static svcparam_key_def svcparam_key_defs[] = { { "mandatory" , 9 }
2188*5afab0e5SDag-Erling Smørgrav , { "alpn" , 4 }
2189*5afab0e5SDag-Erling Smørgrav , { "no-default-alpn", 15 }
2190*5afab0e5SDag-Erling Smørgrav , { "port" , 4 }
2191*5afab0e5SDag-Erling Smørgrav , { "ipv4hint" , 8 }
2192*5afab0e5SDag-Erling Smørgrav , { "ech" , 3 }
2193*5afab0e5SDag-Erling Smørgrav , { "ipv6hint" , 8 }
2194*5afab0e5SDag-Erling Smørgrav , { "dohpath" , 7 } };
2195*5afab0e5SDag-Erling Smørgrav
2196*5afab0e5SDag-Erling Smørgrav static const size_t svcparam_key_defs_len = sizeof(svcparam_key_defs)
2197*5afab0e5SDag-Erling Smørgrav / sizeof(svcparam_key_def);
2198*5afab0e5SDag-Erling Smørgrav
2199*5afab0e5SDag-Erling Smørgrav /* svcparam_key2buffer_str() should actually be in host2str.c, but we need the
2200*5afab0e5SDag-Erling Smørgrav * svcparam_key_defs for it and it is not an exposed symbol anyway.
2201*5afab0e5SDag-Erling Smørgrav */
svcparam_key2buffer_str(ldns_buffer * output,uint16_t key)2202*5afab0e5SDag-Erling Smørgrav ldns_status svcparam_key2buffer_str(ldns_buffer *output, uint16_t key)
2203*5afab0e5SDag-Erling Smørgrav {
2204*5afab0e5SDag-Erling Smørgrav if (key <= LDNS_SVCPARAM_KEY_LAST_KEY)
2205*5afab0e5SDag-Erling Smørgrav ldns_buffer_write_string(output, svcparam_key_defs[key].str);
2206*5afab0e5SDag-Erling Smørgrav else
2207*5afab0e5SDag-Erling Smørgrav ldns_buffer_printf(output, "key%d", (int)key);
2208*5afab0e5SDag-Erling Smørgrav return ldns_buffer_status(output);
2209*5afab0e5SDag-Erling Smørgrav }
2210*5afab0e5SDag-Erling Smørgrav
2211*5afab0e5SDag-Erling Smørgrav static ldns_status
parse_svcparam_key(const char ** s,ldns_svcparam_key * key)2212*5afab0e5SDag-Erling Smørgrav parse_svcparam_key(const char **s, ldns_svcparam_key *key)
2213*5afab0e5SDag-Erling Smørgrav {
2214*5afab0e5SDag-Erling Smørgrav size_t i, len;
2215*5afab0e5SDag-Erling Smørgrav const char *key_str = *s;
2216*5afab0e5SDag-Erling Smørgrav char num_str[6];
2217*5afab0e5SDag-Erling Smørgrav char *endptr;
2218*5afab0e5SDag-Erling Smørgrav unsigned long int num;
2219*5afab0e5SDag-Erling Smørgrav
2220*5afab0e5SDag-Erling Smørgrav /* parse key */
2221*5afab0e5SDag-Erling Smørgrav while (islower((unsigned char)**s) || isdigit((unsigned char)**s)
2222*5afab0e5SDag-Erling Smørgrav || **s == '-')
2223*5afab0e5SDag-Erling Smørgrav *s += 1;
2224*5afab0e5SDag-Erling Smørgrav
2225*5afab0e5SDag-Erling Smørgrav len = *s - key_str;
2226*5afab0e5SDag-Erling Smørgrav for (i = 0; i < svcparam_key_defs_len; i++) {
2227*5afab0e5SDag-Erling Smørgrav if (len == svcparam_key_defs[i].len
2228*5afab0e5SDag-Erling Smørgrav && !strncmp(key_str, svcparam_key_defs[i].str, len)) {
2229*5afab0e5SDag-Erling Smørgrav *key = i;
2230*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_OK;
2231*5afab0e5SDag-Erling Smørgrav }
2232*5afab0e5SDag-Erling Smørgrav }
2233*5afab0e5SDag-Erling Smørgrav /* Also allow "echconfig" from earlier draft versions. */
2234*5afab0e5SDag-Erling Smørgrav if (len == 9 && !strncmp(key_str, "echconfig", 9)) {
2235*5afab0e5SDag-Erling Smørgrav *key = LDNS_SVCPARAM_KEY_ECH;
2236*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_OK;
2237*5afab0e5SDag-Erling Smørgrav }
2238*5afab0e5SDag-Erling Smørgrav if (len < 4 || len > 8 || strncmp(key_str, "key", 3))
2239*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_SVCPARAM_KEY_ERR;
2240*5afab0e5SDag-Erling Smørgrav
2241*5afab0e5SDag-Erling Smørgrav memcpy(num_str, key_str + 3, len - 3);
2242*5afab0e5SDag-Erling Smørgrav num_str[len - 3] = 0;
2243*5afab0e5SDag-Erling Smørgrav num = strtoul(num_str, &endptr, 10);
2244*5afab0e5SDag-Erling Smørgrav if (*endptr || num > 65535)
2245*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_SVCPARAM_KEY_ERR;
2246*5afab0e5SDag-Erling Smørgrav
2247*5afab0e5SDag-Erling Smørgrav /* key65535 is Reserved to be an ("Invalid key"), though there is no
2248*5afab0e5SDag-Erling Smørgrav * physiological reason to deny usage. We restrict ourselves to the
2249*5afab0e5SDag-Erling Smørgrav * anatomical limitations only to maximize serviceability.
2250*5afab0e5SDag-Erling Smørgrav * ```
2251*5afab0e5SDag-Erling Smørgrav * if (num == 65535)
2252*5afab0e5SDag-Erling Smørgrav * return LDNS_STATUS_RESERVED_SVCPARAM_KEY;
2253*5afab0e5SDag-Erling Smørgrav * ```
2254*5afab0e5SDag-Erling Smørgrav */
2255*5afab0e5SDag-Erling Smørgrav *key = num;
2256*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_OK;
2257*5afab0e5SDag-Erling Smørgrav }
2258*5afab0e5SDag-Erling Smørgrav
2259*5afab0e5SDag-Erling Smørgrav static ldns_status
parse_svcparam(const char ** s,uint8_t ** dp,uint8_t * eod)2260*5afab0e5SDag-Erling Smørgrav parse_svcparam(const char **s, uint8_t **dp, uint8_t *eod)
2261*5afab0e5SDag-Erling Smørgrav {
2262*5afab0e5SDag-Erling Smørgrav ldns_svcparam_key key;
2263*5afab0e5SDag-Erling Smørgrav ldns_status st;
2264*5afab0e5SDag-Erling Smørgrav uint8_t *val;
2265*5afab0e5SDag-Erling Smørgrav
2266*5afab0e5SDag-Erling Smørgrav if (*dp + 4 > eod)
2267*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_RDATA_OVERFLOW;
2268*5afab0e5SDag-Erling Smørgrav
2269*5afab0e5SDag-Erling Smørgrav if ((st = parse_svcparam_key(s, &key)))
2270*5afab0e5SDag-Erling Smørgrav return st;
2271*5afab0e5SDag-Erling Smørgrav
2272*5afab0e5SDag-Erling Smørgrav ldns_write_uint16(*dp, key);
2273*5afab0e5SDag-Erling Smørgrav ldns_write_uint16(*dp + 2, 0);
2274*5afab0e5SDag-Erling Smørgrav *dp += 4;
2275*5afab0e5SDag-Erling Smørgrav if (isspace((unsigned char)**s) || !**s)
2276*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_OK;
2277*5afab0e5SDag-Erling Smørgrav
2278*5afab0e5SDag-Erling Smørgrav else if (**s != '=')
2279*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_SYNTAX_ERR;
2280*5afab0e5SDag-Erling Smørgrav *s += 1;
2281*5afab0e5SDag-Erling Smørgrav val = *dp;
2282*5afab0e5SDag-Erling Smørgrav switch(key) {
2283*5afab0e5SDag-Erling Smørgrav case LDNS_SVCPARAM_KEY_MANDATORY:
2284*5afab0e5SDag-Erling Smørgrav st = parse_svcparam_mandatory(s, dp, eod);
2285*5afab0e5SDag-Erling Smørgrav break;
2286*5afab0e5SDag-Erling Smørgrav case LDNS_SVCPARAM_KEY_ALPN:
2287*5afab0e5SDag-Erling Smørgrav st = parse_svcparam_alpn(s, dp, eod);
2288*5afab0e5SDag-Erling Smørgrav break;
2289*5afab0e5SDag-Erling Smørgrav case LDNS_SVCPARAM_KEY_NO_DEFAULT_ALPN:
2290*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_NO_SVCPARAM_VALUE_EXPECTED;
2291*5afab0e5SDag-Erling Smørgrav case LDNS_SVCPARAM_KEY_PORT:
2292*5afab0e5SDag-Erling Smørgrav st = parse_svcparam_port(s, dp, eod);
2293*5afab0e5SDag-Erling Smørgrav break;
2294*5afab0e5SDag-Erling Smørgrav case LDNS_SVCPARAM_KEY_IPV4HINT:
2295*5afab0e5SDag-Erling Smørgrav st = parse_svcparam_ipv4hint(s, dp, eod);
2296*5afab0e5SDag-Erling Smørgrav break;
2297*5afab0e5SDag-Erling Smørgrav case LDNS_SVCPARAM_KEY_ECH:
2298*5afab0e5SDag-Erling Smørgrav st = parse_svcparam_ech(s, dp, eod);
2299*5afab0e5SDag-Erling Smørgrav break;
2300*5afab0e5SDag-Erling Smørgrav case LDNS_SVCPARAM_KEY_IPV6HINT:
2301*5afab0e5SDag-Erling Smørgrav st = parse_svcparam_ipv6hint(s, dp, eod);
2302*5afab0e5SDag-Erling Smørgrav break;
2303*5afab0e5SDag-Erling Smørgrav default:
2304*5afab0e5SDag-Erling Smørgrav st = parse_svcparam_value(s, dp, eod);
2305*5afab0e5SDag-Erling Smørgrav break;
2306*5afab0e5SDag-Erling Smørgrav }
2307*5afab0e5SDag-Erling Smørgrav if (st)
2308*5afab0e5SDag-Erling Smørgrav return st;
2309*5afab0e5SDag-Erling Smørgrav ldns_write_uint16(val - 2, *dp - val);
2310*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_OK;
2311*5afab0e5SDag-Erling Smørgrav }
2312*5afab0e5SDag-Erling Smørgrav
2313*5afab0e5SDag-Erling Smørgrav static int
svcparam_ptr_cmp(const void * a,const void * b)2314*5afab0e5SDag-Erling Smørgrav svcparam_ptr_cmp(const void *a, const void *b)
2315*5afab0e5SDag-Erling Smørgrav {
2316*5afab0e5SDag-Erling Smørgrav uint8_t *x = *(uint8_t **)a , *y = *(uint8_t **)b;
2317*5afab0e5SDag-Erling Smørgrav uint16_t x_type = ldns_read_uint16(x), y_type = ldns_read_uint16(y);
2318*5afab0e5SDag-Erling Smørgrav uint16_t x_len , y_len;
2319*5afab0e5SDag-Erling Smørgrav
2320*5afab0e5SDag-Erling Smørgrav if (x_type != y_type)
2321*5afab0e5SDag-Erling Smørgrav return x_type > y_type ? 1 : -1;
2322*5afab0e5SDag-Erling Smørgrav
2323*5afab0e5SDag-Erling Smørgrav x_len = ldns_read_uint16(x + 2);
2324*5afab0e5SDag-Erling Smørgrav y_len = ldns_read_uint16(y + 2);
2325*5afab0e5SDag-Erling Smørgrav
2326*5afab0e5SDag-Erling Smørgrav return x_len != y_len
2327*5afab0e5SDag-Erling Smørgrav ? (x_len > y_len ? 1 : -1)
2328*5afab0e5SDag-Erling Smørgrav : (x_len == 0 ? 0 : memcmp(x + 4, y + 4, x_len));
2329*5afab0e5SDag-Erling Smørgrav }
2330*5afab0e5SDag-Erling Smørgrav
2331*5afab0e5SDag-Erling Smørgrav ldns_status
ldns_str2rdf_svcparams(ldns_rdf ** rd,const char * str)2332*5afab0e5SDag-Erling Smørgrav ldns_str2rdf_svcparams(ldns_rdf **rd, const char *str)
2333*5afab0e5SDag-Erling Smørgrav {
2334*5afab0e5SDag-Erling Smørgrav uint8_t *data, *dp, *eod, *p, *new_data;
2335*5afab0e5SDag-Erling Smørgrav ldns_status st = LDNS_STATUS_OK;
2336*5afab0e5SDag-Erling Smørgrav size_t length, i;
2337*5afab0e5SDag-Erling Smørgrav size_t nparams = 0;
2338*5afab0e5SDag-Erling Smørgrav uint8_t **svcparams;
2339*5afab0e5SDag-Erling Smørgrav int prev_key;
2340*5afab0e5SDag-Erling Smørgrav
2341*5afab0e5SDag-Erling Smørgrav if (!rd || !str)
2342*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_NULL;
2343*5afab0e5SDag-Erling Smørgrav
2344*5afab0e5SDag-Erling Smørgrav length = strlen(str);
2345*5afab0e5SDag-Erling Smørgrav /* Worst case space requirement. We'll realloc to actual size later. */
2346*5afab0e5SDag-Erling Smørgrav if (!(dp = data = LDNS_XMALLOC(uint8_t, length * 4)))
2347*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
2348*5afab0e5SDag-Erling Smørgrav eod = data + length * 4;
2349*5afab0e5SDag-Erling Smørgrav
2350*5afab0e5SDag-Erling Smørgrav /* Fill data with parsed bytes */
2351*5afab0e5SDag-Erling Smørgrav for (;;) {
2352*5afab0e5SDag-Erling Smørgrav while (isspace((unsigned char)*str))
2353*5afab0e5SDag-Erling Smørgrav str += 1;
2354*5afab0e5SDag-Erling Smørgrav if(!*str)
2355*5afab0e5SDag-Erling Smørgrav break;
2356*5afab0e5SDag-Erling Smørgrav if ((st = parse_svcparam(&str, &dp, eod))) {
2357*5afab0e5SDag-Erling Smørgrav LDNS_FREE(data);
2358*5afab0e5SDag-Erling Smørgrav return st;
2359*5afab0e5SDag-Erling Smørgrav }
2360*5afab0e5SDag-Erling Smørgrav nparams += 1;
2361*5afab0e5SDag-Erling Smørgrav }
2362*5afab0e5SDag-Erling Smørgrav
2363*5afab0e5SDag-Erling Smørgrav /* draft-ietf-dnsop-svcb-https-02 in Section 2.2:
2364*5afab0e5SDag-Erling Smørgrav *
2365*5afab0e5SDag-Erling Smørgrav * SvcParamKeys SHALL appear in increasing numeric order
2366*5afab0e5SDag-Erling Smørgrav *
2367*5afab0e5SDag-Erling Smørgrav * A svcparams array (with pointers to the individual key, value pairs)
2368*5afab0e5SDag-Erling Smørgrav * is created to qsort the pairs in increasing numeric order.
2369*5afab0e5SDag-Erling Smørgrav */
2370*5afab0e5SDag-Erling Smørgrav if (!(svcparams = LDNS_XMALLOC(uint8_t *, nparams))) {
2371*5afab0e5SDag-Erling Smørgrav LDNS_FREE(data);
2372*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
2373*5afab0e5SDag-Erling Smørgrav }
2374*5afab0e5SDag-Erling Smørgrav for ( p = data, i = 0
2375*5afab0e5SDag-Erling Smørgrav ; p < dp && i < nparams
2376*5afab0e5SDag-Erling Smørgrav ; p += 4 + ldns_read_uint16(p + 2))
2377*5afab0e5SDag-Erling Smørgrav svcparams[i++] = p;
2378*5afab0e5SDag-Erling Smørgrav
2379*5afab0e5SDag-Erling Smørgrav qsort(svcparams, i, sizeof(uint8_t *), svcparam_ptr_cmp);
2380*5afab0e5SDag-Erling Smørgrav
2381*5afab0e5SDag-Erling Smørgrav /* Write out the (key, value) pairs to a newly allocated data in
2382*5afab0e5SDag-Erling Smørgrav * sorted order.
2383*5afab0e5SDag-Erling Smørgrav */
2384*5afab0e5SDag-Erling Smørgrav length = dp - data;
2385*5afab0e5SDag-Erling Smørgrav if (!(new_data = LDNS_XMALLOC(uint8_t, length))) {
2386*5afab0e5SDag-Erling Smørgrav LDNS_FREE(data);
2387*5afab0e5SDag-Erling Smørgrav LDNS_FREE(svcparams);
2388*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
2389*5afab0e5SDag-Erling Smørgrav }
2390*5afab0e5SDag-Erling Smørgrav prev_key = -1;
2391*5afab0e5SDag-Erling Smørgrav for ( p = new_data, i = 0
2392*5afab0e5SDag-Erling Smørgrav ; p < new_data + length && i < nparams
2393*5afab0e5SDag-Erling Smørgrav ; p += 4 + ldns_read_uint16(p + 2), i += 1) {
2394*5afab0e5SDag-Erling Smørgrav uint16_t key = ldns_read_uint16(svcparams[i]);
2395*5afab0e5SDag-Erling Smørgrav
2396*5afab0e5SDag-Erling Smørgrav /* In draft-ietf-dnsop-svcb-https-02 Section 2.1:
2397*5afab0e5SDag-Erling Smørgrav *
2398*5afab0e5SDag-Erling Smørgrav * SvcParams ...<snip>... keys MUST NOT be repeated.
2399*5afab0e5SDag-Erling Smørgrav *
2400*5afab0e5SDag-Erling Smørgrav * ldns will not impose this limitation on the library user,
2401*5afab0e5SDag-Erling Smørgrav * but we can merge completely equal repetitions into one.
2402*5afab0e5SDag-Erling Smørgrav * So, not doing
2403*5afab0e5SDag-Erling Smørgrav * ```
2404*5afab0e5SDag-Erling Smørgrav * if (key == prev_key)
2405*5afab0e5SDag-Erling Smørgrav * return LDNS_STATUS_SVCPARAM_KEY_MORE_THAN_ONCE;
2406*5afab0e5SDag-Erling Smørgrav * ```
2407*5afab0e5SDag-Erling Smørgrav * but instead:
2408*5afab0e5SDag-Erling Smørgrav */
2409*5afab0e5SDag-Erling Smørgrav if (key == prev_key && ldns_read_uint16(svcparams[i] + 2)
2410*5afab0e5SDag-Erling Smørgrav == ldns_read_uint16(svcparams[i - 1] + 2)
2411*5afab0e5SDag-Erling Smørgrav && 0 == memcmp( svcparams[i ] + 4
2412*5afab0e5SDag-Erling Smørgrav , svcparams[i - 1] + 4
2413*5afab0e5SDag-Erling Smørgrav , ldns_read_uint16(svcparams[i] + 2))) {
2414*5afab0e5SDag-Erling Smørgrav p -= 4 + ldns_read_uint16(svcparams[i] + 2);
2415*5afab0e5SDag-Erling Smørgrav continue;
2416*5afab0e5SDag-Erling Smørgrav }
2417*5afab0e5SDag-Erling Smørgrav memcpy(p, svcparams[i], 4 + ldns_read_uint16(svcparams[i] + 2));
2418*5afab0e5SDag-Erling Smørgrav prev_key = key;
2419*5afab0e5SDag-Erling Smørgrav }
2420*5afab0e5SDag-Erling Smørgrav LDNS_FREE(data);
2421*5afab0e5SDag-Erling Smørgrav LDNS_FREE(svcparams);
2422*5afab0e5SDag-Erling Smørgrav
2423*5afab0e5SDag-Erling Smørgrav /* Create rdf */
2424*5afab0e5SDag-Erling Smørgrav *rd = ldns_rdf_new(LDNS_RDF_TYPE_SVCPARAMS, p - new_data, new_data);
2425*5afab0e5SDag-Erling Smørgrav if (! *rd) {
2426*5afab0e5SDag-Erling Smørgrav LDNS_FREE(new_data);
2427*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
2428*5afab0e5SDag-Erling Smørgrav }
2429*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_OK;
2430*5afab0e5SDag-Erling Smørgrav }
2431*5afab0e5SDag-Erling Smørgrav #else /* #ifdef RRTYPE_SVCB_HTTPS */
2432*5afab0e5SDag-Erling Smørgrav ldns_status
ldns_str2rdf_svcparams(ldns_rdf ** rd,const char * str)2433*5afab0e5SDag-Erling Smørgrav ldns_str2rdf_svcparams(ldns_rdf **rd, const char *str)
2434*5afab0e5SDag-Erling Smørgrav {
2435*5afab0e5SDag-Erling Smørgrav (void)rd; (void)str;
2436*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_NOT_IMPL;
2437*5afab0e5SDag-Erling Smørgrav }
2438*5afab0e5SDag-Erling Smørgrav #endif /* #ifdef RRTYPE_SVCB_HTTPS */
2439