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