Home | History | Annotate | Line # | Download | only in libbluetooth
sdp_data.c revision 1.1
      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