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 "sldns/str2wire.h" 16 #include "sldns/wire2str.h" 17 #include "sldns/sbuffer.h" 18 #include "sldns/parse.h" 19 #include "sldns/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 */ 40 static 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 139 int 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 144 int 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 166 uint8_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 */ 179 static int 180 rrinternal_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(*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 */ 237 static int 238 rrinternal_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((unsigned char)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 */ 261 static int 262 rrinternal_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 */ 283 static int 284 rrinternal_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 */ 304 static int 305 rrinternal_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 */ 330 static const char* 331 rrinternal_get_delims(sldns_rdf_type rdftype, size_t r_cnt, size_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"; 341 } 342 break; 343 default : break; 344 } 345 return "\n\t "; 346 } 347 348 /* Syntactic sugar for sldns_rr_new_frm_str_internal */ 349 static int 350 sldns_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 */ 357 static int 358 rrinternal_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 */ 381 static int 382 rrinternal_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((unsigned char)*p)) { 388 p++; 389 continue; 390 } 391 if(!isxdigit((unsigned char)*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 */ 416 static int 417 rrinternal_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 */ 463 static int 464 rrinternal_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, size_t r_cnt, size_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 */ 531 static int 532 sldns_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. */ 587 static int 588 sldns_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). */ 610 static int 611 rrinternal_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 size_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 } else if(rdftype == LDNS_RDF_TYPE_INT16_DATA && 668 strcmp(token, "0")!=0) { 669 /* affix len and b64 fields */ 670 if(!sldns_affix_token(strbuf, token, 671 &token_len, "ed, &parens, 672 &pre_data_pos, delimiters, 673 rdftype, &token_strlen)) 674 break; 675 } 676 677 /* normal RR */ 678 if((status=rrinternal_parse_rdf(strbuf, token, 679 token_len, rr, *rr_len, &rr_cur_len, rdftype, 680 rr_type, r_cnt, r_max, dname_len, origin, 681 origin_len)) != 0) { 682 return status; 683 } 684 } 685 } 686 if(!was_unknown_rr_format && r_cnt+1 < r_min) { 687 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_MISSING_VALUE, 688 sldns_buffer_position(strbuf)); 689 } 690 while(parens != 0) { 691 /* read remainder, must be "" */ 692 if(sldns_bget_token_par(strbuf, token, "\n", token_len, 693 &parens, " \t") == -1) { 694 if(parens != 0) 695 return RET_ERR(LDNS_WIREPARSE_ERR_PARENTHESIS, 696 sldns_buffer_position(strbuf)); 697 break; 698 } 699 if(strcmp(token, "") != 0) 700 return RET_ERR(LDNS_WIREPARSE_ERR_PARENTHESIS, 701 sldns_buffer_position(strbuf)); 702 } 703 /* write rdata length */ 704 sldns_write_uint16(rr+dname_len+8, (uint16_t)(rr_cur_len-dname_len-10)); 705 *rr_len = rr_cur_len; 706 return LDNS_WIREPARSE_ERR_OK; 707 } 708 709 /* 710 * trailing spaces are allowed 711 * leading spaces are not allowed 712 * allow ttl to be optional 713 * class is optional too 714 * if ttl is missing, and default_ttl is 0, use DEF_TTL 715 * allow ttl to be written as 1d3h 716 * So the RR should look like. e.g. 717 * miek.nl. 3600 IN MX 10 elektron.atoom.net 718 * or 719 * miek.nl. 1h IN MX 10 elektron.atoom.net 720 * or 721 * miek.nl. IN MX 10 elektron.atoom.net 722 */ 723 static int 724 sldns_str2wire_rr_buf_internal(const char* str, uint8_t* rr, size_t* len, 725 size_t* dname_len, uint32_t default_ttl, uint8_t* origin, 726 size_t origin_len, uint8_t* prev, size_t prev_len, int question) 727 { 728 int status; 729 int not_there = 0; 730 char token[LDNS_MAX_RDFLEN+1]; 731 uint32_t ttl = 0; 732 uint16_t tp = 0, cl = 0; 733 size_t ddlen = 0; 734 735 /* string in buffer */ 736 sldns_buffer strbuf; 737 sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 738 if(!dname_len) dname_len = &ddlen; 739 740 /* parse the owner */ 741 if((status=rrinternal_get_owner(&strbuf, rr, len, dname_len, origin, 742 origin_len, prev, prev_len, token, sizeof(token))) != 0) 743 return status; 744 745 /* parse the [ttl] [class] <type> */ 746 if((status=rrinternal_get_ttl(&strbuf, token, sizeof(token), 747 ¬_there, &ttl, default_ttl)) != 0) 748 return status; 749 if((status=rrinternal_get_class(&strbuf, token, sizeof(token), 750 ¬_there, &cl)) != 0) 751 return status; 752 if((status=rrinternal_get_type(&strbuf, token, sizeof(token), 753 ¬_there, &tp)) != 0) 754 return status; 755 /* put ttl, class, type into the rr result */ 756 if((status=rrinternal_write_typeclassttl(&strbuf, rr, *len, *dname_len, tp, cl, 757 ttl, question)) != 0) 758 return status; 759 /* for a question-RR we are done, no rdata */ 760 if(question) { 761 *len = *dname_len + 4; 762 return LDNS_WIREPARSE_ERR_OK; 763 } 764 765 /* rdata */ 766 if((status=rrinternal_parse_rdata(&strbuf, token, sizeof(token), 767 rr, len, *dname_len, tp, origin, origin_len)) != 0) 768 return status; 769 770 return LDNS_WIREPARSE_ERR_OK; 771 } 772 773 int sldns_str2wire_rr_buf(const char* str, uint8_t* rr, size_t* len, 774 size_t* dname_len, uint32_t default_ttl, uint8_t* origin, 775 size_t origin_len, uint8_t* prev, size_t prev_len) 776 { 777 return sldns_str2wire_rr_buf_internal(str, rr, len, dname_len, 778 default_ttl, origin, origin_len, prev, prev_len, 0); 779 } 780 781 int sldns_str2wire_rr_question_buf(const char* str, uint8_t* rr, size_t* len, 782 size_t* dname_len, uint8_t* origin, size_t origin_len, uint8_t* prev, 783 size_t prev_len) 784 { 785 return sldns_str2wire_rr_buf_internal(str, rr, len, dname_len, 786 0, origin, origin_len, prev, prev_len, 1); 787 } 788 789 uint16_t sldns_wirerr_get_type(uint8_t* rr, size_t len, size_t dname_len) 790 { 791 if(len < dname_len+2) 792 return 0; 793 return sldns_read_uint16(rr+dname_len); 794 } 795 796 uint16_t sldns_wirerr_get_class(uint8_t* rr, size_t len, size_t dname_len) 797 { 798 if(len < dname_len+4) 799 return 0; 800 return sldns_read_uint16(rr+dname_len+2); 801 } 802 803 uint32_t sldns_wirerr_get_ttl(uint8_t* rr, size_t len, size_t dname_len) 804 { 805 if(len < dname_len+8) 806 return 0; 807 return sldns_read_uint32(rr+dname_len+4); 808 } 809 810 uint16_t sldns_wirerr_get_rdatalen(uint8_t* rr, size_t len, size_t dname_len) 811 { 812 if(len < dname_len+10) 813 return 0; 814 return sldns_read_uint16(rr+dname_len+8); 815 } 816 817 uint8_t* sldns_wirerr_get_rdata(uint8_t* rr, size_t len, size_t dname_len) 818 { 819 if(len < dname_len+10) 820 return NULL; 821 return rr+dname_len+10; 822 } 823 824 uint8_t* sldns_wirerr_get_rdatawl(uint8_t* rr, size_t len, size_t dname_len) 825 { 826 if(len < dname_len+10) 827 return NULL; 828 return rr+dname_len+8; 829 } 830 831 const char* sldns_get_errorstr_parse(int e) 832 { 833 sldns_lookup_table *lt; 834 lt = sldns_lookup_by_id(sldns_wireparse_errors, LDNS_WIREPARSE_ERROR(e)); 835 return lt?lt->name:"unknown error"; 836 } 837 838 /* Strip whitespace from the start and the end of <line>. */ 839 char * 840 sldns_strip_ws(char *line) 841 { 842 char *s = line, *e; 843 844 for (s = line; *s && isspace((unsigned char)*s); s++) 845 ; 846 for (e = strchr(s, 0); e > s+2 && isspace((unsigned char)e[-1]) && e[-2] != '\\'; e--) 847 ; 848 *e = 0; 849 return s; 850 } 851 852 int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len, 853 struct sldns_file_parse_state* parse_state) 854 { 855 char line[LDNS_RR_BUF_SIZE+1]; 856 ssize_t size; 857 858 /* read an entire line in from the file */ 859 if((size = sldns_fget_token_l(in, line, LDNS_PARSE_SKIP_SPACE, 860 LDNS_RR_BUF_SIZE, parse_state?&parse_state->lineno:NULL)) 861 == -1) { 862 /* if last line was empty, we are now at feof, which is not 863 * always a parse error (happens when for instance last line 864 * was a comment) 865 */ 866 return LDNS_WIREPARSE_ERR_SYNTAX; 867 } 868 869 /* we can have the situation, where we've read ok, but still got 870 * no bytes to play with, in this case size is 0 */ 871 if(size == 0) { 872 if(*len > 0) 873 rr[0] = 0; 874 *len = 0; 875 *dname_len = 0; 876 return LDNS_WIREPARSE_ERR_OK; 877 } 878 879 if(strncmp(line, "$ORIGIN", 7) == 0 && isspace((unsigned char)line[7])) { 880 int s; 881 strlcpy((char*)rr, line, *len); 882 *len = 0; 883 *dname_len = 0; 884 if(!parse_state) return LDNS_WIREPARSE_ERR_OK; 885 parse_state->origin_len = sizeof(parse_state->origin); 886 s = sldns_str2wire_dname_buf(sldns_strip_ws(line+8), 887 parse_state->origin, &parse_state->origin_len); 888 if(s) parse_state->origin_len = 0; 889 return s; 890 } else if(strncmp(line, "$TTL", 4) == 0 && isspace((unsigned char)line[4])) { 891 const char* end = NULL; 892 strlcpy((char*)rr, line, *len); 893 *len = 0; 894 *dname_len = 0; 895 if(!parse_state) return LDNS_WIREPARSE_ERR_OK; 896 parse_state->default_ttl = sldns_str2period( 897 sldns_strip_ws(line+5), &end); 898 } else if (strncmp(line, "$INCLUDE", 8) == 0) { 899 strlcpy((char*)rr, line, *len); 900 *len = 0; 901 *dname_len = 0; 902 return LDNS_WIREPARSE_ERR_INCLUDE; 903 } else if (strncmp(line, "$", 1) == 0) { 904 strlcpy((char*)rr, line, *len); 905 *len = 0; 906 *dname_len = 0; 907 return LDNS_WIREPARSE_ERR_INCLUDE; 908 } else { 909 int r = sldns_str2wire_rr_buf(line, rr, len, dname_len, 910 parse_state?parse_state->default_ttl:0, 911 (parse_state&&parse_state->origin_len)? 912 parse_state->origin:NULL, 913 parse_state?parse_state->origin_len:0, 914 (parse_state&&parse_state->prev_rr_len)? 915 parse_state->prev_rr:NULL, 916 parse_state?parse_state->prev_rr_len:0); 917 if(r == LDNS_WIREPARSE_ERR_OK && (*dname_len) != 0 && 918 parse_state && 919 (*dname_len) <= sizeof(parse_state->prev_rr)) { 920 memmove(parse_state->prev_rr, rr, *dname_len); 921 parse_state->prev_rr_len = (*dname_len); 922 } 923 return r; 924 } 925 return LDNS_WIREPARSE_ERR_OK; 926 } 927 928 int sldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len, 929 sldns_rdf_type rdftype) 930 { 931 switch (rdftype) { 932 case LDNS_RDF_TYPE_DNAME: 933 return sldns_str2wire_dname_buf(str, rd, len); 934 case LDNS_RDF_TYPE_INT8: 935 return sldns_str2wire_int8_buf(str, rd, len); 936 case LDNS_RDF_TYPE_INT16: 937 return sldns_str2wire_int16_buf(str, rd, len); 938 case LDNS_RDF_TYPE_INT32: 939 return sldns_str2wire_int32_buf(str, rd, len); 940 case LDNS_RDF_TYPE_A: 941 return sldns_str2wire_a_buf(str, rd, len); 942 case LDNS_RDF_TYPE_AAAA: 943 return sldns_str2wire_aaaa_buf(str, rd, len); 944 case LDNS_RDF_TYPE_STR: 945 return sldns_str2wire_str_buf(str, rd, len); 946 case LDNS_RDF_TYPE_APL: 947 return sldns_str2wire_apl_buf(str, rd, len); 948 case LDNS_RDF_TYPE_B64: 949 return sldns_str2wire_b64_buf(str, rd, len); 950 case LDNS_RDF_TYPE_B32_EXT: 951 return sldns_str2wire_b32_ext_buf(str, rd, len); 952 case LDNS_RDF_TYPE_HEX: 953 return sldns_str2wire_hex_buf(str, rd, len); 954 case LDNS_RDF_TYPE_NSEC: 955 return sldns_str2wire_nsec_buf(str, rd, len); 956 case LDNS_RDF_TYPE_TYPE: 957 return sldns_str2wire_type_buf(str, rd, len); 958 case LDNS_RDF_TYPE_CLASS: 959 return sldns_str2wire_class_buf(str, rd, len); 960 case LDNS_RDF_TYPE_CERT_ALG: 961 return sldns_str2wire_cert_alg_buf(str, rd, len); 962 case LDNS_RDF_TYPE_ALG: 963 return sldns_str2wire_alg_buf(str, rd, len); 964 case LDNS_RDF_TYPE_TIME: 965 return sldns_str2wire_time_buf(str, rd, len); 966 case LDNS_RDF_TYPE_PERIOD: 967 return sldns_str2wire_period_buf(str, rd, len); 968 case LDNS_RDF_TYPE_TSIGTIME: 969 return sldns_str2wire_tsigtime_buf(str, rd, len); 970 case LDNS_RDF_TYPE_LOC: 971 return sldns_str2wire_loc_buf(str, rd, len); 972 case LDNS_RDF_TYPE_WKS: 973 return sldns_str2wire_wks_buf(str, rd, len); 974 case LDNS_RDF_TYPE_NSAP: 975 return sldns_str2wire_nsap_buf(str, rd, len); 976 case LDNS_RDF_TYPE_ATMA: 977 return sldns_str2wire_atma_buf(str, rd, len); 978 case LDNS_RDF_TYPE_IPSECKEY: 979 return sldns_str2wire_ipseckey_buf(str, rd, len); 980 case LDNS_RDF_TYPE_NSEC3_SALT: 981 return sldns_str2wire_nsec3_salt_buf(str, rd, len); 982 case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER: 983 return sldns_str2wire_b32_ext_buf(str, rd, len); 984 case LDNS_RDF_TYPE_ILNP64: 985 return sldns_str2wire_ilnp64_buf(str, rd, len); 986 case LDNS_RDF_TYPE_EUI48: 987 return sldns_str2wire_eui48_buf(str, rd, len); 988 case LDNS_RDF_TYPE_EUI64: 989 return sldns_str2wire_eui64_buf(str, rd, len); 990 case LDNS_RDF_TYPE_TAG: 991 return sldns_str2wire_tag_buf(str, rd, len); 992 case LDNS_RDF_TYPE_LONG_STR: 993 return sldns_str2wire_long_str_buf(str, rd, len); 994 case LDNS_RDF_TYPE_TSIGERROR: 995 return sldns_str2wire_tsigerror_buf(str, rd, len); 996 case LDNS_RDF_TYPE_HIP: 997 return sldns_str2wire_hip_buf(str, rd, len); 998 case LDNS_RDF_TYPE_INT16_DATA: 999 return sldns_str2wire_int16_data_buf(str, rd, len); 1000 case LDNS_RDF_TYPE_UNKNOWN: 1001 case LDNS_RDF_TYPE_SERVICE: 1002 return LDNS_WIREPARSE_ERR_NOT_IMPL; 1003 case LDNS_RDF_TYPE_NONE: 1004 default: 1005 break; 1006 } 1007 return LDNS_WIREPARSE_ERR_GENERAL; 1008 } 1009 1010 int sldns_str2wire_int8_buf(const char* str, uint8_t* rd, size_t* len) 1011 { 1012 char* end; 1013 uint8_t r = (uint8_t)strtol((char*)str, &end, 10); 1014 if(*end != 0) 1015 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); 1016 if(*len < 1) 1017 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1018 rd[0] = r; 1019 *len = 1; 1020 return LDNS_WIREPARSE_ERR_OK; 1021 } 1022 1023 int sldns_str2wire_int16_buf(const char* str, uint8_t* rd, size_t* len) 1024 { 1025 char* end; 1026 uint16_t r = (uint16_t)strtol((char*)str, &end, 10); 1027 if(*end != 0) 1028 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); 1029 if(*len < 2) 1030 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1031 sldns_write_uint16(rd, r); 1032 *len = 2; 1033 return LDNS_WIREPARSE_ERR_OK; 1034 } 1035 1036 int sldns_str2wire_int32_buf(const char* str, uint8_t* rd, size_t* len) 1037 { 1038 char* end; 1039 uint32_t r; 1040 errno = 0; /* must set to zero before call, 1041 note race condition on errno */ 1042 if(*str == '-') 1043 r = (uint32_t)strtol((char*)str, &end, 10); 1044 else r = (uint32_t)strtoul((char*)str, &end, 10); 1045 if(*end != 0) 1046 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); 1047 if(errno == ERANGE) 1048 return LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW; 1049 if(*len < 4) 1050 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1051 sldns_write_uint32(rd, r); 1052 *len = 4; 1053 return LDNS_WIREPARSE_ERR_OK; 1054 } 1055 1056 int sldns_str2wire_a_buf(const char* str, uint8_t* rd, size_t* len) 1057 { 1058 struct in_addr address; 1059 if(inet_pton(AF_INET, (char*)str, &address) != 1) 1060 return LDNS_WIREPARSE_ERR_SYNTAX_IP4; 1061 if(*len < sizeof(address)) 1062 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1063 memmove(rd, &address, sizeof(address)); 1064 *len = sizeof(address); 1065 return LDNS_WIREPARSE_ERR_OK; 1066 } 1067 1068 int sldns_str2wire_aaaa_buf(const char* str, uint8_t* rd, size_t* len) 1069 { 1070 #ifdef AF_INET6 1071 uint8_t address[LDNS_IP6ADDRLEN + 1]; 1072 if(inet_pton(AF_INET6, (char*)str, address) != 1) 1073 return LDNS_WIREPARSE_ERR_SYNTAX_IP6; 1074 if(*len < LDNS_IP6ADDRLEN) 1075 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1076 memmove(rd, address, LDNS_IP6ADDRLEN); 1077 *len = LDNS_IP6ADDRLEN; 1078 return LDNS_WIREPARSE_ERR_OK; 1079 #else 1080 return LDNS_WIREPARSE_ERR_NOT_IMPL; 1081 #endif 1082 } 1083 1084 int sldns_str2wire_str_buf(const char* str, uint8_t* rd, size_t* len) 1085 { 1086 uint8_t ch = 0; 1087 size_t sl = 0; 1088 const char* s = str; 1089 /* skip length byte */ 1090 if(*len < 1) 1091 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1092 1093 /* read characters */ 1094 while(sldns_parse_char(&ch, &s)) { 1095 if(sl >= 255) 1096 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, s-str); 1097 if(*len < sl+1) 1098 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1099 s-str); 1100 rd[++sl] = ch; 1101 } 1102 if(!s) 1103 return LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE; 1104 rd[0] = (uint8_t)sl; 1105 *len = sl+1; 1106 return LDNS_WIREPARSE_ERR_OK; 1107 } 1108 1109 int sldns_str2wire_apl_buf(const char* str, uint8_t* rd, size_t* len) 1110 { 1111 const char *my_str = str; 1112 1113 char my_ip_str[64]; 1114 size_t ip_str_len; 1115 1116 uint16_t family; 1117 int negation; 1118 size_t adflength = 0; 1119 uint8_t data[16+4]; 1120 uint8_t prefix; 1121 size_t i; 1122 1123 if(*my_str == '\0') { 1124 /* empty APL element, no data, no string */ 1125 *len = 0; 1126 return LDNS_WIREPARSE_ERR_OK; 1127 } 1128 1129 /* [!]afi:address/prefix */ 1130 if (strlen(my_str) < 2 1131 || strchr(my_str, ':') == NULL 1132 || strchr(my_str, '/') == NULL 1133 || strchr(my_str, ':') > strchr(my_str, '/')) { 1134 return LDNS_WIREPARSE_ERR_INVALID_STR; 1135 } 1136 1137 if (my_str[0] == '!') { 1138 negation = 1; 1139 my_str += 1; 1140 } else { 1141 negation = 0; 1142 } 1143 1144 family = (uint16_t) atoi(my_str); 1145 1146 my_str = strchr(my_str, ':') + 1; 1147 1148 /* need ip addr and only ip addr for inet_pton */ 1149 ip_str_len = (size_t) (strchr(my_str, '/') - my_str); 1150 if(ip_str_len+1 > sizeof(my_ip_str)) 1151 return LDNS_WIREPARSE_ERR_INVALID_STR; 1152 (void)strlcpy(my_ip_str, my_str, sizeof(my_ip_str)); 1153 my_ip_str[ip_str_len] = 0; 1154 1155 if (family == 1) { 1156 /* ipv4 */ 1157 if(inet_pton(AF_INET, my_ip_str, data+4) == 0) 1158 return LDNS_WIREPARSE_ERR_INVALID_STR; 1159 for (i = 0; i < 4; i++) { 1160 if (data[i+4] != 0) { 1161 adflength = i + 1; 1162 } 1163 } 1164 } else if (family == 2) { 1165 /* ipv6 */ 1166 if (inet_pton(AF_INET6, my_ip_str, data+4) == 0) 1167 return LDNS_WIREPARSE_ERR_INVALID_STR; 1168 for (i = 0; i < 16; i++) { 1169 if (data[i+4] != 0) { 1170 adflength = i + 1; 1171 } 1172 } 1173 } else { 1174 /* unknown family */ 1175 return LDNS_WIREPARSE_ERR_INVALID_STR; 1176 } 1177 1178 my_str = strchr(my_str, '/') + 1; 1179 prefix = (uint8_t) atoi(my_str); 1180 1181 sldns_write_uint16(data, family); 1182 data[2] = prefix; 1183 data[3] = (uint8_t)adflength; 1184 if (negation) { 1185 /* set bit 1 of byte 3 */ 1186 data[3] = data[3] | 0x80; 1187 } 1188 1189 if(*len < 4+adflength) 1190 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1191 memmove(rd, data, 4+adflength); 1192 *len = 4+adflength; 1193 return LDNS_WIREPARSE_ERR_OK; 1194 } 1195 1196 int sldns_str2wire_b64_buf(const char* str, uint8_t* rd, size_t* len) 1197 { 1198 size_t sz = sldns_b64_pton_calculate_size(strlen(str)); 1199 int n; 1200 if(strcmp(str, "0") == 0) { 1201 *len = 0; 1202 return LDNS_WIREPARSE_ERR_OK; 1203 } 1204 if(*len < sz) 1205 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1206 n = sldns_b64_pton(str, rd, *len); 1207 if(n < 0) 1208 return LDNS_WIREPARSE_ERR_SYNTAX_B64; 1209 *len = (size_t)n; 1210 return LDNS_WIREPARSE_ERR_OK; 1211 } 1212 1213 int sldns_str2wire_b32_ext_buf(const char* str, uint8_t* rd, size_t* len) 1214 { 1215 size_t slen = strlen(str); 1216 size_t sz = sldns_b32_pton_calculate_size(slen); 1217 int n; 1218 if(*len < 1+sz) 1219 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1220 rd[0] = (uint8_t)sz; 1221 n = sldns_b32_pton_extended_hex(str, slen, rd+1, *len-1); 1222 if(n < 0) 1223 return LDNS_WIREPARSE_ERR_SYNTAX_B32_EXT; 1224 *len = (size_t)n+1; 1225 return LDNS_WIREPARSE_ERR_OK; 1226 } 1227 1228 /** see if the string ends, or ends in whitespace */ 1229 static int 1230 sldns_is_last_of_string(const char* str) 1231 { 1232 if(*str == 0) return 1; 1233 while(isspace((unsigned char)*str)) 1234 str++; 1235 if(*str == 0) return 1; 1236 return 0; 1237 } 1238 1239 int sldns_str2wire_hex_buf(const char* str, uint8_t* rd, size_t* len) 1240 { 1241 const char* s = str; 1242 size_t dlen = 0; /* number of hexdigits parsed */ 1243 while(*s) { 1244 if(isspace((unsigned char)*s)) { 1245 s++; 1246 continue; 1247 } 1248 if(dlen == 0 && *s == '0' && sldns_is_last_of_string(s+1)) { 1249 *len = 0; 1250 return LDNS_WIREPARSE_ERR_OK; 1251 } 1252 if(!isxdigit((unsigned char)*s)) 1253 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1254 if(*len < dlen/2 + 1) 1255 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1256 s-str); 1257 if((dlen&1)==0) 1258 rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; 1259 else rd[dlen/2] += (uint8_t)sldns_hexdigit_to_int(*s++); 1260 dlen++; 1261 } 1262 if((dlen&1)!=0) 1263 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1264 *len = dlen/2; 1265 return LDNS_WIREPARSE_ERR_OK; 1266 } 1267 1268 int sldns_str2wire_nsec_buf(const char* str, uint8_t* rd, size_t* len) 1269 { 1270 const char *delim = "\n\t "; 1271 char token[64]; /* for a type name */ 1272 size_t type_count = 0; 1273 int block; 1274 size_t used = 0; 1275 uint16_t maxtype = 0; 1276 uint8_t typebits[8192]; /* 65536 bits */ 1277 uint8_t window_in_use[256]; 1278 1279 /* string in buffer */ 1280 sldns_buffer strbuf; 1281 sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 1282 1283 /* parse the types */ 1284 memset(typebits, 0, sizeof(typebits)); 1285 memset(window_in_use, 0, sizeof(window_in_use)); 1286 while(sldns_buffer_remaining(&strbuf) > 0 && 1287 sldns_bget_token(&strbuf, token, delim, sizeof(token)) != -1) { 1288 uint16_t t = sldns_get_rr_type_by_name(token); 1289 if(token[0] == 0) 1290 continue; 1291 if(t == 0 && strcmp(token, "TYPE0") != 0) 1292 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE, 1293 sldns_buffer_position(&strbuf)); 1294 typebits[t/8] |= (0x80>>(t%8)); 1295 window_in_use[t/256] = 1; 1296 type_count++; 1297 if(t > maxtype) maxtype = t; 1298 } 1299 1300 /* empty NSEC bitmap */ 1301 if(type_count == 0) { 1302 *len = 0; 1303 return LDNS_WIREPARSE_ERR_OK; 1304 } 1305 1306 /* encode windows {u8 windowblock, u8 bitmaplength, 0-32u8 bitmap}, 1307 * block is 0-255 upper octet of types, length if 0-32. */ 1308 for(block = 0; block <= (int)maxtype/256; block++) { 1309 int i, blocklen = 0; 1310 if(!window_in_use[block]) 1311 continue; 1312 for(i=0; i<32; i++) { 1313 if(typebits[block*32+i] != 0) 1314 blocklen = i+1; 1315 } 1316 if(blocklen == 0) 1317 continue; /* empty window should have been !in_use */ 1318 if(used+blocklen+2 > *len) 1319 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1320 rd[used+0] = (uint8_t)block; 1321 rd[used+1] = (uint8_t)blocklen; 1322 for(i=0; i<blocklen; i++) { 1323 rd[used+2+i] = typebits[block*32+i]; 1324 } 1325 used += blocklen+2; 1326 } 1327 *len = used; 1328 return LDNS_WIREPARSE_ERR_OK; 1329 } 1330 1331 int sldns_str2wire_type_buf(const char* str, uint8_t* rd, size_t* len) 1332 { 1333 uint16_t t = sldns_get_rr_type_by_name(str); 1334 if(t == 0 && strcmp(str, "TYPE0") != 0) 1335 return LDNS_WIREPARSE_ERR_SYNTAX_TYPE; 1336 if(*len < 2) 1337 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1338 sldns_write_uint16(rd, t); 1339 *len = 2; 1340 return LDNS_WIREPARSE_ERR_OK; 1341 } 1342 1343 int sldns_str2wire_class_buf(const char* str, uint8_t* rd, size_t* len) 1344 { 1345 uint16_t c = sldns_get_rr_class_by_name(str); 1346 if(c == 0 && strcmp(str, "CLASS0") != 0) 1347 return LDNS_WIREPARSE_ERR_SYNTAX_CLASS; 1348 if(*len < 2) 1349 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1350 sldns_write_uint16(rd, c); 1351 *len = 2; 1352 return LDNS_WIREPARSE_ERR_OK; 1353 } 1354 1355 /* An certificate alg field can either be specified as a 8 bits number 1356 * or by its symbolic name. Handle both */ 1357 int sldns_str2wire_cert_alg_buf(const char* str, uint8_t* rd, size_t* len) 1358 { 1359 sldns_lookup_table *lt = sldns_lookup_by_name(sldns_cert_algorithms, 1360 str); 1361 if(*len < 2) 1362 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1363 if(lt) { 1364 sldns_write_uint16(rd, (uint16_t)lt->id); 1365 } else { 1366 int s = sldns_str2wire_int16_buf(str, rd, len); 1367 if(s) return s; 1368 if(sldns_read_uint16(rd) == 0) 1369 return LDNS_WIREPARSE_ERR_CERT_BAD_ALGORITHM; 1370 } 1371 *len = 2; 1372 return LDNS_WIREPARSE_ERR_OK; 1373 } 1374 1375 /* An alg field can either be specified as a 8 bits number 1376 * or by its symbolic name. Handle both */ 1377 int sldns_str2wire_alg_buf(const char* str, uint8_t* rd, size_t* len) 1378 { 1379 sldns_lookup_table *lt = sldns_lookup_by_name(sldns_algorithms, str); 1380 if(*len < 1) 1381 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1382 if(lt) { 1383 rd[0] = (uint8_t)lt->id; 1384 *len = 1; 1385 } else { 1386 /* try as-is (a number) */ 1387 return sldns_str2wire_int8_buf(str, rd, len); 1388 } 1389 return LDNS_WIREPARSE_ERR_OK; 1390 } 1391 1392 int sldns_str2wire_tsigerror_buf(const char* str, uint8_t* rd, size_t* len) 1393 { 1394 sldns_lookup_table *lt = sldns_lookup_by_name(sldns_tsig_errors, str); 1395 if(*len < 2) 1396 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1397 if(lt) { 1398 sldns_write_uint16(rd, (uint16_t)lt->id); 1399 *len = 2; 1400 } else { 1401 /* try as-is (a number) */ 1402 return sldns_str2wire_int16_buf(str, rd, len); 1403 } 1404 return LDNS_WIREPARSE_ERR_OK; 1405 } 1406 1407 int sldns_str2wire_time_buf(const char* str, uint8_t* rd, size_t* len) 1408 { 1409 /* convert a time YYYYDDMMHHMMSS to wireformat */ 1410 struct tm tm; 1411 if(*len < 4) 1412 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1413 1414 /* Try to scan the time... */ 1415 memset(&tm, 0, sizeof(tm)); 1416 if (strlen(str) == 14 && sscanf(str, "%4d%2d%2d%2d%2d%2d", 1417 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, 1418 &tm.tm_min, &tm.tm_sec) == 6) { 1419 tm.tm_year -= 1900; 1420 tm.tm_mon--; 1421 /* Check values */ 1422 if (tm.tm_year < 70) 1423 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1424 if (tm.tm_mon < 0 || tm.tm_mon > 11) 1425 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1426 if (tm.tm_mday < 1 || tm.tm_mday > 31) 1427 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1428 if (tm.tm_hour < 0 || tm.tm_hour > 23) 1429 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1430 if (tm.tm_min < 0 || tm.tm_min > 59) 1431 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1432 if (tm.tm_sec < 0 || tm.tm_sec > 59) 1433 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1434 1435 sldns_write_uint32(rd, (uint32_t)sldns_mktime_from_utc(&tm)); 1436 } else { 1437 /* handle it as 32 bits timestamp */ 1438 char *end; 1439 uint32_t l = (uint32_t)strtol((char*)str, &end, 10); 1440 if(*end != 0) 1441 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TIME, 1442 end-(char*)str); 1443 sldns_write_uint32(rd, l); 1444 } 1445 *len = 4; 1446 return LDNS_WIREPARSE_ERR_OK; 1447 } 1448 1449 int sldns_str2wire_tsigtime_buf(const char* str, uint8_t* rd, size_t* len) 1450 { 1451 char* end; 1452 uint64_t t = (uint64_t)strtol((char*)str, &end, 10); 1453 uint16_t high; 1454 uint32_t low; 1455 if(*end != 0) 1456 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TIME, end-str); 1457 if(*len < 6) 1458 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1459 high = (uint16_t)(t>>32); 1460 low = (uint32_t)(t); 1461 sldns_write_uint16(rd, high); 1462 sldns_write_uint32(rd+2, low); 1463 *len = 6; 1464 return LDNS_WIREPARSE_ERR_OK; 1465 } 1466 1467 int sldns_str2wire_period_buf(const char* str, uint8_t* rd, size_t* len) 1468 { 1469 const char* end; 1470 uint32_t p = sldns_str2period(str, &end); 1471 if(*end != 0) 1472 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, end-str); 1473 if(*len < 4) 1474 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1475 sldns_write_uint32(rd, p); 1476 *len = 4; 1477 return LDNS_WIREPARSE_ERR_OK; 1478 } 1479 1480 /** read "<digits>[.<digits>][mM]" into mantissa exponent format for LOC type */ 1481 static int 1482 loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e) 1483 { 1484 uint32_t meters = 0, cm = 0, val; 1485 while (isblank((unsigned char)*my_str)) { 1486 my_str++; 1487 } 1488 meters = (uint32_t)strtol(my_str, &my_str, 10); 1489 if (*my_str == '.') { 1490 my_str++; 1491 cm = (uint32_t)strtol(my_str, &my_str, 10); 1492 } 1493 if (meters >= 1) { 1494 *e = 2; 1495 val = meters; 1496 } else { 1497 *e = 0; 1498 val = cm; 1499 } 1500 while(val >= 10) { 1501 (*e)++; 1502 val /= 10; 1503 } 1504 *m = (uint8_t)val; 1505 1506 if (*e > 9) 1507 return 0; 1508 if (*my_str == 'm' || *my_str == 'M') { 1509 my_str++; 1510 } 1511 *endstr = my_str; 1512 return 1; 1513 } 1514 1515 int sldns_str2wire_loc_buf(const char* str, uint8_t* rd, size_t* len) 1516 { 1517 uint32_t latitude = 0; 1518 uint32_t longitude = 0; 1519 uint32_t altitude = 0; 1520 1521 uint32_t equator = (uint32_t)1<<31; /* 2**31 */ 1522 1523 /* only support version 0 */ 1524 uint32_t h = 0; 1525 uint32_t m = 0; 1526 uint8_t size_b = 1, size_e = 2; 1527 uint8_t horiz_pre_b = 1, horiz_pre_e = 6; 1528 uint8_t vert_pre_b = 1, vert_pre_e = 3; 1529 1530 double s = 0.0; 1531 int northerness; 1532 int easterness; 1533 1534 char *my_str = (char *) str; 1535 1536 if (isdigit((unsigned char) *my_str)) { 1537 h = (uint32_t) strtol(my_str, &my_str, 10); 1538 } else { 1539 return LDNS_WIREPARSE_ERR_INVALID_STR; 1540 } 1541 1542 while (isblank((unsigned char) *my_str)) { 1543 my_str++; 1544 } 1545 1546 if (isdigit((unsigned char) *my_str)) { 1547 m = (uint32_t) strtol(my_str, &my_str, 10); 1548 } else if (*my_str == 'N' || *my_str == 'S') { 1549 goto north; 1550 } else { 1551 return LDNS_WIREPARSE_ERR_INVALID_STR; 1552 } 1553 1554 while (isblank((unsigned char) *my_str)) { 1555 my_str++; 1556 } 1557 1558 if (isdigit((unsigned char) *my_str)) { 1559 s = strtod(my_str, &my_str); 1560 } 1561 1562 /* skip blanks before northerness */ 1563 while (isblank((unsigned char) *my_str)) { 1564 my_str++; 1565 } 1566 1567 north: 1568 if (*my_str == 'N') { 1569 northerness = 1; 1570 } else if (*my_str == 'S') { 1571 northerness = 0; 1572 } else { 1573 return LDNS_WIREPARSE_ERR_INVALID_STR; 1574 } 1575 1576 my_str++; 1577 1578 /* store number */ 1579 s = 1000.0 * s; 1580 /* add a little to make floor in conversion a round */ 1581 s += 0.0005; 1582 latitude = (uint32_t) s; 1583 latitude += 1000 * 60 * m; 1584 latitude += 1000 * 60 * 60 * h; 1585 if (northerness) { 1586 latitude = equator + latitude; 1587 } else { 1588 latitude = equator - latitude; 1589 } 1590 while (isblank((unsigned char)*my_str)) { 1591 my_str++; 1592 } 1593 1594 if (isdigit((unsigned char) *my_str)) { 1595 h = (uint32_t) strtol(my_str, &my_str, 10); 1596 } else { 1597 return LDNS_WIREPARSE_ERR_INVALID_STR; 1598 } 1599 1600 while (isblank((unsigned char) *my_str)) { 1601 my_str++; 1602 } 1603 1604 if (isdigit((unsigned char) *my_str)) { 1605 m = (uint32_t) strtol(my_str, &my_str, 10); 1606 } else if (*my_str == 'E' || *my_str == 'W') { 1607 goto east; 1608 } else { 1609 return LDNS_WIREPARSE_ERR_INVALID_STR; 1610 } 1611 1612 while (isblank((unsigned char)*my_str)) { 1613 my_str++; 1614 } 1615 1616 if (isdigit((unsigned char) *my_str)) { 1617 s = strtod(my_str, &my_str); 1618 } 1619 1620 /* skip blanks before easterness */ 1621 while (isblank((unsigned char)*my_str)) { 1622 my_str++; 1623 } 1624 1625 east: 1626 if (*my_str == 'E') { 1627 easterness = 1; 1628 } else if (*my_str == 'W') { 1629 easterness = 0; 1630 } else { 1631 return LDNS_WIREPARSE_ERR_INVALID_STR; 1632 } 1633 1634 my_str++; 1635 1636 /* store number */ 1637 s *= 1000.0; 1638 /* add a little to make floor in conversion a round */ 1639 s += 0.0005; 1640 longitude = (uint32_t) s; 1641 longitude += 1000 * 60 * m; 1642 longitude += 1000 * 60 * 60 * h; 1643 1644 if (easterness) { 1645 longitude += equator; 1646 } else { 1647 longitude = equator - longitude; 1648 } 1649 1650 altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 + 1651 10000000.0 + 0.5); 1652 if (*my_str == 'm' || *my_str == 'M') { 1653 my_str++; 1654 } 1655 1656 if (strlen(my_str) > 0) { 1657 if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e)) 1658 return LDNS_WIREPARSE_ERR_INVALID_STR; 1659 } 1660 1661 if (strlen(my_str) > 0) { 1662 if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e)) 1663 return LDNS_WIREPARSE_ERR_INVALID_STR; 1664 } 1665 1666 if (strlen(my_str) > 0) { 1667 if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e)) 1668 return LDNS_WIREPARSE_ERR_INVALID_STR; 1669 } 1670 1671 if(*len < 16) 1672 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1673 rd[0] = 0; 1674 rd[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f); 1675 rd[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f); 1676 rd[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f); 1677 sldns_write_uint32(rd + 4, latitude); 1678 sldns_write_uint32(rd + 8, longitude); 1679 sldns_write_uint32(rd + 12, altitude); 1680 *len = 16; 1681 return LDNS_WIREPARSE_ERR_OK; 1682 } 1683 1684 static void 1685 ldns_tolower_str(char* s) 1686 { 1687 if(s) { 1688 while(*s) { 1689 *s = (char)tolower((unsigned char)*s); 1690 s++; 1691 } 1692 } 1693 } 1694 1695 int sldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len) 1696 { 1697 int rd_len = 1; 1698 int have_proto = 0; 1699 char token[50], proto_str[50]; 1700 sldns_buffer strbuf; 1701 sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 1702 proto_str[0]=0; 1703 1704 /* check we have one byte for proto */ 1705 if(*len < 1) 1706 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1707 1708 while(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) > 0) { 1709 ldns_tolower_str(token); 1710 if(!have_proto) { 1711 struct protoent *p = getprotobyname(token); 1712 have_proto = 1; 1713 if(p) rd[0] = (uint8_t)p->p_proto; 1714 else if(strcasecmp(token, "tcp")==0) rd[0]=6; 1715 else if(strcasecmp(token, "udp")==0) rd[0]=17; 1716 else rd[0] = (uint8_t)atoi(token); 1717 (void)strlcpy(proto_str, token, sizeof(proto_str)); 1718 } else { 1719 int serv_port; 1720 struct servent *serv = getservbyname(token, proto_str); 1721 if(serv) serv_port=(int)ntohs((uint16_t)serv->s_port); 1722 else if(strcasecmp(token, "domain")==0) serv_port=53; 1723 else { 1724 serv_port = atoi(token); 1725 if(serv_port == 0 && strcmp(token, "0") != 0) { 1726 #ifdef HAVE_ENDSERVENT 1727 endservent(); 1728 #endif 1729 #ifdef HAVE_ENDPROTOENT 1730 endprotoent(); 1731 #endif 1732 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, 1733 sldns_buffer_position(&strbuf)); 1734 } 1735 if(serv_port < 0 || serv_port > 65535) { 1736 #ifdef HAVE_ENDSERVENT 1737 endservent(); 1738 #endif 1739 #ifdef HAVE_ENDPROTOENT 1740 endprotoent(); 1741 #endif 1742 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, 1743 sldns_buffer_position(&strbuf)); 1744 } 1745 } 1746 if(rd_len < 1+serv_port/8+1) { 1747 /* bitmap is larger, init new bytes at 0 */ 1748 if(*len < 1+(size_t)serv_port/8+1) { 1749 #ifdef HAVE_ENDSERVENT 1750 endservent(); 1751 #endif 1752 #ifdef HAVE_ENDPROTOENT 1753 endprotoent(); 1754 #endif 1755 return RET_ERR( 1756 LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1757 sldns_buffer_position(&strbuf)); 1758 } 1759 memset(rd+rd_len, 0, 1+(size_t)serv_port/8+1-rd_len); 1760 rd_len = 1+serv_port/8+1; 1761 } 1762 rd[1+ serv_port/8] |= (1 << (7 - serv_port % 8)); 1763 } 1764 } 1765 *len = (size_t)rd_len; 1766 1767 #ifdef HAVE_ENDSERVENT 1768 endservent(); 1769 #endif 1770 #ifdef HAVE_ENDPROTOENT 1771 endprotoent(); 1772 #endif 1773 return LDNS_WIREPARSE_ERR_OK; 1774 } 1775 1776 int sldns_str2wire_nsap_buf(const char* str, uint8_t* rd, size_t* len) 1777 { 1778 const char* s = str; 1779 size_t slen; 1780 size_t dlen = 0; /* number of hexdigits parsed */ 1781 1782 /* just a hex string with optional dots? */ 1783 if (s[0] != '0' || s[1] != 'x') 1784 return LDNS_WIREPARSE_ERR_INVALID_STR; 1785 s += 2; 1786 slen = strlen(s); 1787 if(slen > LDNS_MAX_RDFLEN*2) 1788 return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; 1789 while(*s) { 1790 if(isspace((unsigned char)*s) || *s == '.') { 1791 s++; 1792 continue; 1793 } 1794 if(!isxdigit((unsigned char)*s)) 1795 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1796 if(*len < dlen/2 + 1) 1797 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1798 s-str); 1799 if((dlen&1)==0) 1800 rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; 1801 else rd[dlen/2] += sldns_hexdigit_to_int(*s++); 1802 dlen++; 1803 } 1804 if((dlen&1)!=0) 1805 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1806 *len = dlen/2; 1807 return LDNS_WIREPARSE_ERR_OK; 1808 } 1809 1810 int sldns_str2wire_atma_buf(const char* str, uint8_t* rd, size_t* len) 1811 { 1812 const char* s = str; 1813 size_t slen = strlen(str); 1814 size_t dlen = 0; /* number of hexdigits parsed */ 1815 1816 /* just a hex string with optional dots? */ 1817 /* notimpl e.164 format */ 1818 if(slen > LDNS_MAX_RDFLEN*2) 1819 return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; 1820 while(*s) { 1821 if(isspace((unsigned char)*s) || *s == '.') { 1822 s++; 1823 continue; 1824 } 1825 if(!isxdigit((unsigned char)*s)) 1826 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1827 if(*len < dlen/2 + 1) 1828 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1829 s-str); 1830 if((dlen&1)==0) 1831 rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; 1832 else rd[dlen/2] += sldns_hexdigit_to_int(*s++); 1833 dlen++; 1834 } 1835 if((dlen&1)!=0) 1836 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1837 *len = dlen/2; 1838 return LDNS_WIREPARSE_ERR_OK; 1839 } 1840 1841 int sldns_str2wire_ipseckey_buf(const char* str, uint8_t* rd, size_t* len) 1842 { 1843 size_t gwlen = 0, keylen = 0; 1844 int s; 1845 uint8_t gwtype; 1846 char token[512]; 1847 sldns_buffer strbuf; 1848 sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 1849 1850 if(*len < 3) 1851 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1852 /* precedence */ 1853 if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 1854 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1855 sldns_buffer_position(&strbuf)); 1856 rd[0] = (uint8_t)atoi(token); 1857 /* gateway_type */ 1858 if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 1859 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1860 sldns_buffer_position(&strbuf)); 1861 rd[1] = (uint8_t)atoi(token); 1862 gwtype = rd[1]; 1863 /* algorithm */ 1864 if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 1865 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1866 sldns_buffer_position(&strbuf)); 1867 rd[2] = (uint8_t)atoi(token); 1868 1869 /* gateway */ 1870 if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 1871 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1872 sldns_buffer_position(&strbuf)); 1873 if(gwtype == 0) { 1874 /* NOGATEWAY */ 1875 if(strcmp(token, ".") != 0) 1876 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1877 sldns_buffer_position(&strbuf)); 1878 gwlen = 0; 1879 } else if(gwtype == 1) { 1880 /* IP4 */ 1881 gwlen = *len - 3; 1882 s = sldns_str2wire_a_buf(token, rd+3, &gwlen); 1883 if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 1884 } else if(gwtype == 2) { 1885 /* IP6 */ 1886 gwlen = *len - 3; 1887 s = sldns_str2wire_aaaa_buf(token, rd+3, &gwlen); 1888 if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 1889 } else if(gwtype == 3) { 1890 /* DNAME */ 1891 gwlen = *len - 3; 1892 s = sldns_str2wire_dname_buf(token, rd+3, &gwlen); 1893 if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 1894 } else { 1895 /* unknown gateway type */ 1896 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1897 sldns_buffer_position(&strbuf)); 1898 } 1899 /* double check for size */ 1900 if(*len < 3 + gwlen) 1901 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1902 sldns_buffer_position(&strbuf)); 1903 1904 /* publickey in remainder of strbuf */ 1905 keylen = *len - 3 - gwlen; 1906 s = sldns_str2wire_b64_buf((const char*)sldns_buffer_current(&strbuf), 1907 rd+3+gwlen, &keylen); 1908 if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 1909 1910 *len = 3 + gwlen + keylen; 1911 return LDNS_WIREPARSE_ERR_OK; 1912 } 1913 1914 int sldns_str2wire_nsec3_salt_buf(const char* str, uint8_t* rd, size_t* len) 1915 { 1916 int i, salt_length_str = (int)strlen(str); 1917 if (salt_length_str == 1 && str[0] == '-') { 1918 salt_length_str = 0; 1919 } else if (salt_length_str % 2 != 0) { 1920 return LDNS_WIREPARSE_ERR_SYNTAX_HEX; 1921 } 1922 if (salt_length_str > 512) 1923 return LDNS_WIREPARSE_ERR_SYNTAX_HEX; 1924 if(*len < 1+(size_t)salt_length_str / 2) 1925 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1926 rd[0] = (uint8_t) (salt_length_str / 2); 1927 for (i = 0; i < salt_length_str; i += 2) { 1928 if (isxdigit((unsigned char)str[i]) && 1929 isxdigit((unsigned char)str[i+1])) { 1930 rd[1+i/2] = (uint8_t)(sldns_hexdigit_to_int(str[i])*16 1931 + sldns_hexdigit_to_int(str[i+1])); 1932 } else { 1933 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, i); 1934 } 1935 } 1936 *len = 1 + (size_t)rd[0]; 1937 return LDNS_WIREPARSE_ERR_OK; 1938 } 1939 1940 int sldns_str2wire_ilnp64_buf(const char* str, uint8_t* rd, size_t* len) 1941 { 1942 unsigned int a, b, c, d; 1943 uint16_t shorts[4]; 1944 int l; 1945 if(*len < sizeof(shorts)) 1946 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1947 1948 if (sscanf(str, "%4x:%4x:%4x:%4x%n", &a, &b, &c, &d, &l) != 4 || 1949 l != (int)strlen(str) || /* more data to read */ 1950 strpbrk(str, "+-") /* signed hexes */ 1951 ) 1952 return LDNS_WIREPARSE_ERR_SYNTAX_ILNP64; 1953 shorts[0] = htons(a); 1954 shorts[1] = htons(b); 1955 shorts[2] = htons(c); 1956 shorts[3] = htons(d); 1957 memmove(rd, &shorts, sizeof(shorts)); 1958 *len = sizeof(shorts); 1959 return LDNS_WIREPARSE_ERR_OK; 1960 } 1961 1962 int sldns_str2wire_eui48_buf(const char* str, uint8_t* rd, size_t* len) 1963 { 1964 unsigned int a, b, c, d, e, f; 1965 int l; 1966 1967 if(*len < 6) 1968 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1969 if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x%n", 1970 &a, &b, &c, &d, &e, &f, &l) != 6 || 1971 l != (int)strlen(str)) 1972 return LDNS_WIREPARSE_ERR_SYNTAX_EUI48; 1973 rd[0] = a; 1974 rd[1] = b; 1975 rd[2] = c; 1976 rd[3] = d; 1977 rd[4] = e; 1978 rd[5] = f; 1979 *len = 6; 1980 return LDNS_WIREPARSE_ERR_OK; 1981 } 1982 1983 int sldns_str2wire_eui64_buf(const char* str, uint8_t* rd, size_t* len) 1984 { 1985 unsigned int a, b, c, d, e, f, g, h; 1986 int l; 1987 1988 if(*len < 8) 1989 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1990 if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x%n", 1991 &a, &b, &c, &d, &e, &f, &g, &h, &l) != 8 || 1992 l != (int)strlen(str)) 1993 return LDNS_WIREPARSE_ERR_SYNTAX_EUI64; 1994 rd[0] = a; 1995 rd[1] = b; 1996 rd[2] = c; 1997 rd[3] = d; 1998 rd[4] = e; 1999 rd[5] = f; 2000 rd[6] = g; 2001 rd[7] = h; 2002 *len = 8; 2003 return LDNS_WIREPARSE_ERR_OK; 2004 } 2005 2006 int sldns_str2wire_tag_buf(const char* str, uint8_t* rd, size_t* len) 2007 { 2008 size_t slen = strlen(str); 2009 const char* ptr; 2010 2011 if (slen > 255) 2012 return LDNS_WIREPARSE_ERR_SYNTAX_TAG; 2013 if(*len < slen+1) 2014 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2015 for (ptr = str; *ptr; ptr++) { 2016 if(!isalnum((unsigned char)*ptr)) 2017 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TAG, ptr-str); 2018 } 2019 rd[0] = (uint8_t)slen; 2020 memmove(rd+1, str, slen); 2021 *len = slen+1; 2022 return LDNS_WIREPARSE_ERR_OK; 2023 } 2024 2025 int sldns_str2wire_long_str_buf(const char* str, uint8_t* rd, size_t* len) 2026 { 2027 uint8_t ch = 0; 2028 const char* pstr = str; 2029 size_t length = 0; 2030 2031 /* Fill data with parsed bytes */ 2032 while (sldns_parse_char(&ch, &pstr)) { 2033 if(*len < length+1) 2034 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2035 rd[length++] = ch; 2036 } 2037 if(!pstr) 2038 return LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE; 2039 *len = length; 2040 return LDNS_WIREPARSE_ERR_OK; 2041 } 2042 2043 int sldns_str2wire_hip_buf(const char* str, uint8_t* rd, size_t* len) 2044 { 2045 char* s, *end; 2046 int e; 2047 size_t hitlen, pklen = 0; 2048 /* presentation format: 2049 * pk-algo HIThex pubkeybase64 2050 * wireformat: 2051 * hitlen[1byte] pkalgo[1byte] pubkeylen[2byte] [hit] [pubkey] */ 2052 if(*len < 4) 2053 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2054 2055 /* read PK algorithm */ 2056 rd[1] = (uint8_t)strtol((char*)str, &s, 10); 2057 if(*s != ' ') 2058 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, s-(char*)str); 2059 s++; 2060 while(*s == ' ') 2061 s++; 2062 2063 /* read HIT hex tag */ 2064 /* zero terminate the tag (replace later) */ 2065 end = strchr(s, ' '); 2066 if(!end) return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, s-(char*)str); 2067 *end = 0; 2068 hitlen = *len - 4; 2069 if((e = sldns_str2wire_hex_buf(s, rd+4, &hitlen)) != 0) { 2070 *end = ' '; 2071 return RET_ERR_SHIFT(e, s-(char*)str); 2072 } 2073 if(hitlen > 255) { 2074 *end = ' '; 2075 return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, s-(char*)str+255*2); 2076 } 2077 rd[0] = (uint8_t)hitlen; 2078 *end = ' '; 2079 s = end+1; 2080 2081 /* read pubkey base64 sequence */ 2082 pklen = *len - 4 - hitlen; 2083 if((e = sldns_str2wire_b64_buf(s, rd+4+hitlen, &pklen)) != 0) 2084 return RET_ERR_SHIFT(e, s-(char*)str); 2085 if(pklen > 65535) 2086 return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, s-(char*)str+65535); 2087 sldns_write_uint16(rd+2, (uint16_t)pklen); 2088 2089 *len = 4 + hitlen + pklen; 2090 return LDNS_WIREPARSE_ERR_OK; 2091 } 2092 2093 int sldns_str2wire_int16_data_buf(const char* str, uint8_t* rd, size_t* len) 2094 { 2095 char* s; 2096 int n; 2097 n = strtol(str, &s, 10); 2098 if(*len < ((size_t)n)+2) 2099 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2100 if(n > 65535) 2101 return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; 2102 2103 if(n == 0) { 2104 sldns_write_uint16(rd, 0); 2105 *len = 2; 2106 return LDNS_WIREPARSE_ERR_OK; 2107 } 2108 if(*s != ' ') 2109 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, s-(char*)str); 2110 s++; 2111 while(*s == ' ') 2112 s++; 2113 2114 n = sldns_b64_pton(s, rd+2, (*len)-2); 2115 if(n < 0) 2116 return LDNS_WIREPARSE_ERR_SYNTAX_B64; 2117 sldns_write_uint16(rd, (uint16_t)n); 2118 *len = ((size_t)n)+2; 2119 return LDNS_WIREPARSE_ERR_OK; 2120 } 2121