1238104Sdes/* 2238104Sdes * str2host.c 3238104Sdes * 4238104Sdes * conversion routines from the presentation format 5238104Sdes * to the host format 6238104Sdes * 7238104Sdes * a Net::DNS like library for C 8238104Sdes * 9238104Sdes * (c) NLnet Labs, 2004-2006 10238104Sdes * 11238104Sdes * See the file LICENSE for the license 12238104Sdes */ 13238104Sdes#include <ldns/config.h> 14238104Sdes 15238104Sdes#include <ldns/ldns.h> 16238104Sdes 17238104Sdes#ifdef HAVE_SYS_SOCKET_H 18238104Sdes#include <sys/socket.h> 19238104Sdes#endif 20238104Sdes#ifdef HAVE_ARPA_INET_H 21238104Sdes#include <arpa/inet.h> 22238104Sdes#endif 23238104Sdes#include <time.h> 24238104Sdes 25238104Sdes#include <errno.h> 26238104Sdes#ifdef HAVE_NETDB_H 27238104Sdes#include <netdb.h> 28238104Sdes#endif 29238104Sdes 30238104Sdes#include <limits.h> 31238104Sdes#ifdef HAVE_SYS_PARAM_H 32238104Sdes#include <sys/param.h> 33238104Sdes#endif 34238104Sdes 35238104Sdesldns_status 36238104Sdesldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr) 37238104Sdes{ 38238104Sdes char *end = NULL; 39238104Sdes uint16_t *r; 40238104Sdes r = LDNS_MALLOC(uint16_t); 41238104Sdes if(!r) return LDNS_STATUS_MEM_ERR; 42238104Sdes 43238104Sdes *r = htons((uint16_t)strtol((char *)shortstr, &end, 10)); 44238104Sdes 45238104Sdes if(*end != 0) { 46238104Sdes LDNS_FREE(r); 47238104Sdes return LDNS_STATUS_INVALID_INT; 48238104Sdes } else { 49238104Sdes *rd = ldns_rdf_new_frm_data( 50238104Sdes LDNS_RDF_TYPE_INT16, sizeof(uint16_t), r); 51238104Sdes LDNS_FREE(r); 52238104Sdes return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 53238104Sdes } 54238104Sdes} 55238104Sdes 56238104Sdesldns_status 57238104Sdesldns_str2rdf_time(ldns_rdf **rd, const char *time) 58238104Sdes{ 59238104Sdes /* convert a time YYYYDDMMHHMMSS to wireformat */ 60238104Sdes uint16_t *r = NULL; 61238104Sdes struct tm tm; 62238104Sdes uint32_t l; 63238104Sdes char *end; 64238104Sdes 65238104Sdes /* Try to scan the time... */ 66238104Sdes r = (uint16_t*)LDNS_MALLOC(uint32_t); 67238104Sdes if(!r) return LDNS_STATUS_MEM_ERR; 68238104Sdes 69238104Sdes memset(&tm, 0, sizeof(tm)); 70238104Sdes 71238104Sdes if (strlen(time) == 14 && 72238104Sdes 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 73238104Sdes ) { 74238104Sdes tm.tm_year -= 1900; 75238104Sdes tm.tm_mon--; 76238104Sdes /* Check values */ 77238104Sdes if (tm.tm_year < 70) { 78238104Sdes goto bad_format; 79238104Sdes } 80238104Sdes if (tm.tm_mon < 0 || tm.tm_mon > 11) { 81238104Sdes goto bad_format; 82238104Sdes } 83238104Sdes if (tm.tm_mday < 1 || tm.tm_mday > 31) { 84238104Sdes goto bad_format; 85238104Sdes } 86238104Sdes 87238104Sdes if (tm.tm_hour < 0 || tm.tm_hour > 23) { 88238104Sdes goto bad_format; 89238104Sdes } 90238104Sdes 91238104Sdes if (tm.tm_min < 0 || tm.tm_min > 59) { 92238104Sdes goto bad_format; 93238104Sdes } 94238104Sdes 95238104Sdes if (tm.tm_sec < 0 || tm.tm_sec > 59) { 96238104Sdes goto bad_format; 97238104Sdes } 98238104Sdes 99246854Sdes l = htonl(ldns_mktime_from_utc(&tm)); 100238104Sdes memcpy(r, &l, sizeof(uint32_t)); 101238104Sdes *rd = ldns_rdf_new_frm_data( 102238104Sdes LDNS_RDF_TYPE_TIME, sizeof(uint32_t), r); 103238104Sdes LDNS_FREE(r); 104238104Sdes return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 105238104Sdes } else { 106238104Sdes /* handle it as 32 bits timestamp */ 107238104Sdes l = htonl((uint32_t)strtol((char*)time, &end, 10)); 108238104Sdes if(*end != 0) { 109238104Sdes LDNS_FREE(r); 110238104Sdes return LDNS_STATUS_ERR; 111238104Sdes } else { 112238104Sdes memcpy(r, &l, sizeof(uint32_t)); 113238104Sdes *rd = ldns_rdf_new_frm_data( 114238104Sdes LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r); 115238104Sdes LDNS_FREE(r); 116238104Sdes return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 117238104Sdes } 118238104Sdes } 119238104Sdes 120238104Sdes bad_format: 121238104Sdes LDNS_FREE(r); 122238104Sdes return LDNS_STATUS_INVALID_TIME; 123238104Sdes} 124238104Sdes 125238104Sdesldns_status 126238104Sdesldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *salt_str) 127238104Sdes{ 128238104Sdes uint8_t salt_length; 129238104Sdes int c; 130238104Sdes int salt_length_str; 131238104Sdes 132238104Sdes uint8_t *salt; 133238104Sdes uint8_t *data; 134238104Sdes if(rd == NULL) { 135238104Sdes return LDNS_STATUS_NULL; 136238104Sdes } 137238104Sdes 138238104Sdes salt_length_str = (int)strlen(salt_str); 139238104Sdes if (salt_length_str == 1 && salt_str[0] == '-') { 140238104Sdes salt_length_str = 0; 141238104Sdes } else if (salt_length_str % 2 != 0) { 142238104Sdes return LDNS_STATUS_INVALID_HEX; 143238104Sdes } 144238104Sdes if (salt_length_str > 512) { 145238104Sdes return LDNS_STATUS_INVALID_HEX; 146238104Sdes } 147238104Sdes 148238104Sdes salt = LDNS_XMALLOC(uint8_t, salt_length_str / 2); 149238104Sdes if(!salt) { 150238104Sdes return LDNS_STATUS_MEM_ERR; 151238104Sdes } 152238104Sdes for (c = 0; c < salt_length_str; c += 2) { 153238104Sdes if (isxdigit((int) salt_str[c]) && isxdigit((int) salt_str[c+1])) { 154238104Sdes salt[c/2] = (uint8_t) ldns_hexdigit_to_int(salt_str[c]) * 16 + 155238104Sdes ldns_hexdigit_to_int(salt_str[c+1]); 156238104Sdes } else { 157238104Sdes LDNS_FREE(salt); 158238104Sdes return LDNS_STATUS_INVALID_HEX; 159238104Sdes } 160238104Sdes } 161238104Sdes salt_length = (uint8_t) (salt_length_str / 2); 162238104Sdes 163238104Sdes data = LDNS_XMALLOC(uint8_t, 1 + salt_length); 164238104Sdes if(!data) { 165238104Sdes LDNS_FREE(salt); 166238104Sdes return LDNS_STATUS_MEM_ERR; 167238104Sdes } 168238104Sdes data[0] = salt_length; 169238104Sdes memcpy(&data[1], salt, salt_length); 170238104Sdes *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT, 1 + salt_length, data); 171238104Sdes LDNS_FREE(data); 172238104Sdes LDNS_FREE(salt); 173238104Sdes 174238104Sdes return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 175238104Sdes} 176238104Sdes 177238104Sdesldns_status 178238104Sdesldns_str2rdf_period(ldns_rdf **rd,const char *period) 179238104Sdes{ 180238104Sdes uint32_t p; 181238104Sdes const char *end; 182238104Sdes 183238104Sdes /* Allocate required space... */ 184238104Sdes p = ldns_str2period(period, &end); 185238104Sdes 186238104Sdes if (*end != 0) { 187238104Sdes return LDNS_STATUS_ERR; 188238104Sdes } else { 189238104Sdes p = (uint32_t) htonl(p); 190238104Sdes *rd = ldns_rdf_new_frm_data( 191238104Sdes LDNS_RDF_TYPE_PERIOD, sizeof(uint32_t), &p); 192238104Sdes } 193238104Sdes return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 194238104Sdes} 195238104Sdes 196238104Sdesldns_status 197238104Sdesldns_str2rdf_int32(ldns_rdf **rd, const char *longstr) 198238104Sdes{ 199238104Sdes char *end; 200238104Sdes uint16_t *r = NULL; 201238104Sdes uint32_t l; 202238104Sdes 203238104Sdes r = (uint16_t*)LDNS_MALLOC(uint32_t); 204238104Sdes if(!r) return LDNS_STATUS_MEM_ERR; 205238104Sdes errno = 0; /* must set to zero before call, 206238104Sdes note race condition on errno */ 207238104Sdes if(*longstr == '-') 208238104Sdes l = htonl((uint32_t)strtol((char*)longstr, &end, 10)); 209238104Sdes else l = htonl((uint32_t)strtoul((char*)longstr, &end, 10)); 210238104Sdes 211238104Sdes if(*end != 0) { 212238104Sdes LDNS_FREE(r); 213238104Sdes return LDNS_STATUS_ERR; 214238104Sdes } else { 215238104Sdes if (errno == ERANGE) { 216238104Sdes LDNS_FREE(r); 217238104Sdes return LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW; 218238104Sdes } 219238104Sdes memcpy(r, &l, sizeof(uint32_t)); 220238104Sdes *rd = ldns_rdf_new_frm_data( 221238104Sdes LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r); 222238104Sdes LDNS_FREE(r); 223238104Sdes return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 224238104Sdes } 225238104Sdes} 226238104Sdes 227238104Sdesldns_status 228238104Sdesldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr) 229238104Sdes{ 230238104Sdes char *end; 231238104Sdes uint8_t *r = NULL; 232238104Sdes 233238104Sdes r = LDNS_MALLOC(uint8_t); 234238104Sdes if(!r) return LDNS_STATUS_MEM_ERR; 235238104Sdes 236238104Sdes *r = (uint8_t)strtol((char*)bytestr, &end, 10); 237238104Sdes 238238104Sdes if(*end != 0) { 239238104Sdes LDNS_FREE(r); 240238104Sdes return LDNS_STATUS_ERR; 241238104Sdes } else { 242238104Sdes *rd = ldns_rdf_new_frm_data( 243238104Sdes LDNS_RDF_TYPE_INT8, sizeof(uint8_t), r); 244238104Sdes LDNS_FREE(r); 245238104Sdes return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 246238104Sdes } 247238104Sdes} 248238104Sdes 249238104Sdes 250238104Sdes/* 251238104Sdes * Checks whether the escaped value at **s is an octal value or 252238104Sdes * a 'normally' escaped character (and not eos) 253238104Sdes * 254238104Sdes * The string pointer at *s is increased by either 0 (on error), 1 (on 255238104Sdes * normal escapes), or 3 (on octals) 256238104Sdes * 257238104Sdes * Returns the number of bytes read from the escaped string, or 258238104Sdes * 0 on error 259238104Sdes */ 260269257SdesINLINE bool 261269257Sdesparse_escape(uint8_t *ch_p, const char** str_p) 262269257Sdes{ 263238104Sdes uint16_t val; 264269257Sdes 265269257Sdes if ((*str_p)[0] && isdigit((*str_p)[0]) && 266269257Sdes (*str_p)[1] && isdigit((*str_p)[1]) && 267269257Sdes (*str_p)[2] && isdigit((*str_p)[2])) { 268269257Sdes 269269257Sdes val = (uint16_t)(((*str_p)[0] - '0') * 100 + 270269257Sdes ((*str_p)[1] - '0') * 10 + 271269257Sdes ((*str_p)[2] - '0')); 272269257Sdes 273238104Sdes if (val > 255) { 274269257Sdes goto error; 275238104Sdes } 276269257Sdes *ch_p = (uint8_t)val; 277269257Sdes *str_p += 3; 278269257Sdes return true; 279269257Sdes 280269257Sdes } else if ((*str_p)[0] && !isdigit((*str_p)[0])) { 281269257Sdes 282269257Sdes *ch_p = (uint8_t)*(*str_p)++; 283269257Sdes return true; 284238104Sdes } 285269257Sdeserror: 286269257Sdes *str_p = NULL; 287269257Sdes return false; /* LDNS_STATUS_SYNTAX_BAD_ESCAPE */ 288238104Sdes} 289238104Sdes 290269257SdesINLINE bool 291269257Sdesparse_char(uint8_t *ch_p, const char** str_p) 292269257Sdes{ 293269257Sdes switch (**str_p) { 294269257Sdes 295269257Sdes case '\0': return false; 296269257Sdes 297269257Sdes case '\\': *str_p += 1; 298269257Sdes return parse_escape(ch_p, str_p); 299269257Sdes 300269257Sdes default: *ch_p = (uint8_t)*(*str_p)++; 301269257Sdes return true; 302269257Sdes } 303269257Sdes} 304269257Sdes 305238104Sdes/* 306238104Sdes * No special care is taken, all dots are translated into 307238104Sdes * label seperators. 308238104Sdes * Could be made more efficient....we do 3 memcpy's in total... 309238104Sdes */ 310238104Sdesldns_status 311238104Sdesldns_str2rdf_dname(ldns_rdf **d, const char *str) 312238104Sdes{ 313238104Sdes size_t len; 314238104Sdes 315269257Sdes const char *s; 316269257Sdes uint8_t *q, *pq, label_len; 317238104Sdes uint8_t buf[LDNS_MAX_DOMAINLEN + 1]; 318238104Sdes *d = NULL; 319238104Sdes 320238104Sdes len = strlen((char*)str); 321238104Sdes /* octet representation can make strings a lot longer than actual length */ 322238104Sdes if (len > LDNS_MAX_DOMAINLEN * 4) { 323238104Sdes return LDNS_STATUS_DOMAINNAME_OVERFLOW; 324238104Sdes } 325238104Sdes if (0 == len) { 326238104Sdes return LDNS_STATUS_DOMAINNAME_UNDERFLOW; 327238104Sdes } 328238104Sdes 329238104Sdes /* root label */ 330238104Sdes if (1 == len && *str == '.') { 331238104Sdes *d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, 1, "\0"); 332238104Sdes return LDNS_STATUS_OK; 333238104Sdes } 334238104Sdes 335238104Sdes /* get on with the rest */ 336238104Sdes 337238104Sdes /* s is on the current character in the string 338238104Sdes * pq points to where the labellength is going to go 339238104Sdes * label_len keeps track of the current label's length 340238104Sdes * q builds the dname inside the buf array 341238104Sdes */ 342238104Sdes len = 0; 343238104Sdes q = buf+1; 344238104Sdes pq = buf; 345238104Sdes label_len = 0; 346269257Sdes for (s = str; *s; s++, q++) { 347238104Sdes if (q > buf + LDNS_MAX_DOMAINLEN) { 348238104Sdes return LDNS_STATUS_DOMAINNAME_OVERFLOW; 349238104Sdes } 350238104Sdes *q = 0; 351238104Sdes switch (*s) { 352238104Sdes case '.': 353238104Sdes if (label_len > LDNS_MAX_LABELLEN) { 354238104Sdes return LDNS_STATUS_LABEL_OVERFLOW; 355238104Sdes } 356238104Sdes if (label_len == 0) { 357238104Sdes return LDNS_STATUS_EMPTY_LABEL; 358238104Sdes } 359238104Sdes len += label_len + 1; 360238104Sdes *pq = label_len; 361238104Sdes label_len = 0; 362238104Sdes pq = q; 363238104Sdes break; 364238104Sdes case '\\': 365238104Sdes /* octet value or literal char */ 366269257Sdes s += 1; 367269257Sdes if (! parse_escape(q, &s)) { 368238104Sdes return LDNS_STATUS_SYNTAX_BAD_ESCAPE; 369238104Sdes } 370269257Sdes s -= 1; 371269257Sdes label_len++; 372238104Sdes break; 373238104Sdes default: 374269257Sdes *q = (uint8_t)*s; 375238104Sdes label_len++; 376238104Sdes } 377238104Sdes } 378238104Sdes 379238104Sdes /* add root label if last char was not '.' */ 380238104Sdes if (!ldns_dname_str_absolute(str)) { 381238104Sdes if (q > buf + LDNS_MAX_DOMAINLEN) { 382238104Sdes return LDNS_STATUS_DOMAINNAME_OVERFLOW; 383238104Sdes } 384238104Sdes if (label_len > LDNS_MAX_LABELLEN) { 385238104Sdes return LDNS_STATUS_LABEL_OVERFLOW; 386238104Sdes } 387238104Sdes if (label_len == 0) { /* label_len 0 but not . at end? */ 388238104Sdes return LDNS_STATUS_EMPTY_LABEL; 389238104Sdes } 390238104Sdes len += label_len + 1; 391238104Sdes *pq = label_len; 392238104Sdes *q = 0; 393238104Sdes } 394238104Sdes len++; 395238104Sdes 396238104Sdes *d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, len, buf); 397238104Sdes return LDNS_STATUS_OK; 398238104Sdes} 399238104Sdes 400238104Sdesldns_status 401238104Sdesldns_str2rdf_a(ldns_rdf **rd, const char *str) 402238104Sdes{ 403238104Sdes in_addr_t address; 404238104Sdes if (inet_pton(AF_INET, (char*)str, &address) != 1) { 405238104Sdes return LDNS_STATUS_INVALID_IP4; 406238104Sdes } else { 407238104Sdes *rd = ldns_rdf_new_frm_data( 408238104Sdes LDNS_RDF_TYPE_A, sizeof(address), &address); 409238104Sdes } 410238104Sdes return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 411238104Sdes} 412238104Sdes 413238104Sdesldns_status 414238104Sdesldns_str2rdf_aaaa(ldns_rdf **rd, const char *str) 415238104Sdes{ 416238104Sdes uint8_t address[LDNS_IP6ADDRLEN + 1]; 417238104Sdes 418238104Sdes if (inet_pton(AF_INET6, (char*)str, address) != 1) { 419238104Sdes return LDNS_STATUS_INVALID_IP6; 420238104Sdes } else { 421238104Sdes *rd = ldns_rdf_new_frm_data( 422238104Sdes LDNS_RDF_TYPE_AAAA, sizeof(address) - 1, &address); 423238104Sdes } 424238104Sdes return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 425238104Sdes} 426238104Sdes 427238104Sdesldns_status 428238104Sdesldns_str2rdf_str(ldns_rdf **rd, const char *str) 429238104Sdes{ 430269257Sdes uint8_t *data, *dp, ch = 0; 431269257Sdes size_t length; 432238104Sdes 433269257Sdes /* Worst case space requirement. We'll realloc to actual size later. */ 434269257Sdes dp = data = LDNS_XMALLOC(uint8_t, strlen(str) > 255 ? 256 : (strlen(str) + 1)); 435269257Sdes if (! data) { 436269257Sdes return LDNS_STATUS_MEM_ERR; 437238104Sdes } 438238104Sdes 439269257Sdes /* Fill data (up to 255 characters) */ 440269257Sdes while (parse_char(&ch, &str)) { 441269257Sdes if (dp - data >= 255) { 442269257Sdes LDNS_FREE(data); 443269257Sdes return LDNS_STATUS_INVALID_STR; 444238104Sdes } 445269257Sdes *++dp = ch; 446238104Sdes } 447269257Sdes if (! str) { 448269257Sdes return LDNS_STATUS_SYNTAX_BAD_ESCAPE; 449269257Sdes } 450269257Sdes length = (size_t)(dp - data); 451269257Sdes /* Fix last length byte */ 452269257Sdes data[0] = (uint8_t)length; 453238104Sdes 454269257Sdes /* Lose the overmeasure */ 455269257Sdes data = LDNS_XREALLOC(dp = data, uint8_t, length + 1); 456269257Sdes if (! data) { 457269257Sdes LDNS_FREE(dp); 458269257Sdes return LDNS_STATUS_MEM_ERR; 459269257Sdes } 460269257Sdes 461269257Sdes /* Create rdf */ 462269257Sdes *rd = ldns_rdf_new(LDNS_RDF_TYPE_STR, length + 1, data); 463269257Sdes if (! *rd) { 464269257Sdes LDNS_FREE(data); 465269257Sdes return LDNS_STATUS_MEM_ERR; 466269257Sdes } 467269257Sdes return LDNS_STATUS_OK; 468238104Sdes} 469238104Sdes 470238104Sdesldns_status 471238104Sdesldns_str2rdf_apl(ldns_rdf **rd, const char *str) 472238104Sdes{ 473238104Sdes const char *my_str = str; 474238104Sdes 475238104Sdes char *my_ip_str; 476238104Sdes size_t ip_str_len; 477238104Sdes 478238104Sdes uint16_t family; 479238104Sdes bool negation; 480238104Sdes uint8_t afdlength = 0; 481238104Sdes uint8_t *afdpart; 482238104Sdes uint8_t prefix; 483238104Sdes 484238104Sdes uint8_t *data; 485238104Sdes 486238104Sdes size_t i = 0; 487238104Sdes 488238104Sdes /* [!]afi:address/prefix */ 489238104Sdes if (strlen(my_str) < 2 490238104Sdes || strchr(my_str, ':') == NULL 491238104Sdes || strchr(my_str, '/') == NULL 492238104Sdes || strchr(my_str, ':') > strchr(my_str, '/')) { 493238104Sdes return LDNS_STATUS_INVALID_STR; 494238104Sdes } 495238104Sdes 496238104Sdes if (my_str[0] == '!') { 497238104Sdes negation = true; 498238104Sdes my_str += 1; 499238104Sdes } else { 500238104Sdes negation = false; 501238104Sdes } 502238104Sdes 503238104Sdes family = (uint16_t) atoi(my_str); 504238104Sdes 505238104Sdes my_str = strchr(my_str, ':') + 1; 506238104Sdes 507238104Sdes /* need ip addr and only ip addr for inet_pton */ 508238104Sdes ip_str_len = (size_t) (strchr(my_str, '/') - my_str); 509238104Sdes my_ip_str = LDNS_XMALLOC(char, ip_str_len + 1); 510238104Sdes if(!my_ip_str) return LDNS_STATUS_MEM_ERR; 511238104Sdes strncpy(my_ip_str, my_str, ip_str_len + 1); 512238104Sdes my_ip_str[ip_str_len] = '\0'; 513238104Sdes 514238104Sdes if (family == 1) { 515238104Sdes /* ipv4 */ 516238104Sdes afdpart = LDNS_XMALLOC(uint8_t, 4); 517238104Sdes if(!afdpart) { 518238104Sdes LDNS_FREE(my_ip_str); 519238104Sdes return LDNS_STATUS_MEM_ERR; 520238104Sdes } 521238104Sdes if (inet_pton(AF_INET, my_ip_str, afdpart) == 0) { 522238104Sdes LDNS_FREE(my_ip_str); 523238104Sdes LDNS_FREE(afdpart); 524238104Sdes return LDNS_STATUS_INVALID_STR; 525238104Sdes } 526238104Sdes for (i = 0; i < 4; i++) { 527238104Sdes if (afdpart[i] != 0) { 528238104Sdes afdlength = i + 1; 529238104Sdes } 530238104Sdes } 531238104Sdes } else if (family == 2) { 532238104Sdes /* ipv6 */ 533238104Sdes afdpart = LDNS_XMALLOC(uint8_t, 16); 534238104Sdes if(!afdpart) { 535238104Sdes LDNS_FREE(my_ip_str); 536238104Sdes return LDNS_STATUS_MEM_ERR; 537238104Sdes } 538238104Sdes if (inet_pton(AF_INET6, my_ip_str, afdpart) == 0) { 539238104Sdes LDNS_FREE(my_ip_str); 540238104Sdes LDNS_FREE(afdpart); 541238104Sdes return LDNS_STATUS_INVALID_STR; 542238104Sdes } 543238104Sdes for (i = 0; i < 16; i++) { 544238104Sdes if (afdpart[i] != 0) { 545238104Sdes afdlength = i + 1; 546238104Sdes } 547238104Sdes } 548238104Sdes } else { 549238104Sdes /* unknown family */ 550238104Sdes LDNS_FREE(my_ip_str); 551238104Sdes return LDNS_STATUS_INVALID_STR; 552238104Sdes } 553238104Sdes 554238104Sdes my_str = strchr(my_str, '/') + 1; 555238104Sdes prefix = (uint8_t) atoi(my_str); 556238104Sdes 557238104Sdes data = LDNS_XMALLOC(uint8_t, 4 + afdlength); 558238104Sdes if(!data) { 559246854Sdes LDNS_FREE(afdpart); 560238104Sdes LDNS_FREE(my_ip_str); 561238104Sdes return LDNS_STATUS_INVALID_STR; 562238104Sdes } 563238104Sdes ldns_write_uint16(data, family); 564238104Sdes data[2] = prefix; 565238104Sdes data[3] = afdlength; 566238104Sdes if (negation) { 567238104Sdes /* set bit 1 of byte 3 */ 568238104Sdes data[3] = data[3] | 0x80; 569238104Sdes } 570238104Sdes 571238104Sdes memcpy(data + 4, afdpart, afdlength); 572238104Sdes 573238104Sdes *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_APL, afdlength + 4, data); 574238104Sdes LDNS_FREE(afdpart); 575238104Sdes LDNS_FREE(data); 576238104Sdes LDNS_FREE(my_ip_str); 577238104Sdes 578238104Sdes return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 579238104Sdes} 580238104Sdes 581238104Sdesldns_status 582238104Sdesldns_str2rdf_b64(ldns_rdf **rd, const char *str) 583238104Sdes{ 584238104Sdes uint8_t *buffer; 585238104Sdes int16_t i; 586238104Sdes 587238104Sdes buffer = LDNS_XMALLOC(uint8_t, ldns_b64_ntop_calculate_size(strlen(str))); 588238104Sdes if(!buffer) { 589238104Sdes return LDNS_STATUS_MEM_ERR; 590238104Sdes } 591238104Sdes 592238104Sdes i = (uint16_t)ldns_b64_pton((const char*)str, buffer, 593238104Sdes ldns_b64_ntop_calculate_size(strlen(str))); 594238104Sdes if (-1 == i) { 595238104Sdes LDNS_FREE(buffer); 596238104Sdes return LDNS_STATUS_INVALID_B64; 597238104Sdes } else { 598238104Sdes *rd = ldns_rdf_new_frm_data( 599238104Sdes LDNS_RDF_TYPE_B64, (uint16_t) i, buffer); 600238104Sdes } 601238104Sdes LDNS_FREE(buffer); 602238104Sdes 603238104Sdes return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 604238104Sdes} 605238104Sdes 606238104Sdesldns_status 607238104Sdesldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str) 608238104Sdes{ 609238104Sdes uint8_t *buffer; 610238104Sdes int i; 611238104Sdes /* first byte contains length of actual b32 data */ 612238104Sdes uint8_t len = ldns_b32_pton_calculate_size(strlen(str)); 613238104Sdes buffer = LDNS_XMALLOC(uint8_t, len + 1); 614238104Sdes if(!buffer) { 615238104Sdes return LDNS_STATUS_MEM_ERR; 616238104Sdes } 617238104Sdes buffer[0] = len; 618238104Sdes 619238104Sdes i = ldns_b32_pton_extended_hex((const char*)str, strlen(str), buffer + 1, 620238104Sdes ldns_b32_ntop_calculate_size(strlen(str))); 621238104Sdes if (i < 0) { 622238104Sdes LDNS_FREE(buffer); 623238104Sdes return LDNS_STATUS_INVALID_B32_EXT; 624238104Sdes } else { 625238104Sdes *rd = ldns_rdf_new_frm_data( 626238104Sdes LDNS_RDF_TYPE_B32_EXT, (uint16_t) i + 1, buffer); 627238104Sdes } 628238104Sdes LDNS_FREE(buffer); 629238104Sdes 630238104Sdes return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 631238104Sdes} 632238104Sdes 633238104Sdesldns_status 634238104Sdesldns_str2rdf_hex(ldns_rdf **rd, const char *str) 635238104Sdes{ 636238104Sdes uint8_t *t, *t_orig; 637238104Sdes int i; 638238104Sdes size_t len; 639238104Sdes 640238104Sdes len = strlen(str); 641238104Sdes 642238104Sdes if (len > LDNS_MAX_RDFLEN * 2) { 643238104Sdes return LDNS_STATUS_LABEL_OVERFLOW; 644238104Sdes } else { 645238104Sdes t = LDNS_XMALLOC(uint8_t, (len / 2) + 1); 646238104Sdes if(!t) { 647238104Sdes return LDNS_STATUS_MEM_ERR; 648238104Sdes } 649238104Sdes t_orig = t; 650238104Sdes /* Now process octet by octet... */ 651238104Sdes while (*str) { 652238104Sdes *t = 0; 653238104Sdes if (isspace((int) *str)) { 654238104Sdes str++; 655238104Sdes } else { 656238104Sdes for (i = 16; i >= 1; i -= 15) { 657238104Sdes while (*str && isspace((int) *str)) { str++; } 658238104Sdes if (*str) { 659238104Sdes if (isxdigit((int) *str)) { 660238104Sdes *t += ldns_hexdigit_to_int(*str) * i; 661238104Sdes } else { 662238104Sdes LDNS_FREE(t_orig); 663238104Sdes return LDNS_STATUS_ERR; 664238104Sdes } 665238104Sdes ++str; 666238104Sdes } 667238104Sdes } 668238104Sdes ++t; 669238104Sdes } 670238104Sdes } 671238104Sdes *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, 672238104Sdes (size_t) (t - t_orig), 673238104Sdes t_orig); 674238104Sdes LDNS_FREE(t_orig); 675238104Sdes } 676238104Sdes return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 677238104Sdes} 678238104Sdes 679238104Sdesldns_status 680238104Sdesldns_str2rdf_nsec(ldns_rdf **rd, const char *str) 681238104Sdes{ 682238104Sdes const char *delimiters = "\n\t "; 683238104Sdes char *token = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN); 684238104Sdes ldns_buffer *str_buf; 685238104Sdes ssize_t c; 686238104Sdes uint16_t cur_type; 687238104Sdes size_t type_count = 0; 688238104Sdes ldns_rr_type type_list[65536]; 689238104Sdes if(!token) return LDNS_STATUS_MEM_ERR; 690238104Sdes if(rd == NULL) { 691238104Sdes LDNS_FREE(token); 692238104Sdes return LDNS_STATUS_NULL; 693238104Sdes } 694238104Sdes 695238104Sdes str_buf = LDNS_MALLOC(ldns_buffer); 696238104Sdes if(!str_buf) { 697238104Sdes LDNS_FREE(token); 698238104Sdes return LDNS_STATUS_MEM_ERR; 699238104Sdes } 700238104Sdes ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); 701238104Sdes if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { 702238104Sdes LDNS_FREE(str_buf); 703238104Sdes LDNS_FREE(token); 704238104Sdes return LDNS_STATUS_MEM_ERR; 705238104Sdes } 706238104Sdes 707238104Sdes while ((c = ldns_bget_token(str_buf, token, delimiters, LDNS_MAX_RDFLEN)) != -1 && c != 0) { 708238104Sdes if(type_count >= sizeof(type_list)) { 709238104Sdes LDNS_FREE(str_buf); 710238104Sdes LDNS_FREE(token); 711238104Sdes return LDNS_STATUS_ERR; 712238104Sdes } 713238104Sdes cur_type = ldns_get_rr_type_by_name(token); 714238104Sdes type_list[type_count] = cur_type; 715238104Sdes type_count++; 716238104Sdes } 717238104Sdes 718238104Sdes *rd = ldns_dnssec_create_nsec_bitmap(type_list, 719238104Sdes type_count, 720238104Sdes LDNS_RR_TYPE_NSEC); 721238104Sdes 722238104Sdes LDNS_FREE(token); 723238104Sdes ldns_buffer_free(str_buf); 724238104Sdes return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 725238104Sdes} 726238104Sdes 727238104Sdesldns_status 728238104Sdesldns_str2rdf_type(ldns_rdf **rd, const char *str) 729238104Sdes{ 730238104Sdes uint16_t type; 731238104Sdes type = htons(ldns_get_rr_type_by_name(str)); 732238104Sdes /* ldns_rr_type is a 16 bit value */ 733238104Sdes *rd = ldns_rdf_new_frm_data( 734238104Sdes LDNS_RDF_TYPE_TYPE, sizeof(uint16_t), &type); 735238104Sdes return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 736238104Sdes} 737238104Sdes 738238104Sdesldns_status 739238104Sdesldns_str2rdf_class(ldns_rdf **rd, const char *str) 740238104Sdes{ 741238104Sdes uint16_t klass; 742238104Sdes klass = htons(ldns_get_rr_class_by_name(str)); 743238104Sdes /* class is 16 bit */ 744238104Sdes *rd = ldns_rdf_new_frm_data( 745238104Sdes LDNS_RDF_TYPE_CLASS, sizeof(uint16_t), &klass); 746238104Sdes return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 747238104Sdes} 748238104Sdes 749238104Sdes/* An certificate alg field can either be specified as a 8 bits number 750238104Sdes * or by its symbolic name. Handle both 751238104Sdes */ 752238104Sdesldns_status 753238104Sdesldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str) 754238104Sdes{ 755238104Sdes ldns_lookup_table *lt; 756238104Sdes ldns_status st; 757238104Sdes uint8_t idd[2]; 758238104Sdes lt = ldns_lookup_by_name(ldns_cert_algorithms, str); 759238104Sdes st = LDNS_STATUS_OK; 760238104Sdes 761238104Sdes if (lt) { 762238104Sdes ldns_write_uint16(idd, (uint16_t) lt->id); 763238104Sdes *rd = ldns_rdf_new_frm_data( 764238104Sdes LDNS_RDF_TYPE_INT16, sizeof(uint16_t), idd); 765238104Sdes if (!*rd) { 766238104Sdes st = LDNS_STATUS_ERR; 767238104Sdes } 768238104Sdes } else { 769238104Sdes /* try as-is (a number) */ 770238104Sdes st = ldns_str2rdf_int16(rd, str); 771238104Sdes if (st == LDNS_STATUS_OK && 772238104Sdes ldns_rdf2native_int16(*rd) == 0) { 773238104Sdes st = LDNS_STATUS_CERT_BAD_ALGORITHM; 774238104Sdes } 775238104Sdes } 776238104Sdes 777238104Sdes return st; 778238104Sdes} 779238104Sdes 780238104Sdes/* An alg field can either be specified as a 8 bits number 781238104Sdes * or by its symbolic name. Handle both 782238104Sdes */ 783238104Sdesldns_status 784238104Sdesldns_str2rdf_alg(ldns_rdf **rd, const char *str) 785238104Sdes{ 786238104Sdes ldns_lookup_table *lt; 787238104Sdes ldns_status st; 788238104Sdes 789238104Sdes lt = ldns_lookup_by_name(ldns_algorithms, str); 790238104Sdes st = LDNS_STATUS_OK; 791238104Sdes 792238104Sdes if (lt) { 793238104Sdes /* it was given as a integer */ 794238104Sdes *rd = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t) lt->id); 795238104Sdes if (!*rd) { 796238104Sdes st = LDNS_STATUS_ERR; 797238104Sdes } 798238104Sdes } else { 799238104Sdes /* try as-is (a number) */ 800238104Sdes st = ldns_str2rdf_int8(rd, str); 801238104Sdes } 802238104Sdes return st; 803238104Sdes} 804238104Sdes 805238104Sdesldns_status 806238104Sdesldns_str2rdf_unknown( ATTR_UNUSED(ldns_rdf **rd) 807238104Sdes , ATTR_UNUSED(const char *str) 808238104Sdes ) 809238104Sdes{ 810238104Sdes /* this should be caught in an earlier time (general str2host for 811238104Sdes rr's */ 812238104Sdes return LDNS_STATUS_NOT_IMPL; 813238104Sdes} 814238104Sdes 815238104Sdesldns_status 816238104Sdesldns_str2rdf_service( ATTR_UNUSED(ldns_rdf **rd) 817238104Sdes , ATTR_UNUSED(const char *str) 818238104Sdes ) 819238104Sdes{ 820238104Sdes /* is this used? is this actually WKS? or SRV? */ 821238104Sdes return LDNS_STATUS_NOT_IMPL; 822238104Sdes} 823238104Sdes 824238104Sdesstatic int 825238104Sdesloc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e) 826238104Sdes{ 827238104Sdes /* read <digits>[.<digits>][mM] */ 828238104Sdes /* into mantissa exponent format for LOC type */ 829238104Sdes uint32_t meters = 0, cm = 0, val; 830238104Sdes while (isblank(*my_str)) { 831238104Sdes my_str++; 832238104Sdes } 833238104Sdes meters = (uint32_t)strtol(my_str, &my_str, 10); 834238104Sdes if (*my_str == '.') { 835238104Sdes my_str++; 836238104Sdes cm = (uint32_t)strtol(my_str, &my_str, 10); 837238104Sdes } 838238104Sdes if (meters >= 1) { 839238104Sdes *e = 2; 840238104Sdes val = meters; 841238104Sdes } else { 842238104Sdes *e = 0; 843238104Sdes val = cm; 844238104Sdes } 845238104Sdes while(val >= 10) { 846238104Sdes (*e)++; 847238104Sdes val /= 10; 848238104Sdes } 849238104Sdes *m = (uint8_t)val; 850238104Sdes 851238104Sdes if (*e > 9) 852238104Sdes return 0; 853238104Sdes if (*my_str == 'm' || *my_str == 'M') { 854238104Sdes my_str++; 855238104Sdes } 856238104Sdes *endstr = my_str; 857238104Sdes return 1; 858238104Sdes} 859238104Sdes 860238104Sdesldns_status 861238104Sdesldns_str2rdf_loc(ldns_rdf **rd, const char *str) 862238104Sdes{ 863238104Sdes uint32_t latitude = 0; 864238104Sdes uint32_t longitude = 0; 865238104Sdes uint32_t altitude = 0; 866238104Sdes 867238104Sdes uint8_t *data; 868238104Sdes uint32_t equator = (uint32_t) ldns_power(2, 31); 869238104Sdes 870238104Sdes uint32_t h = 0; 871238104Sdes uint32_t m = 0; 872238104Sdes uint8_t size_b = 1, size_e = 2; 873238104Sdes uint8_t horiz_pre_b = 1, horiz_pre_e = 6; 874238104Sdes uint8_t vert_pre_b = 1, vert_pre_e = 3; 875238104Sdes 876238104Sdes double s = 0.0; 877238104Sdes bool northerness; 878238104Sdes bool easterness; 879238104Sdes 880238104Sdes char *my_str = (char *) str; 881238104Sdes 882238104Sdes /* only support version 0 */ 883238104Sdes if (isdigit((int) *my_str)) { 884238104Sdes h = (uint32_t) strtol(my_str, &my_str, 10); 885238104Sdes } else { 886238104Sdes return LDNS_STATUS_INVALID_STR; 887238104Sdes } 888238104Sdes 889238104Sdes while (isblank((int) *my_str)) { 890238104Sdes my_str++; 891238104Sdes } 892238104Sdes 893238104Sdes if (isdigit((int) *my_str)) { 894238104Sdes m = (uint32_t) strtol(my_str, &my_str, 10); 895238104Sdes } else if (*my_str == 'N' || *my_str == 'S') { 896238104Sdes goto north; 897238104Sdes } else { 898238104Sdes return LDNS_STATUS_INVALID_STR; 899238104Sdes } 900238104Sdes 901238104Sdes while (isblank((int) *my_str)) { 902238104Sdes my_str++; 903238104Sdes } 904238104Sdes 905238104Sdes if (isdigit((int) *my_str)) { 906238104Sdes s = strtod(my_str, &my_str); 907238104Sdes } 908238104Sdesnorth: 909238104Sdes while (isblank((int) *my_str)) { 910238104Sdes my_str++; 911238104Sdes } 912238104Sdes 913238104Sdes if (*my_str == 'N') { 914238104Sdes northerness = true; 915238104Sdes } else if (*my_str == 'S') { 916238104Sdes northerness = false; 917238104Sdes } else { 918238104Sdes return LDNS_STATUS_INVALID_STR; 919238104Sdes } 920238104Sdes 921238104Sdes my_str++; 922238104Sdes 923238104Sdes /* store number */ 924238104Sdes s = 1000.0 * s; 925238104Sdes /* add a little to make floor in conversion a round */ 926238104Sdes s += 0.0005; 927238104Sdes latitude = (uint32_t) s; 928238104Sdes latitude += 1000 * 60 * m; 929238104Sdes latitude += 1000 * 60 * 60 * h; 930238104Sdes if (northerness) { 931238104Sdes latitude = equator + latitude; 932238104Sdes } else { 933238104Sdes latitude = equator - latitude; 934238104Sdes } 935238104Sdes while (isblank(*my_str)) { 936238104Sdes my_str++; 937238104Sdes } 938238104Sdes 939238104Sdes if (isdigit((int) *my_str)) { 940238104Sdes h = (uint32_t) strtol(my_str, &my_str, 10); 941238104Sdes } else { 942238104Sdes return LDNS_STATUS_INVALID_STR; 943238104Sdes } 944238104Sdes 945238104Sdes while (isblank((int) *my_str)) { 946238104Sdes my_str++; 947238104Sdes } 948238104Sdes 949238104Sdes if (isdigit((int) *my_str)) { 950238104Sdes m = (uint32_t) strtol(my_str, &my_str, 10); 951238104Sdes } else if (*my_str == 'E' || *my_str == 'W') { 952238104Sdes goto east; 953238104Sdes } else { 954238104Sdes return LDNS_STATUS_INVALID_STR; 955238104Sdes } 956238104Sdes 957238104Sdes while (isblank(*my_str)) { 958238104Sdes my_str++; 959238104Sdes } 960238104Sdes 961238104Sdes if (isdigit((int) *my_str)) { 962238104Sdes s = strtod(my_str, &my_str); 963238104Sdes } 964238104Sdes 965238104Sdeseast: 966238104Sdes while (isblank(*my_str)) { 967238104Sdes my_str++; 968238104Sdes } 969238104Sdes 970238104Sdes if (*my_str == 'E') { 971238104Sdes easterness = true; 972238104Sdes } else if (*my_str == 'W') { 973238104Sdes easterness = false; 974238104Sdes } else { 975238104Sdes return LDNS_STATUS_INVALID_STR; 976238104Sdes } 977238104Sdes 978238104Sdes my_str++; 979238104Sdes 980238104Sdes /* store number */ 981238104Sdes s *= 1000.0; 982238104Sdes /* add a little to make floor in conversion a round */ 983238104Sdes s += 0.0005; 984238104Sdes longitude = (uint32_t) s; 985238104Sdes longitude += 1000 * 60 * m; 986238104Sdes longitude += 1000 * 60 * 60 * h; 987238104Sdes 988238104Sdes if (easterness) { 989238104Sdes longitude += equator; 990238104Sdes } else { 991238104Sdes longitude = equator - longitude; 992238104Sdes } 993238104Sdes 994238104Sdes altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 + 995238104Sdes 10000000.0 + 0.5); 996238104Sdes if (*my_str == 'm' || *my_str == 'M') { 997238104Sdes my_str++; 998238104Sdes } 999238104Sdes 1000238104Sdes if (strlen(my_str) > 0) { 1001238104Sdes if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e)) 1002238104Sdes return LDNS_STATUS_INVALID_STR; 1003238104Sdes } 1004238104Sdes 1005238104Sdes if (strlen(my_str) > 0) { 1006238104Sdes if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e)) 1007238104Sdes return LDNS_STATUS_INVALID_STR; 1008238104Sdes } 1009238104Sdes 1010238104Sdes if (strlen(my_str) > 0) { 1011238104Sdes if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e)) 1012238104Sdes return LDNS_STATUS_INVALID_STR; 1013238104Sdes } 1014238104Sdes 1015238104Sdes data = LDNS_XMALLOC(uint8_t, 16); 1016238104Sdes if(!data) { 1017238104Sdes return LDNS_STATUS_MEM_ERR; 1018238104Sdes } 1019238104Sdes data[0] = 0; 1020238104Sdes data[1] = 0; 1021238104Sdes data[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f); 1022238104Sdes data[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f); 1023238104Sdes data[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f); 1024238104Sdes ldns_write_uint32(data + 4, latitude); 1025238104Sdes ldns_write_uint32(data + 8, longitude); 1026238104Sdes ldns_write_uint32(data + 12, altitude); 1027238104Sdes 1028238104Sdes *rd = ldns_rdf_new_frm_data( 1029238104Sdes LDNS_RDF_TYPE_LOC, 16, data); 1030238104Sdes 1031238104Sdes LDNS_FREE(data); 1032238104Sdes return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 1033238104Sdes} 1034238104Sdes 1035238104Sdesldns_status 1036238104Sdesldns_str2rdf_wks(ldns_rdf **rd, const char *str) 1037238104Sdes{ 1038238104Sdes uint8_t *bitmap = NULL; 1039238104Sdes uint8_t *data; 1040238104Sdes int bm_len = 0; 1041238104Sdes 1042238104Sdes struct protoent *proto = NULL; 1043238104Sdes struct servent *serv = NULL; 1044238104Sdes int serv_port; 1045238104Sdes 1046238104Sdes ldns_buffer *str_buf; 1047238104Sdes 1048238104Sdes char *proto_str = NULL; 1049238104Sdes char *token; 1050238104Sdes if(strlen(str) == 0) 1051238104Sdes token = LDNS_XMALLOC(char, 50); 1052238104Sdes else token = LDNS_XMALLOC(char, strlen(str)+2); 1053238104Sdes if(!token) return LDNS_STATUS_MEM_ERR; 1054238104Sdes 1055238104Sdes str_buf = LDNS_MALLOC(ldns_buffer); 1056238104Sdes if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} 1057238104Sdes ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); 1058238104Sdes if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { 1059238104Sdes LDNS_FREE(str_buf); 1060238104Sdes LDNS_FREE(token); 1061238104Sdes return LDNS_STATUS_MEM_ERR; 1062238104Sdes } 1063238104Sdes 1064238104Sdes while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { 1065238104Sdes if (!proto_str) { 1066238104Sdes proto_str = strdup(token); 1067238104Sdes if (!proto_str) { 1068238104Sdes LDNS_FREE(bitmap); 1069238104Sdes LDNS_FREE(token); 1070238104Sdes ldns_buffer_free(str_buf); 1071238104Sdes return LDNS_STATUS_INVALID_STR; 1072238104Sdes } 1073238104Sdes } else { 1074238104Sdes serv = getservbyname(token, proto_str); 1075238104Sdes if (serv) { 1076238104Sdes serv_port = (int) ntohs((uint16_t) serv->s_port); 1077238104Sdes } else { 1078238104Sdes serv_port = atoi(token); 1079238104Sdes } 1080238104Sdes if (serv_port / 8 >= bm_len) { 1081238104Sdes uint8_t *b2 = LDNS_XREALLOC(bitmap, uint8_t, (serv_port / 8) + 1); 1082238104Sdes if(!b2) { 1083238104Sdes LDNS_FREE(bitmap); 1084238104Sdes LDNS_FREE(token); 1085238104Sdes ldns_buffer_free(str_buf); 1086238104Sdes free(proto_str); 1087238104Sdes return LDNS_STATUS_INVALID_STR; 1088238104Sdes } 1089238104Sdes bitmap = b2; 1090238104Sdes /* set to zero to be sure */ 1091238104Sdes for (; bm_len <= serv_port / 8; bm_len++) { 1092238104Sdes bitmap[bm_len] = 0; 1093238104Sdes } 1094238104Sdes } 1095238104Sdes ldns_set_bit(bitmap + (serv_port / 8), 7 - (serv_port % 8), true); 1096238104Sdes } 1097238104Sdes } 1098238104Sdes 1099238104Sdes if (!proto_str || !bitmap) { 1100238104Sdes LDNS_FREE(bitmap); 1101238104Sdes LDNS_FREE(token); 1102238104Sdes ldns_buffer_free(str_buf); 1103238104Sdes free(proto_str); 1104238104Sdes return LDNS_STATUS_INVALID_STR; 1105238104Sdes } 1106238104Sdes 1107238104Sdes data = LDNS_XMALLOC(uint8_t, bm_len + 1); 1108238104Sdes if(!data) { 1109238104Sdes LDNS_FREE(token); 1110238104Sdes ldns_buffer_free(str_buf); 1111238104Sdes LDNS_FREE(bitmap); 1112238104Sdes free(proto_str); 1113238104Sdes return LDNS_STATUS_INVALID_STR; 1114238104Sdes } 1115238104Sdes if (proto_str) 1116238104Sdes proto = getprotobyname(proto_str); 1117238104Sdes if (proto) { 1118238104Sdes data[0] = (uint8_t) proto->p_proto; 1119238104Sdes } else if (proto_str) { 1120238104Sdes data[0] = (uint8_t) atoi(proto_str); 1121238104Sdes } 1122238104Sdes memcpy(data + 1, bitmap, (size_t) bm_len); 1123238104Sdes 1124238104Sdes *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_WKS, (uint16_t) (bm_len + 1), data); 1125238104Sdes 1126238104Sdes LDNS_FREE(data); 1127238104Sdes LDNS_FREE(token); 1128238104Sdes ldns_buffer_free(str_buf); 1129238104Sdes LDNS_FREE(bitmap); 1130238104Sdes free(proto_str); 1131238104Sdes#ifdef HAVE_ENDSERVENT 1132238104Sdes endservent(); 1133238104Sdes#endif 1134238104Sdes#ifdef HAVE_ENDPROTOENT 1135238104Sdes endprotoent(); 1136238104Sdes#endif 1137238104Sdes 1138238104Sdes if(!*rd) return LDNS_STATUS_MEM_ERR; 1139238104Sdes 1140238104Sdes return LDNS_STATUS_OK; 1141238104Sdes} 1142238104Sdes 1143238104Sdesldns_status 1144238104Sdesldns_str2rdf_nsap(ldns_rdf **rd, const char *str) 1145238104Sdes{ 1146238104Sdes size_t len, i; 1147238104Sdes char* nsap_str = (char*) str; 1148238104Sdes 1149238104Sdes /* just a hex string with optional dots? */ 1150238104Sdes if (str[0] != '0' || str[1] != 'x') { 1151238104Sdes return LDNS_STATUS_INVALID_STR; 1152238104Sdes } else { 1153238104Sdes len = strlen(str); 1154238104Sdes for (i=0; i < len; i++) { 1155238104Sdes if (nsap_str[i] == '.') 1156238104Sdes nsap_str[i] = ' '; 1157238104Sdes } 1158238104Sdes return ldns_str2rdf_hex(rd, str+2); 1159238104Sdes } 1160238104Sdes} 1161238104Sdes 1162238104Sdesldns_status 1163238104Sdesldns_str2rdf_atma(ldns_rdf **rd, const char *str) 1164238104Sdes{ 1165238104Sdes size_t len, i; 1166238104Sdes char* atma_str = (char*) str; 1167238104Sdes ldns_status status; 1168238104Sdes 1169238104Sdes /* just a hex string with optional dots? */ 1170238104Sdes len = strlen(str); 1171238104Sdes for (i=0; i < len; i++) { 1172238104Sdes if (atma_str[i] == '.') 1173238104Sdes atma_str[i] = ' '; 1174238104Sdes } 1175238104Sdes status = ldns_str2rdf_hex(rd, str); 1176238104Sdes if (status != LDNS_STATUS_OK) { 1177238104Sdes ; /* probably in e.164 format than */ 1178238104Sdes } 1179238104Sdes return status; 1180238104Sdes} 1181238104Sdes 1182238104Sdesldns_status 1183238104Sdesldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str) 1184238104Sdes{ 1185238104Sdes uint8_t precedence = 0; 1186238104Sdes uint8_t gateway_type = 0; 1187238104Sdes uint8_t algorithm = 0; 1188238104Sdes char* gateway = NULL; 1189238104Sdes char* publickey = NULL; 1190238104Sdes uint8_t *data; 1191238104Sdes ldns_buffer *str_buf; 1192238104Sdes char *token; 1193238104Sdes int token_count = 0; 1194238104Sdes int ipseckey_len = 0; 1195238104Sdes ldns_rdf* gateway_rdf = NULL; 1196238104Sdes ldns_rdf* publickey_rdf = NULL; 1197238104Sdes ldns_status status = LDNS_STATUS_OK; 1198238104Sdes 1199238104Sdes if(strlen(str) == 0) 1200238104Sdes token = LDNS_XMALLOC(char, 256); 1201238104Sdes else token = LDNS_XMALLOC(char, strlen(str)+2); 1202238104Sdes if(!token) return LDNS_STATUS_MEM_ERR; 1203238104Sdes 1204238104Sdes str_buf = LDNS_MALLOC(ldns_buffer); 1205238104Sdes if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} 1206238104Sdes ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); 1207238104Sdes if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { 1208238104Sdes LDNS_FREE(str_buf); 1209238104Sdes LDNS_FREE(token); 1210238104Sdes return LDNS_STATUS_MEM_ERR; 1211238104Sdes } 1212238104Sdes while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { 1213238104Sdes switch (token_count) { 1214238104Sdes case 0: 1215238104Sdes precedence = (uint8_t)atoi(token); 1216238104Sdes break; 1217238104Sdes case 1: 1218238104Sdes gateway_type = (uint8_t)atoi(token); 1219238104Sdes break; 1220238104Sdes case 2: 1221238104Sdes algorithm = (uint8_t)atoi(token); 1222238104Sdes break; 1223238104Sdes case 3: 1224238104Sdes gateway = strdup(token); 1225238104Sdes if (!gateway || (gateway_type == 0 && 1226238104Sdes (token[0] != '.' || token[1] != '\0'))) { 1227238104Sdes LDNS_FREE(gateway); 1228238104Sdes LDNS_FREE(token); 1229238104Sdes ldns_buffer_free(str_buf); 1230238104Sdes return LDNS_STATUS_INVALID_STR; 1231238104Sdes } 1232238104Sdes break; 1233238104Sdes case 4: 1234238104Sdes publickey = strdup(token); 1235238104Sdes break; 1236238104Sdes default: 1237238104Sdes LDNS_FREE(token); 1238238104Sdes ldns_buffer_free(str_buf); 1239238104Sdes return LDNS_STATUS_INVALID_STR; 1240238104Sdes break; 1241238104Sdes } 1242238104Sdes token_count++; 1243238104Sdes } 1244238104Sdes 1245238104Sdes if (!gateway || !publickey) { 1246238104Sdes if (gateway) 1247238104Sdes LDNS_FREE(gateway); 1248238104Sdes if (publickey) 1249238104Sdes LDNS_FREE(publickey); 1250238104Sdes LDNS_FREE(token); 1251238104Sdes ldns_buffer_free(str_buf); 1252238104Sdes return LDNS_STATUS_INVALID_STR; 1253238104Sdes } 1254238104Sdes 1255238104Sdes if (gateway_type == 1) { 1256238104Sdes status = ldns_str2rdf_a(&gateway_rdf, gateway); 1257238104Sdes } else if (gateway_type == 2) { 1258238104Sdes status = ldns_str2rdf_aaaa(&gateway_rdf, gateway); 1259238104Sdes } else if (gateway_type == 3) { 1260238104Sdes status = ldns_str2rdf_dname(&gateway_rdf, gateway); 1261238104Sdes } 1262238104Sdes 1263238104Sdes if (status != LDNS_STATUS_OK) { 1264238104Sdes if (gateway) 1265238104Sdes LDNS_FREE(gateway); 1266238104Sdes if (publickey) 1267238104Sdes LDNS_FREE(publickey); 1268238104Sdes LDNS_FREE(token); 1269238104Sdes ldns_buffer_free(str_buf); 1270238104Sdes return LDNS_STATUS_INVALID_STR; 1271238104Sdes } 1272238104Sdes 1273238104Sdes status = ldns_str2rdf_b64(&publickey_rdf, publickey); 1274238104Sdes 1275238104Sdes if (status != LDNS_STATUS_OK) { 1276238104Sdes if (gateway) 1277238104Sdes LDNS_FREE(gateway); 1278238104Sdes if (publickey) 1279238104Sdes LDNS_FREE(publickey); 1280238104Sdes LDNS_FREE(token); 1281238104Sdes ldns_buffer_free(str_buf); 1282238104Sdes if (gateway_rdf) ldns_rdf_free(gateway_rdf); 1283238104Sdes return LDNS_STATUS_INVALID_STR; 1284238104Sdes } 1285238104Sdes 1286238104Sdes /* now copy all into one ipseckey rdf */ 1287238104Sdes if (gateway_type) 1288238104Sdes ipseckey_len = 3 + (int)ldns_rdf_size(gateway_rdf) + (int)ldns_rdf_size(publickey_rdf); 1289238104Sdes else 1290238104Sdes ipseckey_len = 3 + (int)ldns_rdf_size(publickey_rdf); 1291238104Sdes 1292238104Sdes data = LDNS_XMALLOC(uint8_t, ipseckey_len); 1293238104Sdes if(!data) { 1294238104Sdes if (gateway) 1295238104Sdes LDNS_FREE(gateway); 1296238104Sdes if (publickey) 1297238104Sdes LDNS_FREE(publickey); 1298238104Sdes LDNS_FREE(token); 1299238104Sdes ldns_buffer_free(str_buf); 1300238104Sdes if (gateway_rdf) ldns_rdf_free(gateway_rdf); 1301238104Sdes if (publickey_rdf) ldns_rdf_free(publickey_rdf); 1302238104Sdes return LDNS_STATUS_MEM_ERR; 1303238104Sdes } 1304238104Sdes 1305238104Sdes data[0] = precedence; 1306238104Sdes data[1] = gateway_type; 1307238104Sdes data[2] = algorithm; 1308238104Sdes 1309238104Sdes if (gateway_type) { 1310238104Sdes memcpy(data + 3, 1311238104Sdes ldns_rdf_data(gateway_rdf), ldns_rdf_size(gateway_rdf)); 1312238104Sdes memcpy(data + 3 + ldns_rdf_size(gateway_rdf), 1313238104Sdes ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf)); 1314238104Sdes } else { 1315238104Sdes memcpy(data + 3, 1316238104Sdes ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf)); 1317238104Sdes } 1318238104Sdes 1319238104Sdes *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_IPSECKEY, (uint16_t) ipseckey_len, data); 1320238104Sdes 1321238104Sdes if (gateway) 1322238104Sdes LDNS_FREE(gateway); 1323238104Sdes if (publickey) 1324238104Sdes LDNS_FREE(publickey); 1325238104Sdes LDNS_FREE(token); 1326238104Sdes ldns_buffer_free(str_buf); 1327238104Sdes ldns_rdf_free(gateway_rdf); 1328238104Sdes ldns_rdf_free(publickey_rdf); 1329238104Sdes LDNS_FREE(data); 1330238104Sdes if(!*rd) return LDNS_STATUS_MEM_ERR; 1331238104Sdes return LDNS_STATUS_OK; 1332238104Sdes} 1333269257Sdes 1334269257Sdesldns_status 1335269257Sdesldns_str2rdf_ilnp64(ldns_rdf **rd, const char *str) 1336269257Sdes{ 1337269257Sdes unsigned int a, b, c, d; 1338269257Sdes uint16_t shorts[4]; 1339269257Sdes int l; 1340269257Sdes 1341269257Sdes if (sscanf(str, "%4x:%4x:%4x:%4x%n", &a, &b, &c, &d, &l) != 4 || 1342269257Sdes l != (int)strlen(str) || /* more data to read */ 1343269257Sdes strpbrk(str, "+-") /* signed hexes */ 1344269257Sdes ) { 1345269257Sdes return LDNS_STATUS_INVALID_ILNP64; 1346269257Sdes } else { 1347269257Sdes shorts[0] = htons(a); 1348269257Sdes shorts[1] = htons(b); 1349269257Sdes shorts[2] = htons(c); 1350269257Sdes shorts[3] = htons(d); 1351269257Sdes *rd = ldns_rdf_new_frm_data( 1352269257Sdes LDNS_RDF_TYPE_ILNP64, 4 * sizeof(uint16_t), &shorts); 1353269257Sdes } 1354269257Sdes return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; 1355269257Sdes} 1356269257Sdes 1357269257Sdesldns_status 1358269257Sdesldns_str2rdf_eui48(ldns_rdf **rd, const char *str) 1359269257Sdes{ 1360269257Sdes unsigned int a, b, c, d, e, f; 1361269257Sdes uint8_t bytes[6]; 1362269257Sdes int l; 1363269257Sdes 1364269257Sdes if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x%n", 1365269257Sdes &a, &b, &c, &d, &e, &f, &l) != 6 || 1366269257Sdes l != (int)strlen(str) || /* more data to read */ 1367269257Sdes strpbrk(str, "+-") /* signed hexes */ 1368269257Sdes ) { 1369269257Sdes return LDNS_STATUS_INVALID_EUI48; 1370269257Sdes } else { 1371269257Sdes bytes[0] = a; 1372269257Sdes bytes[1] = b; 1373269257Sdes bytes[2] = c; 1374269257Sdes bytes[3] = d; 1375269257Sdes bytes[4] = e; 1376269257Sdes bytes[5] = f; 1377269257Sdes *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_EUI48, 6, &bytes); 1378269257Sdes } 1379269257Sdes return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; 1380269257Sdes} 1381269257Sdes 1382269257Sdesldns_status 1383269257Sdesldns_str2rdf_eui64(ldns_rdf **rd, const char *str) 1384269257Sdes{ 1385269257Sdes unsigned int a, b, c, d, e, f, g, h; 1386269257Sdes uint8_t bytes[8]; 1387269257Sdes int l; 1388269257Sdes 1389269257Sdes if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x%n", 1390269257Sdes &a, &b, &c, &d, &e, &f, &g, &h, &l) != 8 || 1391269257Sdes l != (int)strlen(str) || /* more data to read */ 1392269257Sdes strpbrk(str, "+-") /* signed hexes */ 1393269257Sdes ) { 1394269257Sdes return LDNS_STATUS_INVALID_EUI64; 1395269257Sdes } else { 1396269257Sdes bytes[0] = a; 1397269257Sdes bytes[1] = b; 1398269257Sdes bytes[2] = c; 1399269257Sdes bytes[3] = d; 1400269257Sdes bytes[4] = e; 1401269257Sdes bytes[5] = f; 1402269257Sdes bytes[6] = g; 1403269257Sdes bytes[7] = h; 1404269257Sdes *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_EUI64, 8, &bytes); 1405269257Sdes } 1406269257Sdes return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; 1407269257Sdes} 1408269257Sdes 1409269257Sdesldns_status 1410269257Sdesldns_str2rdf_tag(ldns_rdf **rd, const char *str) 1411269257Sdes{ 1412269257Sdes uint8_t *data; 1413269257Sdes const char* ptr; 1414269257Sdes 1415269257Sdes if (strlen(str) > 255) { 1416269257Sdes return LDNS_STATUS_INVALID_TAG; 1417269257Sdes } 1418269257Sdes for (ptr = str; *ptr; ptr++) { 1419269257Sdes if (! isalnum(*ptr)) { 1420269257Sdes return LDNS_STATUS_INVALID_TAG; 1421269257Sdes } 1422269257Sdes } 1423269257Sdes data = LDNS_XMALLOC(uint8_t, strlen(str) + 1); 1424269257Sdes if (!data) { 1425269257Sdes return LDNS_STATUS_MEM_ERR; 1426269257Sdes } 1427269257Sdes data[0] = strlen(str); 1428269257Sdes memcpy(data + 1, str, strlen(str)); 1429269257Sdes 1430269257Sdes *rd = ldns_rdf_new(LDNS_RDF_TYPE_TAG, strlen(str) + 1, data); 1431269257Sdes if (!*rd) { 1432269257Sdes LDNS_FREE(data); 1433269257Sdes return LDNS_STATUS_MEM_ERR; 1434269257Sdes } 1435269257Sdes return LDNS_STATUS_OK; 1436269257Sdes} 1437269257Sdes 1438269257Sdesldns_status 1439269257Sdesldns_str2rdf_long_str(ldns_rdf **rd, const char *str) 1440269257Sdes{ 1441269257Sdes uint8_t *data, *dp, ch = 0; 1442269257Sdes size_t length; 1443269257Sdes 1444269257Sdes /* Worst case space requirement. We'll realloc to actual size later. */ 1445269257Sdes dp = data = LDNS_XMALLOC(uint8_t, strlen(str)); 1446269257Sdes if (! data) { 1447269257Sdes return LDNS_STATUS_MEM_ERR; 1448269257Sdes } 1449269257Sdes 1450269257Sdes /* Fill data with parsed bytes */ 1451269257Sdes while (parse_char(&ch, &str)) { 1452269257Sdes *dp++ = ch; 1453269257Sdes if (dp - data > LDNS_MAX_RDFLEN) { 1454269257Sdes LDNS_FREE(data); 1455269257Sdes return LDNS_STATUS_INVALID_STR; 1456269257Sdes } 1457269257Sdes } 1458269257Sdes if (! str) { 1459269257Sdes return LDNS_STATUS_SYNTAX_BAD_ESCAPE; 1460269257Sdes } 1461269257Sdes length = (size_t)(dp - data); 1462269257Sdes 1463269257Sdes /* Lose the overmeasure */ 1464269257Sdes data = LDNS_XREALLOC(dp = data, uint8_t, length); 1465269257Sdes if (! data) { 1466269257Sdes LDNS_FREE(dp); 1467269257Sdes return LDNS_STATUS_MEM_ERR; 1468269257Sdes } 1469269257Sdes 1470269257Sdes /* Create rdf */ 1471269257Sdes *rd = ldns_rdf_new(LDNS_RDF_TYPE_LONG_STR, length, data); 1472269257Sdes if (! *rd) { 1473269257Sdes LDNS_FREE(data); 1474269257Sdes return LDNS_STATUS_MEM_ERR; 1475269257Sdes } 1476269257Sdes return LDNS_STATUS_OK; 1477269257Sdes} 1478269257Sdes 1479269257Sdesldns_status 1480269257Sdesldns_str2rdf_hip(ldns_rdf **rd, const char *str) 1481269257Sdes{ 1482269257Sdes const char *hit = strchr(str, ' ') + 1; 1483269257Sdes const char *pk = hit == NULL ? NULL : strchr(hit, ' ') + 1; 1484269257Sdes size_t hit_size = hit == NULL ? 0 1485269257Sdes : pk == NULL ? strlen(hit) : (size_t) (pk - hit) - 1; 1486269257Sdes size_t pk_size = pk == NULL ? 0 : strlen(pk); 1487269257Sdes size_t hit_wire_size = (hit_size + 1) / 2; 1488269257Sdes size_t pk_wire_size = ldns_b64_pton_calculate_size(pk_size); 1489269257Sdes size_t rdf_size = 4 + hit_wire_size + pk_wire_size; 1490269257Sdes 1491269257Sdes char *endptr; /* utility var for strtol usage */ 1492269257Sdes int algorithm = strtol(str, &endptr, 10); 1493269257Sdes 1494269257Sdes uint8_t *data, *dp; 1495269257Sdes int hi, lo, written; 1496269257Sdes 1497269257Sdes if (hit_size == 0 || pk_size == 0 || (hit_size + 1) / 2 > 255 1498269257Sdes || rdf_size > LDNS_MAX_RDFLEN 1499269257Sdes || algorithm < 0 || algorithm > 255 1500269257Sdes || (errno != 0 && algorithm == 0) /* out of range */ 1501269257Sdes || endptr == str /* no digits */) { 1502269257Sdes 1503269257Sdes return LDNS_STATUS_SYNTAX_ERR; 1504269257Sdes } 1505269257Sdes if ((data = LDNS_XMALLOC(uint8_t, rdf_size)) == NULL) { 1506269257Sdes 1507269257Sdes return LDNS_STATUS_MEM_ERR; 1508269257Sdes } 1509269257Sdes /* From RFC 5205 section 5. HIP RR Storage Format: 1510269257Sdes ************************************************* 1511269257Sdes 1512269257Sdes 0 1 2 3 1513269257Sdes 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 1514269257Sdes +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1515269257Sdes | HIT length | PK algorithm | PK length | 1516269257Sdes +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1517269257Sdes | | 1518269257Sdes ~ HIT ~ 1519269257Sdes | | 1520269257Sdes + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1521269257Sdes | | | 1522269257Sdes +-+-+-+-+-+-+-+-+-+-+-+ + 1523269257Sdes | Public Key | 1524269257Sdes ~ ~ 1525269257Sdes | | 1526269257Sdes + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1527269257Sdes | | | 1528269257Sdes +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 1529269257Sdes | | 1530269257Sdes ~ Rendezvous Servers ~ 1531269257Sdes | | 1532269257Sdes + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1533269257Sdes | | 1534269257Sdes +-+-+-+-+-+-+-+ */ 1535269257Sdes 1536269257Sdes data[0] = (uint8_t) hit_wire_size; 1537269257Sdes data[1] = (uint8_t) algorithm; 1538269257Sdes 1539269257Sdes for (dp = data + 4; *hit && *hit != ' '; dp++) { 1540269257Sdes 1541269257Sdes if ((hi = ldns_hexdigit_to_int(*hit++)) == -1 || 1542269257Sdes (lo = ldns_hexdigit_to_int(*hit++)) == -1) { 1543269257Sdes 1544269257Sdes LDNS_FREE(data); 1545269257Sdes return LDNS_STATUS_INVALID_HEX; 1546269257Sdes } 1547269257Sdes *dp = (uint8_t) hi << 4 | lo; 1548269257Sdes } 1549269257Sdes if ((written = ldns_b64_pton(pk, dp, pk_wire_size)) <= 0) { 1550269257Sdes 1551269257Sdes LDNS_FREE(data); 1552269257Sdes return LDNS_STATUS_INVALID_B64; 1553269257Sdes } 1554269257Sdes 1555269257Sdes /* Because ldns_b64_pton_calculate_size isn't always correct: 1556269257Sdes * (we have to fix it at some point) 1557269257Sdes */ 1558269257Sdes pk_wire_size = (uint16_t) written; 1559269257Sdes ldns_write_uint16(data + 2, pk_wire_size); 1560269257Sdes rdf_size = 4 + hit_wire_size + pk_wire_size; 1561269257Sdes 1562269257Sdes /* Create rdf */ 1563269257Sdes if (! (*rd = ldns_rdf_new(LDNS_RDF_TYPE_HIP, rdf_size, data))) { 1564269257Sdes 1565269257Sdes LDNS_FREE(data); 1566269257Sdes return LDNS_STATUS_MEM_ERR; 1567269257Sdes } 1568269257Sdes return LDNS_STATUS_OK; 1569269257Sdes} 1570