netinfo.c (16970B)
1 /* netinfo.c -- generated by Trunnel v1.5.3. 2 * https://gitweb.torproject.org/trunnel.git 3 * You probably shouldn't edit this file. 4 */ 5 #include <stdlib.h> 6 #include "trunnel-impl.h" 7 8 #include "netinfo.h" 9 10 #define TRUNNEL_SET_ERROR_CODE(obj) \ 11 do { \ 12 (obj)->trunnel_error_code_ = 1; \ 13 } while (0) 14 15 #if defined(__COVERITY__) || defined(__clang_analyzer__) 16 /* If we're running a static analysis tool, we don't want it to complain 17 * that some of our remaining-bytes checks are dead-code. */ 18 int netinfo_deadcode_dummy__ = 0; 19 #define OR_DEADCODE_DUMMY || netinfo_deadcode_dummy__ 20 #else 21 #define OR_DEADCODE_DUMMY 22 #endif 23 24 #define CHECK_REMAINING(nbytes, label) \ 25 do { \ 26 if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \ 27 goto label; \ 28 } \ 29 } while (0) 30 31 netinfo_addr_t * 32 netinfo_addr_new(void) 33 { 34 netinfo_addr_t *val = trunnel_calloc(1, sizeof(netinfo_addr_t)); 35 if (NULL == val) 36 return NULL; 37 return val; 38 } 39 40 /** Release all storage held inside 'obj', but do not free 'obj'. 41 */ 42 static void 43 netinfo_addr_clear(netinfo_addr_t *obj) 44 { 45 (void) obj; 46 } 47 48 void 49 netinfo_addr_free(netinfo_addr_t *obj) 50 { 51 if (obj == NULL) 52 return; 53 netinfo_addr_clear(obj); 54 trunnel_memwipe(obj, sizeof(netinfo_addr_t)); 55 trunnel_free_(obj); 56 } 57 58 uint8_t 59 netinfo_addr_get_addr_type(const netinfo_addr_t *inp) 60 { 61 return inp->addr_type; 62 } 63 int 64 netinfo_addr_set_addr_type(netinfo_addr_t *inp, uint8_t val) 65 { 66 inp->addr_type = val; 67 return 0; 68 } 69 uint8_t 70 netinfo_addr_get_len(const netinfo_addr_t *inp) 71 { 72 return inp->len; 73 } 74 int 75 netinfo_addr_set_len(netinfo_addr_t *inp, uint8_t val) 76 { 77 inp->len = val; 78 return 0; 79 } 80 uint32_t 81 netinfo_addr_get_addr_ipv4(const netinfo_addr_t *inp) 82 { 83 return inp->addr_ipv4; 84 } 85 int 86 netinfo_addr_set_addr_ipv4(netinfo_addr_t *inp, uint32_t val) 87 { 88 inp->addr_ipv4 = val; 89 return 0; 90 } 91 size_t 92 netinfo_addr_getlen_addr_ipv6(const netinfo_addr_t *inp) 93 { 94 (void)inp; return 16; 95 } 96 97 uint8_t 98 netinfo_addr_get_addr_ipv6(netinfo_addr_t *inp, size_t idx) 99 { 100 trunnel_assert(idx < 16); 101 return inp->addr_ipv6[idx]; 102 } 103 104 uint8_t 105 netinfo_addr_getconst_addr_ipv6(const netinfo_addr_t *inp, size_t idx) 106 { 107 return netinfo_addr_get_addr_ipv6((netinfo_addr_t*)inp, idx); 108 } 109 int 110 netinfo_addr_set_addr_ipv6(netinfo_addr_t *inp, size_t idx, uint8_t elt) 111 { 112 trunnel_assert(idx < 16); 113 inp->addr_ipv6[idx] = elt; 114 return 0; 115 } 116 117 uint8_t * 118 netinfo_addr_getarray_addr_ipv6(netinfo_addr_t *inp) 119 { 120 return inp->addr_ipv6; 121 } 122 const uint8_t * 123 netinfo_addr_getconstarray_addr_ipv6(const netinfo_addr_t *inp) 124 { 125 return (const uint8_t *)netinfo_addr_getarray_addr_ipv6((netinfo_addr_t*)inp); 126 } 127 const char * 128 netinfo_addr_check(const netinfo_addr_t *obj) 129 { 130 if (obj == NULL) 131 return "Object was NULL"; 132 if (obj->trunnel_error_code_) 133 return "A set function failed on this object"; 134 switch (obj->addr_type) { 135 136 case NETINFO_ADDR_TYPE_IPV4: 137 break; 138 139 case NETINFO_ADDR_TYPE_IPV6: 140 break; 141 142 default: 143 break; 144 } 145 return NULL; 146 } 147 148 ssize_t 149 netinfo_addr_encoded_len(const netinfo_addr_t *obj) 150 { 151 ssize_t result = 0; 152 153 if (NULL != netinfo_addr_check(obj)) 154 return -1; 155 156 157 /* Length of u8 addr_type */ 158 result += 1; 159 160 /* Length of u8 len */ 161 result += 1; 162 switch (obj->addr_type) { 163 164 case NETINFO_ADDR_TYPE_IPV4: 165 166 /* Length of u32 addr_ipv4 */ 167 result += 4; 168 break; 169 170 case NETINFO_ADDR_TYPE_IPV6: 171 172 /* Length of u8 addr_ipv6[16] */ 173 result += 16; 174 break; 175 176 default: 177 break; 178 } 179 return result; 180 } 181 int 182 netinfo_addr_clear_errors(netinfo_addr_t *obj) 183 { 184 int r = obj->trunnel_error_code_; 185 obj->trunnel_error_code_ = 0; 186 return r; 187 } 188 ssize_t 189 netinfo_addr_encode(uint8_t *output, const size_t avail, const netinfo_addr_t *obj) 190 { 191 ssize_t result = 0; 192 size_t written = 0; 193 uint8_t *ptr = output; 194 const char *msg; 195 #ifdef TRUNNEL_CHECK_ENCODED_LEN 196 const ssize_t encoded_len = netinfo_addr_encoded_len(obj); 197 #endif 198 199 uint8_t *backptr_len = NULL; 200 201 if (NULL != (msg = netinfo_addr_check(obj))) 202 goto check_failed; 203 204 #ifdef TRUNNEL_CHECK_ENCODED_LEN 205 trunnel_assert(encoded_len >= 0); 206 #endif 207 208 /* Encode u8 addr_type */ 209 trunnel_assert(written <= avail); 210 if (avail - written < 1) 211 goto truncated; 212 trunnel_set_uint8(ptr, (obj->addr_type)); 213 written += 1; ptr += 1; 214 215 /* Encode u8 len */ 216 backptr_len = ptr; 217 trunnel_assert(written <= avail); 218 if (avail - written < 1) 219 goto truncated; 220 trunnel_set_uint8(ptr, (obj->len)); 221 written += 1; ptr += 1; 222 { 223 size_t written_before_union = written; 224 225 /* Encode union addr[addr_type] */ 226 trunnel_assert(written <= avail); 227 switch (obj->addr_type) { 228 229 case NETINFO_ADDR_TYPE_IPV4: 230 231 /* Encode u32 addr_ipv4 */ 232 trunnel_assert(written <= avail); 233 if (avail - written < 4) 234 goto truncated; 235 trunnel_set_uint32(ptr, trunnel_htonl(obj->addr_ipv4)); 236 written += 4; ptr += 4; 237 break; 238 239 case NETINFO_ADDR_TYPE_IPV6: 240 241 /* Encode u8 addr_ipv6[16] */ 242 trunnel_assert(written <= avail); 243 if (avail - written < 16) 244 goto truncated; 245 memcpy(ptr, obj->addr_ipv6, 16); 246 written += 16; ptr += 16; 247 break; 248 249 default: 250 break; 251 } 252 /* Write the length field back to len */ 253 trunnel_assert(written >= written_before_union); 254 #if UINT8_MAX < SIZE_MAX 255 if (written - written_before_union > UINT8_MAX) 256 goto check_failed; 257 #endif 258 trunnel_set_uint8(backptr_len, (written - written_before_union)); 259 } 260 261 262 trunnel_assert(ptr == output + written); 263 #ifdef TRUNNEL_CHECK_ENCODED_LEN 264 { 265 trunnel_assert(encoded_len >= 0); 266 trunnel_assert((size_t)encoded_len == written); 267 } 268 269 #endif 270 271 return written; 272 273 truncated: 274 result = -2; 275 goto fail; 276 check_failed: 277 (void)msg; 278 result = -1; 279 goto fail; 280 fail: 281 trunnel_assert(result < 0); 282 return result; 283 } 284 285 /** As netinfo_addr_parse(), but do not allocate the output object. 286 */ 287 static ssize_t 288 netinfo_addr_parse_into(netinfo_addr_t *obj, const uint8_t *input, const size_t len_in) 289 { 290 const uint8_t *ptr = input; 291 size_t remaining = len_in; 292 ssize_t result = 0; 293 (void)result; 294 295 /* Parse u8 addr_type */ 296 CHECK_REMAINING(1, truncated); 297 obj->addr_type = (trunnel_get_uint8(ptr)); 298 remaining -= 1; ptr += 1; 299 300 /* Parse u8 len */ 301 CHECK_REMAINING(1, truncated); 302 obj->len = (trunnel_get_uint8(ptr)); 303 remaining -= 1; ptr += 1; 304 { 305 size_t remaining_after; 306 CHECK_REMAINING(obj->len, truncated); 307 remaining_after = remaining - obj->len; 308 remaining = obj->len; 309 310 /* Parse union addr[addr_type] */ 311 switch (obj->addr_type) { 312 313 case NETINFO_ADDR_TYPE_IPV4: 314 315 /* Parse u32 addr_ipv4 */ 316 CHECK_REMAINING(4, fail); 317 obj->addr_ipv4 = trunnel_ntohl(trunnel_get_uint32(ptr)); 318 remaining -= 4; ptr += 4; 319 break; 320 321 case NETINFO_ADDR_TYPE_IPV6: 322 323 /* Parse u8 addr_ipv6[16] */ 324 CHECK_REMAINING(16, fail); 325 memcpy(obj->addr_ipv6, ptr, 16); 326 remaining -= 16; ptr += 16; 327 break; 328 329 default: 330 /* Skip to end of union */ 331 ptr += remaining; remaining = 0; 332 break; 333 } 334 if (remaining != 0) 335 goto fail; 336 remaining = remaining_after; 337 } 338 trunnel_assert(ptr + remaining == input + len_in); 339 return len_in - remaining; 340 341 truncated: 342 return -2; 343 fail: 344 result = -1; 345 return result; 346 } 347 348 ssize_t 349 netinfo_addr_parse(netinfo_addr_t **output, const uint8_t *input, const size_t len_in) 350 { 351 ssize_t result; 352 *output = netinfo_addr_new(); 353 if (NULL == *output) 354 return -1; 355 result = netinfo_addr_parse_into(*output, input, len_in); 356 if (result < 0) { 357 netinfo_addr_free(*output); 358 *output = NULL; 359 } 360 return result; 361 } 362 netinfo_cell_t * 363 netinfo_cell_new(void) 364 { 365 netinfo_cell_t *val = trunnel_calloc(1, sizeof(netinfo_cell_t)); 366 if (NULL == val) 367 return NULL; 368 return val; 369 } 370 371 /** Release all storage held inside 'obj', but do not free 'obj'. 372 */ 373 static void 374 netinfo_cell_clear(netinfo_cell_t *obj) 375 { 376 (void) obj; 377 netinfo_addr_free(obj->other_addr); 378 obj->other_addr = NULL; 379 { 380 381 unsigned idx; 382 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->my_addrs); ++idx) { 383 netinfo_addr_free(TRUNNEL_DYNARRAY_GET(&obj->my_addrs, idx)); 384 } 385 } 386 TRUNNEL_DYNARRAY_WIPE(&obj->my_addrs); 387 TRUNNEL_DYNARRAY_CLEAR(&obj->my_addrs); 388 } 389 390 void 391 netinfo_cell_free(netinfo_cell_t *obj) 392 { 393 if (obj == NULL) 394 return; 395 netinfo_cell_clear(obj); 396 trunnel_memwipe(obj, sizeof(netinfo_cell_t)); 397 trunnel_free_(obj); 398 } 399 400 uint32_t 401 netinfo_cell_get_timestamp(const netinfo_cell_t *inp) 402 { 403 return inp->timestamp; 404 } 405 int 406 netinfo_cell_set_timestamp(netinfo_cell_t *inp, uint32_t val) 407 { 408 inp->timestamp = val; 409 return 0; 410 } 411 struct netinfo_addr_st * 412 netinfo_cell_get_other_addr(netinfo_cell_t *inp) 413 { 414 return inp->other_addr; 415 } 416 const struct netinfo_addr_st * 417 netinfo_cell_getconst_other_addr(const netinfo_cell_t *inp) 418 { 419 return netinfo_cell_get_other_addr((netinfo_cell_t*) inp); 420 } 421 int 422 netinfo_cell_set_other_addr(netinfo_cell_t *inp, struct netinfo_addr_st *val) 423 { 424 if (inp->other_addr && inp->other_addr != val) 425 netinfo_addr_free(inp->other_addr); 426 return netinfo_cell_set0_other_addr(inp, val); 427 } 428 int 429 netinfo_cell_set0_other_addr(netinfo_cell_t *inp, struct netinfo_addr_st *val) 430 { 431 inp->other_addr = val; 432 return 0; 433 } 434 uint8_t 435 netinfo_cell_get_n_my_addrs(const netinfo_cell_t *inp) 436 { 437 return inp->n_my_addrs; 438 } 439 int 440 netinfo_cell_set_n_my_addrs(netinfo_cell_t *inp, uint8_t val) 441 { 442 inp->n_my_addrs = val; 443 return 0; 444 } 445 size_t 446 netinfo_cell_getlen_my_addrs(const netinfo_cell_t *inp) 447 { 448 return TRUNNEL_DYNARRAY_LEN(&inp->my_addrs); 449 } 450 451 struct netinfo_addr_st * 452 netinfo_cell_get_my_addrs(netinfo_cell_t *inp, size_t idx) 453 { 454 return TRUNNEL_DYNARRAY_GET(&inp->my_addrs, idx); 455 } 456 457 const struct netinfo_addr_st * 458 netinfo_cell_getconst_my_addrs(const netinfo_cell_t *inp, size_t idx) 459 { 460 return netinfo_cell_get_my_addrs((netinfo_cell_t*)inp, idx); 461 } 462 int 463 netinfo_cell_set_my_addrs(netinfo_cell_t *inp, size_t idx, struct netinfo_addr_st * elt) 464 { 465 netinfo_addr_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->my_addrs, idx); 466 if (oldval && oldval != elt) 467 netinfo_addr_free(oldval); 468 return netinfo_cell_set0_my_addrs(inp, idx, elt); 469 } 470 int 471 netinfo_cell_set0_my_addrs(netinfo_cell_t *inp, size_t idx, struct netinfo_addr_st * elt) 472 { 473 TRUNNEL_DYNARRAY_SET(&inp->my_addrs, idx, elt); 474 return 0; 475 } 476 int 477 netinfo_cell_add_my_addrs(netinfo_cell_t *inp, struct netinfo_addr_st * elt) 478 { 479 #if SIZE_MAX >= UINT8_MAX 480 if (inp->my_addrs.n_ == UINT8_MAX) 481 goto trunnel_alloc_failed; 482 #endif 483 TRUNNEL_DYNARRAY_ADD(struct netinfo_addr_st *, &inp->my_addrs, elt, {}); 484 return 0; 485 trunnel_alloc_failed: 486 TRUNNEL_SET_ERROR_CODE(inp); 487 return -1; 488 } 489 490 struct netinfo_addr_st * * 491 netinfo_cell_getarray_my_addrs(netinfo_cell_t *inp) 492 { 493 return inp->my_addrs.elts_; 494 } 495 const struct netinfo_addr_st * const * 496 netinfo_cell_getconstarray_my_addrs(const netinfo_cell_t *inp) 497 { 498 return (const struct netinfo_addr_st * const *)netinfo_cell_getarray_my_addrs((netinfo_cell_t*)inp); 499 } 500 int 501 netinfo_cell_setlen_my_addrs(netinfo_cell_t *inp, size_t newlen) 502 { 503 struct netinfo_addr_st * *newptr; 504 #if UINT8_MAX < SIZE_MAX 505 if (newlen > UINT8_MAX) 506 goto trunnel_alloc_failed; 507 #endif 508 newptr = trunnel_dynarray_setlen(&inp->my_addrs.allocated_, 509 &inp->my_addrs.n_, inp->my_addrs.elts_, newlen, 510 sizeof(inp->my_addrs.elts_[0]), (trunnel_free_fn_t) netinfo_addr_free, 511 &inp->trunnel_error_code_); 512 if (newlen != 0 && newptr == NULL) 513 goto trunnel_alloc_failed; 514 inp->my_addrs.elts_ = newptr; 515 return 0; 516 trunnel_alloc_failed: 517 TRUNNEL_SET_ERROR_CODE(inp); 518 return -1; 519 } 520 const char * 521 netinfo_cell_check(const netinfo_cell_t *obj) 522 { 523 if (obj == NULL) 524 return "Object was NULL"; 525 if (obj->trunnel_error_code_) 526 return "A set function failed on this object"; 527 { 528 const char *msg; 529 if (NULL != (msg = netinfo_addr_check(obj->other_addr))) 530 return msg; 531 } 532 { 533 const char *msg; 534 535 unsigned idx; 536 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->my_addrs); ++idx) { 537 if (NULL != (msg = netinfo_addr_check(TRUNNEL_DYNARRAY_GET(&obj->my_addrs, idx)))) 538 return msg; 539 } 540 } 541 if (TRUNNEL_DYNARRAY_LEN(&obj->my_addrs) != obj->n_my_addrs) 542 return "Length mismatch for my_addrs"; 543 return NULL; 544 } 545 546 ssize_t 547 netinfo_cell_encoded_len(const netinfo_cell_t *obj) 548 { 549 ssize_t result = 0; 550 551 if (NULL != netinfo_cell_check(obj)) 552 return -1; 553 554 555 /* Length of u32 timestamp */ 556 result += 4; 557 558 /* Length of struct netinfo_addr other_addr */ 559 result += netinfo_addr_encoded_len(obj->other_addr); 560 561 /* Length of u8 n_my_addrs */ 562 result += 1; 563 564 /* Length of struct netinfo_addr my_addrs[n_my_addrs] */ 565 { 566 567 unsigned idx; 568 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->my_addrs); ++idx) { 569 result += netinfo_addr_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->my_addrs, idx)); 570 } 571 } 572 return result; 573 } 574 int 575 netinfo_cell_clear_errors(netinfo_cell_t *obj) 576 { 577 int r = obj->trunnel_error_code_; 578 obj->trunnel_error_code_ = 0; 579 return r; 580 } 581 ssize_t 582 netinfo_cell_encode(uint8_t *output, const size_t avail, const netinfo_cell_t *obj) 583 { 584 ssize_t result = 0; 585 size_t written = 0; 586 uint8_t *ptr = output; 587 const char *msg; 588 #ifdef TRUNNEL_CHECK_ENCODED_LEN 589 const ssize_t encoded_len = netinfo_cell_encoded_len(obj); 590 #endif 591 592 if (NULL != (msg = netinfo_cell_check(obj))) 593 goto check_failed; 594 595 #ifdef TRUNNEL_CHECK_ENCODED_LEN 596 trunnel_assert(encoded_len >= 0); 597 #endif 598 599 /* Encode u32 timestamp */ 600 trunnel_assert(written <= avail); 601 if (avail - written < 4) 602 goto truncated; 603 trunnel_set_uint32(ptr, trunnel_htonl(obj->timestamp)); 604 written += 4; ptr += 4; 605 606 /* Encode struct netinfo_addr other_addr */ 607 trunnel_assert(written <= avail); 608 result = netinfo_addr_encode(ptr, avail - written, obj->other_addr); 609 if (result < 0) 610 goto fail; /* XXXXXXX !*/ 611 written += result; ptr += result; 612 613 /* Encode u8 n_my_addrs */ 614 trunnel_assert(written <= avail); 615 if (avail - written < 1) 616 goto truncated; 617 trunnel_set_uint8(ptr, (obj->n_my_addrs)); 618 written += 1; ptr += 1; 619 620 /* Encode struct netinfo_addr my_addrs[n_my_addrs] */ 621 { 622 623 unsigned idx; 624 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->my_addrs); ++idx) { 625 trunnel_assert(written <= avail); 626 result = netinfo_addr_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->my_addrs, idx)); 627 if (result < 0) 628 goto fail; /* XXXXXXX !*/ 629 written += result; ptr += result; 630 } 631 } 632 633 634 trunnel_assert(ptr == output + written); 635 #ifdef TRUNNEL_CHECK_ENCODED_LEN 636 { 637 trunnel_assert(encoded_len >= 0); 638 trunnel_assert((size_t)encoded_len == written); 639 } 640 641 #endif 642 643 return written; 644 645 truncated: 646 result = -2; 647 goto fail; 648 check_failed: 649 (void)msg; 650 result = -1; 651 goto fail; 652 fail: 653 trunnel_assert(result < 0); 654 return result; 655 } 656 657 /** As netinfo_cell_parse(), but do not allocate the output object. 658 */ 659 static ssize_t 660 netinfo_cell_parse_into(netinfo_cell_t *obj, const uint8_t *input, const size_t len_in) 661 { 662 const uint8_t *ptr = input; 663 size_t remaining = len_in; 664 ssize_t result = 0; 665 (void)result; 666 667 /* Parse u32 timestamp */ 668 CHECK_REMAINING(4, truncated); 669 obj->timestamp = trunnel_ntohl(trunnel_get_uint32(ptr)); 670 remaining -= 4; ptr += 4; 671 672 /* Parse struct netinfo_addr other_addr */ 673 result = netinfo_addr_parse(&obj->other_addr, ptr, remaining); 674 if (result < 0) 675 goto relay_fail; 676 trunnel_assert((size_t)result <= remaining); 677 remaining -= result; ptr += result; 678 679 /* Parse u8 n_my_addrs */ 680 CHECK_REMAINING(1, truncated); 681 obj->n_my_addrs = (trunnel_get_uint8(ptr)); 682 remaining -= 1; ptr += 1; 683 684 /* Parse struct netinfo_addr my_addrs[n_my_addrs] */ 685 TRUNNEL_DYNARRAY_EXPAND(netinfo_addr_t *, &obj->my_addrs, obj->n_my_addrs, {}); 686 { 687 netinfo_addr_t * elt; 688 unsigned idx; 689 for (idx = 0; idx < obj->n_my_addrs; ++idx) { 690 result = netinfo_addr_parse(&elt, ptr, remaining); 691 if (result < 0) 692 goto relay_fail; 693 trunnel_assert((size_t)result <= remaining); 694 remaining -= result; ptr += result; 695 TRUNNEL_DYNARRAY_ADD(netinfo_addr_t *, &obj->my_addrs, elt, {netinfo_addr_free(elt);}); 696 } 697 } 698 trunnel_assert(ptr + remaining == input + len_in); 699 return len_in - remaining; 700 701 truncated: 702 return -2; 703 relay_fail: 704 trunnel_assert(result < 0); 705 return result; 706 trunnel_alloc_failed: 707 return -1; 708 } 709 710 ssize_t 711 netinfo_cell_parse(netinfo_cell_t **output, const uint8_t *input, const size_t len_in) 712 { 713 ssize_t result; 714 *output = netinfo_cell_new(); 715 if (NULL == *output) 716 return -1; 717 result = netinfo_cell_parse_into(*output, input, len_in); 718 if (result < 0) { 719 netinfo_cell_free(*output); 720 *output = NULL; 721 } 722 return result; 723 }