1 /* $NetBSD: sdp_data.c,v 1.1 2009/05/12 10:05:06 plunky Exp $ */ 2 3 /*- 4 * Copyright (c) 2009 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Iain Hibbert. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __RCSID("$NetBSD: sdp_data.c,v 1.1 2009/05/12 10:05:06 plunky Exp $"); 34 35 #include <sdp.h> 36 #include <stdarg.h> 37 #include <stdio.h> 38 #include <vis.h> 39 40 #include "sdp-int.h" 41 42 43 /****************************************************************************** 44 * sdp_data_type(data) 45 * 46 * return SDP data element type 47 */ 48 int 49 sdp_data_type(const sdp_data_t *data) 50 { 51 52 if (data->next + 1 > data->end) 53 return -1; 54 55 return data->next[0]; 56 } 57 58 59 /****************************************************************************** 60 * sdp_data_size(data) 61 * 62 * return the size of SDP data element. This will fail (return -1) if 63 * the data element does not fit into the data space. 64 */ 65 ssize_t 66 sdp_data_size(const sdp_data_t *data) 67 { 68 uint8_t *p = data->next; 69 70 if (p + 1 > data->end) 71 return -1; 72 73 switch (*p++) { 74 case SDP_DATA_NIL: 75 break; 76 77 case SDP_DATA_BOOL: 78 case SDP_DATA_INT8: 79 case SDP_DATA_UINT8: 80 p += 1; 81 break; 82 83 case SDP_DATA_INT16: 84 case SDP_DATA_UINT16: 85 case SDP_DATA_UUID16: 86 p += 2; 87 break; 88 89 case SDP_DATA_INT32: 90 case SDP_DATA_UINT32: 91 case SDP_DATA_UUID32: 92 p += 4; 93 break; 94 95 case SDP_DATA_INT64: 96 case SDP_DATA_UINT64: 97 p += 8; 98 break; 99 100 case SDP_DATA_INT128: 101 case SDP_DATA_UINT128: 102 case SDP_DATA_UUID128: 103 p += 16; 104 break; 105 106 case SDP_DATA_ALT8: 107 case SDP_DATA_SEQ8: 108 case SDP_DATA_STR8: 109 case SDP_DATA_URL8: 110 if (p + 1 > data->end) 111 return -1; 112 113 p += 1 + *p; 114 break; 115 116 case SDP_DATA_ALT16: 117 case SDP_DATA_SEQ16: 118 case SDP_DATA_STR16: 119 case SDP_DATA_URL16: 120 if (p + 2 > data->end) 121 return -1; 122 123 p += 2 + be16dec(p); 124 break; 125 126 case SDP_DATA_ALT32: 127 case SDP_DATA_SEQ32: 128 case SDP_DATA_STR32: 129 case SDP_DATA_URL32: 130 if (p + 4 > data->end) 131 return -1; 132 133 p += 4 + be32dec(p); 134 break; 135 136 default: 137 return -1; 138 } 139 140 if (p > data->end) 141 return -1; 142 143 return (p - data->next); 144 } 145 146 /****************************************************************************** 147 * sdp_data_valid(data) 148 * 149 * validate an SDP data element list recursively, ensuring elements do not 150 * expand past the claimed length and that there is no invalid data. 151 */ 152 static bool 153 _sdp_data_valid(uint8_t *ptr, uint8_t *end) 154 { 155 size_t len; 156 157 while (ptr < end) { 158 if (ptr + 1 > end) 159 return false; 160 161 switch (*ptr++) { 162 case SDP_DATA_NIL: 163 break; 164 165 case SDP_DATA_BOOL: 166 case SDP_DATA_INT8: 167 case SDP_DATA_UINT8: 168 if (ptr + 1 > end) 169 return false; 170 171 ptr += 1; 172 break; 173 174 case SDP_DATA_INT16: 175 case SDP_DATA_UINT16: 176 case SDP_DATA_UUID16: 177 if (ptr + 2 > end) 178 return false; 179 180 ptr += 2; 181 break; 182 183 case SDP_DATA_INT32: 184 case SDP_DATA_UINT32: 185 case SDP_DATA_UUID32: 186 if (ptr + 4 > end) 187 return false; 188 189 ptr += 4; 190 break; 191 192 case SDP_DATA_INT64: 193 case SDP_DATA_UINT64: 194 if (ptr + 8 > end) 195 return false; 196 197 ptr += 8; 198 break; 199 200 case SDP_DATA_INT128: 201 case SDP_DATA_UINT128: 202 case SDP_DATA_UUID128: 203 if (ptr + 16 > end) 204 return false; 205 206 ptr += 16; 207 break; 208 209 case SDP_DATA_STR8: 210 case SDP_DATA_URL8: 211 if (ptr + 1 > end) 212 return false; 213 214 len = *ptr; 215 ptr += 1; 216 217 if (ptr + len > end) 218 return false; 219 220 ptr += len; 221 break; 222 223 case SDP_DATA_STR16: 224 case SDP_DATA_URL16: 225 if (ptr + 2 > end) 226 return false; 227 228 len = be16dec(ptr); 229 ptr += 2; 230 231 if (ptr + len > end) 232 return false; 233 234 ptr += len; 235 break; 236 237 case SDP_DATA_STR32: 238 case SDP_DATA_URL32: 239 if (ptr + 4 > end) 240 return false; 241 242 len = be32dec(ptr); 243 ptr += 4; 244 245 if (ptr + len > end) 246 return false; 247 248 ptr += len; 249 break; 250 251 case SDP_DATA_SEQ8: 252 case SDP_DATA_ALT8: 253 if (ptr + 1 > end) 254 return false; 255 256 len = *ptr; 257 ptr += 1; 258 259 if (ptr + len > end) 260 return false; 261 262 if (!_sdp_data_valid(ptr, ptr + len)) 263 return false; 264 265 ptr += len; 266 break; 267 268 case SDP_DATA_SEQ16: 269 case SDP_DATA_ALT16: 270 if (ptr + 2 > end) 271 return false; 272 273 len = be16dec(ptr); 274 ptr += 2; 275 276 if (ptr + len > end) 277 return false; 278 279 if (!_sdp_data_valid(ptr, ptr + len)) 280 return false; 281 282 ptr += len; 283 break; 284 285 case SDP_DATA_SEQ32: 286 case SDP_DATA_ALT32: 287 if (ptr + 4 > end) 288 return false; 289 290 len = be32dec(ptr); 291 ptr += 4; 292 293 if (ptr + len > end) 294 return false; 295 296 if (!_sdp_data_valid(ptr, ptr + len)) 297 return false; 298 299 ptr += len; 300 break; 301 302 default: 303 return false; 304 } 305 } 306 307 return true; 308 } 309 310 bool 311 sdp_data_valid(const sdp_data_t *data) 312 { 313 314 if (data->next == NULL || data->end == NULL) 315 return false; 316 317 if (data->next >= data->end) 318 return false; 319 320 return _sdp_data_valid(data->next, data->end); 321 } 322 323 /****************************************************************************** 324 * sdp_data_print(data, indent) 325 * 326 * print out a SDP data element list in human readable format 327 */ 328 static void 329 _sdp_put(int indent, const char *type, const char *fmt, ...) 330 { 331 va_list ap; 332 333 indent = printf("%*s%s", indent, "", type); 334 indent = 18 - indent; 335 if (indent < 2) 336 indent = 2; 337 338 printf("%*s", indent, ""); 339 340 va_start(ap, fmt); 341 vprintf(fmt, ap); 342 va_end(ap); 343 344 printf("\n"); 345 } 346 347 static void 348 _sdp_putstr(int indent, int style, const char *type, 349 const uint8_t *str, size_t len) 350 { 351 char buf[50], *dst = buf; 352 353 indent = printf("%*s%s(%zu)", indent, "", type, len); 354 indent = 18 - indent; 355 if (indent < 2) 356 indent = 2; 357 358 printf("%*s", indent, ""); 359 360 style |= VIS_NL; 361 362 while (len > 0 && (dst + 5) < (buf + sizeof(buf))) { 363 dst = vis(dst, str[0], style, (len > 0 ? str[1] : 0)); 364 str++; 365 len--; 366 } 367 368 printf("\"%s%s\n", buf, (len == 0 ? "\"" : " ...")); 369 } 370 371 bool 372 _sdp_data_print(const uint8_t *next, const uint8_t *end, int indent) 373 { 374 size_t len; 375 376 while (next < end) { 377 if (next + 1 > end) 378 return false; 379 380 switch (*next++) { 381 case SDP_DATA_NIL: 382 _sdp_put(indent, "nil", ""); 383 break; 384 385 case SDP_DATA_BOOL: 386 if (next + 1 > end) 387 return false; 388 389 _sdp_put(indent, "bool", "%s", 390 (*next == 0x00 ? "false" : "true")); 391 392 next += 1; 393 break; 394 395 case SDP_DATA_INT8: 396 if (next + 1 > end) 397 return false; 398 399 _sdp_put(indent, "int8", "%" PRId8, 400 *(const int8_t *)next); 401 next += 1; 402 break; 403 404 case SDP_DATA_UINT8: 405 if (next + 1 > end) 406 return false; 407 408 _sdp_put(indent, "uint8", "0x%02" PRIx8, 409 *next); 410 next += 1; 411 break; 412 413 case SDP_DATA_INT16: 414 if (next + 2 > end) 415 return false; 416 417 _sdp_put(indent, "int16", "%" PRId16, 418 (int16_t)be16dec(next)); 419 next += 2; 420 break; 421 422 case SDP_DATA_UINT16: 423 if (next + 2 > end) 424 return false; 425 426 _sdp_put(indent, "uint16", "0x%04" PRIx16, 427 be16dec(next)); 428 next += 2; 429 break; 430 431 case SDP_DATA_UUID16: 432 if (next + 2 > end) 433 return false; 434 435 _sdp_put(indent, "uuid16", "0x%04" PRIx16, 436 be16dec(next)); 437 next += 2; 438 break; 439 440 case SDP_DATA_INT32: 441 if (next + 4 > end) 442 return false; 443 444 _sdp_put(indent, "int32", "%" PRId32, 445 (int32_t)be32dec(next)); 446 next += 4; 447 break; 448 449 case SDP_DATA_UINT32: 450 if (next + 4 > end) 451 return false; 452 453 _sdp_put(indent, "uint32", "0x%08" PRIx32, 454 be32dec(next)); 455 next += 4; 456 break; 457 458 case SDP_DATA_UUID32: 459 if (next + 4 > end) 460 return false; 461 462 _sdp_put(indent, "uuid32", "0x%08" PRIx32, 463 be32dec(next)); 464 next += 4; 465 break; 466 467 case SDP_DATA_INT64: 468 if (next + 8 > end) 469 return false; 470 471 _sdp_put(indent, "int64", "%" PRId64, 472 (int64_t)be64dec(next)); 473 next += 8; 474 break; 475 476 case SDP_DATA_UINT64: 477 if (next + 8 > end) 478 return false; 479 480 _sdp_put(indent, "uint64", "0x%016" PRIx64, 481 be64dec(next)); 482 next += 8; 483 break; 484 485 case SDP_DATA_INT128: 486 if (next + 16 > end) 487 return false; 488 489 _sdp_put(indent, "int128", 490 "0x%02x%02x%02x%02x%02x%02x%02x%02x" 491 "%02x%02x%02x%02x%02x%02x%02x%02x", 492 next[0], next[1], next[2], next[3], 493 next[4], next[5], next[6], next[7], 494 next[8], next[9], next[10], next[11], 495 next[12], next[13], next[14], next[15]); 496 next += 16; 497 break; 498 499 case SDP_DATA_UINT128: 500 if (next + 16 > end) 501 return false; 502 503 _sdp_put(indent, "uint128", 504 "0x%02x%02x%02x%02x%02x%02x%02x%02x" 505 "%02x%02x%02x%02x%02x%02x%02x%02x", 506 next[0], next[1], next[2], next[3], 507 next[4], next[5], next[6], next[7], 508 next[8], next[9], next[10], next[11], 509 next[12], next[13], next[14], next[15]); 510 next += 16; 511 break; 512 513 case SDP_DATA_UUID128: 514 if (next + 16 > end) 515 return false; 516 517 _sdp_put(indent, "uuid128", 518 "%02x%02x%02x%02x-" 519 "%02x%02x-" 520 "%02x%02x-" 521 "%02x%02x-" 522 "%02x%02x%02x%02x%02x%02x", 523 next[0], next[1], next[2], next[3], 524 next[4], next[5], 525 next[6], next[7], 526 next[8], next[9], 527 next[10], next[11], next[12], 528 next[13], next[14], next[15]); 529 next += 16; 530 break; 531 532 case SDP_DATA_STR8: 533 if (next + 1 > end) 534 return false; 535 536 len = *next; 537 next += 1; 538 539 if (next + len > end) 540 return false; 541 542 _sdp_putstr(indent, VIS_CSTYLE, "str8", next, len); 543 next += len; 544 break; 545 546 case SDP_DATA_URL8: 547 if (next + 1 > end) 548 return false; 549 550 len = *next; 551 next += 1; 552 553 if (next + len > end) 554 return false; 555 556 _sdp_putstr(indent, VIS_HTTPSTYLE, "url8", next, len); 557 next += len; 558 break; 559 560 case SDP_DATA_STR16: 561 if (next + 2 > end) 562 return false; 563 564 len = be16dec(next); 565 next += 2; 566 567 if (next + len > end) 568 return false; 569 570 _sdp_putstr(indent, VIS_CSTYLE, "str16", next, len); 571 next += len; 572 break; 573 574 case SDP_DATA_URL16: 575 if (next + 2 > end) 576 return false; 577 578 len = be16dec(next); 579 next += 2; 580 581 if (next + len > end) 582 return false; 583 584 _sdp_putstr(indent, VIS_HTTPSTYLE, "url16", next, len); 585 next += len; 586 break; 587 588 case SDP_DATA_STR32: 589 if (next + 4 > end) 590 return false; 591 592 len = be32dec(next); 593 next += 4; 594 595 if (next + len > end) 596 return false; 597 598 _sdp_putstr(indent, VIS_CSTYLE, "str32", next, len); 599 next += len; 600 break; 601 602 case SDP_DATA_URL32: 603 if (next + 4 > end) 604 return false; 605 606 len = be32dec(next); 607 next += 4; 608 609 if (next + len > end) 610 return false; 611 612 _sdp_putstr(indent, VIS_HTTPSTYLE, "url32", next, len); 613 next += len; 614 break; 615 616 case SDP_DATA_SEQ8: 617 if (next + 1 > end) 618 return false; 619 620 len = *next; 621 next += 1; 622 623 if (next + len > end) 624 return false; 625 626 printf("%*sseq8(%zu)\n", indent, "", len); 627 if (!_sdp_data_print(next, next + len, indent + 1)) 628 return false; 629 630 next += len; 631 break; 632 633 case SDP_DATA_ALT8: 634 if (next + 1 > end) 635 return false; 636 637 len = *next; 638 next += 1; 639 640 if (next + len > end) 641 return false; 642 643 printf("%*salt8(%zu)\n", indent, "", len); 644 if (!_sdp_data_print(next, next + len, indent + 1)) 645 return false; 646 647 next += len; 648 break; 649 650 case SDP_DATA_SEQ16: 651 if (next + 2 > end) 652 return false; 653 654 len = be16dec(next); 655 next += 2; 656 657 if (next + len > end) 658 return false; 659 660 printf("%*sseq16(%zu)\n", indent, "", len); 661 if (!_sdp_data_print(next, next + len, indent + 1)) 662 return false; 663 664 next += len; 665 break; 666 667 case SDP_DATA_ALT16: 668 if (next + 2 > end) 669 return false; 670 671 len = be16dec(next); 672 next += 2; 673 674 if (next + len > end) 675 return false; 676 677 printf("%*salt16(%zu)\n", indent, "", len); 678 if (!_sdp_data_print(next, next + len, indent + 1)) 679 return false; 680 681 next += len; 682 break; 683 684 case SDP_DATA_SEQ32: 685 if (next + 4 > end) 686 return false; 687 688 len = be32dec(next); 689 next += 4; 690 691 if (next + len > end) 692 return false; 693 694 printf("%*sseq32(%zu)\n", indent, "", len); 695 if (!_sdp_data_print(next, next + len, indent + 1)) 696 return false; 697 698 next += len; 699 break; 700 701 case SDP_DATA_ALT32: 702 if (next + 4 > end) 703 return false; 704 705 len = be32dec(next); 706 next += 4; 707 708 if (next + len > end) 709 return false; 710 711 printf("%*salt32(%zu)\n", indent, "", len); 712 if (!_sdp_data_print(next, next + len, indent + 1)) 713 return false; 714 715 next += len; 716 break; 717 718 default: 719 return false; 720 } 721 } 722 723 return true; 724 } 725 726 void 727 sdp_data_print(const sdp_data_t *data, int indent) 728 { 729 730 if (!_sdp_data_print(data->next, data->end, indent)) 731 printf("SDP data error\n"); 732 } 733