xref: /netbsd/lib/libbluetooth/sdp_data.c (revision 6550d01e)
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