1/** 2 * str2wire.c - read txt presentation of RRs 3 * 4 * (c) NLnet Labs, 2005-2006 5 * 6 * See the file LICENSE for the license 7 */ 8 9/** 10 * \file 11 * 12 * Parses text to wireformat. 13 */ 14#include "config.h" 15#include "ldns/str2wire.h" 16#include "ldns/wire2str.h" 17#include "ldns/sbuffer.h" 18#include "ldns/parse.h" 19#include "ldns/parseutil.h" 20#include <ctype.h> 21#ifdef HAVE_TIME_H 22#include <time.h> 23#endif 24#ifdef HAVE_NETDB_H 25#include <netdb.h> 26#endif 27 28/** return an error */ 29#define RET_ERR(e, off) ((int)((e)|((off)<<LDNS_WIREPARSE_SHIFT))) 30/** Move parse error but keep its ID */ 31#define RET_ERR_SHIFT(e, move) RET_ERR(LDNS_WIREPARSE_ERROR(e), LDNS_WIREPARSE_OFFSET(e)+(move)); 32#define LDNS_IP6ADDRLEN (128/8) 33 34/* 35 * No special care is taken, all dots are translated into 36 * label separators. 37 * @param rel: true if the domain is not absolute (not terminated in .). 38 * The output is then still terminated with a '0' rootlabel. 39 */ 40static int sldns_str2wire_dname_buf_rel(const char* str, uint8_t* buf, 41 size_t* olen, int* rel) 42{ 43 size_t len; 44 45 const char *s; 46 uint8_t *q, *pq, label_len; 47 48 if(rel) *rel = 0; 49 len = strlen((char*)str); 50 /* octet representation can make strings a lot longer than actual length */ 51 if (len > LDNS_MAX_DOMAINLEN * 4) { 52 return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, 0); 53 } 54 if (0 == len) { 55 return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_UNDERFLOW, 0); 56 } 57 58 /* root label */ 59 if (1 == len && *str == '.') { 60 if(*olen < 1) 61 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 0); 62 buf[0] = 0; 63 *olen = 1; 64 return LDNS_WIREPARSE_ERR_OK; 65 } 66 67 /* get on with the rest */ 68 69 /* s is on the current character in the string 70 * pq points to where the labellength is going to go 71 * label_len keeps track of the current label's length 72 * q builds the dname inside the buf array 73 */ 74 len = 0; 75 if(*olen < 1) 76 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 0); 77 q = buf+1; 78 pq = buf; 79 label_len = 0; 80 for (s = str; *s; s++, q++) { 81 if (q >= buf + *olen) 82 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, q-buf); 83 if (q > buf + LDNS_MAX_DOMAINLEN) 84 return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, q-buf); 85 switch (*s) { 86 case '.': 87 if (label_len > LDNS_MAX_LABELLEN) { 88 return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, q-buf); 89 } 90 if (label_len == 0) { 91 return RET_ERR(LDNS_WIREPARSE_ERR_EMPTY_LABEL, q-buf); 92 } 93 len += label_len + 1; 94 *q = 0; 95 *pq = label_len; 96 label_len = 0; 97 pq = q; 98 break; 99 case '\\': 100 /* octet value or literal char */ 101 s += 1; 102 if (!sldns_parse_escape(q, &s)) { 103 *q = 0; 104 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE, q-buf); 105 } 106 s -= 1; 107 label_len++; 108 break; 109 default: 110 *q = (uint8_t)*s; 111 label_len++; 112 } 113 } 114 115 /* add root label if last char was not '.' */ 116 if(label_len != 0) { 117 if(rel) *rel = 1; 118 if (q >= buf + *olen) 119 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, q-buf); 120 if (q > buf + LDNS_MAX_DOMAINLEN) { 121 return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, q-buf); 122 } 123 if (label_len > LDNS_MAX_LABELLEN) { 124 return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, q-buf); 125 } 126 if (label_len == 0) { /* label_len 0 but not . at end? */ 127 return RET_ERR(LDNS_WIREPARSE_ERR_EMPTY_LABEL, q-buf); 128 } 129 len += label_len + 1; 130 *pq = label_len; 131 *q = 0; 132 } 133 len++; 134 *olen = len; 135 136 return LDNS_WIREPARSE_ERR_OK; 137} 138 139int sldns_str2wire_dname_buf(const char* str, uint8_t* buf, size_t* len) 140{ 141 return sldns_str2wire_dname_buf_rel(str, buf, len, NULL); 142} 143 144int sldns_str2wire_dname_buf_origin(const char* str, uint8_t* buf, size_t* len, 145 uint8_t* origin, size_t origin_len) 146{ 147 size_t dlen = *len; 148 int rel = 0; 149 int s = sldns_str2wire_dname_buf_rel(str, buf, &dlen, &rel); 150 if(s) return s; 151 152 if(rel && origin && dlen > 0) { 153 if(dlen + origin_len - 1 > LDNS_MAX_DOMAINLEN) 154 return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, 155 LDNS_MAX_DOMAINLEN); 156 if(dlen + origin_len - 1 > *len) 157 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 158 *len); 159 memmove(buf+dlen-1, origin, origin_len); 160 *len = dlen + origin_len - 1; 161 } else 162 *len = dlen; 163 return LDNS_WIREPARSE_ERR_OK; 164} 165 166uint8_t* sldns_str2wire_dname(const char* str, size_t* len) 167{ 168 uint8_t dname[LDNS_MAX_DOMAINLEN+1]; 169 *len = sizeof(dname); 170 if(sldns_str2wire_dname_buf(str, dname, len) == 0) { 171 uint8_t* r = (uint8_t*)malloc(*len); 172 if(r) return memcpy(r, dname, *len); 173 } 174 *len = 0; 175 return NULL; 176} 177 178/** read owner name */ 179static int 180rrinternal_get_owner(sldns_buffer* strbuf, uint8_t* rr, size_t* len, 181 size_t* dname_len, uint8_t* origin, size_t origin_len, uint8_t* prev, 182 size_t prev_len, char* token, size_t token_len) 183{ 184 /* split the rr in its parts -1 signals trouble */ 185 if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { 186 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, 187 sldns_buffer_position(strbuf)); 188 } 189 190 if(strcmp(token, "@") == 0) { 191 uint8_t* tocopy; 192 if (origin) { 193 *dname_len = origin_len; 194 tocopy = origin; 195 } else if (prev) { 196 *dname_len = prev_len; 197 tocopy = prev; 198 } else { 199 /* default to root */ 200 *dname_len = 1; 201 tocopy = (uint8_t*)"\0"; 202 } 203 if(*len < *dname_len) 204 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 205 sldns_buffer_position(strbuf)); 206 memmove(rr, tocopy, *dname_len); 207 } else if(strlen(token) == 0) { 208 /* no ownername was given, try prev, if that fails 209 * origin, else default to root */ 210 uint8_t* tocopy; 211 if(prev) { 212 *dname_len = prev_len; 213 tocopy = prev; 214 } else if(origin) { 215 *dname_len = origin_len; 216 tocopy = origin; 217 } else { 218 *dname_len = 1; 219 tocopy = (uint8_t*)"\0"; 220 } 221 if(*len < *dname_len) 222 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 223 sldns_buffer_position(strbuf)); 224 memmove(rr, tocopy, *dname_len); 225 } else { 226 size_t dlen = *len; 227 int s = sldns_str2wire_dname_buf_origin(token, rr, &dlen, 228 origin, origin_len); 229 if(s) return RET_ERR_SHIFT(s, 230 sldns_buffer_position(strbuf)-strlen(token)); 231 *dname_len = dlen; 232 } 233 return LDNS_WIREPARSE_ERR_OK; 234} 235 236/** read ttl */ 237static int 238rrinternal_get_ttl(sldns_buffer* strbuf, char* token, size_t token_len, 239 int* not_there, uint32_t* ttl, uint32_t default_ttl) 240{ 241 const char* endptr; 242 if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { 243 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TTL, 244 sldns_buffer_position(strbuf)); 245 } 246 *ttl = (uint32_t) sldns_str2period(token, &endptr); 247 248 if (strlen(token) > 0 && !isdigit((int)token[0])) { 249 *not_there = 1; 250 /* ah, it's not there or something */ 251 if (default_ttl == 0) { 252 *ttl = LDNS_DEFAULT_TTL; 253 } else { 254 *ttl = default_ttl; 255 } 256 } 257 return LDNS_WIREPARSE_ERR_OK; 258} 259 260/** read class */ 261static int 262rrinternal_get_class(sldns_buffer* strbuf, char* token, size_t token_len, 263 int* not_there, uint16_t* cl) 264{ 265 /* if 'not_there' then we got token from previous parse routine */ 266 if(!*not_there) { 267 /* parse new token for class */ 268 if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { 269 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_CLASS, 270 sldns_buffer_position(strbuf)); 271 } 272 } else *not_there = 0; 273 *cl = sldns_get_rr_class_by_name(token); 274 /* class can be left out too, assume IN, current token must be type */ 275 if(*cl == 0 && strcmp(token, "CLASS0") != 0) { 276 *not_there = 1; 277 *cl = LDNS_RR_CLASS_IN; 278 } 279 return LDNS_WIREPARSE_ERR_OK; 280} 281 282/** read type */ 283static int 284rrinternal_get_type(sldns_buffer* strbuf, char* token, size_t token_len, 285 int* not_there, uint16_t* tp) 286{ 287 /* if 'not_there' then we got token from previous parse routine */ 288 if(!*not_there) { 289 /* parse new token for type */ 290 if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { 291 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE, 292 sldns_buffer_position(strbuf)); 293 } 294 } 295 *tp = sldns_get_rr_type_by_name(token); 296 if(*tp == 0 && strcmp(token, "TYPE0") != 0) { 297 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE, 298 sldns_buffer_position(strbuf)); 299 } 300 return LDNS_WIREPARSE_ERR_OK; 301} 302 303/** put type, class, ttl into rr buffer */ 304static int 305rrinternal_write_typeclassttl(sldns_buffer* strbuf, uint8_t* rr, size_t len, 306 size_t dname_len, uint16_t tp, uint16_t cl, uint32_t ttl, int question) 307{ 308 if(question) { 309 /* question is : name, type, class */ 310 if(dname_len + 4 > len) 311 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 312 sldns_buffer_position(strbuf)); 313 sldns_write_uint16(rr+dname_len, tp); 314 sldns_write_uint16(rr+dname_len+2, cl); 315 return LDNS_WIREPARSE_ERR_OK; 316 } 317 318 /* type(2), class(2), ttl(4), rdatalen(2 (later)) = 10 */ 319 if(dname_len + 10 > len) 320 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 321 sldns_buffer_position(strbuf)); 322 sldns_write_uint16(rr+dname_len, tp); 323 sldns_write_uint16(rr+dname_len+2, cl); 324 sldns_write_uint32(rr+dname_len+4, ttl); 325 sldns_write_uint16(rr+dname_len+8, 0); /* rdatalen placeholder */ 326 return LDNS_WIREPARSE_ERR_OK; 327} 328 329/** find delimiters for type */ 330static const char* 331rrinternal_get_delims(sldns_rdf_type rdftype, uint16_t r_cnt, uint16_t r_max) 332{ 333 switch(rdftype) { 334 case LDNS_RDF_TYPE_B64 : 335 case LDNS_RDF_TYPE_HEX : /* These rdf types may con- */ 336 case LDNS_RDF_TYPE_LOC : /* tain whitespace, only if */ 337 case LDNS_RDF_TYPE_WKS : /* it is the last rd field. */ 338 case LDNS_RDF_TYPE_IPSECKEY : 339 case LDNS_RDF_TYPE_NSEC : if (r_cnt == r_max - 1) { 340 return "\n\t"; 341 } 342 break; 343 default : break; 344 } 345 return "\n\t "; 346} 347 348/* Syntactic sugar for sldns_rr_new_frm_str_internal */ 349static int 350sldns_rdf_type_maybe_quoted(sldns_rdf_type rdf_type) 351{ 352 return rdf_type == LDNS_RDF_TYPE_STR || 353 rdf_type == LDNS_RDF_TYPE_LONG_STR; 354} 355 356/** see if rdata is quoted */ 357static int 358rrinternal_get_quoted(sldns_buffer* strbuf, const char** delimiters, 359 sldns_rdf_type rdftype) 360{ 361 if(sldns_rdf_type_maybe_quoted(rdftype) && 362 sldns_buffer_remaining(strbuf) > 0) { 363 364 /* skip spaces */ 365 while(sldns_buffer_remaining(strbuf) > 0 && 366 *(sldns_buffer_current(strbuf)) == ' ') { 367 sldns_buffer_skip(strbuf, 1); 368 } 369 370 if(sldns_buffer_remaining(strbuf) > 0 && 371 *(sldns_buffer_current(strbuf)) == '\"') { 372 *delimiters = "\"\0"; 373 sldns_buffer_skip(strbuf, 1); 374 return 1; 375 } 376 } 377 return 0; 378} 379 380/** spool hex data into rdata */ 381static int 382rrinternal_spool_hex(char* token, uint8_t* rr, size_t rr_len, 383 size_t rr_cur_len, size_t* cur_hex_data_size, size_t hex_data_size) 384{ 385 char* p = token; 386 while(*p) { 387 if(isspace(*p)) { 388 p++; 389 continue; 390 } 391 if(!isxdigit(*p)) 392 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_RDATA, 393 p-token); 394 if(*cur_hex_data_size >= hex_data_size) 395 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_RDATA, 396 p-token); 397 /* extra robust check */ 398 if(rr_cur_len+(*cur_hex_data_size)/2 >= rr_len) 399 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 400 p-token); 401 /* see if 16s or 1s */ 402 if( ((*cur_hex_data_size)&1) == 0) { 403 rr[rr_cur_len+(*cur_hex_data_size)/2] = 404 (uint8_t)sldns_hexdigit_to_int(*p)*16; 405 } else { 406 rr[rr_cur_len+(*cur_hex_data_size)/2] += 407 (uint8_t)sldns_hexdigit_to_int(*p); 408 } 409 p++; 410 (*cur_hex_data_size)++; 411 } 412 return LDNS_WIREPARSE_ERR_OK; 413} 414 415/** read unknown rr type format */ 416static int 417rrinternal_parse_unknown(sldns_buffer* strbuf, char* token, size_t token_len, 418 uint8_t* rr, size_t* rr_len, size_t* rr_cur_len, size_t pre_data_pos) 419{ 420 const char* delim = "\n\t "; 421 size_t hex_data_size, cur_hex_data_size; 422 /* go back to before \# 423 * and skip it while setting delimiters better 424 */ 425 sldns_buffer_set_position(strbuf, pre_data_pos); 426 if(sldns_bget_token(strbuf, token, delim, token_len) == -1) 427 return LDNS_WIREPARSE_ERR_GENERAL; /* should not fail */ 428 /* read rdata octet length */ 429 if(sldns_bget_token(strbuf, token, delim, token_len) == -1) { 430 /* something goes very wrong here */ 431 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_RDATA, 432 sldns_buffer_position(strbuf)); 433 } 434 hex_data_size = (size_t)atoi(token); 435 if(hex_data_size > LDNS_MAX_RDFLEN || 436 *rr_cur_len + hex_data_size > *rr_len) { 437 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 438 sldns_buffer_position(strbuf)); 439 } 440 /* copy hex chars into hex str (2 chars per byte) */ 441 hex_data_size *= 2; 442 cur_hex_data_size = 0; 443 while(cur_hex_data_size < hex_data_size) { 444 int status; 445 ssize_t c = sldns_bget_token(strbuf, token, delim, token_len); 446 if((status = rrinternal_spool_hex(token, rr, *rr_len, 447 *rr_cur_len, &cur_hex_data_size, hex_data_size)) != 0) 448 return RET_ERR_SHIFT(status, 449 sldns_buffer_position(strbuf)-strlen(token)); 450 if(c == -1) { 451 if(cur_hex_data_size != hex_data_size) 452 return RET_ERR( 453 LDNS_WIREPARSE_ERR_SYNTAX_RDATA, 454 sldns_buffer_position(strbuf)); 455 break; 456 } 457 } 458 *rr_cur_len += hex_data_size/2; 459 return LDNS_WIREPARSE_ERR_OK; 460} 461 462/** parse normal RR rdata element */ 463static int 464rrinternal_parse_rdf(sldns_buffer* strbuf, char* token, size_t token_len, 465 uint8_t* rr, size_t rr_len, size_t* rr_cur_len, sldns_rdf_type rdftype, 466 uint16_t rr_type, uint16_t r_cnt, uint16_t r_max, size_t dname_len, 467 uint8_t* origin, size_t origin_len) 468{ 469 size_t len; 470 int status; 471 472 switch(rdftype) { 473 case LDNS_RDF_TYPE_DNAME: 474 /* check if the origin should be used or concatenated */ 475 if(strcmp(token, "@") == 0) { 476 uint8_t* tocopy; 477 size_t copylen; 478 if(origin) { 479 copylen = origin_len; 480 tocopy = origin; 481 } else if(rr_type == LDNS_RR_TYPE_SOA) { 482 copylen = dname_len; 483 tocopy = rr; /* copy rr owner name */ 484 } else { 485 copylen = 1; 486 tocopy = (uint8_t*)"\0"; 487 } 488 if((*rr_cur_len) + copylen > rr_len) 489 return RET_ERR( 490 LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 491 sldns_buffer_position(strbuf)); 492 memmove(rr+*rr_cur_len, tocopy, copylen); 493 (*rr_cur_len) += copylen; 494 } else { 495 size_t dlen = rr_len - (*rr_cur_len); 496 int s = sldns_str2wire_dname_buf_origin(token, 497 rr+*rr_cur_len, &dlen, origin, origin_len); 498 if(s) return RET_ERR_SHIFT(s, 499 sldns_buffer_position(strbuf)-strlen(token)); 500 (*rr_cur_len) += dlen; 501 } 502 return LDNS_WIREPARSE_ERR_OK; 503 504 case LDNS_RDF_TYPE_HEX: 505 case LDNS_RDF_TYPE_B64: 506 /* When this is the last rdata field, then the 507 * rest should be read in (cause then these 508 * rdf types may contain spaces). */ 509 if(r_cnt == r_max - 1) { 510 size_t tlen = strlen(token); 511 (void)sldns_bget_token(strbuf, token+tlen, "\n", 512 token_len - tlen); 513 } 514 break; 515 default: 516 break; 517 } 518 519 len = rr_len - (*rr_cur_len); 520 if((status=sldns_str2wire_rdf_buf(token, rr+(*rr_cur_len), &len, 521 rdftype)) != 0) 522 return RET_ERR_SHIFT(status, 523 sldns_buffer_position(strbuf)-strlen(token)); 524 *rr_cur_len += len; 525 return LDNS_WIREPARSE_ERR_OK; 526} 527 528/** 529 * Parse one rdf token. Takes care of quotes and parenthesis. 530 */ 531static int 532sldns_parse_rdf_token(sldns_buffer* strbuf, char* token, size_t token_len, 533 int* quoted, int* parens, size_t* pre_data_pos, 534 const char* delimiters, sldns_rdf_type rdftype, size_t* token_strlen) 535{ 536 size_t slen; 537 538 /* skip spaces */ 539 while(sldns_buffer_remaining(strbuf) > 0 && !*quoted && 540 *(sldns_buffer_current(strbuf)) == ' ') { 541 sldns_buffer_skip(strbuf, 1); 542 } 543 544 *pre_data_pos = sldns_buffer_position(strbuf); 545 if(sldns_bget_token_par(strbuf, token, (*quoted)?"\"":delimiters, 546 token_len, parens, (*quoted)?NULL:" \t") == -1) { 547 return 0; 548 } 549 slen = strlen(token); 550 /* check if not quoted yet, and we have encountered quotes */ 551 if(!*quoted && sldns_rdf_type_maybe_quoted(rdftype) && 552 slen >= 2 && 553 (token[0] == '"' || token[0] == '\'') && 554 (token[slen-1] == '"' || token[slen-1] == '\'')) { 555 /* move token two smaller (quotes) with endnull */ 556 memmove(token, token+1, slen-2); 557 token[slen-2] = 0; 558 slen -= 2; 559 *quoted = 1; 560 } else if(!*quoted && sldns_rdf_type_maybe_quoted(rdftype) && 561 slen >= 2 && 562 (token[0] == '"' || token[0] == '\'')) { 563 /* got the start quote (remove it) but read remainder 564 * of quoted string as well into remainder of token */ 565 memmove(token, token+1, slen-1); 566 token[slen-1] = 0; 567 slen -= 1; 568 *quoted = 1; 569 /* rewind buffer over skipped whitespace */ 570 while(sldns_buffer_position(strbuf) > 0 && 571 (sldns_buffer_current(strbuf)[-1] == ' ' || 572 sldns_buffer_current(strbuf)[-1] == '\t')) { 573 sldns_buffer_skip(strbuf, -1); 574 } 575 if(sldns_bget_token_par(strbuf, token+slen, 576 "\"", token_len-slen, 577 parens, NULL) == -1) { 578 return 0; 579 } 580 slen = strlen(token); 581 } 582 *token_strlen = slen; 583 return 1; 584} 585 586/** Add space and one more rdf token onto the existing token string. */ 587static int 588sldns_affix_token(sldns_buffer* strbuf, char* token, size_t* token_len, 589 int* quoted, int* parens, size_t* pre_data_pos, 590 const char* delimiters, sldns_rdf_type rdftype, size_t* token_strlen) 591{ 592 size_t addlen = *token_len - *token_strlen; 593 size_t addstrlen = 0; 594 595 /* add space */ 596 if(addlen < 1) return 0; 597 token[*token_strlen] = ' '; 598 token[++(*token_strlen)] = 0; 599 600 /* read another token */ 601 addlen = *token_len - *token_strlen; 602 if(!sldns_parse_rdf_token(strbuf, token+*token_strlen, addlen, quoted, 603 parens, pre_data_pos, delimiters, rdftype, &addstrlen)) 604 return 0; 605 (*token_strlen) += addstrlen; 606 return 1; 607} 608 609/** parse rdata from string into rr buffer(-remainder after dname). */ 610static int 611rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len, 612 uint8_t* rr, size_t* rr_len, size_t dname_len, uint16_t rr_type, 613 uint8_t* origin, size_t origin_len) 614{ 615 const sldns_rr_descriptor *desc = sldns_rr_descript((uint16_t)rr_type); 616 uint16_t r_cnt, r_min, r_max; 617 size_t rr_cur_len = dname_len + 10, pre_data_pos, token_strlen; 618 int was_unknown_rr_format = 0, parens = 0, status, quoted; 619 const char* delimiters; 620 sldns_rdf_type rdftype; 621 /* a desc is always returned */ 622 if(!desc) return LDNS_WIREPARSE_ERR_GENERAL; 623 r_max = sldns_rr_descriptor_maximum(desc); 624 r_min = sldns_rr_descriptor_minimum(desc); 625 /* robust check */ 626 if(rr_cur_len > *rr_len) 627 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 628 sldns_buffer_position(strbuf)); 629 630 /* because number of fields can be variable, we can't rely on 631 * _maximum() only */ 632 for(r_cnt=0; r_cnt < r_max; r_cnt++) { 633 rdftype = sldns_rr_descriptor_field_type(desc, r_cnt); 634 delimiters = rrinternal_get_delims(rdftype, r_cnt, r_max); 635 quoted = rrinternal_get_quoted(strbuf, &delimiters, rdftype); 636 637 if(!sldns_parse_rdf_token(strbuf, token, token_len, "ed, 638 &parens, &pre_data_pos, delimiters, rdftype, 639 &token_strlen)) 640 break; 641 642 /* rfc3597 specifies that any type can be represented 643 * with \# method, which can contain spaces... 644 * it does specify size though... */ 645 646 /* unknown RR data */ 647 if(token_strlen>=2 && strncmp(token, "\\#", 2) == 0 && 648 !quoted && (token_strlen == 2 || token[2]==' ')) { 649 was_unknown_rr_format = 1; 650 if((status=rrinternal_parse_unknown(strbuf, token, 651 token_len, rr, rr_len, &rr_cur_len, 652 pre_data_pos)) != 0) 653 return status; 654 } else if(token_strlen > 0 || quoted) { 655 if(rdftype == LDNS_RDF_TYPE_HIP) { 656 /* affix the HIT and PK fields, with a space */ 657 if(!sldns_affix_token(strbuf, token, 658 &token_len, "ed, &parens, 659 &pre_data_pos, delimiters, 660 rdftype, &token_strlen)) 661 break; 662 if(!sldns_affix_token(strbuf, token, 663 &token_len, "ed, &parens, 664 &pre_data_pos, delimiters, 665 rdftype, &token_strlen)) 666 break; 667 } 668 669 /* normal RR */ 670 if((status=rrinternal_parse_rdf(strbuf, token, 671 token_len, rr, *rr_len, &rr_cur_len, rdftype, 672 rr_type, r_cnt, r_max, dname_len, origin, 673 origin_len)) != 0) { 674 return status; 675 } 676 } 677 } 678 if(!was_unknown_rr_format && r_cnt+1 < r_min) { 679 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_MISSING_VALUE, 680 sldns_buffer_position(strbuf)); 681 } 682 while(parens != 0) { 683 /* read remainder, must be "" */ 684 if(sldns_bget_token_par(strbuf, token, "\n", token_len, 685 &parens, " \t") == -1) { 686 if(parens != 0) 687 return RET_ERR(LDNS_WIREPARSE_ERR_PARENTHESIS, 688 sldns_buffer_position(strbuf)); 689 break; 690 } 691 if(strcmp(token, "") != 0) 692 return RET_ERR(LDNS_WIREPARSE_ERR_PARENTHESIS, 693 sldns_buffer_position(strbuf)); 694 } 695 /* write rdata length */ 696 sldns_write_uint16(rr+dname_len+8, rr_cur_len-dname_len-10); 697 *rr_len = rr_cur_len; 698 return LDNS_WIREPARSE_ERR_OK; 699} 700 701/* 702 * trailing spaces are allowed 703 * leading spaces are not allowed 704 * allow ttl to be optional 705 * class is optional too 706 * if ttl is missing, and default_ttl is 0, use DEF_TTL 707 * allow ttl to be written as 1d3h 708 * So the RR should look like. e.g. 709 * miek.nl. 3600 IN MX 10 elektron.atoom.net 710 * or 711 * miek.nl. 1h IN MX 10 elektron.atoom.net 712 * or 713 * miek.nl. IN MX 10 elektron.atoom.net 714 */ 715static int 716sldns_str2wire_rr_buf_internal(const char* str, uint8_t* rr, size_t* len, 717 size_t* dname_len, uint32_t default_ttl, uint8_t* origin, 718 size_t origin_len, uint8_t* prev, size_t prev_len, int question) 719{ 720 int status; 721 int not_there = 0; 722 char token[LDNS_MAX_RDFLEN+1]; 723 uint32_t ttl = 0; 724 uint16_t tp = 0, cl = 0; 725 size_t ddlen = 0; 726 727 /* string in buffer */ 728 sldns_buffer strbuf; 729 sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 730 if(!dname_len) dname_len = &ddlen; 731 732 /* parse the owner */ 733 if((status=rrinternal_get_owner(&strbuf, rr, len, dname_len, origin, 734 origin_len, prev, prev_len, token, sizeof(token))) != 0) 735 return status; 736 737 /* parse the [ttl] [class] <type> */ 738 if((status=rrinternal_get_ttl(&strbuf, token, sizeof(token), 739 ¬_there, &ttl, default_ttl)) != 0) 740 return status; 741 if((status=rrinternal_get_class(&strbuf, token, sizeof(token), 742 ¬_there, &cl)) != 0) 743 return status; 744 if((status=rrinternal_get_type(&strbuf, token, sizeof(token), 745 ¬_there, &tp)) != 0) 746 return status; 747 /* put ttl, class, type into the rr result */ 748 if((status=rrinternal_write_typeclassttl(&strbuf, rr, *len, *dname_len, tp, cl, 749 ttl, question)) != 0) 750 return status; 751 /* for a question-RR we are done, no rdata */ 752 if(question) { 753 *len = *dname_len + 4; 754 return LDNS_WIREPARSE_ERR_OK; 755 } 756 757 /* rdata */ 758 if((status=rrinternal_parse_rdata(&strbuf, token, sizeof(token), 759 rr, len, *dname_len, tp, origin, origin_len)) != 0) 760 return status; 761 762 return LDNS_WIREPARSE_ERR_OK; 763} 764 765int sldns_str2wire_rr_buf(const char* str, uint8_t* rr, size_t* len, 766 size_t* dname_len, uint32_t default_ttl, uint8_t* origin, 767 size_t origin_len, uint8_t* prev, size_t prev_len) 768{ 769 return sldns_str2wire_rr_buf_internal(str, rr, len, dname_len, 770 default_ttl, origin, origin_len, prev, prev_len, 0); 771} 772 773int sldns_str2wire_rr_question_buf(const char* str, uint8_t* rr, size_t* len, 774 size_t* dname_len, uint8_t* origin, size_t origin_len, uint8_t* prev, 775 size_t prev_len) 776{ 777 return sldns_str2wire_rr_buf_internal(str, rr, len, dname_len, 778 0, origin, origin_len, prev, prev_len, 1); 779} 780 781uint16_t sldns_wirerr_get_type(uint8_t* rr, size_t len, size_t dname_len) 782{ 783 if(len < dname_len+2) 784 return 0; 785 return sldns_read_uint16(rr+dname_len); 786} 787 788uint16_t sldns_wirerr_get_class(uint8_t* rr, size_t len, size_t dname_len) 789{ 790 if(len < dname_len+4) 791 return 0; 792 return sldns_read_uint16(rr+dname_len+2); 793} 794 795uint32_t sldns_wirerr_get_ttl(uint8_t* rr, size_t len, size_t dname_len) 796{ 797 if(len < dname_len+8) 798 return 0; 799 return sldns_read_uint32(rr+dname_len+4); 800} 801 802uint16_t sldns_wirerr_get_rdatalen(uint8_t* rr, size_t len, size_t dname_len) 803{ 804 if(len < dname_len+10) 805 return 0; 806 return sldns_read_uint16(rr+dname_len+8); 807} 808 809uint8_t* sldns_wirerr_get_rdata(uint8_t* rr, size_t len, size_t dname_len) 810{ 811 if(len < dname_len+10) 812 return NULL; 813 return rr+dname_len+10; 814} 815 816uint8_t* sldns_wirerr_get_rdatawl(uint8_t* rr, size_t len, size_t dname_len) 817{ 818 if(len < dname_len+10) 819 return NULL; 820 return rr+dname_len+8; 821} 822 823const char* sldns_get_errorstr_parse(int e) 824{ 825 sldns_lookup_table *lt; 826 lt = sldns_lookup_by_id(sldns_wireparse_errors, LDNS_WIREPARSE_ERROR(e)); 827 return lt?lt->name:"unknown error"; 828} 829 830int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len, 831 struct sldns_file_parse_state* parse_state) 832{ 833 char line[LDNS_RR_BUF_SIZE+1]; 834 ssize_t size; 835 836 /* read an entire line in from the file */ 837 if((size = sldns_fget_token_l(in, line, LDNS_PARSE_SKIP_SPACE, 838 LDNS_RR_BUF_SIZE, parse_state?&parse_state->lineno:NULL)) 839 == -1) { 840 /* if last line was empty, we are now at feof, which is not 841 * always a parse error (happens when for instance last line 842 * was a comment) 843 */ 844 return LDNS_WIREPARSE_ERR_SYNTAX; 845 } 846 847 /* we can have the situation, where we've read ok, but still got 848 * no bytes to play with, in this case size is 0 */ 849 if(size == 0) { 850 *len = 0; 851 *dname_len = 0; 852 return LDNS_WIREPARSE_ERR_OK; 853 } 854 855 if(strncmp(line, "$ORIGIN", 7) == 0 && isspace(line[7])) { 856 size_t off = 8; 857 int s; 858 *len = 0; 859 *dname_len = 0; 860 if(!parse_state) return LDNS_WIREPARSE_ERR_OK; 861 while(isspace(line[off])) 862 off++; 863 parse_state->origin_len = sizeof(parse_state->origin); 864 s = sldns_str2wire_dname_buf(line+off, parse_state->origin, 865 &parse_state->origin_len); 866 if(s) parse_state->origin_len = 0; 867 return s; 868 } else if(strncmp(line, "$TTL", 4) == 0 && isspace(line[4])) { 869 const char* end = NULL; 870 size_t off = 8; 871 *len = 0; 872 *dname_len = 0; 873 if(!parse_state) return LDNS_WIREPARSE_ERR_OK; 874 while(isspace(line[off])) 875 off++; 876 parse_state->default_ttl = sldns_str2period(line+off, &end); 877 } else if (strncmp(line, "$INCLUDE", 8) == 0) { 878 *len = 0; 879 *dname_len = 0; 880 return LDNS_WIREPARSE_ERR_INCLUDE; 881 } else { 882 return sldns_str2wire_rr_buf(line, rr, len, dname_len, 883 parse_state?parse_state->default_ttl:0, 884 (parse_state&&parse_state->origin_len)? 885 parse_state->origin:NULL, 886 parse_state->origin_len, 887 (parse_state&&parse_state->prev_rr_len)? 888 parse_state->prev_rr:NULL, 889 parse_state->prev_rr_len); 890 } 891 return LDNS_WIREPARSE_ERR_OK; 892} 893 894int sldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len, 895 sldns_rdf_type rdftype) 896{ 897 switch (rdftype) { 898 case LDNS_RDF_TYPE_DNAME: 899 return sldns_str2wire_dname_buf(str, rd, len); 900 case LDNS_RDF_TYPE_INT8: 901 return sldns_str2wire_int8_buf(str, rd, len); 902 case LDNS_RDF_TYPE_INT16: 903 return sldns_str2wire_int16_buf(str, rd, len); 904 case LDNS_RDF_TYPE_INT32: 905 return sldns_str2wire_int32_buf(str, rd, len); 906 case LDNS_RDF_TYPE_A: 907 return sldns_str2wire_a_buf(str, rd, len); 908 case LDNS_RDF_TYPE_AAAA: 909 return sldns_str2wire_aaaa_buf(str, rd, len); 910 case LDNS_RDF_TYPE_STR: 911 return sldns_str2wire_str_buf(str, rd, len); 912 case LDNS_RDF_TYPE_APL: 913 return sldns_str2wire_apl_buf(str, rd, len); 914 case LDNS_RDF_TYPE_B64: 915 return sldns_str2wire_b64_buf(str, rd, len); 916 case LDNS_RDF_TYPE_B32_EXT: 917 return sldns_str2wire_b32_ext_buf(str, rd, len); 918 case LDNS_RDF_TYPE_HEX: 919 return sldns_str2wire_hex_buf(str, rd, len); 920 case LDNS_RDF_TYPE_NSEC: 921 return sldns_str2wire_nsec_buf(str, rd, len); 922 case LDNS_RDF_TYPE_TYPE: 923 return sldns_str2wire_type_buf(str, rd, len); 924 case LDNS_RDF_TYPE_CLASS: 925 return sldns_str2wire_class_buf(str, rd, len); 926 case LDNS_RDF_TYPE_CERT_ALG: 927 return sldns_str2wire_cert_alg_buf(str, rd, len); 928 case LDNS_RDF_TYPE_ALG: 929 return sldns_str2wire_alg_buf(str, rd, len); 930 case LDNS_RDF_TYPE_TIME: 931 return sldns_str2wire_time_buf(str, rd, len); 932 case LDNS_RDF_TYPE_PERIOD: 933 return sldns_str2wire_period_buf(str, rd, len); 934 case LDNS_RDF_TYPE_LOC: 935 return sldns_str2wire_loc_buf(str, rd, len); 936 case LDNS_RDF_TYPE_WKS: 937 return sldns_str2wire_wks_buf(str, rd, len); 938 case LDNS_RDF_TYPE_NSAP: 939 return sldns_str2wire_nsap_buf(str, rd, len); 940 case LDNS_RDF_TYPE_ATMA: 941 return sldns_str2wire_atma_buf(str, rd, len); 942 case LDNS_RDF_TYPE_IPSECKEY: 943 return sldns_str2wire_ipseckey_buf(str, rd, len); 944 case LDNS_RDF_TYPE_NSEC3_SALT: 945 return sldns_str2wire_nsec3_salt_buf(str, rd, len); 946 case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER: 947 return sldns_str2wire_b32_ext_buf(str, rd, len); 948 case LDNS_RDF_TYPE_ILNP64: 949 return sldns_str2wire_ilnp64_buf(str, rd, len); 950 case LDNS_RDF_TYPE_EUI48: 951 return sldns_str2wire_eui48_buf(str, rd, len); 952 case LDNS_RDF_TYPE_EUI64: 953 return sldns_str2wire_eui64_buf(str, rd, len); 954 case LDNS_RDF_TYPE_TAG: 955 return sldns_str2wire_tag_buf(str, rd, len); 956 case LDNS_RDF_TYPE_LONG_STR: 957 return sldns_str2wire_long_str_buf(str, rd, len); 958 case LDNS_RDF_TYPE_HIP: 959 return sldns_str2wire_hip_buf(str, rd, len); 960 case LDNS_RDF_TYPE_INT16_DATA: 961 return sldns_str2wire_int16_data_buf(str, rd, len); 962 case LDNS_RDF_TYPE_UNKNOWN: 963 case LDNS_RDF_TYPE_SERVICE: 964 return LDNS_WIREPARSE_ERR_NOT_IMPL; 965 case LDNS_RDF_TYPE_NONE: 966 default: 967 break; 968 } 969 return LDNS_WIREPARSE_ERR_GENERAL; 970} 971 972int sldns_str2wire_int8_buf(const char* str, uint8_t* rd, size_t* len) 973{ 974 char* end; 975 uint8_t r = (uint8_t)strtol((char*)str, &end, 10); 976 if(*end != 0) 977 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); 978 if(*len < 1) 979 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 980 rd[0] = r; 981 *len = 1; 982 return LDNS_WIREPARSE_ERR_OK; 983} 984 985int sldns_str2wire_int16_buf(const char* str, uint8_t* rd, size_t* len) 986{ 987 char* end; 988 uint16_t r = (uint16_t)strtol((char*)str, &end, 10); 989 if(*end != 0) 990 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); 991 if(*len < 2) 992 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 993 sldns_write_uint16(rd, r); 994 *len = 2; 995 return LDNS_WIREPARSE_ERR_OK; 996} 997 998int sldns_str2wire_int32_buf(const char* str, uint8_t* rd, size_t* len) 999{ 1000 char* end; 1001 uint32_t r; 1002 errno = 0; /* must set to zero before call, 1003 note race condition on errno */ 1004 if(*str == '-') 1005 r = (uint32_t)strtol((char*)str, &end, 10); 1006 else r = (uint32_t)strtoul((char*)str, &end, 10); 1007 if(*end != 0) 1008 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); 1009 if(errno == ERANGE) 1010 return LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW; 1011 if(*len < 4) 1012 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1013 sldns_write_uint32(rd, r); 1014 *len = 4; 1015 return LDNS_WIREPARSE_ERR_OK; 1016} 1017 1018int sldns_str2wire_a_buf(const char* str, uint8_t* rd, size_t* len) 1019{ 1020 struct in_addr address; 1021 if(inet_pton(AF_INET, (char*)str, &address) != 1) 1022 return LDNS_WIREPARSE_ERR_SYNTAX_IP4; 1023 if(*len < sizeof(address)) 1024 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1025 memmove(rd, &address, sizeof(address)); 1026 *len = sizeof(address); 1027 return LDNS_WIREPARSE_ERR_OK; 1028} 1029 1030int sldns_str2wire_aaaa_buf(const char* str, uint8_t* rd, size_t* len) 1031{ 1032#ifdef AF_INET6 1033 uint8_t address[LDNS_IP6ADDRLEN + 1]; 1034 if(inet_pton(AF_INET6, (char*)str, address) != 1) 1035 return LDNS_WIREPARSE_ERR_SYNTAX_IP6; 1036 if(*len < LDNS_IP6ADDRLEN) 1037 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1038 memmove(rd, address, LDNS_IP6ADDRLEN); 1039 *len = LDNS_IP6ADDRLEN; 1040 return LDNS_WIREPARSE_ERR_OK; 1041#else 1042 return LDNS_WIREPARSE_ERR_NOT_IMPL; 1043#endif 1044} 1045 1046int sldns_str2wire_str_buf(const char* str, uint8_t* rd, size_t* len) 1047{ 1048 uint8_t ch = 0; 1049 size_t sl = 0; 1050 const char* s = str; 1051 /* skip length byte */ 1052 if(*len < 1) 1053 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1054 1055 /* read characters */ 1056 while(sldns_parse_char(&ch, &s)) { 1057 if(sl >= 255) 1058 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, s-str); 1059 if(*len < sl+1) 1060 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1061 s-str); 1062 rd[++sl] = ch; 1063 } 1064 if(!s) 1065 return LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE; 1066 rd[0] = (uint8_t)sl; 1067 *len = sl+1; 1068 return LDNS_WIREPARSE_ERR_OK; 1069} 1070 1071int sldns_str2wire_apl_buf(const char* str, uint8_t* rd, size_t* len) 1072{ 1073 const char *my_str = str; 1074 1075 char my_ip_str[64]; 1076 size_t ip_str_len; 1077 1078 uint16_t family; 1079 int negation; 1080 size_t adflength = 0; 1081 uint8_t data[16+4]; 1082 uint8_t prefix; 1083 size_t i; 1084 1085 if(strlen(my_str) == 0) { 1086 /* empty APL element, no data, no string */ 1087 *len = 0; 1088 return LDNS_WIREPARSE_ERR_OK; 1089 } 1090 1091 /* [!]afi:address/prefix */ 1092 if (strlen(my_str) < 2 1093 || strchr(my_str, ':') == NULL 1094 || strchr(my_str, '/') == NULL 1095 || strchr(my_str, ':') > strchr(my_str, '/')) { 1096 return LDNS_WIREPARSE_ERR_INVALID_STR; 1097 } 1098 1099 if (my_str[0] == '!') { 1100 negation = 1; 1101 my_str += 1; 1102 } else { 1103 negation = 0; 1104 } 1105 1106 family = (uint16_t) atoi(my_str); 1107 1108 my_str = strchr(my_str, ':') + 1; 1109 1110 /* need ip addr and only ip addr for inet_pton */ 1111 ip_str_len = (size_t) (strchr(my_str, '/') - my_str); 1112 if(ip_str_len+1 > sizeof(my_ip_str)) 1113 return LDNS_WIREPARSE_ERR_INVALID_STR; 1114 (void)strlcpy(my_ip_str, my_str, sizeof(my_ip_str)); 1115 my_ip_str[ip_str_len] = 0; 1116 1117 if (family == 1) { 1118 /* ipv4 */ 1119 if(inet_pton(AF_INET, my_ip_str, data+4) == 0) 1120 return LDNS_WIREPARSE_ERR_INVALID_STR; 1121 for (i = 0; i < 4; i++) { 1122 if (data[i+4] != 0) { 1123 adflength = i + 1; 1124 } 1125 } 1126 } else if (family == 2) { 1127 /* ipv6 */ 1128 if (inet_pton(AF_INET6, my_ip_str, data+4) == 0) 1129 return LDNS_WIREPARSE_ERR_INVALID_STR; 1130 for (i = 0; i < 16; i++) { 1131 if (data[i+4] != 0) { 1132 adflength = i + 1; 1133 } 1134 } 1135 } else { 1136 /* unknown family */ 1137 return LDNS_WIREPARSE_ERR_INVALID_STR; 1138 } 1139 1140 my_str = strchr(my_str, '/') + 1; 1141 prefix = (uint8_t) atoi(my_str); 1142 1143 sldns_write_uint16(data, family); 1144 data[2] = prefix; 1145 data[3] = (uint8_t)adflength; 1146 if (negation) { 1147 /* set bit 1 of byte 3 */ 1148 data[3] = data[3] | 0x80; 1149 } 1150 1151 if(*len < 4+adflength) 1152 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1153 memmove(rd, data, 4+adflength); 1154 *len = 4+adflength; 1155 return LDNS_WIREPARSE_ERR_OK; 1156} 1157 1158int sldns_str2wire_b64_buf(const char* str, uint8_t* rd, size_t* len) 1159{ 1160 size_t sz = sldns_b64_pton_calculate_size(strlen(str)); 1161 int n; 1162 if(*len < sz) 1163 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1164 n = sldns_b64_pton(str, rd, *len); 1165 if(n < 0) 1166 return LDNS_WIREPARSE_ERR_SYNTAX_B64; 1167 *len = (size_t)n; 1168 return LDNS_WIREPARSE_ERR_OK; 1169} 1170 1171int sldns_str2wire_b32_ext_buf(const char* str, uint8_t* rd, size_t* len) 1172{ 1173 size_t slen = strlen(str); 1174 size_t sz = sldns_b32_pton_calculate_size(slen); 1175 int n; 1176 if(*len < 1+sz) 1177 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1178 rd[0] = (uint8_t)sz; 1179 n = sldns_b32_pton_extended_hex(str, slen, rd+1, *len-1); 1180 if(n < 0) 1181 return LDNS_WIREPARSE_ERR_SYNTAX_B32_EXT; 1182 *len = (size_t)n+1; 1183 return LDNS_WIREPARSE_ERR_OK; 1184} 1185 1186int sldns_str2wire_hex_buf(const char* str, uint8_t* rd, size_t* len) 1187{ 1188 const char* s = str; 1189 size_t dlen = 0; /* number of hexdigits parsed */ 1190 while(*s) { 1191 if(isspace(*s)) { 1192 s++; 1193 continue; 1194 } 1195 if(!isxdigit(*s)) 1196 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1197 if(*len < dlen/2 + 1) 1198 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1199 s-str); 1200 if((dlen&1)==0) 1201 rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; 1202 else rd[dlen/2] += (uint8_t)sldns_hexdigit_to_int(*s++); 1203 dlen++; 1204 } 1205 if((dlen&1)!=0) 1206 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1207 *len = dlen/2; 1208 return LDNS_WIREPARSE_ERR_OK; 1209} 1210 1211int sldns_str2wire_nsec_buf(const char* str, uint8_t* rd, size_t* len) 1212{ 1213 const char *delim = "\n\t "; 1214 char token[64]; /* for a type name */ 1215 size_t type_count = 0; 1216 int block; 1217 size_t used = 0; 1218 uint16_t maxtype = 0; 1219 uint8_t typebits[8192]; /* 65536 bits */ 1220 uint8_t window_in_use[256]; 1221 1222 /* string in buffer */ 1223 sldns_buffer strbuf; 1224 sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 1225 1226 /* parse the types */ 1227 memset(typebits, 0, sizeof(typebits)); 1228 memset(window_in_use, 0, sizeof(window_in_use)); 1229 while(sldns_buffer_remaining(&strbuf) > 0 && 1230 sldns_bget_token(&strbuf, token, delim, sizeof(token)) != -1) { 1231 uint16_t t = sldns_get_rr_type_by_name(token); 1232 if(token[0] == 0) 1233 continue; 1234 if(t == 0 && strcmp(token, "TYPE0") != 0) 1235 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE, 1236 sldns_buffer_position(&strbuf)); 1237 typebits[t/8] |= (0x80>>(t%8)); 1238 window_in_use[t/256] = 1; 1239 type_count++; 1240 if(t > maxtype) maxtype = t; 1241 } 1242 1243 /* empty NSEC bitmap */ 1244 if(type_count == 0) { 1245 *len = 0; 1246 return LDNS_WIREPARSE_ERR_OK; 1247 } 1248 1249 /* encode windows {u8 windowblock, u8 bitmaplength, 0-32u8 bitmap}, 1250 * block is 0-255 upper octet of types, length if 0-32. */ 1251 for(block = 0; block <= (int)maxtype/256; block++) { 1252 int i, blocklen = 0; 1253 if(!window_in_use[block]) 1254 continue; 1255 for(i=0; i<32; i++) { 1256 if(typebits[block*32+i] != 0) 1257 blocklen = i+1; 1258 } 1259 if(blocklen == 0) 1260 continue; /* empty window should have been !in_use */ 1261 if(used+blocklen+2 > *len) 1262 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1263 rd[used+0] = (uint8_t)block; 1264 rd[used+1] = (uint8_t)blocklen; 1265 for(i=0; i<blocklen; i++) { 1266 rd[used+2+i] = typebits[block*32+i]; 1267 } 1268 used += blocklen+2; 1269 } 1270 *len = used; 1271 return LDNS_WIREPARSE_ERR_OK; 1272} 1273 1274int sldns_str2wire_type_buf(const char* str, uint8_t* rd, size_t* len) 1275{ 1276 uint16_t t = sldns_get_rr_type_by_name(str); 1277 if(t == 0 && strcmp(str, "TYPE0") != 0) 1278 return LDNS_WIREPARSE_ERR_SYNTAX_TYPE; 1279 if(*len < 2) 1280 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1281 sldns_write_uint16(rd, t); 1282 *len = 2; 1283 return LDNS_WIREPARSE_ERR_OK; 1284} 1285 1286int sldns_str2wire_class_buf(const char* str, uint8_t* rd, size_t* len) 1287{ 1288 uint16_t c = sldns_get_rr_class_by_name(str); 1289 if(c == 0 && strcmp(str, "CLASS0") != 0) 1290 return LDNS_WIREPARSE_ERR_SYNTAX_CLASS; 1291 if(*len < 2) 1292 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1293 sldns_write_uint16(rd, c); 1294 *len = 2; 1295 return LDNS_WIREPARSE_ERR_OK; 1296} 1297 1298/* An certificate alg field can either be specified as a 8 bits number 1299 * or by its symbolic name. Handle both */ 1300int sldns_str2wire_cert_alg_buf(const char* str, uint8_t* rd, size_t* len) 1301{ 1302 sldns_lookup_table *lt = sldns_lookup_by_name(sldns_cert_algorithms, 1303 str); 1304 if(*len < 2) 1305 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1306 if(lt) { 1307 sldns_write_uint16(rd, (uint16_t)lt->id); 1308 } else { 1309 int s = sldns_str2wire_int16_buf(str, rd, len); 1310 if(s) return s; 1311 if(sldns_read_uint16(rd) == 0) 1312 return LDNS_WIREPARSE_ERR_CERT_BAD_ALGORITHM; 1313 } 1314 *len = 2; 1315 return LDNS_WIREPARSE_ERR_OK; 1316} 1317 1318/* An alg field can either be specified as a 8 bits number 1319 * or by its symbolic name. Handle both */ 1320int sldns_str2wire_alg_buf(const char* str, uint8_t* rd, size_t* len) 1321{ 1322 sldns_lookup_table *lt = sldns_lookup_by_name(sldns_algorithms, str); 1323 if(*len < 1) 1324 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1325 if(lt) { 1326 rd[0] = (uint8_t)lt->id; 1327 *len = 1; 1328 } else { 1329 /* try as-is (a number) */ 1330 return sldns_str2wire_int8_buf(str, rd, len); 1331 } 1332 return LDNS_WIREPARSE_ERR_OK; 1333} 1334 1335int sldns_str2wire_time_buf(const char* str, uint8_t* rd, size_t* len) 1336{ 1337 /* convert a time YYYYDDMMHHMMSS to wireformat */ 1338 struct tm tm; 1339 if(*len < 4) 1340 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1341 1342 /* Try to scan the time... */ 1343 memset(&tm, 0, sizeof(tm)); 1344 if (strlen(str) == 14 && sscanf(str, "%4d%2d%2d%2d%2d%2d", 1345 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, 1346 &tm.tm_min, &tm.tm_sec) == 6) { 1347 tm.tm_year -= 1900; 1348 tm.tm_mon--; 1349 /* Check values */ 1350 if (tm.tm_year < 70) 1351 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1352 if (tm.tm_mon < 0 || tm.tm_mon > 11) 1353 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1354 if (tm.tm_mday < 1 || tm.tm_mday > 31) 1355 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1356 if (tm.tm_hour < 0 || tm.tm_hour > 23) 1357 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1358 if (tm.tm_min < 0 || tm.tm_min > 59) 1359 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1360 if (tm.tm_sec < 0 || tm.tm_sec > 59) 1361 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1362 1363 sldns_write_uint32(rd, sldns_mktime_from_utc(&tm)); 1364 } else { 1365 /* handle it as 32 bits timestamp */ 1366 char *end; 1367 uint32_t l = (uint32_t)strtol((char*)str, &end, 10); 1368 if(*end != 0) 1369 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TIME, 1370 end-(char*)str); 1371 sldns_write_uint32(rd, l); 1372 } 1373 *len = 4; 1374 return LDNS_WIREPARSE_ERR_OK; 1375} 1376 1377int sldns_str2wire_period_buf(const char* str, uint8_t* rd, size_t* len) 1378{ 1379 const char* end; 1380 uint32_t p = sldns_str2period(str, &end); 1381 if(*end != 0) 1382 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, end-str); 1383 if(*len < 4) 1384 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1385 sldns_write_uint32(rd, p); 1386 *len = 4; 1387 return LDNS_WIREPARSE_ERR_OK; 1388} 1389 1390/** read "<digits>[.<digits>][mM]" into mantissa exponent format for LOC type */ 1391static int 1392loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e) 1393{ 1394 uint32_t meters = 0, cm = 0, val; 1395 while (isblank(*my_str)) { 1396 my_str++; 1397 } 1398 meters = (uint32_t)strtol(my_str, &my_str, 10); 1399 if (*my_str == '.') { 1400 my_str++; 1401 cm = (uint32_t)strtol(my_str, &my_str, 10); 1402 } 1403 if (meters >= 1) { 1404 *e = 2; 1405 val = meters; 1406 } else { 1407 *e = 0; 1408 val = cm; 1409 } 1410 while(val >= 10) { 1411 (*e)++; 1412 val /= 10; 1413 } 1414 *m = (uint8_t)val; 1415 1416 if (*e > 9) 1417 return 0; 1418 if (*my_str == 'm' || *my_str == 'M') { 1419 my_str++; 1420 } 1421 *endstr = my_str; 1422 return 1; 1423} 1424 1425int sldns_str2wire_loc_buf(const char* str, uint8_t* rd, size_t* len) 1426{ 1427 uint32_t latitude = 0; 1428 uint32_t longitude = 0; 1429 uint32_t altitude = 0; 1430 1431 uint32_t equator = (uint32_t)1<<31; /* 2**31 */ 1432 1433 /* only support version 0 */ 1434 uint32_t h = 0; 1435 uint32_t m = 0; 1436 uint8_t size_b = 1, size_e = 2; 1437 uint8_t horiz_pre_b = 1, horiz_pre_e = 6; 1438 uint8_t vert_pre_b = 1, vert_pre_e = 3; 1439 1440 double s = 0.0; 1441 int northerness; 1442 int easterness; 1443 1444 char *my_str = (char *) str; 1445 1446 if (isdigit((int) *my_str)) { 1447 h = (uint32_t) strtol(my_str, &my_str, 10); 1448 } else { 1449 return LDNS_WIREPARSE_ERR_INVALID_STR; 1450 } 1451 1452 while (isblank((int) *my_str)) { 1453 my_str++; 1454 } 1455 1456 if (isdigit((int) *my_str)) { 1457 m = (uint32_t) strtol(my_str, &my_str, 10); 1458 } else if (*my_str == 'N' || *my_str == 'S') { 1459 goto north; 1460 } else { 1461 return LDNS_WIREPARSE_ERR_INVALID_STR; 1462 } 1463 1464 while (isblank((int) *my_str)) { 1465 my_str++; 1466 } 1467 1468 if (isdigit((int) *my_str)) { 1469 s = strtod(my_str, &my_str); 1470 } 1471 1472 /* skip blanks before norterness */ 1473 while (isblank((int) *my_str)) { 1474 my_str++; 1475 } 1476 1477north: 1478 if (*my_str == 'N') { 1479 northerness = 1; 1480 } else if (*my_str == 'S') { 1481 northerness = 0; 1482 } else { 1483 return LDNS_WIREPARSE_ERR_INVALID_STR; 1484 } 1485 1486 my_str++; 1487 1488 /* store number */ 1489 s = 1000.0 * s; 1490 /* add a little to make floor in conversion a round */ 1491 s += 0.0005; 1492 latitude = (uint32_t) s; 1493 latitude += 1000 * 60 * m; 1494 latitude += 1000 * 60 * 60 * h; 1495 if (northerness) { 1496 latitude = equator + latitude; 1497 } else { 1498 latitude = equator - latitude; 1499 } 1500 while (isblank(*my_str)) { 1501 my_str++; 1502 } 1503 1504 if (isdigit((int) *my_str)) { 1505 h = (uint32_t) strtol(my_str, &my_str, 10); 1506 } else { 1507 return LDNS_WIREPARSE_ERR_INVALID_STR; 1508 } 1509 1510 while (isblank((int) *my_str)) { 1511 my_str++; 1512 } 1513 1514 if (isdigit((int) *my_str)) { 1515 m = (uint32_t) strtol(my_str, &my_str, 10); 1516 } else if (*my_str == 'E' || *my_str == 'W') { 1517 goto east; 1518 } else { 1519 return LDNS_WIREPARSE_ERR_INVALID_STR; 1520 } 1521 1522 while (isblank(*my_str)) { 1523 my_str++; 1524 } 1525 1526 if (isdigit((int) *my_str)) { 1527 s = strtod(my_str, &my_str); 1528 } 1529 1530 /* skip blanks before easterness */ 1531 while (isblank(*my_str)) { 1532 my_str++; 1533 } 1534 1535east: 1536 if (*my_str == 'E') { 1537 easterness = 1; 1538 } else if (*my_str == 'W') { 1539 easterness = 0; 1540 } else { 1541 return LDNS_WIREPARSE_ERR_INVALID_STR; 1542 } 1543 1544 my_str++; 1545 1546 /* store number */ 1547 s *= 1000.0; 1548 /* add a little to make floor in conversion a round */ 1549 s += 0.0005; 1550 longitude = (uint32_t) s; 1551 longitude += 1000 * 60 * m; 1552 longitude += 1000 * 60 * 60 * h; 1553 1554 if (easterness) { 1555 longitude += equator; 1556 } else { 1557 longitude = equator - longitude; 1558 } 1559 1560 altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 + 1561 10000000.0 + 0.5); 1562 if (*my_str == 'm' || *my_str == 'M') { 1563 my_str++; 1564 } 1565 1566 if (strlen(my_str) > 0) { 1567 if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e)) 1568 return LDNS_WIREPARSE_ERR_INVALID_STR; 1569 } 1570 1571 if (strlen(my_str) > 0) { 1572 if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e)) 1573 return LDNS_WIREPARSE_ERR_INVALID_STR; 1574 } 1575 1576 if (strlen(my_str) > 0) { 1577 if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e)) 1578 return LDNS_WIREPARSE_ERR_INVALID_STR; 1579 } 1580 1581 if(*len < 16) 1582 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1583 rd[0] = 0; 1584 rd[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f); 1585 rd[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f); 1586 rd[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f); 1587 sldns_write_uint32(rd + 4, latitude); 1588 sldns_write_uint32(rd + 8, longitude); 1589 sldns_write_uint32(rd + 12, altitude); 1590 *len = 16; 1591 return LDNS_WIREPARSE_ERR_OK; 1592} 1593 1594int sldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len) 1595{ 1596 int rd_len = 1; 1597 int have_proto = 0; 1598 char token[50], proto_str[50]; 1599 sldns_buffer strbuf; 1600 sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 1601 proto_str[0]=0; 1602 1603 /* check we have one byte for proto */ 1604 if(*len < 1) 1605 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1606 1607 while(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) > 0) { 1608 if(!have_proto) { 1609 struct protoent *p = getprotobyname(token); 1610 have_proto = 1; 1611 if(p) rd[0] = (uint8_t)p->p_proto; 1612 else rd[0] = (uint8_t)atoi(token); 1613 (void)strlcpy(proto_str, token, sizeof(proto_str)); 1614 } else { 1615 int serv_port; 1616 struct servent *serv = getservbyname(token, proto_str); 1617 if(serv) serv_port=(int)ntohs((uint16_t)serv->s_port); 1618 else { 1619 serv_port = atoi(token); 1620 if(serv_port == 0 && strcmp(token, "0") != 0) { 1621#ifdef HAVE_ENDSERVENT 1622 endservent(); 1623#endif 1624#ifdef HAVE_ENDPROTOENT 1625 endprotoent(); 1626#endif 1627 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, 1628 sldns_buffer_position(&strbuf)); 1629 } 1630 if(serv_port < 0 || serv_port > 65535) { 1631#ifdef HAVE_ENDSERVENT 1632 endservent(); 1633#endif 1634#ifdef HAVE_ENDPROTOENT 1635 endprotoent(); 1636#endif 1637 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, 1638 sldns_buffer_position(&strbuf)); 1639 } 1640 } 1641 if(rd_len < 1+serv_port/8+1) { 1642 /* bitmap is larger, init new bytes at 0 */ 1643 if(*len < 1+(size_t)serv_port/8+1) { 1644#ifdef HAVE_ENDSERVENT 1645 endservent(); 1646#endif 1647#ifdef HAVE_ENDPROTOENT 1648 endprotoent(); 1649#endif 1650 return RET_ERR( 1651 LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1652 sldns_buffer_position(&strbuf)); 1653 } 1654 memset(rd+rd_len, 0, 1+(size_t)serv_port/8+1-rd_len); 1655 rd_len = 1+serv_port/8+1; 1656 } 1657 rd[1+ serv_port/8] |= (1 << (7 - serv_port % 8)); 1658 } 1659 } 1660 *len = (size_t)rd_len; 1661 1662#ifdef HAVE_ENDSERVENT 1663 endservent(); 1664#endif 1665#ifdef HAVE_ENDPROTOENT 1666 endprotoent(); 1667#endif 1668 return LDNS_WIREPARSE_ERR_OK; 1669} 1670 1671int sldns_str2wire_nsap_buf(const char* str, uint8_t* rd, size_t* len) 1672{ 1673 const char* s = str; 1674 size_t slen; 1675 size_t dlen = 0; /* number of hexdigits parsed */ 1676 1677 /* just a hex string with optional dots? */ 1678 if (s[0] != '0' || s[1] != 'x') 1679 return LDNS_WIREPARSE_ERR_INVALID_STR; 1680 s += 2; 1681 slen = strlen(s); 1682 if(slen > LDNS_MAX_RDFLEN*2) 1683 return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; 1684 while(*s) { 1685 if(isspace(*s) || *s == '.') { 1686 s++; 1687 continue; 1688 } 1689 if(!isxdigit(*s)) 1690 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1691 if(*len < dlen/2 + 1) 1692 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1693 s-str); 1694 if((dlen&1)==0) 1695 rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; 1696 else rd[dlen/2] += sldns_hexdigit_to_int(*s++); 1697 dlen++; 1698 } 1699 if((dlen&1)!=0) 1700 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1701 *len = dlen/2; 1702 return LDNS_WIREPARSE_ERR_OK; 1703} 1704 1705int sldns_str2wire_atma_buf(const char* str, uint8_t* rd, size_t* len) 1706{ 1707 const char* s = str; 1708 size_t slen = strlen(str); 1709 size_t dlen = 0; /* number of hexdigits parsed */ 1710 1711 /* just a hex string with optional dots? */ 1712 /* notimpl e.164 format */ 1713 if(slen > LDNS_MAX_RDFLEN*2) 1714 return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; 1715 while(*s) { 1716 if(isspace(*s) || *s == '.') { 1717 s++; 1718 continue; 1719 } 1720 if(!isxdigit(*s)) 1721 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1722 if(*len < dlen/2 + 1) 1723 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1724 s-str); 1725 if((dlen&1)==0) 1726 rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; 1727 else rd[dlen/2] += sldns_hexdigit_to_int(*s++); 1728 dlen++; 1729 } 1730 if((dlen&1)!=0) 1731 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1732 *len = dlen/2; 1733 return LDNS_WIREPARSE_ERR_OK; 1734} 1735 1736int sldns_str2wire_ipseckey_buf(const char* str, uint8_t* rd, size_t* len) 1737{ 1738 size_t gwlen = 0, keylen = 0; 1739 int s; 1740 uint8_t gwtype; 1741 char token[512]; 1742 sldns_buffer strbuf; 1743 sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 1744 1745 if(*len < 3) 1746 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1747 /* precedence */ 1748 if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 1749 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1750 sldns_buffer_position(&strbuf)); 1751 rd[0] = (uint8_t)atoi(token); 1752 /* gateway_type */ 1753 if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 1754 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1755 sldns_buffer_position(&strbuf)); 1756 rd[1] = (uint8_t)atoi(token); 1757 gwtype = rd[1]; 1758 /* algorithm */ 1759 if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 1760 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1761 sldns_buffer_position(&strbuf)); 1762 rd[2] = (uint8_t)atoi(token); 1763 1764 /* gateway */ 1765 if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 1766 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1767 sldns_buffer_position(&strbuf)); 1768 if(gwtype == 0) { 1769 /* NOGATEWAY */ 1770 if(strcmp(token, ".") != 0) 1771 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1772 sldns_buffer_position(&strbuf)); 1773 gwlen = 0; 1774 } else if(gwtype == 1) { 1775 /* IP4 */ 1776 gwlen = *len - 3; 1777 s = sldns_str2wire_a_buf(token, rd+3, &gwlen); 1778 if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 1779 } else if(gwtype == 2) { 1780 /* IP6 */ 1781 gwlen = *len - 3; 1782 s = sldns_str2wire_aaaa_buf(token, rd+3, &gwlen); 1783 if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 1784 } else if(gwtype == 3) { 1785 /* DNAME */ 1786 gwlen = *len - 3; 1787 s = sldns_str2wire_dname_buf(token, rd+3, &gwlen); 1788 if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 1789 } else { 1790 /* unknown gateway type */ 1791 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1792 sldns_buffer_position(&strbuf)); 1793 } 1794 /* double check for size */ 1795 if(*len < 3 + gwlen) 1796 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1797 sldns_buffer_position(&strbuf)); 1798 1799 /* publickey in remainder of strbuf */ 1800 keylen = *len - 3 - gwlen; 1801 s = sldns_str2wire_b64_buf((const char*)sldns_buffer_current(&strbuf), 1802 rd+3+gwlen, &keylen); 1803 if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 1804 1805 *len = 3 + gwlen + keylen; 1806 return LDNS_WIREPARSE_ERR_OK; 1807} 1808 1809int sldns_str2wire_nsec3_salt_buf(const char* str, uint8_t* rd, size_t* len) 1810{ 1811 int i, salt_length_str = (int)strlen(str); 1812 if (salt_length_str == 1 && str[0] == '-') { 1813 salt_length_str = 0; 1814 } else if (salt_length_str % 2 != 0) { 1815 return LDNS_WIREPARSE_ERR_SYNTAX_HEX; 1816 } 1817 if (salt_length_str > 512) 1818 return LDNS_WIREPARSE_ERR_SYNTAX_HEX; 1819 if(*len < 1+(size_t)salt_length_str / 2) 1820 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1821 rd[0] = (uint8_t) (salt_length_str / 2); 1822 for (i = 0; i < salt_length_str; i += 2) { 1823 if (isxdigit((int)str[i]) && isxdigit((int)str[i+1])) { 1824 rd[1+i/2] = (uint8_t)(sldns_hexdigit_to_int(str[i])*16 1825 + sldns_hexdigit_to_int(str[i+1])); 1826 } else { 1827 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, i); 1828 } 1829 } 1830 *len = 1 + (size_t)rd[0]; 1831 return LDNS_WIREPARSE_ERR_OK; 1832} 1833 1834int sldns_str2wire_ilnp64_buf(const char* str, uint8_t* rd, size_t* len) 1835{ 1836 unsigned int a, b, c, d; 1837 uint16_t shorts[4]; 1838 int l; 1839 if(*len < sizeof(shorts)) 1840 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1841 1842 if (sscanf(str, "%4x:%4x:%4x:%4x%n", &a, &b, &c, &d, &l) != 4 || 1843 l != (int)strlen(str) || /* more data to read */ 1844 strpbrk(str, "+-") /* signed hexes */ 1845 ) 1846 return LDNS_WIREPARSE_ERR_SYNTAX_ILNP64; 1847 shorts[0] = htons(a); 1848 shorts[1] = htons(b); 1849 shorts[2] = htons(c); 1850 shorts[3] = htons(d); 1851 memmove(rd, &shorts, sizeof(shorts)); 1852 *len = sizeof(shorts); 1853 return LDNS_WIREPARSE_ERR_OK; 1854} 1855 1856int sldns_str2wire_eui48_buf(const char* str, uint8_t* rd, size_t* len) 1857{ 1858 unsigned int a, b, c, d, e, f; 1859 int l; 1860 1861 if(*len < 6) 1862 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1863 if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x%n", 1864 &a, &b, &c, &d, &e, &f, &l) != 6 || 1865 l != (int)strlen(str)) 1866 return LDNS_WIREPARSE_ERR_SYNTAX_EUI48; 1867 rd[0] = a; 1868 rd[1] = b; 1869 rd[2] = c; 1870 rd[3] = d; 1871 rd[4] = e; 1872 rd[5] = f; 1873 *len = 6; 1874 return LDNS_WIREPARSE_ERR_OK; 1875} 1876 1877int sldns_str2wire_eui64_buf(const char* str, uint8_t* rd, size_t* len) 1878{ 1879 unsigned int a, b, c, d, e, f, g, h; 1880 int l; 1881 1882 if(*len < 8) 1883 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1884 if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x%n", 1885 &a, &b, &c, &d, &e, &f, &g, &h, &l) != 8 || 1886 l != (int)strlen(str)) 1887 return LDNS_WIREPARSE_ERR_SYNTAX_EUI64; 1888 rd[0] = a; 1889 rd[1] = b; 1890 rd[2] = c; 1891 rd[3] = d; 1892 rd[4] = e; 1893 rd[5] = f; 1894 rd[6] = g; 1895 rd[7] = h; 1896 *len = 8; 1897 return LDNS_WIREPARSE_ERR_OK; 1898} 1899 1900int sldns_str2wire_tag_buf(const char* str, uint8_t* rd, size_t* len) 1901{ 1902 size_t slen = strlen(str); 1903 const char* ptr; 1904 1905 if (slen > 255) 1906 return LDNS_WIREPARSE_ERR_SYNTAX_TAG; 1907 if(*len < slen+1) 1908 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1909 for (ptr = str; *ptr; ptr++) { 1910 if(!isalnum(*ptr)) 1911 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TAG, ptr-str); 1912 } 1913 rd[0] = slen; 1914 memmove(rd+1, str, slen); 1915 *len = slen+1; 1916 return LDNS_WIREPARSE_ERR_OK; 1917} 1918 1919int sldns_str2wire_long_str_buf(const char* str, uint8_t* rd, size_t* len) 1920{ 1921 uint8_t ch = 0; 1922 const char* pstr = str; 1923 size_t length = 0; 1924 1925 /* Fill data with parsed bytes */ 1926 while (sldns_parse_char(&ch, &pstr)) { 1927 if(*len < length+1) 1928 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1929 rd[length++] = ch; 1930 } 1931 if(!pstr) 1932 return LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE; 1933 *len = length; 1934 return LDNS_WIREPARSE_ERR_OK; 1935} 1936 1937int sldns_str2wire_hip_buf(const char* str, uint8_t* rd, size_t* len) 1938{ 1939 char* s, *end; 1940 int e; 1941 size_t hitlen, pklen = 0; 1942 /* presentation format: 1943 * pk-algo HIThex pubkeybase64 1944 * wireformat: 1945 * hitlen[1byte] pkalgo[1byte] pubkeylen[2byte] [hit] [pubkey] */ 1946 if(*len < 4) 1947 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1948 1949 /* read PK algorithm */ 1950 rd[1] = (uint8_t)strtol((char*)str, &s, 10); 1951 if(*s != ' ') 1952 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, s-(char*)str); 1953 s++; 1954 while(*s == ' ') 1955 s++; 1956 1957 /* read HIT hex tag */ 1958 /* zero terminate the tag (replace later) */ 1959 end = strchr(s, ' '); 1960 if(!end) return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, s-(char*)str); 1961 *end = 0; 1962 hitlen = *len - 4; 1963 if((e = sldns_str2wire_hex_buf(s, rd+4, &hitlen)) != 0) { 1964 *end = ' '; 1965 return RET_ERR_SHIFT(e, s-(char*)str); 1966 } 1967 if(hitlen > 255) { 1968 *end = ' '; 1969 return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, s-(char*)str+255*2); 1970 } 1971 rd[0] = (uint8_t)hitlen; 1972 *end = ' '; 1973 s = end+1; 1974 1975 /* read pubkey base64 sequence */ 1976 pklen = *len - 4 - hitlen; 1977 if((e = sldns_str2wire_b64_buf(s, rd+4+hitlen, &pklen)) != 0) 1978 return RET_ERR_SHIFT(e, s-(char*)str); 1979 if(pklen > 65535) 1980 return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, s-(char*)str+65535); 1981 sldns_write_uint16(rd+2, pklen); 1982 1983 *len = 4 + hitlen + pklen; 1984 return LDNS_WIREPARSE_ERR_OK; 1985} 1986 1987int sldns_str2wire_int16_data_buf(const char* str, uint8_t* rd, size_t* len) 1988{ 1989 size_t sz = sldns_b64_pton_calculate_size(strlen(str)); 1990 int n; 1991 if(*len < sz+2) 1992 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1993 if(sz > 65535) 1994 return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; 1995 n = sldns_b64_pton(str, rd+2, (*len)-2); 1996 if(n < 0) 1997 return LDNS_WIREPARSE_ERR_SYNTAX_B64; 1998 sldns_write_uint16(rd, (uint16_t)n); 1999 *len = (size_t)n; 2000 return LDNS_WIREPARSE_ERR_OK; 2001} 2002