2 * Routines for wbxml dissection
3 * Copyright 2003, Olivier Biot <olivier.biot (ad) siemens.com>
5 * $Id: packet-wbxml.c,v 1.6 2003/02/27 02:52:50 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
9 * Copyright 1998 Gerald Combs
11 * WAP Binary XML decoding functionality provided by Olivier Biot.
13 * The WAP specifications are found at the WAP Forum:
14 * http://www.wapforum.org/what/Technical.htm
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 /* Edit this file with 4-space tabulation */
43 #ifdef NEED_SNPRINTF_H
44 # include "snprintf.h"
47 #include <epan/packet.h>
49 /* We need the function tvb_get_guintvar() */
50 #include "packet-wap.h"
52 /* The code in this source file dissects the WAP Binary XML content,
53 * and if possible renders it. WBXML mappings are defined in the
54 * "wbxml_map[]" array.
58 * - Although Code Page processing is already foreseen in the tag and
59 * attribute parsing code, there is no mechanism available yet to
60 * properly deal with multiple code pages (see, e.g., the wbxml_map[]
61 * array). As a consequence, the same token rendering will occur,
62 * irrespective of the code pages in use.
63 * As there currently is no registered WBXML type with support of more
64 * than one tag or attribute code page, this is a safe assumption.
66 * - In order to render the XML content, recursion is inevitable at some
67 * point (when a tag with content occurs in the content of a tag with
68 * content). The code will however not recurse if this is not strictly
69 * required (e.g., tag without content in the content of a tag with
72 * - I found it useful to display the XML nesting level as a first "column",
73 * followed by the abbreviated WBXML token interpretation. When a mapping
74 * is defined for the parsed WBXML content, then the XML rendering is
75 * displayed with appropriate indentation (maximum nesting level = 255,
76 * after which the nesting and level will safely roll-over to 0).
80 /************************* Variable declarations *************************/
83 /* Initialize the protocol and registered fields */
84 static int proto_wbxml = -1;
85 static int hf_wbxml_version = -1;
86 static int hf_wbxml_public_id_known = -1;
87 static int hf_wbxml_public_id_literal = -1;
88 static int hf_wbxml_charset = -1;
90 /* Initialize the subtree pointers */
91 static gint ett_wbxml = -1;
92 static gint ett_wbxml_str_tbl = -1;
93 static gint ett_wbxml_content = -1;
97 /********** WBXML related declarations and definitions **********/
99 /* See http://www.wapforum.org/wina/ for an up-to-date list. */
100 #define WBXML_WML_10 0x02
101 #define WBXML_WTA_10 0x03
102 #define WBXML_WML_11 0x04
103 #define WBXML_SI_10 0x05
104 #define WBXML_SL_10 0x06
105 #define WBXML_CO_10 0x07
106 #define WBXML_CHANNEL_10 0x08
107 #define WBXML_WML_12 0x09
108 #define WBXML_WML_13 0x0a
109 #define WBXML_PROV_10 0x0b
110 #define WBXML_WTAWML_12 0x0c
111 #define WBXML_EMN_10 0x0d
112 #define WBXML_DRMREL_10 0x0e
114 static const value_string vals_wbxml_public_ids[] = {
115 /* 0x00 = literal public identifier */
116 { 0x01, "Unknown / missing Public Identifier" },
117 { 0x02, "-//WAPFORUM//DTD WML 1.0//EN (WML 1.0)" },
118 { 0x03, "-//WAPFORUM//DTD WTA 1.0//EN (WTA Event 1.0) - Deprecated" },
119 { 0x04, "-//WAPFORUM//DTD WML 1.1//EN (WML 1.1)" },
120 { 0x05, "-//WAPFORUM//DTD SI 1.0//EN (Service Indication 1.0)" },
121 { 0x06, "-//WAPFORUM//DTD SL 1.0//EN (Service Loading 1.0)" },
122 { 0x07, "-//WAPFORUM//DTD CO 1.0//EN (Cache Operation 1.0)" },
123 { 0x08, "-//WAPFORUM//DTD CHANNEL 1.0//EN (Channel 1.1)" },
124 { 0x09, "-//WAPFORUM//DTD WML 1.2//EN (WML 1.2)" },
125 { 0x0a, "-//WAPFORUM//DTD WML 1.3//EN (WML 1.3)" },
126 { 0x0b, "-//WAPFORUM//DTD PROV 1.0//EN (Provisioning 1.0)" },
127 { 0x0c, "-//WAPFORUM//DTD WTA-WML 1.2//EN (WTA-WML 1.2)" },
128 { 0x0d, "-//WAPFORUM//DTD EMN 1.0//EN (Email Notification 1.0)" },
129 { 0x0e, "-//WAPFORUM//DTD DRMREL 1.0//EN (DRMREL 1.0)" },
136 static const value_string vals_wbxml_versions[] = {
145 /* See WAP-104-WBXML */
146 static const value_string vals_wbxml10_global_tokens[] = {
147 { 0x00, "SWITCH_PAGE" },
157 { 0x44, "LITERAL_C" },
163 { 0x84, "LITERAL_A" },
168 { 0xC3, "RESERVED_2" },
169 { 0xC4, "LITERAL_AC" },
174 /* See WAP-135-WBXML, WAP-154-WBXML, WAP-192-WBXML */
175 static const value_string vals_wbxml1x_global_tokens[] = {
176 { 0x00, "SWITCH_PAGE" },
186 { 0x44, "LITERAL_C" },
192 { 0x84, "LITERAL_A" },
198 { 0xC4, "LITERAL_AC" },
204 /****************************************************************************/
206 /*******************************************
207 * WML 1.0 - Global tokens (EXT) *
208 *******************************************/
209 static const value_string vals_wmlc10_global[] = {
210 { 0x40, "Variable substitution - escaped" },
211 { 0x41, "Variable substitution - unescaped" },
212 { 0x42, "Variable substitution - no transformation" },
213 { 0x80, "Variable substitution - escaped" },
214 { 0x81, "Variable substitution - unescaped" },
215 { 0x82, "Variable substitution - no transformation" },
216 { 0xC0, "Reserved" },
217 { 0xC1, "Reserved" },
218 { 0xC2, "Reserved" },
223 /*******************************************
225 *******************************************/
226 static const value_string vals_wmlc10_tags[] = {
227 /* 0x00 -- 0x04 GLOBAL */
237 { 0xEA, "FIELDSET" },
247 { 0xF4, "OPTGROUP" },
254 { 0xFB, "TEMPLATE" },
263 /*******************************************
264 * WML 1.0 - Attribute Start *
265 *******************************************/
266 static const value_string vals_wmlc10_attrStart[] = {
267 /* 0x00 -- 0x04 GLOBAL */
268 { 0x05, "ACCEPT-CHARSET=" },
269 { 0x06, "ALIGN='BOTTOM'" },
270 { 0x07, "ALIGN='CENTER'" },
271 { 0x08, "ALIGN='LEFT'" },
272 { 0x09, "ALIGN='MIDDLE'" },
273 { 0x0A, "ALIGN='RIGHT'" },
274 { 0x0B, "ALIGN='TOP'" },
276 { 0x0D, "CONTENT=" },
277 { 0x0E, "DEFAULT=" },
279 { 0x10, "EMPTYOK='FALSE'" },
280 { 0x11, "EMPTYOK='TRUE'" },
284 { 0x15, "IDEFAULT=" },
288 { 0x19, "LOCALSRC=" },
289 { 0x1A, "MAXLENGTH=" },
290 { 0x1B, "METHOD='GET'" },
291 { 0x1C, "METHOD='POST'" },
292 { 0x1D, "MODE='NOWRAP'" },
293 { 0x1E, "MODE='WRAP'" },
294 { 0x1F, "MULTIPLE='FALSE'" },
295 { 0x20, "MULTIPLE='TRUE'" },
297 { 0x22, "NEWCONTEXT='FALSE'" },
298 { 0x23, "NEWCONTEXT='TRUE'" },
299 { 0x24, "ONCLICK=" },
300 { 0x25, "ONENTERBACKWARD=" },
301 { 0x26, "ONENTERFORWARD=" },
302 { 0x27, "ONTIMER=" },
303 { 0x28, "OPTIONAL='FALSE'" },
304 { 0x29, "OPTIONAL='TRUE'" },
306 { 0x2B, "POSTDATA=" },
307 { 0x2C, "PUBLIC='FALSE'" },
308 { 0x2D, "PUBLIC='TRUE'" },
310 { 0x2F, "SENDREFERER='FALSE'" },
311 { 0x30, "SENDREFERER='TRUE'" },
314 { 0x33, "STYLE='LIST'" },
315 { 0x34, "STYLE='SET'" },
316 { 0x35, "TABINDEX=" },
319 { 0x38, "TYPE='ACCEPT'" },
320 { 0x39, "TYPE='DELETE'" },
321 { 0x3A, "TYPE='HELP'" },
322 { 0x3B, "TYPE='PASSWORD'" },
323 { 0x3C, "TYPE='ONCLICK'" },
324 { 0x3D, "TYPE='ONENTERBACKWARD'" },
325 { 0x3E, "TYPE='ONENTERFORWARD'" },
326 { 0x3F, "TYPE='ONTIMER'" },
327 /* 0x40 -- 0x44 GLOBAL */
328 { 0x45, "TYPE='OPTIONS'" },
329 { 0x46, "TYPE='PREV'" },
330 { 0x47, "TYPE='RESET'" },
331 { 0x48, "TYPE='TEXT'" },
332 { 0x49, "TYPE='vnd.'" },
334 { 0x4B, "URL='http://'" },
335 { 0x4C, "URL='https://'" },
336 { 0x4D, "USER-AGENT=" },
340 { 0x51, "xml:lang=" },
345 /*******************************************
346 * WML 1.0 - Attribute Value *
347 *******************************************/
348 static const value_string vals_wmlc10_attrValue[] = {
349 /* 0x80 -- 0x84 GLOBAL */
354 { 0x89, "'ACCEPT'" },
355 { 0x8A, "'BOTTOM'" },
357 { 0x8C, "'DELETE'" },
359 { 0x8E, "'http://'" },
360 { 0x8F, "'http://www.'" },
361 { 0x90, "'https://'" },
362 { 0x91, "'https://www.'" },
364 { 0x93, "'MIDDLE'" },
365 { 0x94, "'NOWRAP'" },
366 { 0x95, "'ONCLICK'" },
367 { 0x96, "'ONENTERBACKWARD'" },
368 { 0x97, "'ONENTERFORWARD'" },
369 { 0x98, "'ONTIMER'" },
370 { 0x99, "'OPTIONS'" },
371 { 0x9A, "'PASSWORD'" },
376 { 0x9F, "'UNKNOWN'" },
383 /****************************************************************************/
385 /*******************************************
386 * WML 1.1 - Global tokens (EXT) *
387 *******************************************/
388 #define vals_wmlc11_global vals_wmlc10_global
390 /*******************************************
392 *******************************************/
393 static const value_string vals_wmlc11_tags[] = {
394 /* 0x00 -- 0x04 GLOBAL */
401 { 0x21, "postfield" },
410 { 0x2A, "fieldset" },
420 { 0x34, "optgroup" },
427 { 0x3B, "template" },
436 /*******************************************
437 * WML 1.1 - Attribute Start *
438 *******************************************/
439 static const value_string vals_wmlc11_attrStart[] = {
440 /* 0x00 -- 0x04 GLOBAL */
441 { 0x05, "accept-charset=" },
442 { 0x06, "align='bottom'" },
443 { 0x07, "align='center'" },
444 { 0x08, "align='left'" },
445 { 0x09, "align='middle'" },
446 { 0x0A, "align='right'" },
447 { 0x0B, "align='top'" },
449 { 0x0D, "content=" },
452 { 0x10, "emptyok='false'" },
453 { 0x11, "emptyok='true'" },
461 { 0x19, "localsrc=" },
462 { 0x1A, "maxlength=" },
463 { 0x1B, "method='get'" },
464 { 0x1C, "method='post'" },
465 { 0x1D, "mode='nowrap'" },
466 { 0x1E, "mode='wrap'" },
467 { 0x1F, "multiple='false'" },
468 { 0x20, "multiple='true'" },
470 { 0x22, "newcontext='false'" },
471 { 0x23, "newcontext='true'" },
473 { 0x25, "onenterbackward=" },
474 { 0x26, "onenterforward=" },
475 { 0x27, "ontimer=" },
476 { 0x28, "optional='false'" },
477 { 0x29, "optional='true'" },
481 { 0x2F, "sendreferer='false'" },
482 { 0x30, "sendreferer='true'" },
485 { 0x33, "ordered='false'" },
486 { 0x34, "ordered='true'" },
487 { 0x35, "tabindex=" },
490 { 0x38, "type='accept'" },
491 { 0x39, "type='delete'" },
492 { 0x3A, "type='help'" },
493 { 0x3B, "type='password'" },
494 { 0x3C, "type='onpick'" },
495 { 0x3D, "type='onenterbackward'" },
496 { 0x3E, "type='onenterforward'" },
497 { 0x3F, "type='ontimer'" },
498 /* 0x40 -- 0x44 GLOBAL */
499 { 0x45, "type='options'" },
500 { 0x46, "type='prev'" },
501 { 0x47, "type='reset'" },
502 { 0x48, "type='text'" },
503 { 0x49, "type='vnd.'" },
505 { 0x4B, "href='http://'" },
506 { 0x4C, "href='https://'" },
510 { 0x50, "xml:lang=" },
513 { 0x53, "columns=" },
516 { 0x56, "forua='false'" },
517 { 0x57, "forua='true'" },
518 { 0x58, "src='http://'" },
519 { 0x59, "src='https://'" },
520 { 0x5A, "http-equiv=" },
521 { 0x5B, "http-equiv='Content-Type'" },
522 { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
523 { 0x5D, "http-equiv='Expires'" },
528 /*******************************************
529 * WML 1.1 - Attribute Value *
530 *******************************************/
531 static const value_string vals_wmlc11_attrValue[] = {
532 /* 0x80 -- 0x84 GLOBAL */
537 { 0x89, "'accept'" },
538 { 0x8A, "'bottom'" },
540 { 0x8C, "'delete'" },
542 { 0x8E, "'http://'" },
543 { 0x8F, "'http://www.'" },
544 { 0x90, "'https://'" },
545 { 0x91, "'https://www.'" },
547 { 0x93, "'middle'" },
548 { 0x94, "'nowrap'" },
549 { 0x95, "'onpick'" },
550 { 0x96, "'onenterbackward'" },
551 { 0x97, "'onenterforward'" },
552 { 0x98, "'ontimer'" },
553 { 0x99, "'options'" },
554 { 0x9A, "'password'" },
559 { 0x9F, "'unknown'" },
566 /****************************************************************************/
568 /*******************************************
569 * WML 1.2 - Global tokens (EXT) *
570 *******************************************/
571 #define vals_wmlc12_global vals_wmlc11_global
573 /*******************************************
575 *******************************************/
576 static const value_string vals_wmlc12_tags[] = {
577 /* 0x00 -- 0x04 GLOBAL */
585 { 0x21, "postfield" },
594 { 0x2A, "fieldset" },
604 { 0x34, "optgroup" },
611 { 0x3B, "template" },
620 /*******************************************
621 * WML 1.2 - Attribute Start *
622 *******************************************/
623 static const value_string vals_wmlc12_attrStart[] = {
624 /* 0x00 -- 0x04 GLOBAL */
625 { 0x05, "accept-charset=" },
626 { 0x06, "align='bottom'" },
627 { 0x07, "align='center'" },
628 { 0x08, "align='left'" },
629 { 0x09, "align='middle'" },
630 { 0x0A, "align='right'" },
631 { 0x0B, "align='top'" },
633 { 0x0D, "content=" },
636 { 0x10, "emptyok='false'" },
637 { 0x11, "emptyok='true'" },
645 { 0x19, "localsrc=" },
646 { 0x1A, "maxlength=" },
647 { 0x1B, "method='get'" },
648 { 0x1C, "method='post'" },
649 { 0x1D, "mode='nowrap'" },
650 { 0x1E, "mode='wrap'" },
651 { 0x1F, "multiple='false'" },
652 { 0x20, "multiple='true'" },
654 { 0x22, "newcontext='false'" },
655 { 0x23, "newcontext='true'" },
657 { 0x25, "onenterbackward=" },
658 { 0x26, "onenterforward=" },
659 { 0x27, "ontimer=" },
660 { 0x28, "optional='false'" },
661 { 0x29, "optional='true'" },
665 { 0x2F, "sendreferer='false'" },
666 { 0x30, "sendreferer='true'" },
669 { 0x33, "ordered='false'" },
670 { 0x34, "ordered='true'" },
671 { 0x35, "tabindex=" },
674 { 0x38, "type='accept'" },
675 { 0x39, "type='delete'" },
676 { 0x3A, "type='help'" },
677 { 0x3B, "type='password'" },
678 { 0x3C, "type='onpick'" },
679 { 0x3D, "type='onenterbackward'" },
680 { 0x3E, "type='onenterforward'" },
681 { 0x3F, "type='ontimer'" },
682 /* 0x40 -- 0x44 GLOBAL */
683 { 0x45, "type='options'" },
684 { 0x46, "type='prev'" },
685 { 0x47, "type='reset'" },
686 { 0x48, "type='text'" },
687 { 0x49, "type='vnd.'" },
689 { 0x4B, "href='http://'" },
690 { 0x4C, "href='https://'" },
694 { 0x50, "xml:lang=" },
697 { 0x53, "columns=" },
700 { 0x56, "forua='false'" },
701 { 0x57, "forua='true'" },
702 { 0x58, "src='http://'" },
703 { 0x59, "src='https://'" },
704 { 0x5A, "http-equiv=" },
705 { 0x5B, "http-equiv='Content-Type'" },
706 { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
707 { 0x5D, "http-equiv='Expires'" },
708 { 0x5E, "accesskey=" },
709 { 0x5F, "enctype=" },
710 { 0x60, "enctype='application/x-www-form-urlencoded'" },
711 { 0x61, "enctype='multipart/form-data'" },
716 /*******************************************
717 * WML 1.2 - Attribute Value *
718 *******************************************/
719 #define vals_wmlc12_attrValue vals_wmlc11_attrValue
720 /* Same as WML 1.1 */
723 /****************************************************************************/
725 /*******************************************
726 * WML 1.3 - Global tokens (EXT) *
727 *******************************************/
728 #define vals_wmlc13_global vals_wmlc11_global
730 /*******************************************
732 *******************************************/
733 #define vals_wmlc13_tags vals_wmlc12_tags
734 /* Same as WML 1.1 */
736 /*******************************************
737 * WML 1.3 - Attribute Start *
738 *******************************************/
739 static const value_string vals_wmlc13_attrStart[] = {
740 /* 0x00 -- 0x04 GLOBAL */
741 { 0x05, "accept-charset=" },
742 { 0x06, "align='bottom'" },
743 { 0x07, "align='center'" },
744 { 0x08, "align='left'" },
745 { 0x09, "align='middle'" },
746 { 0x0A, "align='right'" },
747 { 0x0B, "align='top'" },
749 { 0x0D, "content=" },
752 { 0x10, "emptyok='false'" },
753 { 0x11, "emptyok='true'" },
761 { 0x19, "localsrc=" },
762 { 0x1A, "maxlength=" },
763 { 0x1B, "method='get'" },
764 { 0x1C, "method='post'" },
765 { 0x1D, "mode='nowrap'" },
766 { 0x1E, "mode='wrap'" },
767 { 0x1F, "multiple='false'" },
768 { 0x20, "multiple='true'" },
770 { 0x22, "newcontext='false'" },
771 { 0x23, "newcontext='true'" },
773 { 0x25, "onenterbackward=" },
774 { 0x26, "onenterforward=" },
775 { 0x27, "ontimer=" },
776 { 0x28, "optional='false'" },
777 { 0x29, "optional='true'" },
781 { 0x2F, "sendreferer='false'" },
782 { 0x30, "sendreferer='true'" },
785 { 0x33, "ordered='false'" },
786 { 0x34, "ordered='true'" },
787 { 0x35, "tabindex=" },
790 { 0x38, "type='accept'" },
791 { 0x39, "type='delete'" },
792 { 0x3A, "type='help'" },
793 { 0x3B, "type='password'" },
794 { 0x3C, "type='onpick'" },
795 { 0x3D, "type='onenterbackward'" },
796 { 0x3E, "type='onenterforward'" },
797 { 0x3F, "type='ontimer'" },
798 /* 0x40 -- 0x44 GLOBAL */
799 { 0x45, "type='options'" },
800 { 0x46, "type='prev'" },
801 { 0x47, "type='reset'" },
802 { 0x48, "type='text'" },
803 { 0x49, "type='vnd.'" },
805 { 0x4B, "href='http://'" },
806 { 0x4C, "href='https://'" },
810 { 0x50, "xml:lang=" },
813 { 0x53, "columns=" },
816 { 0x56, "forua='false'" },
817 { 0x57, "forua='true'" },
818 { 0x58, "src='http://'" },
819 { 0x59, "src='https://'" },
820 { 0x5A, "http-equiv=" },
821 { 0x5B, "http-equiv='Content-Type'" },
822 { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
823 { 0x5D, "http-equiv='Expires'" },
824 { 0x5E, "accesskey=" },
825 { 0x5F, "enctype=" },
826 { 0x60, "enctype='application/x-www-form-urlencoded'" },
827 { 0x61, "enctype='multipart/form-data'" },
828 { 0x62, "xml:space='preserve'" },
829 { 0x63, "xml:space='default'" },
830 { 0x64, "cache-control='no-cache'" },
835 /*******************************************
836 * WML 1.3 - Attribute Value *
837 *******************************************/
838 #define vals_wmlc13_attrValue vals_wmlc11_attrValue
839 /* Same as WML 1.1 */
842 /****************************************************************************/
844 /*******************************************
845 * SI 1.0 - Global tokens (EXT) *
846 *******************************************/
847 static const value_string vals_sic10_global[] = {
852 /*******************************************
854 *******************************************/
855 static const value_string vals_sic10_tags[] = {
856 /* 0x00 -- 0x04 GLOBAL */
858 { 0x06, "indication" },
865 /*******************************************
866 * SI 1.0 - Attribute Start *
867 *******************************************/
868 static const value_string vals_sic10_attrStart[] = {
869 /* 0x00 -- 0x04 GLOBAL */
870 { 0x05, "action='signal-none'" },
871 { 0x06, "action='signal-low'" },
872 { 0x07, "action='signal-medium'" },
873 { 0x08, "action='signal-high'" },
874 { 0x09, "action='delete'" },
875 { 0x0a, "created=" },
877 { 0x0c, "href='http://'" },
878 { 0x0d, "href='http://www.'" },
879 { 0x0e, "href='https://'" },
880 { 0x0f, "href='https://www.'" },
881 { 0x10, "si-expires=" },
888 /*******************************************
889 * SI 1.0 - Attribute Value *
890 *******************************************/
891 static const value_string vals_sic10_attrValue[] = {
892 /* 0x80 -- 0x84 GLOBAL */
901 /****************************************************************************/
904 /*******************************************
905 * SL 1.0 - Global tokens (EXT) *
906 *******************************************/
907 static const value_string vals_slc10_global[] = {
912 /*******************************************
914 *******************************************/
915 static const value_string vals_slc10_tags[] = {
916 /* 0x00 -- 0x04 GLOBAL */
922 /*******************************************
923 * SL 1.0 - Attribute Start *
924 *******************************************/
925 static const value_string vals_slc10_attrStart[] = {
926 /* 0x00 -- 0x04 GLOBAL */
927 { 0x05, "action='execute-low'" },
928 { 0x06, "action='execute-high'" },
929 { 0x07, "action='cache'" },
931 { 0x09, "href='http://'" },
932 { 0x0a, "href='http://www.'" },
933 { 0x0b, "href='https://'" },
934 { 0x0c, "href='https://www.'" },
939 /*******************************************
940 * SL 1.0 - Attribute Value *
941 *******************************************/
942 static const value_string vals_slc10_attrValue[] = {
943 /* 0x80 -- 0x84 GLOBAL */
952 /****************************************************************************/
955 /*******************************************
956 * CO 1.0 - Global tokens (EXT) *
957 *******************************************/
958 static const value_string vals_coc10_global[] = {
963 /*******************************************
965 *******************************************/
966 static const value_string vals_coc10_tags[] = {
967 /* 0x00 -- 0x04 GLOBAL */
969 { 0x06, "invalidate-object" },
970 { 0x07, "invalidate-service" },
975 /*******************************************
976 * CO 1.0 - Attribute Start *
977 *******************************************/
978 static const value_string vals_coc10_attrStart[] = {
979 /* 0x00 -- 0x04 GLOBAL */
981 { 0x06, "uri='http://'" },
982 { 0x07, "uri='http://www.'" },
983 { 0x08, "uri='https://'" },
984 { 0x09, "uri='https://www.'" },
989 /*******************************************
990 * CO 1.0 - Attribute Value *
991 *******************************************/
992 static const value_string vals_coc10_attrValue[] = {
993 /* 0x80 -- 0x84 GLOBAL */
1003 /****************************************************************************/
1006 /*******************************************
1007 * PROV 1.0 - Global tokens (EXT) *
1008 *******************************************/
1009 static const value_string vals_provc10_global[] = {
1014 /*******************************************
1016 *******************************************/
1017 static const value_string vals_provc10_tags[] = {
1018 /* 0x00 -- 0x04 GLOBAL */
1019 { 0x05, "wap-provisioningdoc" },
1020 { 0x06, "characteristic" },
1026 /*******************************************
1027 * PROV 1.0 - Attribute Start *
1028 *******************************************/
1029 static const value_string vals_provc10_attrStart[] = {
1030 /* 0x00 -- 0x04 GLOBAL */
1033 { 0x07, "name='NAME'" },
1034 { 0x08, "name='NAP-ADDRESS'" },
1035 { 0x09, "name='NAP-ADDRTYPE'" },
1036 { 0x0A, "name='CALLTYPE'" },
1037 { 0x0B, "name='VALIDUNTIL'" },
1038 { 0x0C, "name='AUTHTYPE'" },
1039 { 0x0D, "name='AUTHNAME'" },
1040 { 0x0E, "name='AUTHSECRET'" },
1041 { 0x0F, "name='LINGER'" },
1042 { 0x10, "name='BEARER'" },
1043 { 0x11, "name='NAPID'" },
1044 { 0x12, "name='COUNTRY'" },
1045 { 0x13, "name='NETWORK'" },
1046 { 0x14, "name='INTERNET'" },
1047 { 0x15, "name='PROXY-ID'" },
1048 { 0x16, "name='PROXY-PROVIDER-ID'" },
1049 { 0x17, "name='DOMAIN'" },
1050 { 0x18, "name='PROVURL'" },
1051 { 0x19, "name='PXAUTH-TYPE'" },
1052 { 0x1A, "name='PXAUTH-ID'" },
1053 { 0x1B, "name='PXAUTH-PW'" },
1054 { 0x1C, "name='STARTPAGE'" },
1055 { 0x1D, "name='BASAUTH-ID'" },
1056 { 0x1E, "name='BASAUTH-PW'" },
1057 { 0x1F, "name='PUSHENABLED'" },
1058 { 0x20, "name='PXADDR'" },
1059 { 0x21, "name='PXADDRTYPE'" },
1060 { 0x22, "name='TO-NAPID'" },
1061 { 0x23, "name='PORTNBR'" },
1062 { 0x24, "name='SERVICE'" },
1063 { 0x25, "name='LINKSPEED'" },
1064 { 0x26, "name='DNLINKSPEED'" },
1065 { 0x27, "name='LOCAL-ADDR'" },
1066 { 0x28, "name='LOCAL-ADDRTYPE'" },
1067 { 0x29, "name='CONTEXT-ALLOW'" },
1068 { 0x2A, "name='TRUST'" },
1069 { 0x2B, "name='MASTER'" },
1070 { 0x2C, "name='SID'" },
1071 { 0x2D, "name='SOC'" },
1072 { 0x2E, "name='WSP-VERSION'" },
1073 { 0x2F, "name='PHYSICAL-PROXY-ID'" },
1074 { 0x30, "name='CLIENT-ID'" },
1075 { 0x31, "name='DELIVERY-ERR-SDU'" },
1076 { 0x32, "name='DELIVERY-ORDER'" },
1077 { 0x33, "name='TRAFFIC-CLASS'" },
1078 { 0x34, "name='MAX-SDU-SIZE'" },
1079 { 0x35, "name='MAX-BITRATE-UPLINK'" },
1080 { 0x36, "name='MAX-BITRATE-DNLINK'" },
1081 { 0x37, "name='RESIDUAL-BER'" },
1082 { 0x38, "name='SDU-ERROR-RATIO'" },
1083 { 0x39, "name='TRAFFIC-HANDL-PRIO'" },
1084 { 0x3A, "name='TRANSFER-DELAY'" },
1085 { 0x3B, "name='GUARANTEED-BITRATE-UPLINK'" },
1086 { 0x3C, "name='GUARANTEED-BITRATE-DNLINK'" },
1088 /* 0x40 -- 0x44 GLOBAL */
1089 { 0x45, "version=" },
1090 { 0x46, "version='1.0'" },
1093 { 0x51, "type='PXLOGICAL'" },
1094 { 0x52, "type='PXPHYSICAL'" },
1095 { 0x53, "type='PORT'" },
1096 { 0x54, "type='VALIDITY'" },
1097 { 0x55, "type='NAPDEF'" },
1098 { 0x56, "type='BOOTSTRAP'" },
1099 { 0x57, "type='VENDORCONFIG'" },
1100 { 0x58, "type='CLIENTIDENTITY'" },
1101 { 0x59, "type='PXAUTHINFO'" },
1102 { 0x5A, "type='NAPAUTHINFO'" },
1107 /*******************************************
1108 * PROV 1.0 - Attribute Value *
1109 *******************************************/
1110 static const value_string vals_provc10_attrValue[] = {
1111 /* 0x80 -- 0x84 GLOBAL */
1118 { 0x8B, "TETRA-ITSI" },
1121 { 0x90, "ANALOG-MODEM" },
1125 { 0x94, "BIT-TRANSPARENT" },
1126 { 0x95, "DIRECT-ASYNCHRONOUS-DATA-SERVICE" },
1130 { 0x9C, "HTTP-BASIC" },
1131 { 0x9D, "HTTP-DIGEST" },
1132 { 0x9E, "WTLS-SS" },
1134 { 0xA2, "GSM-USSD" },
1135 { 0xA3, "GSM-SMS" },
1136 { 0xA4, "ANSI-136-GUTS" },
1137 { 0xA5, "IS-95-CDMA-SMS" },
1138 { 0xA6, "IS-95-CDMA-CSD" },
1139 { 0xA7, "IS-95-CDMA-PACKET" },
1140 { 0xA8, "ANSI-136-CSD" },
1141 { 0xA9, "ANSI-136-GPRS" },
1142 { 0xAA, "GSM-CSD" },
1143 { 0xAB, "GSM-GPRS" },
1144 { 0xAC, "AMPS-CDPD" },
1145 { 0xAD, "PDC-CSD" },
1146 { 0xAE, "PDC-PACKET" },
1147 { 0xAF, "IDEN-SMS" },
1148 { 0xB0, "IDEN-CSD" },
1149 { 0xB1, "IDEN-PACKET" },
1150 { 0xB2, "FLEX/REFLEX" },
1151 { 0xB3, "PHS-SMS" },
1152 { 0xB4, "PHS-CSD" },
1153 { 0xB5, "TETRA-SDS" },
1154 { 0xB6, "TETRA-PACKET" },
1155 { 0xB7, "ANSI-136-GHOST" },
1156 { 0xB8, "MOBITEX-MPAK" },
1158 /* 0xC0 -- 0xC4 GLOBAL */
1159 { 0xC5, "AUTOBAUDING" },
1163 { 0xCC, "CL-SEC-WSP" },
1164 { 0xCD, "CO-SEC-WSP" },
1165 { 0xCE, "CL-SEC-WTA" },
1166 { 0xCF, "CO-SEC-WTA" },
1172 /****************************************************************************/
1176 /* The struct object contains references to objects defined above!
1180 const guint8 defined;
1181 const value_string *global;
1182 const value_string *tags;
1183 const value_string *attrStart;
1184 const value_string *attrValue;
1185 } wbxml_mapping_table;
1187 /* BEWARE: values 0 and 1 are not defined, so we start from 2
1189 static const wbxml_mapping_table wbxml_map[] = {
1190 { /* 0x00 = literal public identifier */
1191 FALSE, NULL, NULL, NULL, NULL
1193 { /* 0x01 = Unknown or missing public identifier */
1194 FALSE, NULL, NULL, NULL, NULL
1196 { /* 0x02 = WML 1.0 */
1197 TRUE, vals_wmlc10_global, vals_wmlc10_tags,
1198 vals_wmlc10_attrStart, vals_wmlc10_attrValue
1200 { /* 0x03 = WTA 1.0 - Deprecated */
1201 FALSE, NULL, NULL, NULL, NULL
1203 { /* 0x04 = WML 1.1 */
1204 TRUE, vals_wmlc11_global, vals_wmlc11_tags,
1205 vals_wmlc11_attrStart, vals_wmlc11_attrValue
1207 { /* 0x05 = SI 1.0 */
1208 TRUE, vals_sic10_global, vals_sic10_tags,
1209 vals_sic10_attrStart, vals_sic10_attrValue
1211 { /* 0x06 = SL 1.0 */
1212 TRUE, vals_slc10_global, vals_slc10_tags,
1213 vals_slc10_attrStart, vals_slc10_attrValue
1215 { /* 0x07 = CO 1.0 */
1216 TRUE, vals_coc10_global, vals_coc10_tags,
1217 vals_coc10_attrStart, vals_coc10_attrValue
1219 { /* 0x08 = CHANNEL 1.0 */
1220 FALSE, NULL, NULL, NULL, NULL
1222 { /* 0x09 = WML 1.2 */
1223 TRUE, vals_wmlc12_global, vals_wmlc12_tags,
1224 vals_wmlc12_attrStart, vals_wmlc12_attrValue
1226 { /* 0x0A = WML 1.3 */
1227 TRUE, vals_wmlc13_global, vals_wmlc13_tags,
1228 vals_wmlc13_attrStart, vals_wmlc13_attrValue
1230 { /* 0x0B = PROV 1.0 */
1231 TRUE, vals_provc10_global, vals_provc10_tags,
1232 vals_provc10_attrStart, vals_provc10_attrValue
1234 { /* 0x0C = WTA-WML 1.2 */
1235 FALSE, NULL, NULL, NULL, NULL
1237 { /* 0x0D = EMN 1.0 */
1238 FALSE, NULL, NULL, NULL, NULL
1240 { /* 0x0E = DRMREL 1.0 */
1241 FALSE, NULL, NULL, NULL, NULL
1244 /* Update the entry below when the table above is appended */
1245 #define WBXML_MAP_MAX_ID 0x0E
1250 /************************** Function prototypes **************************/
1255 dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
1259 proto_register_wbxml(void);
1262 /* Parse and display the WBXML string table
1265 show_wbxml_string_table (proto_tree *tree, tvbuff_t *tvb, guint32 str_tbl,
1266 guint32 str_tbl_len);
1269 /* Return a pointer to the string in the string table.
1270 * Can also be hacked for inline string retrieval.
1273 strtbl_lookup (tvbuff_t *tvb, guint32 str_tbl, guint32 offset, guint32 *len);
1276 /* Parse data while in STAG state
1279 parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
1280 guint32 str_tbl, guint8 *level,
1281 guint8 *codepage_stag, guint8 *codepage_attr, guint32 *parsed_length);
1284 /* Parse data while in STAG state;
1285 * interpret tokens as defined by content type
1288 parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
1289 guint32 str_tbl, guint8 *level,
1290 guint8 *codepage_stag, guint8 *codepage_attr, guint32 *parsed_length,
1291 const wbxml_mapping_table *map);
1294 /* Parse data while in ATTR state
1297 parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb,
1298 guint32 offset, guint32 str_tbl, guint8 level,
1299 guint8 *codepage_attr, guint32 *parsed_length);
1302 /* Parse data while in ATTR state;
1303 * interpret tokens as defined by content type
1306 parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb,
1307 guint32 offset, guint32 str_tbl, guint8 level,
1308 guint8 *codepage_attr, guint32 *parsed_length,
1309 const wbxml_mapping_table *map);
1314 /****************** WBXML protocol dissection functions ******************/
1319 /* Code to actually dissect the packets */
1321 dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1324 /* Set up structures needed to add the protocol subtree and manage it */
1326 proto_tree *wbxml_tree; /* Main WBXML tree */
1327 proto_tree *wbxml_str_tbl_tree; /* String table subtree */
1328 proto_tree *wbxml_content_tree; /* Content subtree */
1334 guint32 charset_len;
1336 guint32 publicid_index = 0;
1337 guint32 publicid_len;
1339 guint32 str_tbl_len;
1340 guint8 level = 0; /* WBXML recursion level */
1341 guint8 codepage_stag = 0; /* Initial codepage in state = STAG */
1342 guint8 codepage_attr = 0; /* Initial codepage in state = ATTR */
1346 * Version 1.0: version publicid strtbl BODY
1347 * Version 1.x: version publicid charset strtbl BODY
1349 * Last valid format: WBXML 1.3
1351 switch ( version = tvb_get_guint8 (tvb, 0) ) {
1352 case 0x00: /* WBXML/1.0 */
1355 case 0x01: /* WBXML/1.1 */
1356 case 0x02: /* WBXML/1.2 */
1357 case 0x03: /* WBXML/1.3 */
1364 if (check_col(pinfo->cinfo, COL_INFO))
1365 col_append_fstr(pinfo->cinfo, COL_INFO, " (WBXML %s:",
1366 match_strval (version, vals_wbxml_versions));
1368 /* In the interest of speed, if "tree" is NULL, don't do any work not
1369 necessary to generate protocol tree items. */
1371 /* create display subtree for the protocol */
1372 ti = proto_tree_add_item (tree, proto_wbxml, tvb, 0, -1, FALSE);
1373 wbxml_tree = proto_item_add_subtree(ti, ett_wbxml);
1376 proto_tree_add_uint (wbxml_tree, hf_wbxml_version,
1377 tvb, 0, 1, version);
1380 publicid = tvb_get_guintvar(tvb, 1, &publicid_len);
1381 if (publicid) { /* Known Public ID */
1382 if (check_col(pinfo->cinfo, COL_INFO))
1383 col_append_fstr(pinfo->cinfo, COL_INFO, " Public ID \"%s\")",
1384 match_strval (publicid, vals_wbxml_public_ids));
1385 proto_tree_add_uint(wbxml_tree, hf_wbxml_public_id_known,
1386 tvb, 1, publicid_len, publicid);
1387 } else { /* Public identifier in string table */
1388 publicid_index = tvb_get_guintvar (tvb, 1+publicid_len, &len);
1389 publicid_len += len;
1391 offset = 1 + publicid_len;
1393 /* Version-specific handling of Charset */
1394 switch ( version ) {
1395 case 0x00: /* WBXML/1.0 */
1399 case 0x01: /* WBXML/1.1 */
1400 case 0x02: /* WBXML/1.2 */
1401 case 0x03: /* WBXML/1.3 */
1403 charset = tvb_get_guintvar (tvb, offset, &charset_len);
1404 offset += charset_len;
1407 default: /* Impossible since return already earlier */
1411 /* String table: read string table length in bytes */
1412 str_tbl_len = tvb_get_guintvar (tvb, offset, &len);
1413 str_tbl = offset + len; /* Start of 1st string in string table */
1416 /* Now we can add public ID, charset (if available),
1417 * and string table */
1418 if ( ! publicid ) { /* Read Public ID from string table */
1419 token = strtbl_lookup (tvb, str_tbl, publicid_index, NULL);
1420 if (check_col(pinfo->cinfo, COL_INFO))
1421 col_append_fstr(pinfo->cinfo, COL_INFO, " Public ID \"%s\")",
1423 proto_tree_add_string (wbxml_tree, hf_wbxml_public_id_literal,
1424 tvb, 1, publicid_len, token?token:"[NULL STRING]");
1426 if ( version ) { /* Charset */
1427 proto_tree_add_uint (wbxml_tree, hf_wbxml_charset,
1428 tvb, 1+publicid_len, charset_len, charset);
1431 ti = proto_tree_add_text(wbxml_tree,
1432 tvb, offset, len + str_tbl_len, "String table: %u bytes",
1435 if (wbxml_tree && str_tbl_len) { /* Display string table as subtree */
1436 wbxml_str_tbl_tree = proto_item_add_subtree (ti,
1438 show_wbxml_string_table (wbxml_str_tbl_tree, tvb,
1439 str_tbl, str_tbl_len);
1442 /* Data starts HERE */
1443 offset += len + str_tbl_len;
1445 /* The WBXML BODY starts here */
1446 ti = proto_tree_add_text (wbxml_tree, tvb, offset, -1,
1447 "Data representation");
1448 wbxml_content_tree = proto_item_add_subtree (ti, ett_wbxml_content);
1450 /* The parse_wbxml_X() functions will process the content correctly,
1451 * irrespective of the WBXML version used. For the WBXML body, this
1452 * means that there is a different processing for the global token
1453 * RESERVED_2 (WBXML 1.0) or OPAQUE (WBXML 1.x with x > 0).
1455 if (wbxml_tree) { /* Show only if visible */
1458 printf ("WBXML - Content Type : \"%s\"\n",
1459 match_strval (publicid, vals_wbxml_public_ids));
1461 /* Look in wbxml_map[] table for defined mapping */
1462 if (publicid < WBXML_MAP_MAX_ID) {
1463 if (wbxml_map[publicid].defined) {
1464 proto_tree_add_text (wbxml_content_tree, tvb,
1467 "| WBXML Token Description "
1469 parse_wbxml_tag_defined (wbxml_content_tree,
1470 tvb, offset, str_tbl, &level,
1471 &codepage_stag, &codepage_attr, &len,
1472 wbxml_map + publicid);
1475 proto_tree_add_text (wbxml_content_tree, tvb,
1477 "Rendering of this content type"
1478 " not (yet) supported");
1481 /* Default: WBXML only, no interpretation of the content */
1482 proto_tree_add_text (wbxml_content_tree, tvb, offset, -1,
1483 "Level | State | WBXML Token Description "
1485 parse_wbxml_tag (wbxml_content_tree, tvb, offset,
1487 &codepage_stag, &codepage_attr, &len);
1490 proto_tree_add_text (wbxml_content_tree, tvb, offset, -1,
1491 "WBXML 1.0 decoding not yet supported");
1500 /* Return a pointer to the string in the string table.
1501 * Can also be hacked for inline string retrieval.
1504 strtbl_lookup (tvbuff_t *tvb, guint32 str_tbl, guint32 offset, guint32 *len)
1506 if (len) { /* The "hack" call for inline string reading */
1507 *len = tvb_strsize (tvb, str_tbl+offset);
1508 return tvb_get_ptr (tvb, str_tbl+offset, *len);
1509 } else { /* Normal string table reading */
1510 return tvb_get_ptr (tvb, str_tbl+offset,
1511 tvb_strsize (tvb, str_tbl+offset));
1518 /* Parse and display the WBXML string table (in a 3-column table format).
1519 * This function displays:
1520 * - the offset in the string table,
1521 * - the length of the string
1525 show_wbxml_string_table (proto_tree *tree, tvbuff_t *tvb, guint32 str_tbl,
1526 guint32 str_tbl_len)
1528 guint32 off = str_tbl;
1530 guint32 end = str_tbl + str_tbl_len;
1533 proto_tree_add_text (tree, tvb, off, end,
1534 "Start | Length | String");
1536 /* Hack the string table lookup function */
1537 str = strtbl_lookup (tvb, off, 0, &len);
1538 proto_tree_add_text (tree, tvb, off, len,
1540 off - str_tbl, len, str);
1548 /* Indentation code is based on a static const array of space characters.
1549 * At least one single space is returned */
1550 static const char indent_buffer[514] = " "
1559 ; /* Generate XML indentation (length = 1 + 2 * 256 + 1 for '\0') */
1561 static const char * Indent (guint8 level) {
1562 return indent_buffer + (512 - 2 * (level));
1568 /********************
1569 * WBXML tag tokens *
1570 ********************
1572 * Bit Mask : Example
1573 * -------------------
1574 * 00.. .... : <tag />
1581 * atrtribute1="value1"
1582 * atrtribute2="value2"
1586 * atrtribute1="value1"
1587 * atrtribute2="value2"
1592 * NOTE: an XML PI is parsed as an attribute list (same syntax).
1598 /* This function parses the WBXML and maps known token interpretations
1599 * to the WBXML tokens. As a result, the original XML document can be
1600 * recreated. Indentation is generated in order to ease reading.
1602 * Attribute parsing is done in parse_wbxml_attribute_list_defined().
1604 * The wbxml_mapping_table entry *map contains the actual token mapping.
1606 * NOTE: In order to parse the content, some recursion is required.
1607 * However, for performance reasons, recursion has been avoided
1608 * where possible (tags without content within tags with content).
1609 * This is achieved by means of the parsing_tag_content and tag_save*
1612 * NOTE: Code page switches not yet processed in the code!
1614 * NOTE: See above for known token mappings.
1617 parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
1618 guint32 str_tbl, guint8 *level,
1619 guint8 *codepage_stag, guint8 *codepage_attr, guint32 *parsed_length,
1620 const wbxml_mapping_table *map)
1622 guint32 tvb_len = tvb_reported_length (tvb);
1623 guint32 off = offset;
1629 guint32 tag_len; /* Length of the index (uintvar) from a LITERAL tag */
1630 guint8 tag_save_known = 0; /* Will contain peek & 0x3F (tag identity) */
1631 guint8 tag_new_known = 0; /* Will contain peek & 0x3F (tag identity) */
1632 const char *tag_save_literal; /* Will contain the LITERAL tag identity */
1633 const char *tag_new_literal; /* Will contain the LITERAL tag identity */
1634 guint8 parsing_tag_content = FALSE; /* Are we parsing content from a
1635 tag with content: <x>Content</x>
1637 The initial state is FALSE.
1638 This state will trigger recursion. */
1639 tag_save_literal = NULL; /* Prevents compiler warning */
1642 printf ("WBXML - parse_wbxml_tag_defined (level = %d, offset = %d)\n",
1645 while (off < tvb_len) {
1646 peek = tvb_get_guint8 (tvb, off);
1648 printf("WBXML - STAG: level = %3d, peek = 0x%02X, off = %d, "
1650 *level, peek, off, tvb_len);
1652 if ((peek & 0x3F) < 4) switch (peek) { /* Global tokens in state = STAG
1653 but not the LITERAL tokens */
1654 case 0x00: /* SWITCH_PAGE */
1655 peek = tvb_get_guint8 (tvb, off+1);
1656 proto_tree_add_text (tree, tvb, off, 2,
1657 " Tag | SWITCH_PAGE (Tag code page) "
1658 "| Code page switch (was: %d, is: %d)",
1659 *codepage_stag, peek);
1660 *codepage_stag = peek;
1663 case 0x01: /* END: only possible for Tag with Content */
1664 if (tag_save_known) {
1665 proto_tree_add_text (tree, tvb, off, 1,
1666 " %3d | Tag | END (Known Tag 0x%02X) "
1668 *level, tag_save_known, Indent (*level),
1669 match_strval (tag_save_known, map->tags));
1670 } else { /* Literal TAG */
1671 proto_tree_add_text (tree, tvb, off, 1,
1672 " %3d | Tag | END (Literal Tag) "
1674 *level, Indent (*level), tag_save_literal);
1678 *parsed_length = off - offset;
1681 case 0x02: /* ENTITY */
1682 ent = tvb_get_guintvar (tvb, off+1, &len);
1683 proto_tree_add_text (tree, tvb, off, 1+len,
1684 " %3d | Tag | ENTITY "
1686 *level, Indent (*level), ent);
1689 case 0x03: /* STR_I */
1690 /* Hack the string table lookup function */
1691 str = strtbl_lookup (tvb, off+1, 0, &len);
1692 proto_tree_add_text (tree, tvb, off, 1+len,
1693 " %3d | Tag | STR_I (Inline string) "
1695 *level, Indent(*level), str);
1698 case 0x40: /* EXT_I_0 */
1699 case 0x41: /* EXT_I_1 */
1700 case 0x42: /* EXT_I_2 */
1701 /* Extension tokens */
1702 /* Hack the string table lookup function */
1703 str = strtbl_lookup (tvb, off+1, 0, &len);
1704 proto_tree_add_text (tree, tvb, off, 1+len,
1705 " %3d | Tag | EXT_I_%1x (Extension Token) "
1707 *level, peek & 0x0f, Indent (*level),
1708 match_strval (peek, map->global), str);
1712 proto_tree_add_text (tree, tvb, off, 1,
1713 " %3d | Tag | PI (XML Processing Instruction) "
1715 *level, Indent (*level));
1716 parse_wbxml_attribute_list (tree, tvb, off, str_tbl,
1717 *level, codepage_attr, &len);
1719 proto_tree_add_text (tree, tvb, off-1, 1,
1720 " %3d | Tag | END (PI) "
1722 *level, Indent (*level));
1724 case 0x80: /* EXT_T_0 */
1725 case 0x81: /* EXT_T_1 */
1726 case 0x82: /* EXT_T_2 */
1727 /* Extension tokens */
1728 index = tvb_get_guintvar (tvb, off+1, &len);
1729 str = strtbl_lookup (tvb, str_tbl, index, NULL);
1730 proto_tree_add_text (tree, tvb, off, 1+len,
1731 " %3d | Tag | EXT_T_%1x (Extension Token) "
1733 *level, peek & 0x0f, Indent (*level),
1734 match_strval (peek, map->global), str);
1737 case 0x83: /* STR_T */
1738 index = tvb_get_guintvar (tvb, off+1, &len);
1739 str = strtbl_lookup (tvb, str_tbl, index, NULL);
1740 proto_tree_add_text (tree, tvb, off, 1+len,
1741 " %3d | Tag | STR_T (Tableref string) "
1743 *level, Indent (*level), str);
1746 case 0xC0: /* EXT_0 */
1747 case 0xC1: /* EXT_1 */
1748 case 0xC2: /* EXT_2 */
1749 /* Extension tokens */
1750 proto_tree_add_text (tree, tvb, off, 1,
1751 " %3d | Tag | EXT_%1x (Extension Token) "
1753 *level, peek & 0x0f, Indent (*level),
1754 match_strval (peek, map->global));
1757 case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
1758 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
1759 index = tvb_get_guintvar (tvb, off+1, &len);
1760 proto_tree_add_text (tree, tvb, off, 1 + len + index,
1761 " %3d | Tag | OPAQUE (Opaque data) "
1762 "| %s(%d bytes of opaque data)",
1763 *level, Indent (*level), index);
1765 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
1766 proto_tree_add_text (tree, tvb, off, 1,
1767 " Tag | RESERVED_2 (Invalid Token!) "
1768 "| WBXML 1.0 parsing stops here.");
1769 /* Stop processing as it is impossible to parse now */
1771 *parsed_length = off - offset;
1776 /* No default clause, as all cases have been treated */
1777 } else { /* LITERAL or Known TAG */
1779 * We must store the initial tag, and also retrieve the new tag.
1781 * There are 4 possibilities:
1783 * 1. Known tag followed by a known tag
1784 * 2. Known tag followed by a LITERAL tag
1785 * 3. LITERAL tag followed by Known tag
1786 * 4. LITERAL tag followed by LITERAL tag
1789 /* Store the new tag */
1791 if ((peek & 0x3F) == 4) { /* LITERAL */
1792 index = tvb_get_guintvar (tvb, off+1, &tag_len);
1793 tag_new_literal = strtbl_lookup (tvb, str_tbl, index, NULL);
1794 tag_new_known = 0; /* invalidate known tag_new */
1796 tag_new_known = peek & 0x3F;
1797 tag_new_literal = NULL; /* invalidate LITERAL tag_new */
1801 * Parsing of TAG starts HERE
1803 if (peek & 0x40) { /* Content present */
1805 * [!] An explicit END token is expected in these cases!
1806 * ==> Recursion possible if we encounter a tag with content;
1807 * recursion will return at the explicit END token.
1809 if (parsing_tag_content) { /* Recurse */
1811 printf ("WBXML: Tag in Tag - RECURSE! (off = %d)\n",off);
1813 /* Do not process the attribute list:
1814 * recursion will take care of it */
1816 parse_wbxml_tag_defined (tree, tvb, off, str_tbl, level,
1817 codepage_stag, codepage_attr, &len, map);
1819 } else { /* Now we will have content to parse */
1820 /* Save the start tag so we can properly close it later. */
1821 if ((peek & 0x3F) == 4) {
1822 tag_save_literal = tag_new_literal;
1825 tag_save_known = tag_new_known;
1826 tag_save_literal = NULL;
1828 /* Process the attribute list if present */
1829 if (peek & 0x80) { /* Content and Attribute list present */
1830 if (tag_new_known) { /* Known tag */
1831 proto_tree_add_text (tree, tvb, off, 1,
1833 "| Known Tag 0x%02X (AC) "
1835 *level, tag_new_known, Indent (*level),
1836 match_strval (tag_new_known, map->tags));
1838 } else { /* LITERAL tag */
1839 proto_tree_add_text (tree, tvb, off, 1,
1841 "| LITERAL_AC (Literal tag) (AC) "
1843 *level, Indent (*level), tag_new_literal);
1846 parse_wbxml_attribute_list_defined (tree, tvb,
1848 *level, codepage_attr, &len, map);
1850 proto_tree_add_text (tree, tvb, off-1, 1,
1852 "| END (attribute list) "
1854 *level, Indent (*level));
1855 } else { /* Content, no Attribute list */
1856 if (tag_new_known) { /* Known tag */
1857 proto_tree_add_text (tree, tvb, off, 1,
1859 "| Known Tag 0x%02X (.C) "
1861 *level, tag_new_known, Indent (*level),
1862 match_strval (tag_new_known, map->tags));
1864 } else { /* LITERAL tag */
1865 proto_tree_add_text (tree, tvb, off, 1,
1867 "| LITERAL_C (Literal Tag) (.C) "
1869 *level, Indent (*level), tag_new_literal);
1873 /* The data that follows in the parsing process
1874 * represents content for the opening tag
1875 * we've just processed in the lines above.
1876 * Next time we encounter a tag with content: recurse
1878 parsing_tag_content = TRUE;
1880 printf ("WBXML: Tag in Tag - No recursion this time! "
1881 "(off = %d)\n", off);
1884 } else { /* No Content */
1886 printf ("WBXML: <Tag/> in Tag - No recursion! "
1887 "(off = %d)\n", off);
1890 if (peek & 0x80) { /* No Content, Attribute list present */
1891 if (tag_new_known) { /* Known tag */
1892 proto_tree_add_text (tree, tvb, off, 1,
1894 "| Known Tag 0x%02X (A.) "
1896 *level, tag_new_known, Indent (*level),
1897 match_strval (tag_new_known, map->tags));
1899 parse_wbxml_attribute_list_defined (tree, tvb,
1901 *level, codepage_attr, &len, map);
1903 proto_tree_add_text (tree, tvb, off-1, 1,
1905 "| END (Known Tag) "
1907 *level, Indent (*level));
1908 } else { /* LITERAL tag */
1909 proto_tree_add_text (tree, tvb, off, 1,
1911 "| LITERAL_A (Literal Tag) (A.) "
1913 *level, Indent (*level), tag_new_literal);
1915 parse_wbxml_attribute_list_defined (tree, tvb,
1917 *level, codepage_attr, &len, map);
1919 proto_tree_add_text (tree, tvb, off-1, 1,
1921 "| END (Literal Tag) "
1923 *level, Indent (*level));
1925 } else { /* No Content, No Attribute list */
1926 if (tag_new_known) { /* Known tag */
1927 proto_tree_add_text (tree, tvb, off, 1,
1929 "| Known Tag 0x%02x (..) "
1931 *level, tag_new_known, Indent (*level),
1932 match_strval (tag_new_known, map->tags));
1934 } else { /* LITERAL tag */
1935 proto_tree_add_text (tree, tvb, off, 1,
1937 "| LITERAL (Literal Tag) (..) "
1939 *level, Indent (*level), tag_new_literal);
1945 } /* if (tag & 0x3F) >= 5 */
1952 /* This function performs the WBXML decoding as in parse_wbxml_tag_defined()
1953 * but this time no WBXML mapping is performed.
1955 * Attribute parsing is done in parse_wbxml_attribute_list().
1957 * NOTE: Code page switches not yet processed in the code!
1960 parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
1961 guint32 str_tbl, guint8 *level,
1962 guint8 *codepage_stag, guint8 *codepage_attr, guint32 *parsed_length)
1964 guint32 tvb_len = tvb_reported_length (tvb);
1965 guint32 off = offset;
1971 guint32 tag_len; /* Length of the index (uintvar) from a LITERAL tag */
1972 guint8 tag_save_known = 0; /* Will contain peek & 0x3F (tag identity) */
1973 guint8 tag_new_known = 0; /* Will contain peek & 0x3F (tag identity) */
1974 const char *tag_save_literal; /* Will contain the LITERAL tag identity */
1975 const char *tag_new_literal; /* Will contain the LITERAL tag identity */
1976 guint8 parsing_tag_content = FALSE; /* Are we parsing content from a
1977 tag with content: <x>Content</x>
1979 The initial state is FALSE.
1980 This state will trigger recursion. */
1981 tag_save_literal = NULL; /* Prevents compiler warning */
1984 printf ("WBXML - parse_wbxml_tag (level = %d, offset = %d)\n",
1987 while (off < tvb_len) {
1988 peek = tvb_get_guint8 (tvb, off);
1990 printf("WBXML - STAG: level = %3d, peek = 0x%02X, off = %d, "
1992 *level, peek, off, tvb_len);
1994 if ((peek & 0x3F) < 4) switch (peek) { /* Global tokens in state = STAG
1995 but not the LITERAL tokens */
1996 case 0x00: /* SWITCH_PAGE */
1997 peek = tvb_get_guint8 (tvb, off+1);
1998 proto_tree_add_text (tree, tvb, off, 2,
1999 " Tag | SWITCH_PAGE (Tag code page) "
2000 "| Code page switch (was: %d, is: %d)",
2001 *codepage_stag, peek);
2002 *codepage_stag = peek;
2005 case 0x01: /* END: only possible for Tag with Content */
2006 if (tag_save_known) {
2007 proto_tree_add_text (tree, tvb, off, 1,
2008 " %3d | Tag | END (Known Tag 0x%02X) "
2009 "| %s</Tag_0x%02X>",
2010 *level, tag_save_known, Indent (*level),
2012 } else { /* Literal TAG */
2013 proto_tree_add_text (tree, tvb, off, 1,
2014 " %3d | Tag | END (Literal Tag) "
2016 *level, Indent (*level), tag_save_literal);
2020 *parsed_length = off - offset;
2023 case 0x02: /* ENTITY */
2024 ent = tvb_get_guintvar (tvb, off+1, &len);
2025 proto_tree_add_text (tree, tvb, off, 1+len,
2026 " %3d | Tag | ENTITY "
2028 *level, Indent (*level), ent);
2031 case 0x03: /* STR_I */
2032 /* Hack the string table lookup function */
2033 str = strtbl_lookup (tvb, off+1, 0, &len);
2034 proto_tree_add_text (tree, tvb, off, 1+len,
2035 " %3d | Tag | STR_I (Inline string) "
2037 *level, Indent(*level), str);
2040 case 0x40: /* EXT_I_0 */
2041 case 0x41: /* EXT_I_1 */
2042 case 0x42: /* EXT_I_2 */
2043 /* Extension tokens */
2044 /* Hack the string table lookup function */
2045 str = strtbl_lookup (tvb, off+1, 0, &len);
2046 proto_tree_add_text (tree, tvb, off, 1+len,
2047 " %3d | Tag | EXT_I_%1x (Extension Token) "
2048 "| %s(Inline string extension: \'%s\')",
2049 *level, peek & 0x0f, Indent (*level), str);
2053 proto_tree_add_text (tree, tvb, off, 1,
2054 " %3d | Tag | PI (XML Processing Instruction) "
2056 *level, Indent (*level));
2057 parse_wbxml_attribute_list (tree, tvb, off, str_tbl,
2058 *level, codepage_attr, &len);
2060 proto_tree_add_text (tree, tvb, off-1, 1,
2061 " %3d | Tag | END (PI) "
2063 *level, Indent (*level));
2065 case 0x80: /* EXT_T_0 */
2066 case 0x81: /* EXT_T_1 */
2067 case 0x82: /* EXT_T_2 */
2068 /* Extension tokens */
2069 index = tvb_get_guintvar (tvb, off+1, &len);
2070 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2071 proto_tree_add_text (tree, tvb, off, 1+len,
2072 " %3d | Tag | EXT_T_%1x (Extension Token) "
2073 "| %s(Tableref string extension: \'%s\')",
2074 *level, peek & 0x0f, Indent (*level), str);
2077 case 0x83: /* STR_T */
2078 index = tvb_get_guintvar (tvb, off+1, &len);
2079 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2080 proto_tree_add_text (tree, tvb, off, 1+len,
2081 " %3d | Tag | STR_T (Tableref string) "
2083 *level, Indent (*level), str);
2086 case 0xC0: /* EXT_0 */
2087 case 0xC1: /* EXT_1 */
2088 case 0xC2: /* EXT_2 */
2089 /* Extension tokens */
2090 proto_tree_add_text (tree, tvb, off, 1,
2091 " %3d | Tag | EXT_%1x (Extension Token) "
2092 "| %s(Single-byte extension)",
2093 *level, peek & 0x0f, Indent (*level));
2096 case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
2097 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
2098 index = tvb_get_guintvar (tvb, off+1, &len);
2099 proto_tree_add_text (tree, tvb, off, 1 + len + index,
2100 " %3d | Tag | OPAQUE (Opaque data) "
2101 "| %s(%d bytes of opaque data)",
2102 *level, Indent (*level), index);
2104 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
2105 proto_tree_add_text (tree, tvb, off, 1,
2106 " Tag | RESERVED_2 (Invalid Token!) "
2107 "| WBXML 1.0 parsing stops here.");
2108 /* Stop processing as it is impossible to parse now */
2110 *parsed_length = off - offset;
2115 /* No default clause, as all cases have been treated */
2116 } else { /* LITERAL or Known TAG */
2118 * We must store the initial tag, and also retrieve the new tag.
2120 * There are 4 possibilities:
2122 * 1. Known tag followed by a known tag
2123 * 2. Known tag followed by a LITERAL tag
2124 * 3. LITERAL tag followed by Known tag
2125 * 4. LITERAL tag followed by LITERAL tag
2128 /* Store the new tag */
2130 if ((peek & 0x3F) == 4) { /* LITERAL */
2131 index = tvb_get_guintvar (tvb, off+1, &tag_len);
2132 tag_new_literal = strtbl_lookup (tvb, str_tbl, index, NULL);
2133 tag_new_known = 0; /* invalidate known tag_new */
2135 tag_new_known = peek & 0x3F;
2136 tag_new_literal = NULL; /* invalidate LITERAL tag_new */
2140 * Parsing of TAG starts HERE
2142 if (peek & 0x40) { /* Content present */
2144 * [!] An explicit END token is expected in these cases!
2145 * ==> Recursion possible if we encounter a tag with content;
2146 * recursion will return at the explicit END token.
2148 if (parsing_tag_content) { /* Recurse */
2150 printf ("WBXML: Tag in Tag - RECURSE! (off = %d)\n",off);
2152 /* Do not process the attribute list:
2153 * recursion will take care of it */
2155 parse_wbxml_tag (tree, tvb, off, str_tbl, level,
2156 codepage_stag, codepage_attr, &len);
2158 } else { /* Now we will have content to parse */
2159 /* Save the start tag so we can properly close it later. */
2160 if ((peek & 0x3F) == 4) {
2161 tag_save_literal = tag_new_literal;
2164 tag_save_known = tag_new_known;
2165 tag_save_literal = NULL;
2167 /* Process the attribute list if present */
2168 if (peek & 0x80) { /* Content and Attribute list present */
2169 if (tag_new_known) { /* Known tag */
2170 proto_tree_add_text (tree, tvb, off, 1,
2172 "| Known Tag 0x%02X (AC) "
2174 *level, tag_new_known, Indent (*level),
2177 } else { /* LITERAL tag */
2178 proto_tree_add_text (tree, tvb, off, 1,
2180 "| LITERAL_AC (Literal tag) (AC) "
2182 *level, Indent (*level), tag_new_literal);
2185 parse_wbxml_attribute_list (tree, tvb, off, str_tbl,
2186 *level, codepage_attr, &len);
2188 proto_tree_add_text (tree, tvb, off-1, 1,
2190 "| END (attribute list) "
2192 *level, Indent (*level));
2193 } else { /* Content, no Attribute list */
2194 if (tag_new_known) { /* Known tag */
2195 proto_tree_add_text (tree, tvb, off, 1,
2197 "| Known Tag 0x%02X (.C) "
2199 *level, tag_new_known, Indent (*level),
2202 } else { /* LITERAL tag */
2203 proto_tree_add_text (tree, tvb, off, 1,
2205 "| LITERAL_C (Literal Tag) (.C) "
2207 *level, Indent (*level), tag_new_literal);
2211 /* The data that follows in the parsing process
2212 * represents content for the opening tag
2213 * we've just processed in the lines above.
2214 * Next time we encounter a tag with content: recurse
2216 parsing_tag_content = TRUE;
2218 printf ("WBXML: Tag in Tag - No recursion this time! "
2219 "(off = %d)\n", off);
2222 } else { /* No Content */
2224 printf ("WBXML: <Tag/> in Tag - No recursion! "
2225 "(off = %d)\n", off);
2228 if (peek & 0x80) { /* No Content, Attribute list present */
2229 if (tag_new_known) { /* Known tag */
2230 proto_tree_add_text (tree, tvb, off, 1,
2232 "| Known Tag 0x%02X (A.) "
2234 *level, tag_new_known, Indent (*level),
2237 parse_wbxml_attribute_list (tree, tvb, off, str_tbl,
2238 *level, codepage_attr, &len);
2240 proto_tree_add_text (tree, tvb, off-1, 1,
2242 "| END (Known Tag) "
2244 *level, Indent (*level));
2245 } else { /* LITERAL tag */
2246 proto_tree_add_text (tree, tvb, off, 1,
2248 "| LITERAL_A (Literal Tag) (A.) "
2250 *level, Indent (*level), tag_new_literal);
2252 parse_wbxml_attribute_list (tree, tvb, off, str_tbl,
2253 *level, codepage_attr, &len);
2255 proto_tree_add_text (tree, tvb, off-1, 1,
2257 "| END (Literal Tag) "
2259 *level, Indent (*level));
2261 } else { /* No Content, No Attribute list */
2262 if (tag_new_known) { /* Known tag */
2263 proto_tree_add_text (tree, tvb, off, 1,
2265 "| Known Tag 0x%02x (..) "
2266 "| %s<Tag_0x%02X />",
2267 *level, tag_new_known, Indent (*level),
2270 } else { /* LITERAL tag */
2271 proto_tree_add_text (tree, tvb, off, 1,
2273 "| LITERAL (Literal Tag) (..) "
2275 *level, Indent (*level), tag_new_literal);
2281 } /* if (tag & 0x3F) >= 5 */
2288 /**************************
2289 * WBXML Attribute tokens *
2290 **************************
2291 * Bit Mask : Example
2292 * -------------------
2293 * 0... .... : attr= (attribute name)
2294 * href="http://" (attribute name with start of attribute value)
2295 * 1... .... : "www." (attribute value, or part of it)
2302 /* This function parses the WBXML and maps known token interpretations
2303 * to the WBXML tokens. As a result, the original XML document can be
2304 * recreated. Indentation is generated in order to ease reading.
2306 * This function performs attribute list parsing.
2308 * The wbxml_mapping_table entry *map contains the actual token mapping.
2310 * NOTE: See above for known token mappings.
2312 * NOTE: Code page switches not yet processed in the code!
2315 parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb,
2316 guint32 offset, guint32 str_tbl, guint8 level,
2317 guint8 *codepage_attr, guint32 *parsed_length,
2318 const wbxml_mapping_table *map)
2320 guint32 tvb_len = tvb_reported_length (tvb);
2321 guint32 off = offset;
2329 printf ("WBXML - parse_wbxml_attr_defined (level = %d, offset = %d)\n",
2332 /* Parse attributes */
2333 while (off < tvb_len) {
2334 peek = tvb_get_guint8 (tvb, off);
2336 printf("WBXML - ATTR: level = %3d, peek = 0x%02X, off = %d, "
2338 level, peek, off, tvb_len);
2340 if ((peek & 0x3F) < 5) switch (peek) { /* Global tokens
2342 case 0x00: /* SWITCH_PAGE */
2343 peek = tvb_get_guint8 (tvb, off+1);
2344 proto_tree_add_text (tree, tvb, off, 2,
2345 " Attr | SWITCH_PAGE (Attr code page) "
2346 "| Code page switch (was: %d, is: %d)",
2347 *codepage_attr, peek);
2348 *codepage_attr = peek;
2351 case 0x01: /* END */
2353 * The Attribute END token means either ">" or "/>"
2354 * and as a consequence both must be trated separately.
2355 * This is done in the TAG state parser.
2358 *parsed_length = off - offset;
2360 case 0x02: /* ENTITY */
2361 ent = tvb_get_guintvar (tvb, off+1, &len);
2362 proto_tree_add_text (tree, tvb, off, 1+len,
2363 " %3d | Attr | ENTITY "
2365 level, Indent (level), ent);
2368 case 0x03: /* STR_I */
2369 /* Hack the string table lookup function */
2370 str = strtbl_lookup (tvb, off+1, 0, &len);
2371 proto_tree_add_text (tree, tvb, off, 1+len,
2372 " %3d | Attr | STR_I (Inline string) "
2374 level, Indent (level), str);
2377 case 0x04: /* LITERAL */
2378 index = tvb_get_guintvar (tvb, off+1, &len);
2379 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2380 proto_tree_add_text (tree, tvb, off, 1+len,
2381 " %3d | Attr | LITERAL (Literal Attribute) "
2383 level, Indent (level), str);
2386 case 0x40: /* EXT_I_0 */
2387 case 0x41: /* EXT_I_1 */
2388 case 0x42: /* EXT_I_2 */
2389 /* Extension tokens */
2390 /* Hack the string table lookup function */
2391 str = strtbl_lookup (tvb, off+1, 0, &len);
2392 proto_tree_add_text (tree, tvb, off, 1+len,
2393 " %3d | Attr | EXT_I_%1x (Extension Token) "
2395 level, peek & 0x0f, Indent (level),
2396 match_strval (peek, map->global), str);
2399 /* 0x43 impossible in ATTR state */
2400 /* 0x44 impossible in ATTR state */
2401 case 0x80: /* EXT_T_0 */
2402 case 0x81: /* EXT_T_1 */
2403 case 0x82: /* EXT_T_2 */
2404 /* Extension tokens */
2405 index = tvb_get_guintvar (tvb, off+1, &len);
2406 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2407 proto_tree_add_text (tree, tvb, off, 1+len,
2408 " %3d | Attr | EXT_T_%1x (Extension Token) "
2410 level, peek & 0x0f, Indent (level),
2411 match_strval (peek, map->global), str);
2414 case 0x83: /* EXT_T */
2415 index = tvb_get_guintvar (tvb, off+1, &len);
2416 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2417 proto_tree_add_text (tree, tvb, off, 1+len,
2418 " %3d | Attr | STR_T (Tableref string) "
2420 level, Indent (level), str);
2423 /* 0x84 impossible in ATTR state */
2424 case 0xC0: /* EXT_0 */
2425 case 0xC1: /* EXT_1 */
2426 case 0xC2: /* EXT_2 */
2427 /* Extension tokens */
2428 proto_tree_add_text (tree, tvb, off, 1,
2429 " %3d | Attr | EXT_%1x (Extension Token) "
2431 level, peek & 0x0f, Indent (level),
2432 match_strval (peek, map->global));
2435 case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
2436 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
2437 index = tvb_get_guintvar (tvb, off+1, &len);
2438 proto_tree_add_text (tree, tvb, off, 1 + len + index,
2439 " %3d | Attr | OPAQUE (Opaque data) "
2440 "| %s(%d bytes of opaque data)",
2441 level, Indent (level), index);
2443 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
2444 proto_tree_add_text (tree, tvb, off, 1,
2445 " Attr | RESERVED_2 (Invalid Token!) "
2446 "| WBXML 1.0 parsing stops here.");
2447 /* Stop processing as it is impossible to parse now */
2449 *parsed_length = off - offset;
2453 /* 0xC4 impossible in ATTR state */
2455 proto_tree_add_text (tree, tvb, off, 1,
2456 " %3d | Attr | %-10s (Invalid Token!) "
2457 "| WBXML parsing stops here.",
2458 level, match_strval (peek, vals_wbxml1x_global_tokens));
2459 /* Move to end of buffer */
2462 } else { /* Known atribute token */
2463 if (peek & 0x80) { /* attrValue */
2464 proto_tree_add_text (tree, tvb, off, 1,
2465 " %3d | Attr | Known attrValue 0x%02X "
2467 level, peek & 0x7f, Indent (level),
2468 match_strval (peek, map->attrValue));
2470 } else { /* attrStart */
2471 proto_tree_add_text (tree, tvb, off, 1,
2472 " %3d | Attr | Known attrStart 0x%02X "
2474 level, peek & 0x7f, Indent (level),
2475 match_strval (peek, map->attrStart));
2485 /* This function performs the WBXML attribute decoding as in
2486 * parse_wbxml_attribute_list_defined() but this time no WBXML mapping
2489 * This function performs attribute list parsing.
2491 * NOTE: Code page switches not yet processed in the code!
2494 parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb,
2495 guint32 offset, guint32 str_tbl, guint8 level,
2496 guint8 *codepage_attr, guint32 *parsed_length)
2498 guint32 tvb_len = tvb_reported_length (tvb);
2499 guint32 off = offset;
2507 printf ("WBXML - parse_wbxml_attr_defined (level = %d, offset = %d)\n",
2510 /* Parse attributes */
2511 while (off < tvb_len) {
2512 peek = tvb_get_guint8 (tvb, off);
2514 printf("WBXML - ATTR: level = %3d, peek = 0x%02X, off = %d, "
2516 level, peek, off, tvb_len);
2518 if ((peek & 0x3F) < 5) switch (peek) { /* Global tokens
2520 case 0x00: /* SWITCH_PAGE */
2521 peek = tvb_get_guint8 (tvb, off+1);
2522 proto_tree_add_text (tree, tvb, off, 2,
2523 " Attr | SWITCH_PAGE (Attr code page) "
2524 "| Code page switch (was: %d, is: %d)",
2525 *codepage_attr, peek);
2526 *codepage_attr = peek;
2529 case 0x01: /* END */
2531 * The Attribute END token means either ">" or "/>"
2532 * and as a consequence both must be trated separately.
2533 * This is done in the TAG state parser.
2536 *parsed_length = off - offset;
2538 case 0x02: /* ENTITY */
2539 ent = tvb_get_guintvar (tvb, off+1, &len);
2540 proto_tree_add_text (tree, tvb, off, 1+len,
2541 " %3d | Attr | ENTITY "
2543 level, Indent (level), ent);
2546 case 0x03: /* STR_I */
2547 /* Hack the string table lookup function */
2548 str = strtbl_lookup (tvb, off+1, 0, &len);
2549 proto_tree_add_text (tree, tvb, off, 1+len,
2550 " %3d | Attr | STR_I (Inline string) "
2552 level, Indent (level), str);
2555 case 0x04: /* LITERAL */
2556 index = tvb_get_guintvar (tvb, off+1, &len);
2557 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2558 proto_tree_add_text (tree, tvb, off, 1+len,
2559 " %3d | Attr | LITERAL (Literal Attribute) "
2561 level, Indent (level), str);
2564 case 0x40: /* EXT_I_0 */
2565 case 0x41: /* EXT_I_1 */
2566 case 0x42: /* EXT_I_2 */
2567 /* Extension tokens */
2568 /* Hack the string table lookup function */
2569 str = strtbl_lookup (tvb, off+1, 0, &len);
2570 proto_tree_add_text (tree, tvb, off, 1+len,
2571 " %3d | Attr | EXT_I_%1x (Extension Token) "
2572 "| %s(Inline string extension: \'%s\')",
2573 level, peek & 0x0f, Indent (level), str);
2576 /* 0x43 impossible in ATTR state */
2577 /* 0x44 impossible in ATTR state */
2578 case 0x80: /* EXT_T_0 */
2579 case 0x81: /* EXT_T_1 */
2580 case 0x82: /* EXT_T_2 */
2581 /* Extension tokens */
2582 index = tvb_get_guintvar (tvb, off+1, &len);
2583 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2584 proto_tree_add_text (tree, tvb, off, 1+len,
2585 " %3d | Attr | EXT_T_%1x (Extension Token) "
2586 "| %s(Tableref string extension: \'%s\')",
2587 level, peek & 0x0f, Indent (level), str);
2590 case 0x83: /* EXT_T */
2591 index = tvb_get_guintvar (tvb, off+1, &len);
2592 str = strtbl_lookup (tvb, str_tbl, index, NULL);
2593 proto_tree_add_text (tree, tvb, off, 1+len,
2594 " %3d | Attr | STR_T (Tableref string) "
2596 level, Indent (level), str);
2599 /* 0x84 impossible in ATTR state */
2600 case 0xC0: /* EXT_0 */
2601 case 0xC1: /* EXT_1 */
2602 case 0xC2: /* EXT_2 */
2603 /* Extension tokens */
2604 proto_tree_add_text (tree, tvb, off, 1,
2605 " %3d | Attr | EXT_%1x (Extension Token) "
2606 "| %s(Single-byte extension)",
2607 level, peek & 0x0f, Indent (level));
2610 case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
2611 if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
2612 index = tvb_get_guintvar (tvb, off+1, &len);
2613 proto_tree_add_text (tree, tvb, off, 1 + len + index,
2614 " %3d | Attr | OPAQUE (Opaque data) "
2615 "| %s(%d bytes of opaque data)",
2616 level, Indent (level), index);
2618 } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
2619 proto_tree_add_text (tree, tvb, off, 1,
2620 " Attr | RESERVED_2 (Invalid Token!) "
2621 "| WBXML 1.0 parsing stops here.");
2622 /* Stop processing as it is impossible to parse now */
2624 *parsed_length = off - offset;
2628 /* 0xC4 impossible in ATTR state */
2630 proto_tree_add_text (tree, tvb, off, 1,
2631 " %3d | Attr | %-10s (Invalid Token!) "
2632 "| WBXML parsing stops here.",
2633 level, match_strval (peek, vals_wbxml1x_global_tokens));
2634 /* Move to end of buffer */
2637 } else { /* Known atribute token */
2638 if (peek & 0x80) { /* attrValue */
2639 proto_tree_add_text (tree, tvb, off, 1,
2640 " %3d | Attr | Known attrValue 0x%02X "
2641 "| %sattrValue_0x%02X",
2642 level, peek & 0x7f, Indent (level), peek);
2644 } else { /* attrStart */
2645 proto_tree_add_text (tree, tvb, off, 1,
2646 " %3d | Attr | Known attrStart 0x%02X "
2647 "| %sattrStart_0x%02X",
2648 level, peek & 0x7f, Indent (level), peek);
2658 /****************** Register the protocol with Ethereal ******************/
2660 /* This format is required because a script is used to build the C function
2661 * that calls the protocol registration.
2665 proto_register_wbxml(void)
2668 /* Setup list of header fields See Section 1.6.1 for details*/
2669 static hf_register_info hf[] = {
2670 { &hf_wbxml_version,
2674 VALS ( vals_wbxml_versions ), 0x00,
2675 "WBXML Version", HFILL }
2678 { &hf_wbxml_public_id_known,
2679 { "Public Identifier (known)",
2680 "wbxml.public_id.known",
2681 FT_UINT32, BASE_HEX,
2682 VALS ( vals_wbxml_public_ids ), 0x00,
2683 "WBXML Known Public Identifier (integer)",
2687 { &hf_wbxml_public_id_literal,
2688 { "Public Identifier (literal)",
2689 "wbxml.public_id.literal",
2690 FT_STRING, BASE_NONE,
2692 "WBXML Literal Public Identifier (text string)",
2696 { &hf_wbxml_charset,
2699 FT_UINT32, BASE_HEX,
2700 VALS ( vals_character_sets ), 0x00,
2701 "WBXML Character Set", HFILL }
2706 /* Setup protocol subtree array */
2707 static gint *ett[] = {
2713 /* Register the protocol name and description */
2714 proto_wbxml = proto_register_protocol(
2720 /* Required function calls to register the header fields and subtrees used */
2721 proto_register_field_array(proto_wbxml, hf, array_length(hf));
2722 proto_register_subtree_array(ett, array_length(ett));
2724 register_dissector("wbxml", dissect_wbxml, proto_wbxml);
2725 /* register_init_routine(dissect_wbxml); */
2726 /* wbxml_handle = find_dissector("wsp-co"); */
2731 proto_reg_handoff_wbxml(void)
2733 dissector_handle_t wbxml_handle;
2735 /* Heuristic dissectors would be declared by means of:
2736 * heur_dissector_add("wsp", dissect_wbxml_heur, proto_wbxml);
2739 wbxml_handle = create_dissector_handle(dissect_wbxml, proto_wbxml);
2741 /* Register the WSP content types (defined as protocol port)
2742 * for WBXML dissection.
2744 * See http://www.wapforum.org/wina/wsp-content-type.htm
2747 /**** Well-known WBXML WSP Content-Type values ****/
2749 /* application/vnd.wap.wmlc */
2750 dissector_add("wsp.content_type.type", 0x14, wbxml_handle);
2752 /* application/vnd.wap.wta-eventc */
2753 dissector_add("wsp.content_type.type", 0x16, wbxml_handle);
2755 /* application/vnd.wap.wbxml */
2756 dissector_add("wsp.content_type.type", 0x29, wbxml_handle);
2758 /* application/vnd.wap.sic */
2759 dissector_add("wsp.content_type.type", 0x2E, wbxml_handle);
2761 /* application/vnd.wap.slc */
2762 dissector_add("wsp.content_type.type", 0x30, wbxml_handle);
2764 /* application/vnd.wap.coc */
2765 dissector_add("wsp.content_type.type", 0x32, wbxml_handle);
2767 /* application/vnd.wap.connectivity-wbxml */
2768 dissector_add("wsp.content_type.type", 0x36, wbxml_handle);
2770 /* application/vnd.wap.locc+wbxml */
2771 dissector_add("wsp.content_type.type", 0x40, wbxml_handle);
2773 /* application/vnd.syncml.dm+wbxml */
2774 dissector_add("wsp.content_type.type", 0x42, wbxml_handle);
2776 /* application/vnd.oma.drm.rights+wbxml */
2777 dissector_add("wsp.content_type.type", 0x4B, wbxml_handle);
2779 #ifdef WSP_DISSECTOR_REGISTERS_ContentType_AS_FourByteGuint
2781 /**** Registered WBXML WSP Content-Type values ****/
2783 /* application/vnd.uplanet.cacheop-wbxml */
2784 dissector_add("wsp.content_type.type", 0x0201, wbxml_handle);
2786 /* application/vnd.uplanet.alert-wbxml */
2787 dissector_add("wsp.content_type.type", 0x0203, wbxml_handle);
2789 /* application/vnd.uplanet.list-wbxml */
2790 dissector_add("wsp.content_type.type", 0x0204, wbxml_handle);
2792 /* application/vnd.uplanet.listcmd-wbxml */
2793 dissector_add("wsp.content_type.type", 0x0205, wbxml_handle);
2795 /* application/vnd.uplanet.channel-wbxml */
2796 dissector_add("wsp.content_type.type", 0x0206, wbxml_handle);
2798 /* application/vnd.uplanet.bearer-choice-wbxml */
2799 dissector_add("wsp.content_type.type", 0x0209, wbxml_handle);
2801 /* application/vnd.phonecom.mmc-wbxml */
2802 dissector_add("wsp.content_type.type", 0x020A, wbxml_handle);
2804 /* application/vnd.nokia.syncset+wbxml */
2805 dissector_add("wsp.content_type.type", 0x020B, wbxml_handle);