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