xref: /netbsd-src/lib/libbluetooth/sdp_data.c (revision e057b2281aca041d3f7988132b436b52e1247afe)
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
sdp_data_type(const sdp_data_t * data)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
sdp_data_size(const sdp_data_t * data)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
_sdp_data_valid(uint8_t * ptr,uint8_t * end)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
sdp_data_valid(const sdp_data_t * data)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
_sdp_put(int indent,const char * type,const char * fmt,...)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
_sdp_putstr(int indent,const char * type,const uint8_t * str,size_t len)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
_sdp_data_print(const uint8_t * next,const uint8_t * end,int indent)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
sdp_data_print(const sdp_data_t * data,int indent)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