1/* $NetBSD: sdp_data.c,v 1.3 2011/09/15 17:51:57 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.3 2011/09/15 17:51:57 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 */ 48int 49sdp_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 */ 65ssize_t 66sdp_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 */ 152static 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 310bool 311sdp_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 */ 328static __printflike(3, 4) 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 347static void 348_sdp_putstr(int indent, const char *type, const uint8_t *str, size_t len) 349{ 350 char buf[50], *dst = buf; 351 int style; 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_CSTYLE | VIS_NL; 361 buf[0] = '\0'; 362 363 while (len > 0 && (dst + 5) < (buf + sizeof(buf))) { 364 dst = vis(dst, str[0], style, (len > 0 ? str[1] : 0)); 365 str++; 366 len--; 367 } 368 369 printf("\"%s%s\n", buf, (len == 0 ? "\"" : " ...")); 370} 371 372bool 373_sdp_data_print(const uint8_t *next, const uint8_t *end, int indent) 374{ 375 size_t len; 376 377 while (next < end) { 378 if (next + 1 > end) 379 return false; 380 381 switch (*next++) { 382 case SDP_DATA_NIL: 383 _sdp_put(indent, "nil", ""); 384 break; 385 386 case SDP_DATA_BOOL: 387 if (next + 1 > end) 388 return false; 389 390 _sdp_put(indent, "bool", "%s", 391 (*next == 0x00 ? "false" : "true")); 392 393 next += 1; 394 break; 395 396 case SDP_DATA_INT8: 397 if (next + 1 > end) 398 return false; 399 400 _sdp_put(indent, "int8", "%" PRId8, 401 *(const int8_t *)next); 402 next += 1; 403 break; 404 405 case SDP_DATA_UINT8: 406 if (next + 1 > end) 407 return false; 408 409 _sdp_put(indent, "uint8", "0x%02" PRIx8, 410 *next); 411 next += 1; 412 break; 413 414 case SDP_DATA_INT16: 415 if (next + 2 > end) 416 return false; 417 418 _sdp_put(indent, "int16", "%" PRId16, 419 (int16_t)be16dec(next)); 420 next += 2; 421 break; 422 423 case SDP_DATA_UINT16: 424 if (next + 2 > end) 425 return false; 426 427 _sdp_put(indent, "uint16", "0x%04" PRIx16, 428 be16dec(next)); 429 next += 2; 430 break; 431 432 case SDP_DATA_UUID16: 433 if (next + 2 > end) 434 return false; 435 436 _sdp_put(indent, "uuid16", "0x%04" PRIx16, 437 be16dec(next)); 438 next += 2; 439 break; 440 441 case SDP_DATA_INT32: 442 if (next + 4 > end) 443 return false; 444 445 _sdp_put(indent, "int32", "%" PRId32, 446 (int32_t)be32dec(next)); 447 next += 4; 448 break; 449 450 case SDP_DATA_UINT32: 451 if (next + 4 > end) 452 return false; 453 454 _sdp_put(indent, "uint32", "0x%08" PRIx32, 455 be32dec(next)); 456 next += 4; 457 break; 458 459 case SDP_DATA_UUID32: 460 if (next + 4 > end) 461 return false; 462 463 _sdp_put(indent, "uuid32", "0x%08" PRIx32, 464 be32dec(next)); 465 next += 4; 466 break; 467 468 case SDP_DATA_INT64: 469 if (next + 8 > end) 470 return false; 471 472 _sdp_put(indent, "int64", "%" PRId64, 473 (int64_t)be64dec(next)); 474 next += 8; 475 break; 476 477 case SDP_DATA_UINT64: 478 if (next + 8 > end) 479 return false; 480 481 _sdp_put(indent, "uint64", "0x%016" PRIx64, 482 be64dec(next)); 483 next += 8; 484 break; 485 486 case SDP_DATA_INT128: 487 if (next + 16 > end) 488 return false; 489 490 _sdp_put(indent, "int128", 491 "0x%02x%02x%02x%02x%02x%02x%02x%02x" 492 "%02x%02x%02x%02x%02x%02x%02x%02x", 493 next[0], next[1], next[2], next[3], 494 next[4], next[5], next[6], next[7], 495 next[8], next[9], next[10], next[11], 496 next[12], next[13], next[14], next[15]); 497 next += 16; 498 break; 499 500 case SDP_DATA_UINT128: 501 if (next + 16 > end) 502 return false; 503 504 _sdp_put(indent, "uint128", 505 "0x%02x%02x%02x%02x%02x%02x%02x%02x" 506 "%02x%02x%02x%02x%02x%02x%02x%02x", 507 next[0], next[1], next[2], next[3], 508 next[4], next[5], next[6], next[7], 509 next[8], next[9], next[10], next[11], 510 next[12], next[13], next[14], next[15]); 511 next += 16; 512 break; 513 514 case SDP_DATA_UUID128: 515 if (next + 16 > end) 516 return false; 517 518 _sdp_put(indent, "uuid128", 519 "%02x%02x%02x%02x-" 520 "%02x%02x-" 521 "%02x%02x-" 522 "%02x%02x-" 523 "%02x%02x%02x%02x%02x%02x", 524 next[0], next[1], next[2], next[3], 525 next[4], next[5], 526 next[6], next[7], 527 next[8], next[9], 528 next[10], next[11], next[12], 529 next[13], next[14], next[15]); 530 next += 16; 531 break; 532 533 case SDP_DATA_STR8: 534 if (next + 1 > end) 535 return false; 536 537 len = *next; 538 next += 1; 539 540 if (next + len > end) 541 return false; 542 543 _sdp_putstr(indent, "str8", next, len); 544 next += len; 545 break; 546 547 case SDP_DATA_URL8: 548 if (next + 1 > end) 549 return false; 550 551 len = *next; 552 next += 1; 553 554 if (next + len > end) 555 return false; 556 557 _sdp_putstr(indent, "url8", next, len); 558 next += len; 559 break; 560 561 case SDP_DATA_STR16: 562 if (next + 2 > end) 563 return false; 564 565 len = be16dec(next); 566 next += 2; 567 568 if (next + len > end) 569 return false; 570 571 _sdp_putstr(indent, "str16", next, len); 572 next += len; 573 break; 574 575 case SDP_DATA_URL16: 576 if (next + 2 > end) 577 return false; 578 579 len = be16dec(next); 580 next += 2; 581 582 if (next + len > end) 583 return false; 584 585 _sdp_putstr(indent, "url16", next, len); 586 next += len; 587 break; 588 589 case SDP_DATA_STR32: 590 if (next + 4 > end) 591 return false; 592 593 len = be32dec(next); 594 next += 4; 595 596 if (next + len > end) 597 return false; 598 599 _sdp_putstr(indent, "str32", next, len); 600 next += len; 601 break; 602 603 case SDP_DATA_URL32: 604 if (next + 4 > end) 605 return false; 606 607 len = be32dec(next); 608 next += 4; 609 610 if (next + len > end) 611 return false; 612 613 _sdp_putstr(indent, "url32", next, len); 614 next += len; 615 break; 616 617 case SDP_DATA_SEQ8: 618 if (next + 1 > end) 619 return false; 620 621 len = *next; 622 next += 1; 623 624 if (next + len > end) 625 return false; 626 627 printf("%*sseq8(%zu)\n", indent, "", len); 628 if (!_sdp_data_print(next, next + len, indent + 1)) 629 return false; 630 631 next += len; 632 break; 633 634 case SDP_DATA_ALT8: 635 if (next + 1 > end) 636 return false; 637 638 len = *next; 639 next += 1; 640 641 if (next + len > end) 642 return false; 643 644 printf("%*salt8(%zu)\n", indent, "", len); 645 if (!_sdp_data_print(next, next + len, indent + 1)) 646 return false; 647 648 next += len; 649 break; 650 651 case SDP_DATA_SEQ16: 652 if (next + 2 > end) 653 return false; 654 655 len = be16dec(next); 656 next += 2; 657 658 if (next + len > end) 659 return false; 660 661 printf("%*sseq16(%zu)\n", indent, "", len); 662 if (!_sdp_data_print(next, next + len, indent + 1)) 663 return false; 664 665 next += len; 666 break; 667 668 case SDP_DATA_ALT16: 669 if (next + 2 > end) 670 return false; 671 672 len = be16dec(next); 673 next += 2; 674 675 if (next + len > end) 676 return false; 677 678 printf("%*salt16(%zu)\n", indent, "", len); 679 if (!_sdp_data_print(next, next + len, indent + 1)) 680 return false; 681 682 next += len; 683 break; 684 685 case SDP_DATA_SEQ32: 686 if (next + 4 > end) 687 return false; 688 689 len = be32dec(next); 690 next += 4; 691 692 if (next + len > end) 693 return false; 694 695 printf("%*sseq32(%zu)\n", indent, "", len); 696 if (!_sdp_data_print(next, next + len, indent + 1)) 697 return false; 698 699 next += len; 700 break; 701 702 case SDP_DATA_ALT32: 703 if (next + 4 > end) 704 return false; 705 706 len = be32dec(next); 707 next += 4; 708 709 if (next + len > end) 710 return false; 711 712 printf("%*salt32(%zu)\n", indent, "", len); 713 if (!_sdp_data_print(next, next + len, indent + 1)) 714 return false; 715 716 next += len; 717 break; 718 719 default: 720 return false; 721 } 722 } 723 724 return true; 725} 726 727void 728sdp_data_print(const sdp_data_t *data, int indent) 729{ 730 731 if (!_sdp_data_print(data->next, data->end, indent)) 732 printf("SDP data error\n"); 733} 734