Home | History | Annotate | Line # | Download | only in libbluetooth
      1 /*	$NetBSD: sdp_data.c,v 1.4 2012/03/22 23:46:49 joerg 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.4 2012/03/22 23:46:49 joerg 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 __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 
    347 static 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 
    372 bool
    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 
    727 void
    728 sdp_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