Remove the literal WSP content type dissector table, and replace it with the "media_t...
[obnox/wireshark/wip.git] / packet-wsp.c
1 /* packet-wsp.c
2  *
3  * Routines to dissect WSP component of WAP traffic.
4  *
5  * $Id: packet-wsp.c,v 1.93 2003/12/07 18:09:52 obiot Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * WAP dissector based on original work by Ben Fowler
12  * Updated by Neil Hunter <neil.hunter@energis-squared.com>
13  * WTLS support by Alexandre P. Ferreira (Splice IP)
14  * Openwave header support by Dermot Bradley <dermot.bradley@openwave.com>
15  * Code optimizations, header value dissection simplification with parse error
16  * notification and macros, extra missing headers, WBXML registration
17  * by Olivier Biot <olivier.biot(ad)siemens.com>.
18  *
19  * This program is free software; you can redistribute it and/or
20  * modify it under the terms of the GNU General Public License
21  * as published by the Free Software Foundation; either version 2
22  * of the License, or (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program; if not, write to the Free Software
31  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
32  */
33
34 /* Edit with a 4-space tabulation */
35
36 #ifdef HAVE_CONFIG_H
37 # include "config.h"
38 #endif
39
40 #include <stdio.h>
41 #include <stdlib.h>
42
43 #ifdef NEED_SNPRINTF_H
44 # include "snprintf.h"
45 #endif
46
47 #include <string.h>
48 #include <glib.h>
49 #include <epan/packet.h>
50 #include <epan/ipv6-utils.h>
51 #include <epan/conversation.h>
52
53 #include "packet-wap.h"
54 #include "packet-wsp.h"
55
56 #define PLURALIZE(x)    ( (x) == 1 ? "" : "s" )
57
58 /* Statistics (see doc/README.tapping) */
59 #include "tap.h"
60 static int wsp_tap = -1;
61
62
63 /* File scoped variables for the protocol and registered fields */
64 static int proto_wsp                                    = HF_EMPTY;
65
66 /*
67  * Initialize the header field pointers
68  */
69
70 /* WSP header fields and their subfields if available */
71 static int hf_hdr_name                                  = HF_EMPTY;
72 static int hf_hdr_id                                    = HF_EMPTY;
73 static int hf_hdr_accept                                = HF_EMPTY;
74 static int hf_hdr_accept_charset                = HF_EMPTY;
75 static int hf_hdr_accept_encoding               = HF_EMPTY;
76 static int hf_hdr_accept_language               = HF_EMPTY;
77 static int hf_hdr_accept_ranges                 = HF_EMPTY;
78 static int hf_hdr_age                                   = HF_EMPTY;
79 static int hf_hdr_allow                                 = HF_EMPTY;
80 static int hf_hdr_authorization                 = HF_EMPTY;
81 static int hf_hdr_authorization_scheme                  = HF_EMPTY; /* Subfield */
82 static int hf_hdr_authorization_user_id                 = HF_EMPTY; /* Subfield */
83 static int hf_hdr_authorization_password                = HF_EMPTY; /* Subfield */
84 static int hf_hdr_cache_control                 = HF_EMPTY;
85 static int hf_hdr_connection                    = HF_EMPTY;
86 static int hf_hdr_content_base                  = HF_EMPTY;
87 static int hf_hdr_content_encoding              = HF_EMPTY;
88 static int hf_hdr_content_language              = HF_EMPTY;
89 static int hf_hdr_content_length                = HF_EMPTY;
90 static int hf_hdr_content_location              = HF_EMPTY;
91 static int hf_hdr_content_md5                   = HF_EMPTY;
92 static int hf_hdr_content_range                 = HF_EMPTY;
93 static int hf_hdr_content_range_first_byte_pos  = HF_EMPTY; /* Subfield */
94 static int hf_hdr_content_range_entity_length   = HF_EMPTY; /* Subfield */
95 static int hf_hdr_content_type                  = HF_EMPTY;
96 static int hf_hdr_date                                  = HF_EMPTY;
97 static int hf_hdr_etag                                  = HF_EMPTY;
98 static int hf_hdr_expires                               = HF_EMPTY;
99 static int hf_hdr_from                                  = HF_EMPTY;
100 static int hf_hdr_host                                  = HF_EMPTY;
101 static int hf_hdr_if_modified_since             = HF_EMPTY;
102 static int hf_hdr_if_match                              = HF_EMPTY;
103 static int hf_hdr_if_none_match                 = HF_EMPTY;
104 static int hf_hdr_if_range                              = HF_EMPTY;
105 static int hf_hdr_if_unmodified_since   = HF_EMPTY;
106 static int hf_hdr_last_modified                 = HF_EMPTY;
107 static int hf_hdr_location                              = HF_EMPTY;
108 static int hf_hdr_max_forwards                  = HF_EMPTY;
109 static int hf_hdr_pragma                                = HF_EMPTY;
110 static int hf_hdr_proxy_authenticate    = HF_EMPTY;
111 static int hf_hdr_proxy_authenticate_scheme             = HF_EMPTY; /* Subfield */
112 static int hf_hdr_proxy_authenticate_realm              = HF_EMPTY; /* Subfield */
113 static int hf_hdr_proxy_authorization   = HF_EMPTY;
114 static int hf_hdr_proxy_authorization_scheme    = HF_EMPTY; /* Subfield */
115 static int hf_hdr_proxy_authorization_user_id   = HF_EMPTY; /* Subfield */
116 static int hf_hdr_proxy_authorization_password  = HF_EMPTY; /* Subfield */
117 static int hf_hdr_public                                = HF_EMPTY;
118 static int hf_hdr_range                                 = HF_EMPTY;
119 static int hf_hdr_range_first_byte_pos                  = HF_EMPTY; /* Subfield */
120 static int hf_hdr_range_last_byte_pos                   = HF_EMPTY; /* Subfield */
121 static int hf_hdr_range_suffix_length                   = HF_EMPTY; /* Subfield */
122 static int hf_hdr_referer                               = HF_EMPTY;
123 static int hf_hdr_retry_after                   = HF_EMPTY;
124 static int hf_hdr_server                                = HF_EMPTY;
125 static int hf_hdr_transfer_encoding             = HF_EMPTY;
126 static int hf_hdr_upgrade                               = HF_EMPTY;
127 static int hf_hdr_user_agent                    = HF_EMPTY;
128 static int hf_hdr_vary                                  = HF_EMPTY;
129 static int hf_hdr_via                                   = HF_EMPTY;
130 static int hf_hdr_warning                               = HF_EMPTY;
131 static int hf_hdr_warning_code                                  = HF_EMPTY; /* Subfield */
132 static int hf_hdr_warning_agent                                 = HF_EMPTY; /* Subfield */
133 static int hf_hdr_warning_text                                  = HF_EMPTY; /* Subfield */
134 static int hf_hdr_www_authenticate              = HF_EMPTY;
135 static int hf_hdr_www_authenticate_scheme               = HF_EMPTY; /* Subfield */
136 static int hf_hdr_www_authenticate_realm                = HF_EMPTY; /* Subfield */
137 static int hf_hdr_content_disposition   = HF_EMPTY;
138 static int hf_hdr_application_id                = HF_EMPTY;
139 static int hf_hdr_content_uri                   = HF_EMPTY;
140 static int hf_hdr_initiator_uri                 = HF_EMPTY;
141 static int hf_hdr_bearer_indication             = HF_EMPTY;
142 static int hf_hdr_push_flag                             = HF_EMPTY;
143 static int hf_hdr_push_flag_auth                                = HF_EMPTY; /* Subfield */
144 static int hf_hdr_push_flag_trust                               = HF_EMPTY; /* Subfield */
145 static int hf_hdr_push_flag_last                                = HF_EMPTY; /* Subfield */
146 static int hf_hdr_profile                               = HF_EMPTY;
147 static int hf_hdr_profile_diff                  = HF_EMPTY;
148 static int hf_hdr_profile_warning               = HF_EMPTY;
149 static int hf_hdr_expect                                = HF_EMPTY;
150 static int hf_hdr_te                                    = HF_EMPTY;
151 static int hf_hdr_trailer                               = HF_EMPTY;
152 static int hf_hdr_x_wap_tod                             = HF_EMPTY;
153 static int hf_hdr_content_id                    = HF_EMPTY;
154 static int hf_hdr_set_cookie                    = HF_EMPTY;
155 static int hf_hdr_cookie                                = HF_EMPTY;
156 static int hf_hdr_encoding_version              = HF_EMPTY;
157 static int hf_hdr_x_wap_security                = HF_EMPTY;
158 static int hf_hdr_x_wap_application_id  = HF_EMPTY;
159 static int hf_hdr_accept_application    = HF_EMPTY;
160
161
162 /* Openwave headers */
163 static int hf_hdr_openwave_x_up_proxy_operator_domain   = HF_EMPTY;
164 static int hf_hdr_openwave_x_up_proxy_home_page                 = HF_EMPTY;
165 static int hf_hdr_openwave_x_up_proxy_uplink_version    = HF_EMPTY;
166 static int hf_hdr_openwave_x_up_proxy_ba_realm                  = HF_EMPTY;
167 static int hf_hdr_openwave_x_up_proxy_request_uri               = HF_EMPTY;
168 #if 0
169 static int hf_hdr_openwave_x_up_proxy_client_id                 = HF_EMPTY;
170 #endif
171 static int hf_hdr_openwave_x_up_proxy_bookmark                  = HF_EMPTY;
172 static int hf_hdr_openwave_x_up_proxy_push_seq                  = HF_EMPTY;
173 static int hf_hdr_openwave_x_up_proxy_notify                    = HF_EMPTY;
174 static int hf_hdr_openwave_x_up_proxy_net_ask                   = HF_EMPTY;
175 static int hf_hdr_openwave_x_up_proxy_tod                               = HF_EMPTY;
176 static int hf_hdr_openwave_x_up_proxy_ba_enable                 = HF_EMPTY;
177 static int hf_hdr_openwave_x_up_proxy_redirect_enable   = HF_EMPTY;
178 static int hf_hdr_openwave_x_up_proxy_redirect_status   = HF_EMPTY;
179 static int hf_hdr_openwave_x_up_proxy_linger                    = HF_EMPTY;
180 static int hf_hdr_openwave_x_up_proxy_enable_trust              = HF_EMPTY;
181 static int hf_hdr_openwave_x_up_proxy_trust                             = HF_EMPTY;
182 static int hf_hdr_openwave_x_up_devcap_has_color                = HF_EMPTY;
183 static int hf_hdr_openwave_x_up_devcap_num_softkeys             = HF_EMPTY;
184 static int hf_hdr_openwave_x_up_devcap_softkey_size             = HF_EMPTY;
185 static int hf_hdr_openwave_x_up_devcap_screen_chars             = HF_EMPTY;
186 static int hf_hdr_openwave_x_up_devcap_screen_pixels    = HF_EMPTY;
187 static int hf_hdr_openwave_x_up_devcap_em_size                  = HF_EMPTY;
188 static int hf_hdr_openwave_x_up_devcap_screen_depth             = HF_EMPTY;
189 static int hf_hdr_openwave_x_up_devcap_immed_alert              = HF_EMPTY;
190 static int hf_hdr_openwave_x_up_devcap_gui                              = HF_EMPTY;
191 static int hf_hdr_openwave_x_up_proxy_trans_charset             = HF_EMPTY;
192 static int hf_hdr_openwave_x_up_proxy_push_accept               = HF_EMPTY;
193
194
195 /* WSP parameter fields */
196 static int hf_parameter_q                                       = HF_EMPTY;
197 static int hf_parameter_charset                         = HF_EMPTY;
198 #if 0
199 static int hf_parameter_textual                         = HF_EMPTY;
200 static int hf_parameter_type                            = HF_EMPTY;
201 static int hf_parameter_name                            = HF_EMPTY;
202 static int hf_parameter_filename                        = HF_EMPTY;
203 static int hf_parameter_start                           = HF_EMPTY;
204 static int hf_parameter_start_info                      = HF_EMPTY;
205 static int hf_parameter_comment                         = HF_EMPTY;
206 static int hf_parameter_domain                          = HF_EMPTY;
207 static int hf_parameter_path                            = HF_EMPTY;
208 static int hf_parameter_sec                                     = HF_EMPTY;
209 static int hf_parameter_mac                                     = HF_EMPTY;
210 static int hf_parameter_upart_type                      = HF_EMPTY;
211 static int hf_parameter_upart_type_value        = HF_EMPTY;
212 static int hf_parameter_level                           = HF_EMPTY;
213 #endif
214
215 /* Old header fields */
216
217 static int hf_wsp_header_tid                            = HF_EMPTY;
218 static int hf_wsp_header_pdu_type                       = HF_EMPTY;
219 static int hf_wsp_version_major                         = HF_EMPTY;
220 static int hf_wsp_version_minor                         = HF_EMPTY;
221 static int hf_wsp_capability_length                     = HF_EMPTY;
222 static int hf_wsp_capabilities_section                  = HF_EMPTY;
223 static int hf_wsp_capabilities_client_SDU               = HF_EMPTY;
224 static int hf_wsp_capabilities_server_SDU               = HF_EMPTY;
225 static int hf_wsp_capabilities_protocol_opt             = HF_EMPTY;
226 static int hf_wsp_capabilities_method_MOR               = HF_EMPTY;
227 static int hf_wsp_capabilities_push_MOR                 = HF_EMPTY;
228 static int hf_wsp_capabilities_extended_methods         = HF_EMPTY;
229 static int hf_wsp_capabilities_header_code_pages        = HF_EMPTY;
230 static int hf_wsp_capabilities_aliases                  = HF_EMPTY;
231 static int hf_wsp_header_uri_len                        = HF_EMPTY;
232 static int hf_wsp_header_uri                            = HF_EMPTY;
233 static int hf_wsp_server_session_id                     = HF_EMPTY;
234 static int hf_wsp_header_status                         = HF_EMPTY;
235 static int hf_wsp_header_length                         = HF_EMPTY;
236 static int hf_wsp_headers_section                       = HF_EMPTY;
237 static int hf_wsp_header                                = HF_EMPTY;
238 static int hf_wsp_content_type                          = HF_EMPTY;
239 static int hf_wsp_content_type_str                      = HF_EMPTY;
240 static int hf_wsp_parameter_well_known_charset          = HF_EMPTY;
241 static int hf_wsp_parameter_type                        = HF_EMPTY;
242 static int hf_wsp_parameter_name                        = HF_EMPTY;
243 static int hf_wsp_parameter_filename                    = HF_EMPTY;
244 static int hf_wsp_parameter_start                       = HF_EMPTY;
245 static int hf_wsp_parameter_start_info                  = HF_EMPTY;
246 static int hf_wsp_parameter_comment                     = HF_EMPTY;
247 static int hf_wsp_parameter_domain                      = HF_EMPTY;
248 static int hf_wsp_parameter_path                        = HF_EMPTY;
249 static int hf_wsp_parameter_sec                 = HF_EMPTY;
250 static int hf_wsp_parameter_mac                 = HF_EMPTY;
251 static int hf_wsp_parameter_upart_type                  = HF_EMPTY;
252 static int hf_wsp_parameter_upart_type_value            = HF_EMPTY;
253 static int hf_wsp_parameter_level                       = HF_EMPTY;
254 static int hf_wsp_reply_data                            = HF_EMPTY;
255 static int hf_wsp_post_data                             = HF_EMPTY;
256 static int hf_wsp_push_data                             = HF_EMPTY;
257 static int hf_wsp_multipart_data                        = HF_EMPTY;
258 static int hf_wsp_mpart                                 = HF_EMPTY;
259
260 /* Header code page shift sequence */
261 static int hf_wsp_header_shift_code                     = HF_EMPTY;
262
263 /* WSP Redirect fields */
264 static int hf_wsp_redirect_flags                        = HF_EMPTY;
265 static int hf_wsp_redirect_permanent                    = HF_EMPTY;
266 static int hf_wsp_redirect_reuse_security_session       = HF_EMPTY;
267 static int hf_wsp_redirect_afl                          = HF_EMPTY;
268 static int hf_wsp_redirect_afl_bearer_type_included     = HF_EMPTY;
269 static int hf_wsp_redirect_afl_port_number_included     = HF_EMPTY;
270 static int hf_wsp_redirect_afl_address_len              = HF_EMPTY;
271 static int hf_wsp_redirect_bearer_type                  = HF_EMPTY;
272 static int hf_wsp_redirect_port_num                     = HF_EMPTY;
273 static int hf_wsp_redirect_ipv4_addr                    = HF_EMPTY;
274 static int hf_wsp_redirect_ipv6_addr                    = HF_EMPTY;
275 static int hf_wsp_redirect_addr                         = HF_EMPTY;
276
277 /*
278  * Initialize the subtree pointers
279  */
280
281 /* WSP tree */
282 static gint ett_wsp                                     = ETT_EMPTY;
283 /* WSP headers tree */
284 static gint ett_header                                  = ETT_EMPTY;
285 /* WSP header subtree */
286 static gint ett_headers                                 = ETT_EMPTY;
287 /* CO-WSP session capabilities */
288 static gint ett_capabilities                    = ETT_EMPTY;
289 static gint ett_post                                    = ETT_EMPTY;
290 static gint ett_redirect_flags                  = ETT_EMPTY;
291 static gint ett_redirect_afl                    = ETT_EMPTY;
292 static gint ett_multiparts                              = ETT_EMPTY;
293 static gint ett_mpartlist                               = ETT_EMPTY;
294
295
296
297 /* Handle for WSP-over-UDP dissector */
298 static dissector_handle_t wsp_fromudp_handle;
299
300 /* Handle for WTP-over-UDP dissector */
301 static dissector_handle_t wtp_fromudp_handle;
302
303 /* Handle for WBXML dissector */
304 static dissector_handle_t wbxml_handle;
305
306 const value_string vals_pdu_type[] = {
307         { 0x00, "Reserved" },
308         { 0x01, "Connect" },
309         { 0x02, "ConnectReply" },
310         { 0x03, "Redirect" },
311         { 0x04, "Reply" },
312         { 0x05, "Disconnect" },
313         { 0x06, "Push" },
314         { 0x07, "ConfirmedPush" },
315         { 0x08, "Suspend" },
316         { 0x09, "Resume" },
317
318         /* 0x10 - 0x3F Unassigned */
319
320         { 0x40, "Get" },
321         { 0x41, "Options" },
322         { 0x42, "Head" },
323         { 0x43, "Delete" },
324         { 0x44, "Trace" },
325
326         /* 0x45 - 0x4F Unassigned (Get PDU) */
327         /* 0x50 - 0x5F Extended method (Get PDU) */
328         { 0x50, "Extended Get Method 0"},
329         { 0x51, "Extended Get Method 1"},
330         { 0x52, "Extended Get Method 2"},
331         { 0x53, "Extended Get Method 3"},
332         { 0x54, "Extended Get Method 4"},
333         { 0x55, "Extended Get Method 5"},
334         { 0x56, "Extended Get Method 6"},
335         { 0x57, "Extended Get Method 7"},
336         { 0x58, "Extended Get Method 8"},
337         { 0x59, "Extended Get Method 9"},
338         { 0x5A, "Extended Get Method 10"},
339         { 0x5B, "Extended Get Method 11"},
340         { 0x5C, "Extended Get Method 12"},
341         { 0x5D, "Extended Get Method 13"},
342         { 0x5E, "Extended Get Method 14"},
343         { 0x5F, "Extended Get Method 15"},
344
345         { 0x60, "Post" },
346         { 0x61, "Put" },
347
348         /* 0x62 - 0x6F Unassigned (Post PDU) */
349         /* 0x70 - 0x7F Extended method (Post PDU) */
350         { 0x70, "Extended Post Method 0"},
351         { 0x71, "Extended Post Method 1"},
352         { 0x72, "Extended Post Method 2"},
353         { 0x73, "Extended Post Method 3"},
354         { 0x74, "Extended Post Method 4"},
355         { 0x75, "Extended Post Method 5"},
356         { 0x76, "Extended Post Method 6"},
357         { 0x77, "Extended Post Method 7"},
358         { 0x78, "Extended Post Method 8"},
359         { 0x79, "Extended Post Method 9"},
360         { 0x7A, "Extended Post Method 10"},
361         { 0x7B, "Extended Post Method 11"},
362         { 0x7C, "Extended Post Method 12"},
363         { 0x7D, "Extended Post Method 13"},
364         { 0x7E, "Extended Post Method 14"},
365         { 0x7F, "Extended Post Method 15"},
366
367         /* 0x80 - 0xFF Reserved */
368
369         { 0x00, NULL }
370
371 };
372
373 /* The WSP status codes are inherited from the HTTP status codes */
374 const value_string vals_status[] = {
375         /* 0x00 - 0x0F Reserved */
376
377         { 0x10, "100 Continue" },
378         { 0x11, "101 Switching Protocols" },
379
380         { 0x20, "200 OK" },
381         { 0x21, "201 Created" },
382         { 0x22, "202 Accepted" },
383         { 0x23, "203 Non-Authoritative Information" },
384         { 0x24, "204 No Content" },
385         { 0x25, "205 Reset Content" },
386         { 0x26, "206 Partial Content" },
387
388         { 0x30, "300 Multiple Choices" },
389         { 0x31, "301 Moved Permanently" },
390         { 0x32, "302 Moved Temporarily" },
391         { 0x33, "303 See Other" },
392         { 0x34, "304 Not Modified" },
393         { 0x35, "305 Use Proxy" },
394         { 0x37, "307 Temporary Redirect" },
395
396         { 0x40, "400 Bad Request" },
397         { 0x41, "401 Unauthorised" },
398         { 0x42, "402 Payment Required" },
399         { 0x43, "403 Forbidden" },
400         { 0x44, "404 Not Found" },
401         { 0x45, "405 Method Not Allowed" },
402         { 0x46, "406 Not Acceptable" },
403         { 0x47, "407 Proxy Authentication Required" },
404         { 0x48, "408 Request Timeout" },
405         { 0x49, "409 Conflict" },
406         { 0x4A, "410 Gone" },
407         { 0x4B, "411 Length Required" },
408         { 0x4C, "412 Precondition Failed" },
409         { 0x4D, "413 Request Entity Too Large" },
410         { 0x4E, "414 Request-URI Too Large" },
411         { 0x4F, "415 Unsupported Media Type" },
412         { 0x50, "416 Requested Range Not Satisfiable" },
413         { 0x51, "417 Expectation Failed" },
414
415         { 0x60, "500 Internal Server Error" },
416         { 0x61, "501 Not Implemented" },
417         { 0x62, "502 Bad Gateway" },
418         { 0x63, "503 Service Unavailable" },
419         { 0x64, "504 Gateway Timeout" },
420         { 0x65, "505 WSP/HTTP Version Not Supported" },
421
422         { 0x00, NULL }
423 };
424
425 const value_string vals_wsp_reason_codes[] = {
426         { 0xE0, "Protocol Error (Illegal PDU)" },
427         { 0xE1, "Session disconnected" },
428         { 0xE2, "Session suspended" },
429         { 0xE3, "Session resumed" },
430         { 0xE4, "Peer congested" },
431         { 0xE5, "Session connect failed" },
432         { 0xE6, "Maximum receive unit size exceeded" },
433         { 0xE7, "Maximum outstanding requests exceeded" },
434         { 0xE8, "Peer request" },
435         { 0xE9, "Network error" },
436         { 0xEA, "User request" },
437         { 0xEB, "No specific cause, no retries" },
438         { 0xEC, "Push message cannot be delivered" },
439         { 0xED, "Push message discarded" },
440         { 0xEE, "Content type cannot be processed" },
441
442         { 0x00, NULL }
443 };
444
445 /*
446  * Field names.
447  */
448 #define FN_ACCEPT               0x00
449 #define FN_ACCEPT_CHARSET_DEP   0x01    /* encoding version 1.1, deprecated */
450 #define FN_ACCEPT_ENCODING_DEP  0x02    /* encoding version 1.1, deprecated */
451 #define FN_ACCEPT_LANGUAGE      0x03
452 #define FN_ACCEPT_RANGES        0x04
453 #define FN_AGE                  0x05
454 #define FN_ALLOW                0x06
455 #define FN_AUTHORIZATION        0x07
456 #define FN_CACHE_CONTROL_DEP    0x08    /* encoding version 1.1, deprecated */
457 #define FN_CONNECTION           0x09
458 #define FN_CONTENT_BASE         0x0A
459 #define FN_CONTENT_ENCODING     0x0B
460 #define FN_CONTENT_LANGUAGE     0x0C
461 #define FN_CONTENT_LENGTH       0x0D
462 #define FN_CONTENT_LOCATION     0x0E
463 #define FN_CONTENT_MD5          0x0F
464 #define FN_CONTENT_RANGE_DEP    0x10    /* encoding version 1.1, deprecated */
465 #define FN_CONTENT_TYPE         0x11
466 #define FN_DATE                 0x12
467 #define FN_ETAG                 0x13
468 #define FN_EXPIRES              0x14
469 #define FN_FROM                 0x15
470 #define FN_HOST                 0x16
471 #define FN_IF_MODIFIED_SINCE    0x17
472 #define FN_IF_MATCH             0x18
473 #define FN_IF_NONE_MATCH        0x19
474 #define FN_IF_RANGE             0x1A
475 #define FN_IF_UNMODIFIED_SINCE  0x1B
476 #define FN_LOCATION             0x1C
477 #define FN_LAST_MODIFIED        0x1D
478 #define FN_MAX_FORWARDS         0x1E
479 #define FN_PRAGMA               0x1F
480 #define FN_PROXY_AUTHENTICATE   0x20
481 #define FN_PROXY_AUTHORIZATION  0x21
482 #define FN_PUBLIC               0x22
483 #define FN_RANGE                0x23
484 #define FN_REFERER              0x24
485 #define FN_RETRY_AFTER          0x25
486 #define FN_SERVER               0x26
487 #define FN_TRANSFER_ENCODING    0x27
488 #define FN_UPGRADE              0x28
489 #define FN_USER_AGENT           0x29
490 #define FN_VARY                 0x2A
491 #define FN_VIA                  0x2B
492 #define FN_WARNING              0x2C
493 #define FN_WWW_AUTHENTICATE     0x2D
494 #define FN_CONTENT_DISPOSITION  0x2E
495 #define FN_X_WAP_APPLICATION_ID 0x2F
496 #define FN_X_WAP_CONTENT_URI    0x30
497 #define FN_X_WAP_INITIATOR_URI  0x31
498 #define FN_ACCEPT_APPLICATION   0x32
499 #define FN_BEARER_INDICATION    0x33
500 #define FN_PUSH_FLAG            0x34
501 #define FN_PROFILE              0x35
502 #define FN_PROFILE_DIFF         0x36
503 #define FN_PROFILE_WARNING      0x37
504 #define FN_EXPECT               0x38
505 #define FN_TE                   0x39
506 #define FN_TRAILER              0x3A
507 #define FN_ACCEPT_CHARSET       0x3B    /* encoding version 1.3 */
508 #define FN_ACCEPT_ENCODING      0x3C    /* encoding version 1.3 */
509 #define FN_CACHE_CONTROL        0x3D    /* encoding version 1.3 */
510 #define FN_CONTENT_RANGE        0x3E    /* encoding version 1.3 */
511 #define FN_X_WAP_TOD            0x3F
512 #define FN_CONTENT_ID           0x40
513 #define FN_SET_COOKIE           0x41
514 #define FN_COOKIE               0x42
515 #define FN_ENCODING_VERSION     0x43
516 #define FN_PROFILE_WARNING14    0x44    /* encoding version 1.4 */
517 #define FN_CONTENT_DISPOSITION14        0x45    /* encoding version 1.4 */
518 #define FN_X_WAP_SECURITY       0x46
519 #define FN_CACHE_CONTROL14      0x47    /* encoding version 1.4 */
520
521
522 /*
523  * Openwave field names.
524  */
525 #define FN_OPENWAVE_PROXY_PUSH_ADDR             0x00
526 #define FN_OPENWAVE_PROXY_PUSH_ACCEPT           0x01
527 #define FN_OPENWAVE_PROXY_PUSH_SEQ              0x02
528 #define FN_OPENWAVE_PROXY_NOTIFY                0x03
529 #define FN_OPENWAVE_PROXY_OPERATOR_DOMAIN       0x04
530 #define FN_OPENWAVE_PROXY_HOME_PAGE             0x05
531 #define FN_OPENWAVE_DEVCAP_HAS_COLOR            0x06
532 #define FN_OPENWAVE_DEVCAP_NUM_SOFTKEYS         0x07
533 #define FN_OPENWAVE_DEVCAP_SOFTKEY_SIZE         0x08
534 #define FN_OPENWAVE_DEVCAP_SCREEN_CHARS         0x09
535 #define FN_OPENWAVE_DEVCAP_SCREEN_PIXELS        0x0A
536 #define FN_OPENWAVE_DEVCAP_EM_SIZE              0x0B
537 #define FN_OPENWAVE_DEVCAP_SCREEN_DEPTH         0x0C
538 #define FN_OPENWAVE_DEVCAP_IMMED_ALERT          0x0D
539 #define FN_OPENWAVE_PROXY_NET_ASK               0x0E
540 #define FN_OPENWAVE_PROXY_UPLINK_VERSION        0x0F
541 #define FN_OPENWAVE_PROXY_TOD                   0x10
542 #define FN_OPENWAVE_PROXY_BA_ENABLE             0x11
543 #define FN_OPENWAVE_PROXY_BA_REALM              0x12
544 #define FN_OPENWAVE_PROXY_REDIRECT_ENABLE       0x13
545 #define FN_OPENWAVE_PROXY_REQUEST_URI           0x14
546 #define FN_OPENWAVE_PROXY_REDIRECT_STATUS       0x15
547 #define FN_OPENWAVE_PROXY_TRANS_CHARSET         0x16
548 #define FN_OPENWAVE_PROXY_LINGER                0x17
549 #define FN_OPENWAVE_PROXY_CLIENT_ID             0x18
550 #define FN_OPENWAVE_PROXY_ENABLE_TRUST          0x19
551 #define FN_OPENWAVE_PROXY_TRUST_OLD             0x1A
552 #define FN_OPENWAVE_PROXY_TRUST                 0x20
553 #define FN_OPENWAVE_PROXY_BOOKMARK              0x21
554 #define FN_OPENWAVE_DEVCAP_GUI                  0x22
555
556 static const value_string vals_openwave_field_names[] = {
557         { FN_OPENWAVE_PROXY_PUSH_ADDR,         "x-up-proxy-push-addr" },
558         { FN_OPENWAVE_PROXY_PUSH_ACCEPT,       "x-up-proxy-push-accept" },
559         { FN_OPENWAVE_PROXY_PUSH_SEQ,          "x-up-proxy-seq" },
560         { FN_OPENWAVE_PROXY_NOTIFY,            "x-up-proxy-notify" },
561         { FN_OPENWAVE_PROXY_OPERATOR_DOMAIN,   "x-up-proxy-operator-domain" },
562         { FN_OPENWAVE_PROXY_HOME_PAGE,         "x-up-proxy-home-page" },
563         { FN_OPENWAVE_DEVCAP_HAS_COLOR,        "x-up-devcap-has-color" },
564         { FN_OPENWAVE_DEVCAP_NUM_SOFTKEYS,     "x-up-devcap-num-softkeys" },
565         { FN_OPENWAVE_DEVCAP_SOFTKEY_SIZE,     "x-up-devcap-softkey-size" },
566         { FN_OPENWAVE_DEVCAP_SCREEN_CHARS,     "x-up-devcap-screen-chars" },
567         { FN_OPENWAVE_DEVCAP_SCREEN_PIXELS,    "x-up-devcap-screen-pixels" },
568         { FN_OPENWAVE_DEVCAP_EM_SIZE,          "x-up-devcap-em-size" },
569         { FN_OPENWAVE_DEVCAP_SCREEN_DEPTH,     "x-up-devcap-screen-depth" },
570         { FN_OPENWAVE_DEVCAP_IMMED_ALERT,      "x-up-devcap-immed-alert" },
571         { FN_OPENWAVE_PROXY_NET_ASK,           "x-up-proxy-net-ask" },
572         { FN_OPENWAVE_PROXY_UPLINK_VERSION,    "x-up-proxy-uplink-version" },
573         { FN_OPENWAVE_PROXY_TOD,               "x-up-proxy-tod" },
574         { FN_OPENWAVE_PROXY_BA_ENABLE,         "x-up-proxy-ba-enable" },
575         { FN_OPENWAVE_PROXY_BA_REALM,          "x-up-proxy-ba-realm" },
576         { FN_OPENWAVE_PROXY_REDIRECT_ENABLE,   "x-up-proxy-redirect-enable" },
577         { FN_OPENWAVE_PROXY_REQUEST_URI,       "x-up-proxy-request-uri" },
578         { FN_OPENWAVE_PROXY_REDIRECT_STATUS,   "x-up-proxy-redirect-status" },
579         { FN_OPENWAVE_PROXY_TRANS_CHARSET,     "x-up-proxy-trans-charset" },
580         { FN_OPENWAVE_PROXY_LINGER,            "x-up-proxy-linger" },
581         { FN_OPENWAVE_PROXY_CLIENT_ID,         "x-up-proxy-client-id" },
582         { FN_OPENWAVE_PROXY_ENABLE_TRUST,      "x-up-proxy-enable-trust" },
583         { FN_OPENWAVE_PROXY_TRUST_OLD,         "x-up-proxy-trust-old" },
584         { FN_OPENWAVE_PROXY_TRUST,             "x-up-proxy-trust" },
585         { FN_OPENWAVE_PROXY_BOOKMARK,          "x-up-proxy-bookmark" },
586         { FN_OPENWAVE_DEVCAP_GUI,              "x-up-devcap-gui" },
587         { 0,                                   NULL }
588 };
589
590
591 static const value_string vals_field_names[] = {
592         { FN_ACCEPT,               "Accept" },
593         { FN_ACCEPT_CHARSET_DEP,   "Accept-Charset (encoding 1.1)" },
594         { FN_ACCEPT_ENCODING_DEP,  "Accept-Encoding (encoding 1.1)" },
595         { FN_ACCEPT_LANGUAGE,      "Accept-Language" },
596         { FN_ACCEPT_RANGES,        "Accept-Ranges" },
597         { FN_AGE,                  "Age" },
598         { FN_ALLOW,                "Allow" },
599         { FN_AUTHORIZATION,        "Authorization" },
600         { FN_CACHE_CONTROL_DEP,    "Cache-Control (encoding 1.1)" },
601         { FN_CONNECTION,           "Connection" },
602         { FN_CONTENT_BASE,         "Content-Base" },
603         { FN_CONTENT_ENCODING,     "Content-Encoding" },
604         { FN_CONTENT_LANGUAGE,     "Content-Language" },
605         { FN_CONTENT_LENGTH,       "Content-Length" },
606         { FN_CONTENT_LOCATION,     "Content-Location" },
607         { FN_CONTENT_MD5,          "Content-MD5" },
608         { FN_CONTENT_RANGE_DEP,    "Content-Range (encoding 1.1)" },
609         { FN_CONTENT_TYPE,         "Content-Type" },
610         { FN_DATE,                 "Date" },
611         { FN_ETAG,                 "ETag" },
612         { FN_EXPIRES,              "Expires" },
613         { FN_FROM,                 "From" },
614         { FN_HOST,                 "Host" },
615         { FN_IF_MODIFIED_SINCE,    "If-Modified-Since" },
616         { FN_IF_MATCH,             "If-Match" },
617         { FN_IF_NONE_MATCH,        "If-None-Match" },
618         { FN_IF_RANGE,             "If-Range" },
619         { FN_IF_UNMODIFIED_SINCE,  "If-Unmodified-Since" },
620         { FN_LOCATION,             "Location" },
621         { FN_LAST_MODIFIED,        "Last-Modified" },
622         { FN_MAX_FORWARDS,         "Max-Forwards" },
623         { FN_PRAGMA,               "Pragma" },
624         { FN_PROXY_AUTHENTICATE,   "Proxy-Authenticate" },
625         { FN_PROXY_AUTHORIZATION,  "Proxy-Authorization" },
626         { FN_PUBLIC,               "Public" },
627         { FN_RANGE,                "Range" },
628         { FN_REFERER,              "Referer" },
629         { FN_RETRY_AFTER,          "Retry-After" },
630         { FN_SERVER,               "Server" },
631         { FN_TRANSFER_ENCODING,    "Transfer-Encoding" },
632         { FN_UPGRADE,              "Upgrade" },
633         { FN_USER_AGENT,           "User-Agent" },
634         { FN_VARY,                 "Vary" },
635         { FN_VIA,                  "Via" },
636         { FN_WARNING,              "Warning" },
637         { FN_WWW_AUTHENTICATE,     "WWW-Authenticate" },
638         { FN_CONTENT_DISPOSITION,  "Content-Disposition" },
639         { FN_X_WAP_APPLICATION_ID, "X-Wap-Application-ID" },
640         { FN_X_WAP_CONTENT_URI,    "X-Wap-Content-URI" },
641         { FN_X_WAP_INITIATOR_URI,  "X-Wap-Initiator-URI" },
642         { FN_ACCEPT_APPLICATION,   "Accept-Application" },
643         { FN_BEARER_INDICATION,    "Bearer-Indication" },
644         { FN_PUSH_FLAG,            "Push-Flag" },
645         { FN_PROFILE,              "Profile" },
646         { FN_PROFILE_DIFF,         "Profile-Diff" },
647         { FN_PROFILE_WARNING,      "Profile-Warning" },
648         { FN_EXPECT,               "Expect" },
649         { FN_TE,                   "TE" },
650         { FN_TRAILER,              "Trailer" },
651         { FN_ACCEPT_CHARSET,       "Accept-Charset" },
652         { FN_ACCEPT_ENCODING,      "Accept-Encoding" },
653         { FN_CACHE_CONTROL,        "Cache-Control" },
654         { FN_CONTENT_RANGE,        "Content-Range" },
655         { FN_X_WAP_TOD,            "X-Wap-Tod" },
656         { FN_CONTENT_ID,           "Content-ID" },
657         { FN_SET_COOKIE,           "Set-Cookie" },
658         { FN_COOKIE,               "Cookie" },
659         { FN_ENCODING_VERSION,     "Encoding-Version" },
660         { FN_PROFILE_WARNING14,    "Profile-Warning (encoding 1.4)" },
661         { FN_CONTENT_DISPOSITION14,"Content-Disposition (encoding 1.4)" },
662         { FN_X_WAP_SECURITY,       "X-WAP-Security" },
663         { FN_CACHE_CONTROL14,      "Cache-Control (encoding 1.4)" },
664         { 0,                       NULL }
665 };
666
667 /*
668  * Bearer types (from the WDP specification).
669  */
670 #define BT_IPv4                 0x00
671 #define BT_IPv6                 0x01
672 #define BT_GSM_USSD             0x02
673 #define BT_GSM_SMS              0x03
674 #define BT_ANSI_136_GUTS        0x04
675 #define BT_IS_95_SMS            0x05
676 #define BT_IS_95_CSD            0x06
677 #define BT_IS_95_PACKET_DATA    0x07
678 #define BT_ANSI_136_CSD         0x08
679 #define BT_ANSI_136_PACKET_DATA 0x09
680 #define BT_GSM_CSD              0x0A
681 #define BT_GSM_GPRS             0x0B
682 #define BT_GSM_USSD_IPv4        0x0C
683 #define BT_AMPS_CDPD            0x0D
684 #define BT_PDC_CSD              0x0E
685 #define BT_PDC_PACKET_DATA      0x0F
686 #define BT_IDEN_SMS             0x10
687 #define BT_IDEN_CSD             0x11
688 #define BT_IDEN_PACKET_DATA     0x12
689 #define BT_PAGING_FLEX          0x13
690 #define BT_PHS_SMS              0x14
691 #define BT_PHS_CSD              0x15
692 #define BT_GSM_USSD_GSM_SC      0x16
693 #define BT_TETRA_SDS_ITSI       0x17
694 #define BT_TETRA_SDS_MSISDN     0x18
695 #define BT_TETRA_PACKET_DATA    0x19
696 #define BT_PAGING_REFLEX        0x1A
697 #define BT_GSM_USSD_MSISDN      0x1B
698 #define BT_MOBITEX_MPAK         0x1C
699 #define BT_ANSI_136_GHOST       0x1D
700
701 static const value_string vals_bearer_types[] = {
702         { BT_IPv4,                 "IPv4" },
703         { BT_IPv6,                 "IPv6" },
704         { BT_GSM_USSD,             "GSM USSD" },
705         { BT_GSM_SMS,              "GSM SMS" },
706         { BT_ANSI_136_GUTS,        "ANSI-136 GUTS/R-Data" },
707         { BT_IS_95_SMS,            "IS-95 CDMA SMS" },
708         { BT_IS_95_CSD,            "IS-95 CDMA CSD" },
709         { BT_IS_95_PACKET_DATA,    "IS-95 CDMA Packet data" },
710         { BT_ANSI_136_CSD,         "ANSI-136 CSD" },
711         { BT_ANSI_136_PACKET_DATA, "ANSI-136 Packet data" },
712         { BT_GSM_CSD,              "GSM CSD" },
713         { BT_GSM_GPRS,             "GSM GPRS" },
714         { BT_GSM_USSD_IPv4,        "GSM USSD (IPv4 addresses)" },
715         { BT_AMPS_CDPD,            "AMPS CDPD" },
716         { BT_PDC_CSD,              "PDC CSD" },
717         { BT_PDC_PACKET_DATA,      "PDC Packet data" },
718         { BT_IDEN_SMS,             "IDEN SMS" },
719         { BT_IDEN_CSD,             "IDEN CSD" },
720         { BT_IDEN_PACKET_DATA,     "IDEN Packet data" },
721         { BT_PAGING_FLEX,          "Paging network FLEX(TM)" },
722         { BT_PHS_SMS,              "PHS SMS" },
723         { BT_PHS_CSD,              "PHS CSD" },
724         { BT_GSM_USSD_GSM_SC,      "GSM USSD (GSM Service Code addresses)" },
725         { BT_TETRA_SDS_ITSI,       "TETRA SDS (ITSI addresses)" },
726         { BT_TETRA_SDS_MSISDN,     "TETRA SDS (MSISDN addresses)" },
727         { BT_TETRA_PACKET_DATA,    "TETRA Packet data" },
728         { BT_PAGING_REFLEX,        "Paging network ReFLEX(TM)" },
729         { BT_GSM_USSD_MSISDN,      "GSM USSD (MSISDN addresses)" },
730         { BT_MOBITEX_MPAK,         "Mobitex MPAK" },
731         { BT_ANSI_136_GHOST,       "ANSI-136 GHOST/R-Data" },
732         { 0,                       NULL }
733 };
734
735 static const value_string vals_content_types[] = {
736         /* Well-known media types */
737         { 0x00, "*/*" },
738         { 0x01, "text/*" },
739         { 0x02, "text/html" },
740         { 0x03, "text/plain" },
741         { 0x04, "text/x-hdml" },
742         { 0x05, "text/x-ttml" },
743         { 0x06, "text/x-vCalendar" },
744         { 0x07, "text/x-vCard" },
745         { 0x08, "text/vnd.wap.wml" },
746         { 0x09, "text/vnd.wap.wmlscript" },
747         { 0x0A, "text/vnd.wap.channel" },
748         { 0x0B, "multipart/*" },
749         { 0x0C, "multipart/mixed" },
750         { 0x0D, "multipart/form-data" },
751         { 0x0E, "multipart/byteranges" },
752         { 0x0F, "multipart/alternative" },
753         { 0x10, "application/*" },
754         { 0x11, "application/java-vm" },
755         { 0x12, "application/x-www-form-urlencoded" },
756         { 0x13, "application/x-hdmlc" },
757         { 0x14, "application/vnd.wap.wmlc" },
758         { 0x15, "application/vnd.wap.wmlscriptc" },
759         { 0x16, "application/vnd.wap.channelc" },
760         { 0x17, "application/vnd.wap.uaprof" },
761         { 0x18, "application/vnd.wap.wtls-ca-certificate" },
762         { 0x19, "application/vnd.wap.wtls-user-certificate" },
763         { 0x1A, "application/x-x509-ca-cert" },
764         { 0x1B, "application/x-x509-user-cert" },
765         { 0x1C, "image/*" },
766         { 0x1D, "image/gif" },
767         { 0x1E, "image/jpeg" },
768         { 0x1F, "image/tiff" },
769         { 0x20, "image/png" },
770         { 0x21, "image/vnd.wap.wbmp" },
771         { 0x22, "application/vnd.wap.multipart.*" },
772         { 0x23, "application/vnd.wap.multipart.mixed" },
773         { 0x24, "application/vnd.wap.multipart.form-data" },
774         { 0x25, "application/vnd.wap.multipart.byteranges" },
775         { 0x26, "application/vnd.wap.multipart.alternative" },
776         { 0x27, "application/xml" },
777         { 0x28, "text/xml" },
778         { 0x29, "application/vnd.wap.wbxml" },
779         { 0x2A, "application/x-x968-cross-cert" },
780         { 0x2B, "application/x-x968-ca-cert" },
781         { 0x2C, "application/x-x968-user-cert" },
782         { 0x2D, "text/vnd.wap.si" },
783         { 0x2E, "application/vnd.wap.sic" },
784         { 0x2F, "text/vnd.wap.sl" },
785         { 0x30, "application/vnd.wap.slc" },
786         { 0x31, "text/vnd.wap.co" },
787         { 0x32, "application/vnd.wap.coc" },
788         { 0x33, "application/vnd.wap.multipart.related" },
789         { 0x34, "application/vnd.wap.sia" },
790         { 0x35, "text/vnd.wap.connectivity-xml" },
791         { 0x36, "application/vnd.wap.connectivity-wbxml" },
792         { 0x37, "application/pkcs7-mime" },
793         { 0x38, "application/vnd.wap.hashed-certificate" },
794         { 0x39, "application/vnd.wap.signed-certificate" },
795         { 0x3A, "application/vnd.wap.cert-response" },
796         { 0x3B, "application/xhtml+xml" },
797         { 0x3C, "application/wml+xml" },
798         { 0x3D, "text/css" },
799         { 0x3E, "application/vnd.wap.mms-message" },
800         { 0x3F, "application/vnd.wap.rollover-certificate" },
801         { 0x40, "application/vnd.wap.locc+wbxml"},
802         { 0x41, "application/vnd.wap.loc+xml"},
803         { 0x42, "application/vnd.syncml.dm+wbxml"},
804         { 0x43, "application/vnd.syncml.dm+xml"},
805         { 0x44, "application/vnd.syncml.notification"},
806         { 0x45, "application/vnd.wap.xhtml+xml"},
807         { 0x46, "application/vnd.wv.csp.cir"},
808         { 0x47, "application/vnd.oma.dd+xml"},
809         { 0x48, "application/vnd.oma.drm.message"},
810         { 0x49, "application/vnd.oma.drm.content"},
811         { 0x4A, "application/vnd.oma.drm.rights+xml"},
812         { 0x4B, "application/vnd.oma.drm.rights+wbxml"},
813         { 0x4C, "application/vnd.wv.csp+xml"},
814         { 0x4D, "application/vnd.wv.csp+wbxml"},
815         /* The following media types are registered by 3rd parties */ 
816         { 0x0201, "application/vnd.uplanet.cachop-wbxml" },
817         { 0x0202, "application/vnd.uplanet.signal" },
818         { 0x0203, "application/vnd.uplanet.alert-wbxml" },
819         { 0x0204, "application/vnd.uplanet.list-wbxml" },
820         { 0x0205, "application/vnd.uplanet.listcmd-wbxml" },
821         { 0x0206, "application/vnd.uplanet.channel-wbxml" },
822         { 0x0207, "application/vnd.uplanet.provisioning-status-uri" },
823         { 0x0208, "x-wap.multipart/vnd.uplanet.header-set" },
824         { 0x0209, "application/vnd.uplanet.bearer-choice-wbxml" },
825         { 0x020A, "application/vnd.phonecom.mmc-wbxml" },
826         { 0x020B, "application/vnd.nokia.syncset+wbxml" },
827         { 0x020C, "image/x-up-wpng"},
828         { 0x0300, "application/iota.mmc-wbxml"},
829         { 0x0301, "application/iota.mmc-xml"},
830         { 0x00, NULL }
831 };
832
833 static const value_string vals_languages[] = {
834         { 0x01, "Afar (aa)" },
835         { 0x02, "Abkhazian (ab)" },
836         { 0x03, "Afrikaans (af)" },
837         { 0x04, "Amharic (am)" },
838         { 0x05, "Arabic (ar)" },
839         { 0x06, "Assamese (as)" },
840         { 0x07, "Aymara (ay)" },
841         { 0x08, "Azerbaijani (az)" },
842         { 0x09, "Bashkir (ba)" },
843         { 0x0A, "Byelorussian (be)" },
844         { 0x0B, "Bulgarian (bg)" },
845         { 0x0C, "Bihari (bh)" },
846         { 0x0D, "Bislama (bi)" },
847         { 0x0E, "Bengali; Bangla (bn)" },
848         { 0x0F, "Tibetan (bo)" },
849         { 0x10, "Breton (br)" },
850         { 0x11, "Catalan (ca)" },
851         { 0x12, "Corsican (co)" },
852         { 0x13, "Czech (cs)" },
853         { 0x14, "Welsh (cy)" },
854         { 0x15, "Danish (da)" },
855         { 0x16, "German (de)" },
856         { 0x17, "Bhutani (dz)" },
857         { 0x18, "Greek (el)" },
858         { 0x19, "English (en)" },
859         { 0x1A, "Esperanto (eo)" },
860         { 0x1B, "Spanish (es)" },
861         { 0x1C, "Estonian (et)" },
862         { 0x1D, "Basque (eu)" },
863         { 0x1E, "Persian (fa)" },
864         { 0x1F, "Finnish (fi)" },
865         { 0x20, "Fiji (fj)" },
866         { 0x21, "Urdu (ur)" },
867         { 0x22, "French (fr)" },
868         { 0x23, "Uzbek (uz)" },
869         { 0x24, "Irish (ga)" },
870         { 0x25, "Scots Gaelic (gd)" },
871         { 0x26, "Galician (gl)" },
872         { 0x27, "Guarani (gn)" },
873         { 0x28, "Gujarati (gu)" },
874         { 0x29, "Hausa (ha)" },
875         { 0x2A, "Hebrew (formerly iw) (he)" },
876         { 0x2B, "Hindi (hi)" },
877         { 0x2C, "Croatian (hr)" },
878         { 0x2D, "Hungarian (hu)" },
879         { 0x2E, "Armenian (hy)" },
880         { 0x2F, "Vietnamese (vi)" },
881         { 0x30, "Indonesian (formerly in) (id)" },
882         { 0x31, "Wolof (wo)" },
883         { 0x32, "Xhosa (xh)" },
884         { 0x33, "Icelandic (is)" },
885         { 0x34, "Italian (it)" },
886         { 0x35, "Yoruba (yo)" },
887         { 0x36, "Japanese (ja)" },
888         { 0x37, "Javanese (jw)" },
889         { 0x38, "Georgian (ka)" },
890         { 0x39, "Kazakh (kk)" },
891         { 0x3A, "Zhuang (za)" },
892         { 0x3B, "Cambodian (km)" },
893         { 0x3C, "Kannada (kn)" },
894         { 0x3D, "Korean (ko)" },
895         { 0x3E, "Kashmiri (ks)" },
896         { 0x3F, "Kurdish (ku)" },
897         { 0x40, "Kirghiz (ky)" },
898         { 0x41, "Chinese (zh)" },
899         { 0x42, "Lingala (ln)" },
900         { 0x43, "Laothian (lo)" },
901         { 0x44, "Lithuanian (lt)" },
902         { 0x45, "Latvian, Lettish (lv)" },
903         { 0x46, "Malagasy (mg)" },
904         { 0x47, "Maori (mi)" },
905         { 0x48, "Macedonian (mk)" },
906         { 0x49, "Malayalam (ml)" },
907         { 0x4A, "Mongolian (mn)" },
908         { 0x4B, "Moldavian (mo)" },
909         { 0x4C, "Marathi (mr)" },
910         { 0x4D, "Malay (ms)" },
911         { 0x4E, "Maltese (mt)" },
912         { 0x4F, "Burmese (my)" },
913         { 0x50, "Ukrainian (uk)" },
914         { 0x51, "Nepali (ne)" },
915         { 0x52, "Dutch (nl)" },
916         { 0x53, "Norwegian (no)" },
917         { 0x54, "Occitan (oc)" },
918         { 0x55, "(Afan) Oromo (om)" },
919         { 0x56, "Oriya (or)" },
920         { 0x57, "Punjabi (pa)" },
921         { 0x58, "Polish (po)" },
922         { 0x59, "Pashto, Pushto (ps)" },
923         { 0x5A, "Portuguese (pt)" },
924         { 0x5B, "Quechua (qu)" },
925         { 0x5C, "Zulu (zu)" },
926         { 0x5D, "Kirundi (rn)" },
927         { 0x5E, "Romanian (ro)" },
928         { 0x5F, "Russian (ru)" },
929         { 0x60, "Kinyarwanda (rw)" },
930         { 0x61, "Sanskrit (sa)" },
931         { 0x62, "Sindhi (sd)" },
932         { 0x63, "Sangho (sg)" },
933         { 0x64, "Serbo-Croatian (sh)" },
934         { 0x65, "Sinhalese (si)" },
935         { 0x66, "Slovak (sk)" },
936         { 0x67, "Slovenian (sl)" },
937         { 0x68, "Samoan (sm)" },
938         { 0x69, "Shona (sn)" },
939         { 0x6A, "Somali (so)" },
940         { 0x6B, "Albanian (sq)" },
941         { 0x6C, "Serbian (sr)" },
942         { 0x6D, "Siswati (ss)" },
943         { 0x6E, "Sesotho (st)" },
944         { 0x6F, "Sundanese (su)" },
945         { 0x70, "Swedish (sv)" },
946         { 0x71, "Swahili (sw)" },
947         { 0x72, "Tamil (ta)" },
948         { 0x73, "Telugu (te)" },
949         { 0x74, "Tajik (tg)" },
950         { 0x75, "Thai (th)" },
951         { 0x76, "Tigrinya (ti)" },
952         { 0x77, "Turkmen (tk)" },
953         { 0x78, "Tagalog (tl)" },
954         { 0x79, "Setswana (tn)" },
955         { 0x7A, "Tonga (to)" },
956         { 0x7B, "Turkish (tr)" },
957         { 0x7C, "Tsonga (ts)" },
958         { 0x7D, "Tatar (tt)" },
959         { 0x7E, "Twi (tw)" },
960         { 0x7F, "Uighur (ug)" },
961         { 0x81, "Nauru (na)" },
962         { 0x82, "Faeroese (fo)" },
963         { 0x83, "Frisian (fy)" },
964         { 0x84, "Interlingua (ia)" },
965         { 0x85, "Volapuk (vo)" },
966         { 0x86, "Interlingue (ie)" },
967         { 0x87, "Inupiak (ik)" },
968         { 0x88, "Yiddish (formerly ji) (yi)" },
969         { 0x89, "Inuktitut (iu)" },
970         { 0x8A, "Greenlandic (kl)" },
971         { 0x8B, "Latin (la)" },
972         { 0x8C, "Rhaeto-Romance (rm)" },
973         { 0x00, NULL }
974 };
975
976
977 #define CACHE_CONTROL_NO_CACHE                  0x00
978 #define CACHE_CONTROL_NO_STORE                  0x01
979 #define CACHE_CONTROL_MAX_AGE                   0x02
980 #define CACHE_CONTROL_MAX_STALE                 0x03
981 #define CACHE_CONTROL_MIN_FRESH                 0x04
982 #define CACHE_CONTROL_ONLY_IF_CACHED    0x05
983 #define CACHE_CONTROL_PUBLIC                    0x06
984 #define CACHE_CONTROL_PRIVATE                   0x07
985 #define CACHE_CONTROL_NO_TRANSFORM              0x08
986 #define CACHE_CONTROL_MUST_REVALIDATE   0x09
987 #define CACHE_CONTROL_PROXY_REVALIDATE  0x0A
988 #define CACHE_CONTROL_S_MAXAGE                  0x0B
989
990 static const value_string vals_cache_control[] = {
991         { CACHE_CONTROL_NO_CACHE,         "no-cache" },
992         { CACHE_CONTROL_NO_STORE,         "no-store" },
993         { CACHE_CONTROL_MAX_AGE,          "max-age" },
994         { CACHE_CONTROL_MAX_STALE,        "max-stale" },
995         { CACHE_CONTROL_MIN_FRESH,        "min-fresh" },
996         { CACHE_CONTROL_ONLY_IF_CACHED,   "only-if-cached" },
997         { CACHE_CONTROL_PUBLIC,           "public" },
998         { CACHE_CONTROL_PRIVATE,          "private" },
999         { CACHE_CONTROL_NO_TRANSFORM,     "no-transform" },
1000         { CACHE_CONTROL_MUST_REVALIDATE,  "must-revalidate" },
1001         { CACHE_CONTROL_PROXY_REVALIDATE, "proxy-revalidate" },
1002         { CACHE_CONTROL_S_MAXAGE,         "s-max-age" },
1003
1004         { 0x00, NULL }
1005 };
1006
1007 static const value_string vals_wap_application_ids[] = {
1008         /* Well-known WAP applications */
1009         { 0x00, "x-wap-application:*"},
1010         { 0x01, "x-wap-application:push.sia"},
1011         { 0x02, "x-wap-application:wml.ua"},
1012         { 0x03, "x-wap-application:wta.ua"},
1013         { 0x04, "x-wap-application:mms.ua"},
1014         { 0x05, "x-wap-application:push.syncml"},
1015         { 0x06, "x-wap-application:loc.ua"},
1016         { 0x07, "x-wap-application:syncml.dm"},
1017         { 0x08, "x-wap-application:drm.ua"},
1018         { 0x09, "x-wap-application:emn.ua"},
1019         { 0x0A, "x-wap-application:wv.ua"},
1020         /* Registered by 3rd parties */
1021         { 0x8000, "x-wap-microsoft:localcontent.ua"},
1022         { 0x8001, "x-wap-microsoft:IMclient.ua"},
1023         { 0x8002, "x-wap-docomo:imode.mail.ua"},
1024         { 0x8003, "x-wap-docomo:imode.mr.ua"},
1025         { 0x8004, "x-wap-docomo:imode.mf.ua"},
1026         { 0x8005, "x-motorola:location.ua"},
1027         { 0x8006, "x-motorola:now.ua"},
1028         { 0x8007, "x-motorola:otaprov.ua"},
1029         { 0x8008, "x-motorola:browser.ua"},
1030         { 0x8009, "x-motorola:splash.ua"},
1031         /* 0x800A: unassigned */
1032         { 0x800B, "x-wap-nai:mvsw.command"},
1033         /* 0x800C -- 0x800F: unassigned */
1034         { 0x8010, "x-wap-openwave:iota.ua"},
1035         /* 0x8011 -- 0x8FFF: unassigned */
1036         { 0x9000, "x-wap-docomo:imode.mail2.ua"},
1037         { 0x9001, "x-oma-nec:otaprov.ua"},
1038         { 0x9002, "x-oma-nokia:call.ua"},
1039         { 0x9003, "x-oma-coremobility:sqa.ua"},
1040
1041         { 0x00, NULL }
1042 };
1043
1044
1045 /* Parameters and well-known encodings */
1046 static const value_string vals_wsp_parameter_sec[] = {
1047         { 0x00, "NETWPIN" },
1048         { 0x01, "USERPIN" },
1049         { 0x02, "USERNETWPIN" },
1050         { 0x03, "USERPINMAC" },
1051
1052         { 0x00, NULL }
1053 };
1054
1055 /* Warning codes and mappings */
1056 static const value_string vals_wsp_warning_code[] = {
1057         { 10, "110 Response is stale" },
1058         { 11, "111 Revalidation failed" },
1059         { 12, "112 Disconnected operation" },
1060         { 13, "113 Heuristic expiration" },
1061         { 14, "214 Transformation applied" },
1062         { 99, "199/299 Miscellaneous warning" },
1063
1064         { 0, NULL }
1065 };
1066
1067 static const value_string vals_wsp_warning_code_short[] = {
1068         { 10, "110" },
1069         { 11, "111" },
1070         { 12, "112" },
1071         { 13, "113" },
1072         { 14, "214" },
1073         { 99, "199/299" },
1074
1075         { 0, NULL }
1076 };
1077
1078 /* Profile-Warning codes - see http://www.w3.org/TR/NOTE-CCPPexchange */
1079 static const value_string vals_wsp_profile_warning_code[] = {
1080         { 0x10, "100 OK" },
1081         { 0x11, "101 Used stale profile" },
1082         { 0x12, "102 Not used profile" },
1083         { 0x20, "200 Not applied" },
1084         { 0x21, "101 Content selection applied" },
1085         { 0x22, "202 Content generation applied" },
1086         { 0x23, "203 Transformation applied" },
1087
1088         { 0x00, NULL }
1089 };
1090
1091 /* Well-known TE values */
1092 static const value_string vals_well_known_te[] = {
1093         { 0x82, "chunked" },
1094         { 0x83, "identity" },
1095         { 0x84, "gzip" },
1096         { 0x85, "compress" },
1097         { 0x86, "deflate" },
1098
1099         { 0x00, NULL }
1100 };
1101
1102
1103 /*
1104  * Redirect flags.
1105  */
1106 #define PERMANENT_REDIRECT              0x80
1107 #define REUSE_SECURITY_SESSION  0x40
1108
1109 /*
1110  * Redirect address flags and length.
1111  */
1112 #define BEARER_TYPE_INCLUDED    0x80
1113 #define PORT_NUMBER_INCLUDED    0x40
1114 #define ADDRESS_LEN                             0x3f
1115
1116 static const true_false_string yes_no_truth = {
1117         "Yes" ,
1118         "No"
1119 };
1120
1121 static const value_string vals_false_true[] = {
1122         { 0, "False" },
1123         { 1, "True" },
1124         { 0, NULL },
1125 };
1126
1127 enum {
1128         WSP_PDU_RESERVED                = 0x00,
1129         WSP_PDU_CONNECT                 = 0x01,
1130         WSP_PDU_CONNECTREPLY    = 0x02,
1131         WSP_PDU_REDIRECT                = 0x03,                 /* No sample data */
1132         WSP_PDU_REPLY                   = 0x04,
1133         WSP_PDU_DISCONNECT              = 0x05,
1134         WSP_PDU_PUSH                    = 0x06,                 /* No sample data */
1135         WSP_PDU_CONFIRMEDPUSH   = 0x07,                 /* No sample data */
1136         WSP_PDU_SUSPEND                 = 0x08,                 /* No sample data */
1137         WSP_PDU_RESUME                  = 0x09,                 /* No sample data */
1138
1139         WSP_PDU_GET                             = 0x40,
1140         WSP_PDU_OPTIONS                 = 0x41,                 /* No sample data */
1141         WSP_PDU_HEAD                    = 0x42,                 /* No sample data */
1142         WSP_PDU_DELETE                  = 0x43,                 /* No sample data */
1143         WSP_PDU_TRACE                   = 0x44,                 /* No sample data */
1144
1145         WSP_PDU_POST                    = 0x60,
1146         WSP_PDU_PUT                             = 0x61,                 /* No sample data */
1147 };
1148
1149 #define VAL_STRING_SIZE 200
1150
1151 typedef enum {
1152         VALUE_LEN_SUPPLIED,
1153         VALUE_IS_TEXT_STRING,
1154         VALUE_IN_LEN,
1155 } value_type_t;
1156
1157 static dissector_table_t wsp_dissector_table;
1158 static dissector_table_t wsp_dissector_table_text;
1159 static heur_dissector_list_t heur_subdissector_list;
1160
1161 static void add_uri (proto_tree *, packet_info *, tvbuff_t *, guint, guint);
1162
1163 static void add_post_variable (proto_tree *, tvbuff_t *, guint, guint, guint, guint);
1164 static void add_multipart_data (proto_tree *, tvbuff_t *);
1165
1166 static void add_capabilities (proto_tree *tree, tvbuff_t *tvb, int type);
1167 static void add_capability_vals(tvbuff_t *, gboolean, int, guint, guint, char *, size_t);
1168 static guint get_uintvar (tvbuff_t *, guint, guint);
1169
1170
1171
1172 /*
1173  * Dissect the WSP header part.
1174  * This function calls wkh_XXX functions that dissect well-known headers.
1175  */
1176 static void add_headers (proto_tree *tree, tvbuff_t *tvb);
1177
1178 /* The following macros define WSP basic data structures as found
1179  * in the ABNF notation of WSP headers.
1180  * Currently all text data types are mapped to text_string.
1181  */
1182 #define is_short_integer(x)             ( (x) & 0x80 )
1183 #define is_long_integer(x)              ( (x) <= 30 )
1184 #define is_date_value(x)                is_long_integer(x)
1185 #define is_integer_value(x)             (is_short_integer(x) || is_long_integer(x))
1186 #define is_delta_seconds_value(x)       is_integer_value(x)
1187 /* Text string == *TEXT 0x00, thus also an empty string matches the rule! */
1188 #define is_text_string(x)       ( ((x) == 0) || ( ((x) >= 32) && ((x) <= 127)) ) 
1189 #define is_quoted_string(x)             ( (x) == 0x22 ) /* " */
1190 #define is_token_text(x)                is_text_string(x)
1191 #define is_text_value(x)                is_text_string(x)
1192 #define is_uri_value(x)                 is_text_string(x)
1193
1194 #define get_uintvar_integer(val,tvb,start,len,ok) \
1195         val = tvb_get_guintvar(tvb,start,&len); \
1196         if (len>5) ok = FALSE; else ok = TRUE;
1197 #define get_short_integer(val,tvb,start,len,ok) \
1198         val = tvb_get_guint8(tvb,start); \
1199         if (val & 0x80) ok = TRUE; else ok=FALSE; \
1200         val &= 0x7F; len = 1;
1201 #define get_long_integer(val,tvb,start,len,ok) \
1202         len = tvb_get_guint8(tvb,start); \
1203         ok = TRUE; /* Valid lengths for us are 1-4 */ \
1204         if (len==1) { val = tvb_get_guint8(tvb,start+1); } \
1205         else if (len==2) { val = tvb_get_ntohs(tvb,start+1); } \
1206         else if (len==3) { val = tvb_get_ntoh24(tvb,start+1); } \
1207         else if (len==4) { val = tvb_get_ntohl(tvb,start+1); } \
1208         else ok = FALSE; \
1209         len++; /* Add the 1st octet to the length */
1210 #define get_integer_value(val,tvb,start,len,ok) \
1211         len = tvb_get_guint8(tvb,start); \
1212         ok = TRUE; \
1213         if (len & 0x80) { val = len & 0x7F; len = 0; } \
1214         else if (len==1) { val = tvb_get_guint8(tvb,start+1); } \
1215         else if (len==2) { val = tvb_get_ntohs(tvb,start+1); } \
1216         else if (len==3) { val = tvb_get_ntoh24(tvb,start+1); } \
1217         else if (len==4) { val = tvb_get_ntohl(tvb,start+1); } \
1218         else ok = FALSE; \
1219         len++; /* Add the 1st octet to the length */
1220 #define get_date_value(val,tvb,start,len,ok) \
1221         get_long_integer(val,tvb,start,len,ok)
1222 #define get_delta_seconds_value(val,tvb,start,len,ok) \
1223         get_integer_value(val,tvb,start,len,ok)
1224
1225 /* NOTE - Don't forget to g_free() the str value after its usage as the
1226  * tvb_get_string[z]() functions return g_malloc()ed memory! */ 
1227 #define get_text_string(str,tvb,start,len,ok) \
1228         if (is_text_string(tvb_get_guint8(tvb,start))) { \
1229                 str = tvb_get_stringz(tvb,start,&len); \
1230                 g_assert (str); \
1231                 ok = TRUE; \
1232         } else { len = 0; str = NULL; ok = FALSE; }
1233 #define get_token_text(str,tvb,start,len,ok) \
1234         get_text_string(str,tvb,start,len,ok)
1235 #define get_extension_media(str,tvb,start,len,ok) \
1236         get_text_string(str,tvb,start,len,ok)
1237 #define get_text_value(str,tvb,start,len,ok) \
1238         get_text_string(str,tvb,start,len,ok)
1239 #define get_quoted_string(str,tvb,start,len,ok) \
1240         get_text_string(str,tvb,start,len,ok)
1241 #define get_uri_value(str,tvb,start,len,ok) \
1242         get_text_string(str,tvb,start,len,ok)
1243
1244 #define get_version_value(val,str,tvb,start,len,ok) \
1245         val = tvb_get_guint8(tvb,start); \
1246         ok = TRUE; \
1247         if (val & 0x80) { /* High nibble "." Low nibble */ \
1248                 len = 1; \
1249                 val &= 0x7F; \
1250                 str = g_strdup_printf("%u.%u", val >> 4, val & 0x0F); \
1251         } else { get_text_string(str,tvb,start,len,ok); }
1252         
1253 /* Parameter parser */
1254 static int
1255 parameter (proto_tree *tree, proto_item *ti, tvbuff_t *tvb, int start, int len);
1256 static int
1257 parameter_value_q (proto_tree *tree, proto_item *ti, tvbuff_t *tvb, int start);
1258
1259 #define InvalidValueForHeader(hdr) \
1260         "<Error: Invalid value for the '" hdr "' header>"
1261 #define InvalidTextualHeader \
1262         "<Error: Invalid zero-length textual header>"
1263 #define TrailingQuoteWarning \
1264         " <Warning: Quoted-string value has been encoded with a trailing quote>"
1265
1266 /* WSP well-known header parsing function prototypes;
1267  * will be listed in the function lookup table WellKnownHeaders[] */
1268 static guint32 wkh_default (proto_tree *tree, tvbuff_t *tvb,
1269                 guint32 hdr_start);
1270 static guint32 wkh_accept (proto_tree *tree, tvbuff_t *tvb,
1271                 guint32 hdr_start);
1272 static guint32 wkh_content_type (proto_tree *tree, tvbuff_t *tvb,
1273                 guint32 hdr_start);
1274 static guint32 wkh_accept_charset (proto_tree *tree, tvbuff_t *tvb,
1275                 guint32 hdr_start);
1276 static guint32 wkh_accept_language (proto_tree *tree, tvbuff_t *tvb,
1277                 guint32 hdr_start);
1278 static guint32 wkh_connection (proto_tree *tree, tvbuff_t *tvb,
1279                 guint32 hdr_start);
1280 static guint32 wkh_push_flag (proto_tree *tree, tvbuff_t *tvb,
1281                 guint32 header_start);
1282 static guint32 wkh_vary (proto_tree *tree, tvbuff_t *tvb,
1283                 guint32 hdr_start);
1284 static guint32 wkh_accept_ranges (proto_tree *tree, tvbuff_t *tvb,
1285                 guint32 hdr_start);
1286 static guint32 wkh_content_disposition (proto_tree *tree, tvbuff_t *tvb,
1287                 guint32 hdr_start);
1288 static guint32 wkh_accept_encoding (proto_tree *tree, tvbuff_t *tvb,
1289                 guint32 hdr_start);
1290 static guint32 wkh_content_encoding (proto_tree *tree, tvbuff_t *tvb,
1291                 guint32 hdr_start);
1292 static guint32 wkh_transfer_encoding (proto_tree *tree, tvbuff_t *tvb,
1293                 guint32 hdr_start);
1294 static guint32 wkh_pragma (proto_tree *tree, tvbuff_t *tvb,
1295                 guint32 hdr_start);
1296 /* Single short-integer value */
1297 static guint32 wkh_x_wap_security (proto_tree *tree, tvbuff_t *tvb,
1298                 guint32 hdr_start);
1299 /* Text */
1300 static guint32 wkh_content_base (proto_tree *tree, tvbuff_t *tvb,
1301                 guint32 hdr_start);
1302 static guint32 wkh_content_location (proto_tree *tree, tvbuff_t *tvb,
1303                 guint32 hdr_start);
1304 static guint32 wkh_etag (proto_tree *tree, tvbuff_t *tvb,
1305                 guint32 hdr_start);
1306 static guint32 wkh_from (proto_tree *tree, tvbuff_t *tvb,
1307                 guint32 hdr_start);
1308 static guint32 wkh_host (proto_tree *tree, tvbuff_t *tvb,
1309                 guint32 hdr_start);
1310 static guint32 wkh_if_match (proto_tree *tree, tvbuff_t *tvb,
1311                 guint32 hdr_start);
1312 static guint32 wkh_if_none_match (proto_tree *tree, tvbuff_t *tvb,
1313                 guint32 hdr_start);
1314 static guint32 wkh_location (proto_tree *tree, tvbuff_t *tvb,
1315                 guint32 hdr_start);
1316 static guint32 wkh_referer (proto_tree *tree, tvbuff_t *tvb,
1317                 guint32 hdr_start);
1318 static guint32 wkh_server (proto_tree *tree, tvbuff_t *tvb,
1319                 guint32 hdr_start);
1320 static guint32 wkh_user_agent (proto_tree *tree, tvbuff_t *tvb,
1321                 guint32 hdr_start);
1322 static guint32 wkh_upgrade (proto_tree *tree, tvbuff_t *tvb,
1323                 guint32 hdr_start);
1324 static guint32 wkh_via (proto_tree *tree, tvbuff_t *tvb,
1325                 guint32 hdr_start);
1326 static guint32 wkh_content_uri (proto_tree *tree, tvbuff_t *tvb,
1327                 guint32 hdr_start);
1328 static guint32 wkh_initiator_uri (proto_tree *tree, tvbuff_t *tvb,
1329                 guint32 hdr_start);
1330 static guint32 wkh_profile (proto_tree *tree, tvbuff_t *tvb,
1331                 guint32 hdr_start);
1332 static guint32 wkh_content_id (proto_tree *tree, tvbuff_t *tvb,
1333                 guint32 hdr_start);
1334 /* Date-value or text */
1335 static guint32 wkh_if_range (proto_tree *tree, tvbuff_t *tvb,
1336                 guint32 hdr_start);
1337 /* Date-value */
1338 static guint32 wkh_date (proto_tree *tree, tvbuff_t *tvb,
1339                 guint32 hdr_start);
1340 static guint32 wkh_expires (proto_tree *tree, tvbuff_t *tvb,
1341                 guint32 hdr_start);
1342 static guint32 wkh_if_modified_since (proto_tree *tree, tvbuff_t *tvb,
1343                 guint32 hdr_start);
1344 static guint32 wkh_if_unmodified_since (proto_tree *tree, tvbuff_t *tvb,
1345                 guint32 hdr_start);
1346 static guint32 wkh_last_modified (proto_tree *tree, tvbuff_t *tvb,
1347                 guint32 hdr_start);
1348 /* Date-value with special meaning */
1349 static guint32 wkh_x_wap_tod (proto_tree *tree, tvbuff_t *tvb,
1350                 guint32 hdr_start);
1351 /* Delta-seconds-value */
1352 static guint32 wkh_age (proto_tree *tree, tvbuff_t *tvb,
1353                 guint32 hdr_start);
1354 /* Challenge */
1355 static guint32 wkh_proxy_authenticate (proto_tree *tree, tvbuff_t *tvb,
1356                 guint32 hdr_start);
1357 static guint32 wkh_www_authenticate (proto_tree *tree, tvbuff_t *tvb,
1358                 guint32 hdr_start);
1359 /* Credentials */
1360 static guint32 wkh_authorization (proto_tree *tree, tvbuff_t *tvb,
1361                 guint32 hdr_start);
1362 static guint32 wkh_proxy_authorization (proto_tree *tree, tvbuff_t *tvb,
1363                 guint32 hdr_start);
1364 /* Pragma */
1365 static guint32 wkh_pragma (proto_tree *tree, tvbuff_t *tvb,
1366                 guint32 hdr_start);
1367 /* Integer-value */
1368 static guint32 wkh_content_length (proto_tree *tree, tvbuff_t *tvb,
1369                 guint32 hdr_start);
1370 static guint32 wkh_max_forwards (proto_tree *tree, tvbuff_t *tvb,
1371                 guint32 hdr_start);
1372
1373 /* Integer lookup value */
1374 static guint32 wkh_bearer_indication (proto_tree *tree, tvbuff_t *tvb,
1375                 guint32 hdr_start);
1376
1377 /* WAP application ID value */
1378 static guint32 wkh_x_wap_application_id (proto_tree *tree, tvbuff_t *tvb,
1379                 guint32 hdr_start);
1380 static guint32 wkh_accept_application (proto_tree *tree, tvbuff_t *tvb,
1381                 guint32 hdr_start);
1382 static guint32 wkh_content_language (proto_tree *tree, tvbuff_t *tvb,
1383                 guint32 hdr_start);
1384
1385 /* Allow and Public */
1386 static guint32 wkh_allow(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start);
1387 static guint32 wkh_public(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start);
1388
1389 /* Cache-control */
1390 static guint32 wkh_cache_control (proto_tree *tree, tvbuff_t *tvb,
1391                 guint32 hdr_start);
1392 /* Warning */
1393 static guint32 wkh_warning (proto_tree *tree, tvbuff_t *tvb,
1394                 guint32 hdr_start);
1395 /* Profile-warning */
1396 static guint32 wkh_profile_warning (proto_tree *tree, tvbuff_t *tvb,
1397                 guint32 hdr_start);
1398
1399 /* Content-MD5 */
1400 static guint32 wkh_content_md5 (proto_tree *tree, tvbuff_t *tvb,
1401                 guint32 hdr_start);
1402
1403 /* WSP encoding version */
1404 static guint32 wkh_encoding_version (proto_tree *tree, tvbuff_t *tvb,
1405                 guint32 hdr_start);
1406
1407 /* Content-Range and Range */
1408 static guint32 wkh_content_range (proto_tree *tree, tvbuff_t *tvb,
1409                 guint32 hdr_start);
1410 static guint32 wkh_range (proto_tree *tree, tvbuff_t *tvb,
1411                 guint32 hdr_start);
1412
1413 /* TE */
1414 static guint32 wkh_te (proto_tree *tree, tvbuff_t *tvb,
1415                 guint32 hdr_start);
1416
1417 /* Header value */
1418 static guint32 wkh_trailer (proto_tree *tree, tvbuff_t *tvb,
1419                 guint32 hdr_start);
1420
1421 /* TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO
1422 static guint32 wkh_retry_after (proto_tree *tree, tvbuff_t *tvb,
1423                 guint32 hdr_start);
1424 static guint32 wkh_profile_diff (proto_tree *tree, tvbuff_t *tvb,
1425                 guint32 hdr_start);
1426 static guint32 wkh_expect (proto_tree *tree, tvbuff_t *tvb,
1427                 guint32 hdr_start);
1428 static guint32 wkh_set_cookie (proto_tree *tree, tvbuff_t *tvb,
1429                 guint32 hdr_start);
1430 static guint32 wkh_cookie (proto_tree *tree, tvbuff_t *tvb,
1431                 guint32 hdr_start);
1432 */
1433
1434
1435 /* WSP well-known Openwave header parsing function prototypes;
1436  * will be listed in the function lookup table WellKnownOpenwaveHeaders[] */
1437 static guint32 wkh_openwave_default (proto_tree *tree, tvbuff_t *tvb,
1438                 guint32 hdr_start);
1439 /* Textual headers */
1440 static guint32 wkh_openwave_x_up_proxy_operator_domain(proto_tree *tree,
1441                 tvbuff_t *tvb, guint32 hdr_start);
1442 static guint32 wkh_openwave_x_up_proxy_home_page(proto_tree *tree,
1443                 tvbuff_t *tvb, guint32 hdr_start);
1444 static guint32 wkh_openwave_x_up_proxy_uplink_version(proto_tree *tree,
1445                 tvbuff_t *tvb, guint32 hdr_start);
1446 static guint32 wkh_openwave_x_up_proxy_ba_realm(proto_tree *tree,
1447                 tvbuff_t *tvb, guint32 hdr_start);
1448 static guint32 wkh_openwave_x_up_proxy_request_uri(proto_tree *tree,
1449                 tvbuff_t *tvb, guint32 hdr_start);
1450 static guint32 wkh_openwave_x_up_proxy_bookmark(proto_tree *tree,
1451                 tvbuff_t *tvb, guint32 hdr_start);
1452 /* Integer headers */
1453 static guint32 wkh_openwave_x_up_proxy_push_seq(proto_tree *tree,
1454                 tvbuff_t *tvb, guint32 hdr_start);
1455 static guint32 wkh_openwave_x_up_proxy_notify(proto_tree *tree,
1456                 tvbuff_t *tvb, guint32 hdr_start);
1457 static guint32 wkh_openwave_x_up_proxy_net_ask(proto_tree *tree,
1458                 tvbuff_t *tvb, guint32 hdr_start);
1459 static guint32 wkh_openwave_x_up_proxy_tod (proto_tree *tree,
1460                 tvbuff_t *tvb, guint32 hdr_start);
1461 static guint32 wkh_openwave_x_up_proxy_ba_enable(proto_tree *tree,
1462                 tvbuff_t *tvb, guint32 hdr_start);
1463 static guint32 wkh_openwave_x_up_proxy_redirect_enable(proto_tree *tree,
1464                 tvbuff_t *tvb, guint32 hdr_start);
1465 static guint32 wkh_openwave_x_up_proxy_redirect_status(proto_tree *tree,
1466                 tvbuff_t *tvb, guint32 hdr_start);
1467 static guint32 wkh_openwave_x_up_proxy_linger(proto_tree *tree,
1468                 tvbuff_t *tvb, guint32 hdr_start);
1469 static guint32 wkh_openwave_x_up_proxy_enable_trust(proto_tree *tree,
1470                 tvbuff_t *tvb, guint32 hdr_start);
1471 static guint32 wkh_openwave_x_up_proxy_trust(proto_tree *tree,
1472                 tvbuff_t *tvb, guint32 hdr_start);
1473 static guint32 wkh_openwave_x_up_devcap_has_color(proto_tree *tree,
1474                 tvbuff_t *tvb, guint32 hdr_start);
1475 static guint32 wkh_openwave_x_up_devcap_num_softkeys(proto_tree *tree,
1476                 tvbuff_t *tvb, guint32 hdr_start);
1477 static guint32 wkh_openwave_x_up_devcap_softkey_size(proto_tree *tree,
1478                 tvbuff_t *tvb, guint32 hdr_start);
1479 static guint32 wkh_openwave_x_up_devcap_screen_chars(proto_tree *tree,
1480                 tvbuff_t *tvb, guint32 hdr_start);
1481 static guint32 wkh_openwave_x_up_devcap_screen_pixels(proto_tree *tree,
1482                 tvbuff_t *tvb, guint32 hdr_start);
1483 static guint32 wkh_openwave_x_up_devcap_em_size(proto_tree *tree,
1484                 tvbuff_t *tvb, guint32 hdr_start);
1485 static guint32 wkh_openwave_x_up_devcap_screen_depth(proto_tree *tree,
1486                 tvbuff_t *tvb, guint32 hdr_start);
1487 static guint32 wkh_openwave_x_up_devcap_immed_alert(proto_tree *tree,
1488                 tvbuff_t *tvb, guint32 hdr_start);
1489 static guint32 wkh_openwave_x_up_devcap_gui(proto_tree *tree,
1490                 tvbuff_t *tvb, guint32 hdr_start);
1491
1492 static guint32 wkh_openwave_x_up_proxy_trans_charset(proto_tree *tree,
1493                 tvbuff_t *tvb, guint32 hdr_start);
1494 static guint32 wkh_openwave_x_up_proxy_push_accept(proto_tree *tree,
1495                 tvbuff_t *tvb, guint32 hdr_start);
1496
1497
1498 /* Define a pointer to function data type for the well-known header
1499  * lookup table below */
1500 typedef guint32 (*hdr_parse_func_ptr) (proto_tree *, tvbuff_t *, guint32);
1501
1502 /* Lookup table for well-known header parsing functions */
1503 static const hdr_parse_func_ptr WellKnownHeader[128] = {
1504         /* 0x00 */      wkh_accept,                             /* 0x01 */      wkh_accept_charset,
1505         /* 0x02 */      wkh_accept_encoding,    /* 0x03 */      wkh_accept_language,
1506         /* 0x04 */      wkh_accept_ranges,              /* 0x05 */      wkh_age,
1507         /* 0x06 */      wkh_allow,                              /* 0x07 */      wkh_authorization,
1508         /* 0x08 */      wkh_cache_control,              /* 0x09 */      wkh_connection,
1509         /* 0x0A */      wkh_content_base,               /* 0x0B */      wkh_content_encoding,
1510         /* 0x0C */      wkh_content_language,   /* 0x0D */      wkh_content_length,
1511         /* 0x0E */      wkh_content_location,   /* 0x0F */      wkh_content_md5,
1512         /* 0x10 */      wkh_content_range,              /* 0x11 */      wkh_content_type,
1513         /* 0x12 */      wkh_date,                               /* 0x13 */      wkh_etag,
1514         /* 0x14 */      wkh_expires,                    /* 0x15 */      wkh_from,
1515         /* 0x16 */      wkh_host,                               /* 0x17 */      wkh_if_modified_since,
1516         /* 0x18 */      wkh_if_match,                   /* 0x19 */      wkh_if_none_match,
1517         /* 0x1A */      wkh_if_range,                   /* 0x1B */      wkh_if_unmodified_since,
1518         /* 0x1C */      wkh_location,                   /* 0x1D */      wkh_last_modified,
1519         /* 0x1E */      wkh_max_forwards,               /* 0x1F */      wkh_pragma,
1520         /* 0x20 */      wkh_proxy_authenticate, /* 0x21 */      wkh_proxy_authorization,
1521         /* 0x22 */      wkh_public,                             /* 0x23 */      wkh_range,
1522         /* 0x24 */      wkh_referer,                    /* 0x25 */      wkh_default,
1523         /* 0x26 */      wkh_server,                             /* 0x27 */      wkh_transfer_encoding,
1524         /* 0x28 */      wkh_upgrade,                    /* 0x29 */      wkh_user_agent,
1525         /* 0x2A */      wkh_vary,                               /* 0x2B */      wkh_via,
1526         /* 0x2C */      wkh_warning,                    /* 0x2D */      wkh_www_authenticate,
1527         /* 0x2E */      wkh_content_disposition,/* 0x2F */      wkh_x_wap_application_id,
1528         /* 0x30 */      wkh_content_uri,                /* 0x31 */      wkh_initiator_uri,
1529         /* 0x32 */      wkh_accept_application, /* 0x33 */      wkh_bearer_indication,
1530         /* 0x34 */      wkh_push_flag,                  /* 0x35 */      wkh_profile,
1531         /* 0x36 */      wkh_default,                    /* 0x37 */      wkh_profile_warning,
1532         /* 0x38 */      wkh_default,                    /* 0x39 */      wkh_te,
1533         /* 0x3A */      wkh_trailer,                    /* 0x3B */      wkh_accept_charset,
1534         /* 0x3C */      wkh_accept_encoding,    /* 0x3D */      wkh_cache_control,
1535         /* 0x3E */      wkh_content_range,              /* 0x3F */      wkh_x_wap_tod,
1536         /* 0x40 */      wkh_content_id,                 /* 0x41 */      wkh_default,
1537         /* 0x42 */      wkh_default,                    /* 0x43 */      wkh_encoding_version,
1538         /* 0x44 */      wkh_profile_warning,    /* 0x45 */      wkh_content_disposition,
1539         /* 0x46 */      wkh_x_wap_security,             /* 0x47 */      wkh_cache_control,
1540         /*******************************************************
1541          *** The following headers are not (yet) registered. ***
1542          *******************************************************/
1543         /* 0x48 */      wkh_default,                    /* 0x49 */      wkh_default,
1544         /* 0x4A */      wkh_default,                    /* 0x4B */      wkh_default,
1545         /* 0x4C */      wkh_default,                    /* 0x4D */      wkh_default,
1546         /* 0x4E */      wkh_default,                    /* 0x4F */      wkh_default,
1547         /* 0x50 */      wkh_default,                    /* 0x51 */      wkh_default,
1548         /* 0x52 */      wkh_default,                    /* 0x53 */      wkh_default,
1549         /* 0x54 */      wkh_default,                    /* 0x55 */      wkh_default,
1550         /* 0x56 */      wkh_default,                    /* 0x57 */      wkh_default,
1551         /* 0x58 */      wkh_default,                    /* 0x59 */      wkh_default,
1552         /* 0x5A */      wkh_default,                    /* 0x5B */      wkh_default,
1553         /* 0x5C */      wkh_default,                    /* 0x5D */      wkh_default,
1554         /* 0x5E */      wkh_default,                    /* 0x5F */      wkh_default,
1555         /* 0x60 */      wkh_default,                    /* 0x61 */      wkh_default,
1556         /* 0x62 */      wkh_default,                    /* 0x63 */      wkh_default,
1557         /* 0x64 */      wkh_default,                    /* 0x65 */      wkh_default,
1558         /* 0x66 */      wkh_default,                    /* 0x67 */      wkh_default,
1559         /* 0x68 */      wkh_default,                    /* 0x69 */      wkh_default,
1560         /* 0x6A */      wkh_default,                    /* 0x6B */      wkh_default,
1561         /* 0x6C */      wkh_default,                    /* 0x6D */      wkh_default,
1562         /* 0x6E */      wkh_default,                    /* 0x6F */      wkh_default,
1563         /* 0x70 */      wkh_default,                    /* 0x71 */      wkh_default,
1564         /* 0x72 */      wkh_default,                    /* 0x73 */      wkh_default,
1565         /* 0x74 */      wkh_default,                    /* 0x75 */      wkh_default,
1566         /* 0x76 */      wkh_default,                    /* 0x77 */      wkh_default,
1567         /* 0x78 */      wkh_default,                    /* 0x79 */      wkh_default,
1568         /* 0x7A */      wkh_default,                    /* 0x7B */      wkh_default,
1569         /* 0x7C */      wkh_default,                    /* 0x7D */      wkh_default,
1570         /* 0x7E */      wkh_default,                    /* 0x7F */      wkh_default,
1571 }; 
1572
1573 /* Lookup table for well-known header parsing functions */
1574 static const hdr_parse_func_ptr WellKnownOpenwaveHeader[128] = {
1575         /* 0x00 */      wkh_openwave_default,
1576         /* 0x01 */      wkh_openwave_x_up_proxy_push_accept,
1577         /* 0x02 */      wkh_openwave_x_up_proxy_push_seq,
1578         /* 0x03 */      wkh_openwave_x_up_proxy_notify,
1579         /* 0x04 */      wkh_openwave_x_up_proxy_operator_domain,
1580         /* 0x05 */      wkh_openwave_x_up_proxy_home_page,
1581         /* 0x06 */      wkh_openwave_x_up_devcap_has_color,
1582         /* 0x07 */      wkh_openwave_x_up_devcap_num_softkeys,
1583         /* 0x08 */      wkh_openwave_x_up_devcap_softkey_size,
1584         /* 0x09 */      wkh_openwave_x_up_devcap_screen_chars,
1585         /* 0x0A */      wkh_openwave_x_up_devcap_screen_pixels,
1586         /* 0x0B */      wkh_openwave_x_up_devcap_em_size,
1587         /* 0x0C */      wkh_openwave_x_up_devcap_screen_depth,
1588         /* 0x0D */      wkh_openwave_x_up_devcap_immed_alert,
1589         /* 0x0E */      wkh_openwave_x_up_proxy_net_ask,
1590         /* 0x0F */      wkh_openwave_x_up_proxy_uplink_version,
1591         /* 0x10 */      wkh_openwave_x_up_proxy_tod,
1592         /* 0x11 */      wkh_openwave_x_up_proxy_ba_enable,
1593         /* 0x12 */      wkh_openwave_x_up_proxy_ba_realm,
1594         /* 0x13 */      wkh_openwave_x_up_proxy_redirect_enable,
1595         /* 0x14 */      wkh_openwave_x_up_proxy_request_uri,
1596         /* 0x15 */      wkh_openwave_x_up_proxy_redirect_status,
1597         /* 0x16 */      wkh_openwave_x_up_proxy_trans_charset,
1598         /* 0x17 */      wkh_openwave_x_up_proxy_linger,
1599         /* 0x18 */      wkh_openwave_default,
1600         /* 0x19 */      wkh_openwave_x_up_proxy_enable_trust,
1601         /* 0x1A */      wkh_openwave_x_up_proxy_trust,
1602         /* 0x1B */      wkh_openwave_default,
1603         /* 0x1C */      wkh_openwave_default,
1604         /* 0x1D */      wkh_openwave_default,
1605         /* 0x1E */      wkh_openwave_default,
1606         /* 0x1F */      wkh_openwave_default,
1607         /* 0x20 */      wkh_openwave_x_up_proxy_trust,
1608         /* 0x21 */      wkh_openwave_x_up_proxy_bookmark,
1609         /* 0x22 */      wkh_openwave_x_up_devcap_gui,
1610         /*******************************************************
1611          *** The following headers are not (yet) registered. ***
1612          *******************************************************/
1613         /* 0x23 */      wkh_openwave_default,
1614         /* 0x24 */      wkh_openwave_default,           /* 0x25 */      wkh_openwave_default,
1615         /* 0x26 */      wkh_openwave_default,           /* 0x27 */      wkh_openwave_default,
1616         /* 0x28 */      wkh_openwave_default,           /* 0x29 */      wkh_openwave_default,
1617         /* 0x2A */      wkh_openwave_default,           /* 0x2B */      wkh_openwave_default,
1618         /* 0x2C */      wkh_openwave_default,           /* 0x2D */      wkh_openwave_default,
1619         /* 0x2E */      wkh_openwave_default,           /* 0x2F */      wkh_openwave_default,
1620         /* 0x30 */      wkh_openwave_default,           /* 0x31 */      wkh_openwave_default,
1621         /* 0x32 */      wkh_openwave_default,           /* 0x33 */      wkh_openwave_default,
1622         /* 0x34 */      wkh_openwave_default,           /* 0x35 */      wkh_openwave_default,
1623         /* 0x36 */      wkh_openwave_default,           /* 0x37 */      wkh_openwave_default,
1624         /* 0x38 */      wkh_openwave_default,           /* 0x39 */      wkh_openwave_default,
1625         /* 0x3A */      wkh_openwave_default,           /* 0x3B */      wkh_openwave_default,
1626         /* 0x3C */      wkh_openwave_default,           /* 0x3D */      wkh_openwave_default,
1627         /* 0x3E */      wkh_openwave_default,           /* 0x3F */      wkh_openwave_default,
1628         /* 0x40 */      wkh_openwave_default,           /* 0x41 */      wkh_openwave_default,
1629         /* 0x42 */      wkh_openwave_default,           /* 0x43 */      wkh_openwave_default,
1630         /* 0x44 */      wkh_openwave_default,           /* 0x45 */      wkh_openwave_default,
1631         /* 0x46 */      wkh_openwave_default,           /* 0x47 */      wkh_openwave_default,
1632         /* 0x48 */      wkh_openwave_default,           /* 0x49 */      wkh_openwave_default,
1633         /* 0x4A */      wkh_openwave_default,           /* 0x4B */      wkh_openwave_default,
1634         /* 0x4C */      wkh_openwave_default,           /* 0x4D */      wkh_openwave_default,
1635         /* 0x4E */      wkh_openwave_default,           /* 0x4F */      wkh_openwave_default,
1636         /* 0x50 */      wkh_openwave_default,           /* 0x51 */      wkh_openwave_default,
1637         /* 0x52 */      wkh_openwave_default,           /* 0x53 */      wkh_openwave_default,
1638         /* 0x54 */      wkh_openwave_default,           /* 0x55 */      wkh_openwave_default,
1639         /* 0x56 */      wkh_openwave_default,           /* 0x57 */      wkh_openwave_default,
1640         /* 0x58 */      wkh_openwave_default,           /* 0x59 */      wkh_openwave_default,
1641         /* 0x5A */      wkh_openwave_default,           /* 0x5B */      wkh_openwave_default,
1642         /* 0x5C */      wkh_openwave_default,           /* 0x5D */      wkh_openwave_default,
1643         /* 0x5E */      wkh_openwave_default,           /* 0x5F */      wkh_openwave_default,
1644         /* 0x60 */      wkh_openwave_default,           /* 0x61 */      wkh_openwave_default,
1645         /* 0x62 */      wkh_openwave_default,           /* 0x63 */      wkh_openwave_default,
1646         /* 0x64 */      wkh_openwave_default,           /* 0x65 */      wkh_openwave_default,
1647         /* 0x66 */      wkh_openwave_default,           /* 0x67 */      wkh_openwave_default,
1648         /* 0x68 */      wkh_openwave_default,           /* 0x69 */      wkh_openwave_default,
1649         /* 0x6A */      wkh_openwave_default,           /* 0x6B */      wkh_openwave_default,
1650         /* 0x6C */      wkh_openwave_default,           /* 0x6D */      wkh_openwave_default,
1651         /* 0x6E */      wkh_openwave_default,           /* 0x6F */      wkh_openwave_default,
1652         /* 0x70 */      wkh_openwave_default,           /* 0x71 */      wkh_openwave_default,
1653         /* 0x72 */      wkh_openwave_default,           /* 0x73 */      wkh_openwave_default,
1654         /* 0x74 */      wkh_openwave_default,           /* 0x75 */      wkh_openwave_default,
1655         /* 0x76 */      wkh_openwave_default,           /* 0x77 */      wkh_openwave_default,
1656         /* 0x78 */      wkh_openwave_default,           /* 0x79 */      wkh_openwave_default,
1657         /* 0x7A */      wkh_openwave_default,           /* 0x7B */      wkh_openwave_default,
1658         /* 0x7C */      wkh_openwave_default,           /* 0x7D */      wkh_openwave_default,
1659         /* 0x7E */      wkh_openwave_default,           /* 0x7F */      wkh_openwave_default,
1660 }; 
1661
1662
1663
1664
1665
1666
1667 /* WSP header format
1668  *   1st byte: 0x00        : <Not allowed>
1669  *   1st byte: 0x01 -- 0x1F: <Shorthand Header Code Page switch>
1670  *   1st byte: 0x20 -- 0x7E: <Textual header (C string)>
1671  *       Followed with: <Textual header value (C string)>
1672  *   1st byte: 0x7F        : <Header Code Page switch>
1673  *       Followed with: 2nd byte: <Header Code Page>
1674  *   1st byte: 0x80 -- 0xFF: <Binary header (7-bit encoded ID)>
1675  *       Followed with:
1676  *         2nd byte: 0x00 -- 0x1E: <Value Length (bytes)>
1677  *             Followed with: <Len> bytes of data
1678  *         2nd byte: 0x1F        : <Value Length is a guintvar>
1679  *             Followed with: <guintvar Len>
1680  *             Followed with: <Len> bytes of data
1681  *         2nd byte: 0x20 -- 0x7F: <Textual header value (C string)>
1682  *         2nd byte: 0x80 -- 0xFF: <Binary value (7-bit encoded ID)>
1683  */
1684 static void
1685 add_headers (proto_tree *tree, tvbuff_t *tvb)
1686 {
1687         guint8 hdr_id, val_id, codepage = 1;
1688         gint32 tvb_len = tvb_length(tvb);
1689         gint32 offset = 0, hdr_len, hdr_start;
1690         gint32 val_len, val_start;
1691         guint8 *hdr_str, *val_str;
1692         proto_tree *wsp_headers;
1693         proto_item *ti;
1694         guint8 ok;
1695         guint32 val = 0;
1696         nstime_t tv;
1697
1698         if (offset >= tvb_len)
1699                 return; /* No headers! */
1700
1701         ti = proto_tree_add_item(tree, hf_wsp_headers_section,
1702                         tvb, offset, tvb_len, bo_little_endian);
1703         wsp_headers = proto_item_add_subtree(ti, ett_headers);
1704
1705         while (offset < tvb_len) {
1706                 hdr_start = offset;
1707                 hdr_id = tvb_get_guint8(tvb, offset);
1708                 if (hdr_id & 0x80) { /* Well-known header */
1709                         hdr_len = 1;
1710                         val_start = ++offset;
1711                         val_id = tvb_get_guint8(tvb, val_start);
1712                         /* Call header value dissector for given header */
1713                         if (codepage == 1) { /* Default header code page */
1714 #ifdef DEBUG
1715                                 printf("DBG: %s\n", match_strval (hdr_id & 0x7f, vals_field_names));
1716 #endif
1717                                 offset = WellKnownHeader[hdr_id & 0x7F](wsp_headers, tvb,
1718                                                 hdr_start);
1719                         } else { /* Openwave header code page */
1720                                 /* Here I'm delibarately assuming that Openwave is the only
1721                                  * company that defines a WSP header code page. */
1722 #ifdef DEBUG
1723                                 printf("DBG: %s\n", match_strval (hdr_id & 0x7f, vals_openwave_field_names));
1724 #endif
1725                                 offset = WellKnownOpenwaveHeader[hdr_id & 0x7F](wsp_headers,
1726                                                 tvb, hdr_start);
1727                         }
1728                 } else if (hdr_id == 0x7F) { /* HCP shift sequence */
1729                         codepage = tvb_get_guint8(tvb, offset+1);
1730                         proto_tree_add_uint(wsp_headers, hf_wsp_header_shift_code,
1731                                         tvb, offset, 2, codepage);
1732                         offset += 2;
1733                 } else if (hdr_id >= 0x20) { /* Textual header */
1734                         /* Header name MUST be NUL-ended string ==> tvb_get_stringz() */
1735                         hdr_str = tvb_get_stringz(tvb, hdr_start, &hdr_len);
1736                         val_start = hdr_start + hdr_len;
1737                         val_id = tvb_get_guint8(tvb, val_start);
1738                         /* Call header value dissector for given header */
1739                         if (val_id >= 0x20 && val_id <=0x7E) { /* OK! */
1740                                 val_str = tvb_get_stringz(tvb, val_start, &val_len);
1741                                 g_assert(val_str);
1742                                 offset = val_start + val_len;
1743                                 proto_tree_add_text(wsp_headers,tvb,hdr_start,offset-hdr_start,
1744                                                 "%s: %s", hdr_str, val_str);
1745                                 g_free (val_str);
1746                         } else {
1747                                 /* Old-style X-WAP-TOD uses a non-textual value
1748                                  * after a textual header. */
1749                                 if (strcasecmp(hdr_str, "x-wap.tod") == 0) {
1750                                         get_delta_seconds_value(val, tvb, val_start, val_len, ok);
1751                                         if (ok) {
1752                                                 if (val == 0) {
1753                                                         ti = proto_tree_add_string (wsp_headers,
1754                                                                         hf_hdr_x_wap_tod,
1755                                                                         tvb, hdr_start, hdr_len + val_len,
1756                                                                         "Requesting Time Of Day");
1757                                                 } else {
1758                                                         tv.secs = val;
1759                                                         tv.nsecs = 0;
1760                                                         val_str = abs_time_to_str(&tv);
1761                                                         g_assert (val_str);
1762                                                         ti = proto_tree_add_string (wsp_headers,
1763                                                                         hf_hdr_x_wap_tod,
1764                                                                         tvb, hdr_start, hdr_len + val_len, val_str);
1765                                                 }
1766                                                 proto_item_append_text(ti, " <Warning: "
1767                                                                 "should be encoded as a textual value>");
1768                                         } else {
1769                                                 /* I prefer using X-Wap-Tod to the real hdr_str */
1770                                                 proto_tree_add_string (wsp_headers, hf_hdr_x_wap_tod,
1771                                                                 tvb, hdr_start, hdr_len + val_len,
1772                                                                 InvalidValueForHeader("X-Wap-Tod"));
1773                                         }
1774                                 } else {
1775                                         proto_tree_add_text (wsp_headers, tvb, hdr_start, hdr_len,
1776                                                         "<Error: Invalid value for the textual '%s' header"
1777                                                         " (should be a textual value)>",
1778                                                         hdr_str);
1779                                 }
1780                                 offset = tvb_len;
1781                         }
1782                         proto_tree_add_string_hidden(wsp_headers, hf_hdr_name,
1783                                         tvb, hdr_start, offset - hdr_start, hdr_str);
1784                 } else if (hdr_id > 0) { /* Shorthand HCP switch */
1785                         codepage = hdr_id;
1786                         proto_tree_add_uint (wsp_headers, hf_wsp_header_shift_code,
1787                                         tvb, offset, 1, codepage);
1788                         offset++;
1789                 } else {
1790                         proto_tree_add_text (wsp_headers, tvb, hdr_start, 1,
1791                                         InvalidTextualHeader);
1792                         offset = tvb_len;
1793                 }
1794         }
1795 }
1796
1797
1798 /* The following macros hide common processing for all well-known headers
1799  * and shortens the code to be written in a wkh_XXX() function.
1800  * Even declarations are hidden by a macro.
1801  *
1802  * Define a wkh_XXX() function as follows:
1803  *
1804  * static guint32
1805  * wkh_XXX (proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
1806  * {
1807  *              wkh_0_Declarations;
1808  *              << add other required declarations here >>
1809  *
1810  *              wkh_1_WellKnownValue;
1811  *                      << add well-known value proto item here; don't forget to set the
1812  *                      ok variable to TRUE if parsing was correct >>
1813  *              wkh_2_TextualValue;
1814  *                      << add textual value proto item here; don't forget to set the
1815  *                      ok variable to TRUE if parsing was correct >>
1816  *              wkh_3_ValueWithLength;
1817  *                      << add custom code for value processing and value proto item here >>
1818  *
1819  *              wkh_4_End(hf);
1820  *                      << This macro takes care of parse errors within the header value;
1821  *                      it requires the header field index if the header has not yet been
1822  *                      written to the protocol tree (ti == NULL). >>
1823  * }
1824  *
1825  *      NOTE:   You only need to write parsing code for the successful case,
1826  *                      Errors are automatically reported through the wkh_4_End() macro
1827  *                      when ok <> TRUE.
1828  */
1829
1830 /* The following code is the generic template with which the value of a
1831  * well-known header can be processed. Not all sections yield a semantically
1832  * correct result, so appropriate error information must be provided.
1833  */
1834
1835
1836 #define wkh_0_Declarations                                      /* Declarations for Parsing */ \
1837         gboolean ok = FALSE; /* Triggers error notification code at end */ \
1838         proto_item *ti = NULL; /* Needed for error notification at end */ \
1839         guint32 val_start = hdr_start + 1; \
1840         guint8 hdr_id = tvb_get_guint8 (tvb, hdr_start) & 0x7F; \
1841         guint8 val_id = tvb_get_guint8 (tvb, val_start); \
1842         guint32 offset = val_start; /* Offset to one past this header */ \
1843         guint32 val_len; /* length for value with length field */ \
1844         guint32 val_len_len; /* length of length field */ \
1845         guint8 *val_str = NULL
1846
1847 #define wkh_1_WellKnownValue                            /* Parse Well Known Value */ \
1848         proto_tree_add_string_hidden(tree, hf_hdr_name, \
1849                         tvb, hdr_start, offset - hdr_start, \
1850                         val_to_str (hdr_id, vals_field_names, \
1851                                 "<Unknown WSP header field 0x%02X>")); \
1852         if (val_id & 0x80) { /* Well-known value */ \
1853                 offset++; \
1854                 /* Well-known value processing starts HERE \
1855                  * \
1856                  * BEGIN */
1857
1858 #define wkh_2_TextualValue                                      /* Parse Textual Value */ \
1859                 /* END */ \
1860         } else if ((val_id == 0) || (val_id >= 0x20)) { /* Textual value */ \
1861                 val_str = tvb_get_stringz (tvb, val_start, &val_len); \
1862                 g_assert(val_str); \
1863                 offset = val_start + val_len; \
1864                 /* Textual value processing starts HERE \
1865                  * \
1866                  * BEGIN */
1867
1868 #define wkh_3_ValueWithLength                           /* Parse Value With Length */ \
1869                 /* END */ \
1870                 g_free(val_str); \
1871         } else { /* val_start points to 1st byte of length field */ \
1872                 if (val_id == 0x1F) { /* Value Length = guintvar */ \
1873                         val_len = tvb_get_guintvar(tvb, val_start + 1, &val_len_len); \
1874                         val_len_len++; /* 0x1F length indicator byte */ \
1875                 } else { /* Short length followed by Len data octets */ \
1876                         val_len = tvb_get_guint8(tvb, offset); \
1877                         val_len_len = 1; \
1878                 } \
1879                 offset += val_len_len + val_len; \
1880                 /* Value with length processing starts HERE \
1881                  * The value lies between val_start and offset: \
1882                  *  - Value Length:     Start  = val_start \
1883                  *                                      Length = val_len_len \
1884                  *  - Value Data  :     Start  = val_start + val_len_len \
1885                  *                                      Length = val_len \
1886                  *                                      End    = offset - 1 \
1887                  * BEGIN */
1888
1889 #define wkh_4_End(hf)                                           /* End of value parsing */ \
1890                 /* END */ \
1891         } \
1892         /* Check for errors */ \
1893         if (! ok) { \
1894                 if (ti) { /* Append to protocol tree item label */ \
1895                         proto_item_append_text(ti, \
1896                                         " <Error: Invalid header value>"); \
1897                 } else if (hf > 0) { /* Create protocol tree item */ \
1898                         proto_tree_add_string(tree, hf, \
1899                                         tvb, hdr_start, offset - hdr_start, \
1900                                         " <Error: Invalid header value>"); \
1901                 } else { /* Create anonymous header field entry */ \
1902                         proto_tree_add_text(tree, tvb, hdr_start, offset - hdr_start, \
1903                                         "%s: <Error: Invalid header value>", \
1904                                         val_to_str (hdr_id, vals_field_names, \
1905                                                 "<Unknown WSP header field 0x%02X>")); \
1906                 } \
1907         } \
1908         return offset;
1909
1910
1911 /*
1912  * This yields the following default header value parser function body
1913  */
1914 static guint32
1915 wkh_default(proto_tree *tree, tvbuff_t *tvb,
1916                 guint32 hdr_start)
1917 {
1918         wkh_0_Declarations;
1919
1920         ok = TRUE; /* Bypass error checking as we don't parse the values! */
1921
1922         wkh_1_WellKnownValue;
1923                 ti = proto_tree_add_text (tree, tvb, hdr_start, offset - hdr_start,
1924                                 "%s: (Undecoded well-known value 0x%02x)",
1925                                 val_to_str (hdr_id, vals_field_names,
1926                                         "<Unknown WSP header field 0x%02X>"), val_id & 0x7F);
1927         wkh_2_TextualValue;
1928                 ti = proto_tree_add_text(tree, tvb, hdr_start, offset - hdr_start,
1929                                 "%s: %s",
1930                                 val_to_str (hdr_id, vals_field_names,
1931                                         "<Unknown WSP header field 0x%02X>"), val_str);
1932         wkh_3_ValueWithLength;
1933                 ti = proto_tree_add_text (tree, tvb, hdr_start, offset - hdr_start,
1934                                 "%s: (Undecoded value in general form with length indicator)",
1935                                 val_to_str (hdr_id, vals_field_names,
1936                                         "<Unknown WSP header field 0x%02X>"));
1937
1938         wkh_4_End(HF_EMPTY); /* The default parser has no associated hf_index;
1939                                                         additionally the error code is always bypassed */
1940 }
1941
1942
1943 /* Content-type processing uses the following common core: */
1944 #define wkh_content_type_header(underscored,Text) \
1945 static guint32 \
1946 wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start) \
1947 { \
1948         wkh_0_Declarations; \
1949         guint32 off, val = 0, len; \
1950         guint8 peek; \
1951         proto_tree *parameter_tree = NULL; \
1952         \
1953         wkh_1_WellKnownValue; \
1954                 ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
1955                                 tvb, hdr_start, offset - hdr_start, \
1956                                 val_to_str(val_id & 0x7F, vals_content_types, \
1957                                         "(Unknown content type identifier 0x%X)")); \
1958                 ok = TRUE; \
1959         wkh_2_TextualValue; \
1960                 /* Sometimes with a No-Content response, a NULL content type \
1961                  * is reported. Process this correctly! */ \
1962                 if (*val_str) { \
1963                         ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
1964                                         tvb, hdr_start, offset - hdr_start, \
1965                                         val_str); \
1966                 } else { \
1967                         ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
1968                                         tvb, hdr_start, offset - hdr_start, \
1969                                         "<no content type has been specified>"); \
1970                 } \
1971                 ok = TRUE; \
1972         wkh_3_ValueWithLength; \
1973                 off = val_start + val_len_len; \
1974                 peek = tvb_get_guint8(tvb, off); \
1975                 if (is_text_string(peek)) { \
1976                         get_extension_media(val_str, tvb, off, len, ok); \
1977                         /* As we're using val_str, it is automatically g_free()d */ \
1978                         off += len; /* off now points to 1st byte after string */ \
1979                         ti = proto_tree_add_string (tree, hf_hdr_ ## underscored, \
1980                                         tvb, hdr_start, offset - hdr_start, val_str); \
1981                 } else if (is_integer_value(peek)) { \
1982                         get_integer_value(val, tvb, off, len, ok); \
1983                         if (ok) { \
1984                                 ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
1985                                                 tvb, hdr_start, offset - hdr_start, \
1986                                                 val_to_str(val, vals_content_types, \
1987                                                         "(Unknown content type identifier 0x%X)")); \
1988                         } \
1989                         off += len; \
1990                 } \
1991                 /* Remember: offset == val_start + val_len + val_len_len */ \
1992                 if (ok && (off < offset)) { /* Add parameters if any */ \
1993                         parameter_tree = proto_item_add_subtree (ti, ett_header); \
1994                         while (off < offset) { \
1995                                 off = parameter (parameter_tree, ti, tvb, off, offset - off); \
1996                         } \
1997                 } \
1998         \
1999         wkh_4_End(hf_hdr_ ## underscored); \
2000 }
2001
2002
2003 /*
2004  * Accept-value =
2005  *        Short-integer
2006  *      | Extension-media
2007  *      | ( Value-length ( Extension-media | Integer-value ) *( Parameter ) )
2008  */
2009 wkh_content_type_header(accept, "Accept")
2010
2011
2012 /*
2013  * Content-type-value =
2014  *        Short-integer
2015  *      | Extension-media
2016  *      | ( Value-length ( Extension-media | Integer-value ) *( Parameter ) )
2017  *
2018  * Beware: this header should not appear as such; it is dissected elsewhere
2019  * and at the same time the content type is used for subdissectors.
2020  * It is here for the sake of completeness.
2021  */
2022 wkh_content_type_header(content_type, "Content-Type")
2023
2024
2025 /*
2026  * Content-type-value =
2027  *        Short-integer
2028  *      | Extension-media
2029  *      | ( Value-length ( Extension-media | Integer-value ) *( Parameter ) )
2030  *
2031  * This function adds the content type value to the protocol tree,
2032  * and computes either the numeric or textual media type in return,
2033  * which will be used for further subdissection (e.g., MMS, WBXML).
2034  */
2035 guint32
2036 add_content_type(proto_tree *tree, tvbuff_t *tvb, guint32 val_start,
2037                 guint32 *well_known_content, const char **textual_content)
2038 {
2039         /* Replace wkh_0_Declarations with slightly modified declarations
2040          * so we can still make use of the wkh_[1-4]_XXX macros! */
2041         guint32 hdr_start = val_start; /* No header name, only value! */
2042         guint8 hdr_id = FN_CONTENT_TYPE; /* Same remark */
2043         guint8 val_id = tvb_get_guint8 (tvb, val_start);
2044         guint32 offset = val_start; /* Offset to one past this header */
2045         guint32 val_len; /* length for value with length field */
2046         guint32 val_len_len; /* length of length field */
2047         guint8 *val_str = NULL;
2048         guint32 off, val = 0, len;
2049         guint8 peek;
2050         gboolean ok = FALSE;
2051         proto_item *ti = NULL;
2052         proto_tree *parameter_tree = NULL;
2053
2054         *textual_content = NULL;
2055         *well_known_content = 0;
2056
2057         wkh_1_WellKnownValue;
2058                 ti = proto_tree_add_string(tree, hf_hdr_content_type,
2059                                 tvb, hdr_start, offset - hdr_start,
2060                                 val_to_str(val_id & 0x7F, vals_content_types,
2061                                         "<Unknown content type identifier 0x%X>"));
2062                 *well_known_content = val_id & 0x7F;
2063                 ok = TRUE;
2064         wkh_2_TextualValue;
2065                 /* Sometimes with a No-Content response, a NULL content type
2066                  * is reported. Process this correctly! */
2067                 if (*val_str) {
2068                         ti = proto_tree_add_string(tree, hf_hdr_content_type,
2069                                         tvb, hdr_start, offset - hdr_start,
2070                                         val_str);
2071                         /* As we're using val_str, it is automatically g_free()d */
2072                         *textual_content = g_strdup(val_str);
2073                         *well_known_content = 0;
2074                 } else {
2075                         ti = proto_tree_add_string(tree, hf_hdr_content_type,
2076                                         tvb, hdr_start, offset - hdr_start,
2077                                         "<no content type has been specified>");
2078                         *textual_content = NULL;
2079                         *well_known_content = 0;
2080                 }
2081                 ok = TRUE;
2082         wkh_3_ValueWithLength;
2083                 off = val_start + val_len_len;
2084                 peek = tvb_get_guint8(tvb, off);
2085                 if (is_text_string(peek)) {
2086                         get_extension_media(val_str, tvb, off, len, ok);
2087                         /* As we're using val_str, it is automatically g_free()d */
2088                         /* ??? Not sure anymore, we're in wkh_3, not in wkh_2 ! */
2089                         off += len; /* off now points to 1st byte after string */
2090                         ti = proto_tree_add_string (tree, hf_hdr_content_type,
2091                                         tvb, hdr_start, offset - hdr_start, val_str);
2092                         /* Following statement: required? */
2093                         *textual_content = g_strdup(val_str);
2094                         *well_known_content = 0;
2095                 } else if (is_integer_value(peek)) {
2096                         get_integer_value(val, tvb, off, len, ok);
2097                         if (ok) {
2098                                 ti = proto_tree_add_string(tree, hf_hdr_content_type,
2099                                                 tvb, hdr_start, offset - hdr_start,
2100                                                 val_to_str(val, vals_content_types,
2101                                                         "<Unknown content type identifier 0x%X>"));
2102                                 *textual_content = NULL;
2103                                 *well_known_content = val;
2104                         }
2105                         off += len;
2106                 } /* else ok = FALSE */
2107                 /* Remember: offset == val_start + val_len_len + val_len */
2108                 if (ok && (off < offset)) { /* Add parameters if any */
2109                         parameter_tree = proto_item_add_subtree (ti, ett_header);
2110                         while (off < offset) {
2111                                 off = parameter (parameter_tree, ti, tvb, off, offset - off);
2112                         }
2113                 }
2114
2115         wkh_4_End(hf_hdr_content_type);
2116 }
2117
2118
2119 /*
2120  * Template for accept_X headers with optional Q parameter value
2121  */
2122 #define wkh_accept_x_q_header(underscored,Text,valueString,valueName) \
2123 static guint32 \
2124 wkh_ ## underscored (proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start) \
2125 { \
2126         wkh_0_Declarations; \
2127         guint32 off, val = 0, len; \
2128         guint8 peek; \
2129         proto_tree *parameter_tree = NULL; \
2130         \
2131         wkh_1_WellKnownValue; \
2132                 ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
2133                                 tvb, hdr_start, offset - hdr_start, \
2134                                 val_to_str(val_id & 0x7F, valueString, \
2135                                         "<Unknown " valueName " identifier 0x%X>")); \
2136                 ok = TRUE; \
2137         wkh_2_TextualValue; \
2138                 ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
2139                                 tvb, hdr_start, offset - hdr_start, val_str); \
2140                 ok = TRUE; \
2141         wkh_3_ValueWithLength; \
2142                 off = val_start + val_len_len; \
2143                 peek = tvb_get_guint8(tvb, off); \
2144                 if (is_text_string(peek)) { \
2145                         get_token_text(val_str, tvb, off, len, ok); \
2146                         /* As we're using val_str, it is automatically g_free()d */ \
2147                         off += len; /* off now points to 1st byte after string */ \
2148                         ti = proto_tree_add_string (tree, hf_hdr_ ## underscored, \
2149                                         tvb, hdr_start, offset - hdr_start, val_str); \
2150                 } else if (is_integer_value(peek)) { \
2151                         get_integer_value(val, tvb, off, len, ok); \
2152                         if (ok) { \
2153                                 ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
2154                                                 tvb, hdr_start, offset - hdr_start, \
2155                                                 val_to_str(val, valueString, \
2156                                                         "<Unknown " valueName " identifier 0x%X>")); \
2157                         } \
2158                         off += len; \
2159                 } /* else ok = FALSE */ \
2160                 /* Remember: offset == val_start + val_len */ \
2161                 if (ok && (off < offset)) { /* Add Q-value if available */ \
2162                         parameter_tree = proto_item_add_subtree (ti, ett_header); \
2163                         off = parameter_value_q (parameter_tree, ti, tvb, off); \
2164                 } \
2165         \
2166         wkh_4_End(hf_hdr_ ## underscored); \
2167 }
2168
2169 /*
2170  * Accept-charset-value =
2171  *        Short-integer
2172  *      | Extension-media
2173  *      | ( Value-length ( Token-text | Integer-value ) [ Q-value ] )
2174  */
2175 wkh_accept_x_q_header(accept_charset, "Accept-Charset",
2176                 vals_character_sets, "character set")
2177 /*
2178  * Accept-language-value =
2179  *        Short-integer
2180  *      | Extension-media
2181  *      | ( Value-length ( Text-string | Integer-value ) [ Q-value ] )
2182  */
2183 wkh_accept_x_q_header(accept_language, "Accept-Language",
2184                 vals_languages, "language")
2185
2186
2187 /*
2188  * Push-flag-value = Short-integer
2189  */
2190 static guint32
2191 wkh_push_flag(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
2192 {
2193         wkh_0_Declarations;
2194         proto_tree *subtree = NULL;
2195
2196         wkh_1_WellKnownValue;
2197                 ti = proto_tree_add_string(tree, hf_hdr_push_flag,
2198                                 tvb, hdr_start, offset - hdr_start, "");
2199                 subtree = proto_item_add_subtree(ti, ett_header);
2200                 proto_tree_add_uint(subtree, hf_hdr_push_flag_auth,
2201                                 tvb, val_start, 1, val_id);
2202                 proto_tree_add_uint(subtree, hf_hdr_push_flag_trust,
2203                                 tvb, val_start, 1, val_id);
2204                 proto_tree_add_uint(subtree, hf_hdr_push_flag_last,
2205                                 tvb, val_start, 1, val_id);
2206                 if (val_id & 0x01)
2207                         proto_item_append_string(ti, " (Initiator URI authenticated)");
2208                 if (val_id & 0x02)
2209                         proto_item_append_string(ti, " (Content trusted)");
2210                 if (val_id & 0x04)
2211                         proto_item_append_string(ti, " (Last push message)");
2212                 if (val_id & 0x78)
2213                         proto_item_append_text(ti, " <Warning: Reserved flags set>");
2214                 else
2215                         ok = TRUE;
2216         wkh_2_TextualValue;
2217                 /* Invalid */
2218         wkh_3_ValueWithLength;
2219                 /* Invalid */
2220         wkh_4_End(hf_hdr_push_flag);
2221 }
2222
2223
2224 /*
2225  * Allow-value =
2226  *     Short-integer
2227  */
2228 static guint32
2229 wkh_allow(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
2230 {
2231         wkh_0_Declarations;
2232
2233         wkh_1_WellKnownValue;
2234                 val_id &= 0x7F;
2235                 if (val_id >= 0x40) { /* Valid WSP method */
2236                         ti = proto_tree_add_string(tree, hf_hdr_allow,
2237                                         tvb, hdr_start, offset - hdr_start,
2238                                         val_to_str(val_id & 0x7F, vals_pdu_type,
2239                                                 "<Unknown WSP method 0x%02X>"));
2240                         ok = TRUE;
2241                 }
2242         wkh_2_TextualValue;
2243                 /* Invalid */
2244         wkh_3_ValueWithLength;
2245                 /* Invalid */
2246         wkh_4_End(hf_hdr_allow);
2247 }
2248
2249
2250 /*
2251  * Public-value =
2252  *     Token-text | Short-integer
2253  */
2254 static guint32
2255 wkh_public(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
2256 {
2257         wkh_0_Declarations;
2258
2259         wkh_1_WellKnownValue;
2260                 val_id &= 0x7F;
2261                 if (val_id >= 0x40) { /* Valid WSP method */
2262                         ti = proto_tree_add_string(tree, hf_hdr_public,
2263                                         tvb, hdr_start, offset - hdr_start,
2264                                         val_to_str(val_id & 0x7F, vals_pdu_type,
2265                                                 "<Unknown WSP method 0x%02X>"));
2266                         ok = TRUE;
2267                 }
2268         wkh_2_TextualValue;
2269                 ti = proto_tree_add_string(tree, hf_hdr_public,
2270                                 tvb, hdr_start, offset - hdr_start, val_str);
2271                 ok = TRUE;
2272         wkh_3_ValueWithLength;
2273                 /* Invalid */
2274         wkh_4_End(hf_hdr_public);
2275 }
2276
2277
2278 /*
2279  * Vary-value =
2280  *     Token-text | Short-integer
2281  */
2282 static guint32
2283 wkh_vary(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
2284 {
2285         wkh_0_Declarations;
2286
2287         wkh_1_WellKnownValue;
2288                 ti = proto_tree_add_string(tree, hf_hdr_vary,
2289                                 tvb, hdr_start, offset - hdr_start,
2290                                 val_to_str(val_id & 0x7F, vals_field_names,
2291                                         "<Unknown WSP header field 0x%02X>"));
2292                 ok = TRUE;
2293         wkh_2_TextualValue;
2294                 ti = proto_tree_add_string(tree, hf_hdr_vary,
2295                                 tvb, hdr_start, offset - hdr_start,
2296                                 val_str);
2297                 ok = TRUE;
2298         wkh_3_ValueWithLength;
2299                 /* Invalid */
2300         wkh_4_End(hf_hdr_vary);
2301 }
2302
2303
2304 /*
2305  * X-wap-security-value = 0x80
2306  */
2307 static guint32
2308 wkh_x_wap_security(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
2309 {
2310         wkh_0_Declarations;
2311
2312         wkh_1_WellKnownValue;
2313                 if (val_id == 0x80) {
2314                         ti = proto_tree_add_string(tree, hf_hdr_x_wap_security,
2315                                         tvb, hdr_start, offset - hdr_start, "close-subordinate");
2316                         ok = TRUE;
2317                 }
2318         wkh_2_TextualValue;
2319                 /* Invalid */
2320         wkh_3_ValueWithLength;
2321                 /* Invalid */
2322         wkh_4_End(hf_hdr_x_wap_security);
2323 }
2324
2325
2326 /*
2327  * Connection-value = 0x80 | Token-text
2328  */
2329 static guint32
2330 wkh_connection(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
2331 {
2332         wkh_0_Declarations;
2333
2334         wkh_1_WellKnownValue;
2335                 if (val_id == 0x80) {
2336                         ti = proto_tree_add_string(tree, hf_hdr_connection,
2337                                         tvb, hdr_start, offset - hdr_start, "close");
2338                         ok = TRUE;
2339                 }
2340         wkh_2_TextualValue;
2341                 ti = proto_tree_add_string(tree, hf_hdr_connection,
2342                                 tvb, hdr_start, offset - hdr_start, val_str);
2343                 ok = TRUE;
2344         wkh_3_ValueWithLength;
2345                 /* Invalid */
2346         wkh_4_End(hf_hdr_connection);
2347 }
2348
2349
2350 /*
2351  * Transfer-encoding-value = 0x80 | Token-text
2352  */
2353 static guint32
2354 wkh_transfer_encoding(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
2355 {
2356         wkh_0_Declarations;
2357
2358         wkh_1_WellKnownValue;
2359                 if (val_id == 0x80) {
2360                         ti = proto_tree_add_string(tree, hf_hdr_transfer_encoding,
2361                                         tvb, hdr_start, offset - hdr_start, "chunked");
2362                         ok = TRUE;
2363                 }
2364         wkh_2_TextualValue;
2365                 ti = proto_tree_add_string(tree, hf_hdr_transfer_encoding,
2366                                 tvb, hdr_start, offset - hdr_start, val_str);
2367                 ok = TRUE;
2368         wkh_3_ValueWithLength;
2369                 /* Invalid */
2370         wkh_4_End(hf_hdr_transfer_encoding);
2371 }
2372
2373
2374 /*
2375  * Accept-range-value = 0x80 | 0x81 | Token-text
2376  */
2377 static guint32
2378 wkh_accept_ranges(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
2379 {
2380         wkh_0_Declarations;
2381
2382         wkh_1_WellKnownValue;
2383                 switch (val_id) {
2384                         case 0x80: /* none */
2385                                 ti = proto_tree_add_string(tree, hf_hdr_accept_ranges,
2386                                                 tvb, hdr_start, offset - hdr_start, "none");
2387                                 ok = TRUE;
2388                                 break;
2389                         case 0x81: /* bytes */
2390                                 ti = proto_tree_add_string(tree, hf_hdr_accept_ranges,
2391                                                 tvb, hdr_start, offset - hdr_start, "bytes");
2392                                 ok = TRUE;
2393                                 break;
2394                 }
2395         wkh_2_TextualValue;
2396                 ti = proto_tree_add_string(tree, hf_hdr_accept_ranges,
2397                                 tvb, hdr_start, offset - hdr_start, val_str);
2398                 ok = TRUE;
2399         wkh_3_ValueWithLength;
2400                 /* Invalid */
2401         wkh_4_End(hf_hdr_accept_ranges);
2402 }
2403
2404
2405 /*
2406  * Content-encoding-value = 0x80 | 0x81 | 0x82 | Token-text
2407  */
2408 static guint32
2409 wkh_content_encoding(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
2410 {
2411         wkh_0_Declarations;
2412
2413         wkh_1_WellKnownValue;
2414                 switch (val_id) {
2415                         case 0x80: /* gzip */
2416                                 ti = proto_tree_add_string(tree, hf_hdr_content_encoding,
2417                                                 tvb, hdr_start, offset - hdr_start, "gzip");
2418                                 ok = TRUE;
2419                                 break;
2420                         case 0x81: /* compress */
2421                                 ti = proto_tree_add_string(tree, hf_hdr_content_encoding,
2422                                                 tvb, hdr_start, offset - hdr_start, "compress");
2423                                 ok = TRUE;
2424                                 break;
2425                         case 0x82: /* deflate */
2426                                 ti = proto_tree_add_string(tree, hf_hdr_content_encoding,
2427                                                 tvb, hdr_start, offset - hdr_start, "deflate");
2428                                 ok = TRUE;
2429                                 break;
2430                 }
2431         wkh_2_TextualValue;
2432                 ti = proto_tree_add_string(tree, hf_hdr_content_encoding,
2433                                 tvb, hdr_start, offset - hdr_start, val_str);
2434                 ok = TRUE;
2435         wkh_3_ValueWithLength;
2436                 /* Invalid */
2437         wkh_4_End(hf_hdr_content_encoding);
2438 }
2439
2440
2441 /*
2442  * Accept-encoding-value =
2443  *        Short-integer
2444  *      | Token-text
2445  *      | ( Value-length ( Short-integer | Text-string ) [ Q-value ] )
2446  */
2447 static guint32
2448 wkh_accept_encoding(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
2449 {
2450         wkh_0_Declarations;
2451         guint32 len, off;
2452         guint8 peek;
2453         gchar *str;
2454         proto_tree *parameter_tree = NULL;
2455
2456         wkh_1_WellKnownValue;
2457                 switch (val_id) {
2458                         case 0x80: /* gzip */
2459                                 ti = proto_tree_add_string(tree, hf_hdr_accept_encoding,
2460                                                 tvb, hdr_start, offset - hdr_start, "gzip");
2461                                 ok = TRUE;
2462                                 break;
2463                         case 0x81: /* compress */
2464                                 ti = proto_tree_add_string(tree, hf_hdr_accept_encoding,
2465                                                 tvb, hdr_start, offset - hdr_start, "compress");
2466                                 ok = TRUE;
2467                                 break;
2468                         case 0x82: /* deflate */
2469                                 ti = proto_tree_add_string(tree, hf_hdr_accept_encoding,
2470                                                 tvb, hdr_start, offset - hdr_start, "deflate");
2471                                 ok = TRUE;
2472                                 break;
2473                 }
2474         wkh_2_TextualValue;
2475                 proto_tree_add_string(tree, hf_hdr_accept_encoding,
2476                                 tvb, hdr_start, offset - hdr_start, val_str);
2477                 ok = TRUE;
2478         wkh_3_ValueWithLength;
2479                 off = val_start + val_len_len;
2480                 peek = tvb_get_guint8(tvb, off);
2481                 if (is_short_integer(peek)) {
2482                         switch (val_id) {
2483                                 case 0x80: /* gzip */
2484                                         ti = proto_tree_add_string(tree, hf_hdr_accept_encoding,
2485                                                         tvb, hdr_start, offset - hdr_start, "gzip");
2486                                         ok = TRUE;
2487                                         break;
2488                                 case 0x81: /* compress */
2489                                         ti = proto_tree_add_string(tree, hf_hdr_accept_encoding,
2490                                                         tvb, hdr_start, offset - hdr_start, "compress");
2491                                         ok = TRUE;
2492                                         break;
2493                                 case 0x82: /* deflate */
2494                                         ti = proto_tree_add_string(tree, hf_hdr_accept_encoding,
2495                                                         tvb, hdr_start, offset - hdr_start, "deflate");
2496                                         ok = TRUE;
2497                                         break;
2498                                 case 0x83: /* any */
2499                                         ti = proto_tree_add_string(tree, hf_hdr_accept_encoding,
2500                                                         tvb, hdr_start, offset - hdr_start, "*");
2501                                         ok = TRUE;
2502                                         break;
2503                         }
2504                         off++;
2505                 } else {
2506                         get_token_text(str, tvb, off, len, ok);
2507                         if (ok) {
2508                                 ti = proto_tree_add_string(tree, hf_hdr_accept_encoding,
2509                                                 tvb, hdr_start, offset - hdr_start, str);
2510                                 g_free(str);
2511                         }
2512                         off += len;
2513                 }
2514                 if (ok) {
2515                         /* Remember: offset == val_start + val_len_len + val_len */
2516                         if (off < offset) { /* Add Q-value if available */
2517                                 parameter_tree = proto_item_add_subtree(ti, ett_header);
2518                                 off = parameter_value_q(parameter_tree, ti, tvb, off);
2519                         }
2520                 }
2521         wkh_4_End(hf_hdr_accept_encoding);
2522 }
2523
2524
2525 /*
2526  * Content-disposition-value = Value-length ( Disposition ) *( Parameter )
2527  *      Disposition = Form-data | Attachment | Inline | Token-text
2528  *      Form-data = 0x80
2529  *      Attachment = 0x81
2530  *      Inline = 0x82
2531  * We handle this as:
2532  *      Value-length ( Short-integer | Text-string ) *( Parameter )
2533  */
2534 static guint32
2535 wkh_content_disposition(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
2536 {
2537         wkh_0_Declarations;
2538         guint32 len, off;
2539         guint8 peek;
2540         gchar *str;
2541         proto_tree *parameter_tree = NULL;
2542
2543         wkh_1_WellKnownValue;
2544                 /* Invalid */
2545         wkh_2_TextualValue;
2546                 /* Invalid */
2547         wkh_3_ValueWithLength;
2548                 off = val_start + val_len_len;
2549                 peek = tvb_get_guint8(tvb, off);
2550                 if (is_short_integer(peek)) {
2551                         switch (peek) {
2552                                 case 0x80: /* form-data */
2553                                         ti = proto_tree_add_string(tree, hf_hdr_content_disposition,
2554                                                         tvb, hdr_start, offset - hdr_start, "form-data");
2555                                         ok = TRUE;
2556                                         break;
2557                                 case 0x81: /* attachment */
2558                                         ti = proto_tree_add_string(tree, hf_hdr_content_disposition,
2559                                                         tvb, hdr_start, offset - hdr_start, "attachment");
2560                                         ok = TRUE;
2561                                         break;
2562                                 case 0x82: /* inline */
2563                                         ti = proto_tree_add_string(tree, hf_hdr_content_disposition,
2564                                                         tvb, hdr_start, offset - hdr_start, "inline");
2565                                         ok = TRUE;
2566                                         break;
2567                         }
2568                         off++;
2569                 } else {
2570                         get_token_text(str, tvb, off, len, ok);
2571                         if (ok) {
2572                                 ti = proto_tree_add_string(tree, hf_hdr_content_disposition,
2573                                                 tvb, hdr_start, offset - hdr_start, str);
2574                                 g_free(str);
2575                         }
2576                         off += len;
2577                 }
2578                 if ((ok) && (off < offset)) {
2579                         /* Remember: offset == val_start + val_len_len + val_len */
2580                         parameter_tree = proto_item_add_subtree(ti, ett_header);
2581                         while (off < offset) { /* Add parameters if available */
2582                                 off = parameter(parameter_tree, ti, tvb, off, offset - off);
2583                         }
2584                 }
2585         wkh_4_End(hf_hdr_content_disposition);
2586 }
2587
2588
2589 /*
2590  * Common code for headers with only a textual value
2591  * is written in the macro below:
2592  */
2593 #define wkh_text_header(underscored,Text) \
2594 static guint32 \
2595 wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start) \
2596 { \
2597         wkh_0_Declarations; \
2598         \
2599         wkh_1_WellKnownValue; \
2600                 /* Invalid */ \
2601         wkh_2_TextualValue; \
2602                 ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
2603                                 tvb, hdr_start, offset - hdr_start, val_str); \
2604                 ok = TRUE; \
2605         wkh_3_ValueWithLength; \
2606                 /* Invalid */ \
2607         wkh_4_End(hf_hdr_ ## underscored); \
2608 }
2609
2610 /* Text-only headers: */
2611 wkh_text_header(content_base, "Content-Base")
2612 wkh_text_header(content_location, "Content-Location")
2613 wkh_text_header(etag, "ETag")
2614 wkh_text_header(from, "From")
2615 wkh_text_header(host, "Host")
2616 wkh_text_header(if_match, "If-Match")
2617 wkh_text_header(if_none_match, "If-None-Match")
2618 wkh_text_header(location, "Location")
2619 wkh_text_header(referer, "Referer")
2620 wkh_text_header(server, "Server")
2621 wkh_text_header(user_agent, "User-Agent")
2622 wkh_text_header(upgrade, "Upgrade")
2623 wkh_text_header(via, "Via")
2624 wkh_text_header(content_uri, "Content-Uri")
2625 wkh_text_header(initiator_uri, "Initiator-Uri")
2626 wkh_text_header(profile, "Profile")
2627
2628 /*
2629  * Same for quoted-string value
2630  */
2631 #define wkh_quoted_string_header(underscored,Text) \
2632 static guint32 \
2633 wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start) \
2634 { \
2635         wkh_0_Declarations; \
2636         gchar *str; \
2637         \
2638         wkh_1_WellKnownValue; \
2639                 /* Invalid */ \
2640         wkh_2_TextualValue; \
2641                 if (is_quoted_string(val_str[0])) { \
2642                         if (is_quoted_string(val_str[val_len-2])) { \
2643                                 /* Trailing quote - issue a warning */ \
2644                                 str = g_strdup_printf("%s" TrailingQuoteWarning, val_str); \
2645                         } else { /* OK (no trailing quote) */ \
2646                                 str = g_strdup_printf("%s\"", val_str); \
2647                         } \
2648                         ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
2649                                         tvb, hdr_start, offset - hdr_start, str); \
2650                         g_free(str); \
2651                 } else { \
2652                         ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
2653                                         tvb, hdr_start, offset - hdr_start, val_str); \
2654                         proto_item_append_text(ti, \
2655                                         " <Warning: should be encoded as a Quoted-string>"); \
2656                 } \
2657                 ok = TRUE; \
2658         wkh_3_ValueWithLength; \
2659                 /* Invalid */ \
2660         wkh_4_End(hf_hdr_ ## underscored); \
2661 }
2662
2663 wkh_quoted_string_header(content_id, "Content-ID")
2664
2665
2666 /*
2667  * Common code for headers with only a textual or a date value
2668  * is written in the macro below:
2669  */
2670 #define wkh_text_or_date_value_header(underscored,Text) \
2671 static guint32 \
2672 wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start) \
2673 { \
2674         wkh_0_Declarations; \
2675         guint32 val = 0, off = val_start, len; \
2676         nstime_t tv; \
2677         gchar *str; /* may not be freed! */ \
2678         \
2679         wkh_1_WellKnownValue; \
2680                 /* Invalid */ \
2681         wkh_2_TextualValue; \
2682                 ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
2683                                 tvb, hdr_start, offset - hdr_start, val_str); \
2684                 ok = TRUE; \
2685         wkh_3_ValueWithLength; \
2686                 if (val_id <= 4) { /* Length field already parsed by macro! */ \
2687                         get_date_value(val, tvb, off, len, ok); \
2688                         if (ok) { \
2689                                 tv.secs = val; \
2690                                 tv.nsecs = 0; \
2691                                 str = abs_time_to_str(&tv); \
2692                                 g_assert(str); \
2693                                 ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
2694                                                 tvb, hdr_start, offset - hdr_start, str); \
2695                                 /* BEHOLD: do NOT try to free str, as this generates a core
2696                                  * dump!  It looks like abs_time_to_str() is buggy or works
2697                                  * with static data. */ \
2698                         } \
2699                 } \
2700         wkh_4_End(hf_hdr_ ## underscored); \
2701 }
2702
2703 /* If-Range */
2704 wkh_text_or_date_value_header(if_range,"If-Range")
2705
2706
2707 /*
2708  * Common code for headers with only a date value
2709  * is written in the macro below:
2710  */
2711 #define wkh_date_value_header(underscored,Text) \
2712 static guint32 \
2713 wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start) \
2714 { \
2715         wkh_0_Declarations; \
2716         guint32 val = 0, off = val_start, len; \
2717         nstime_t tv; \
2718         gchar *str; /* may not be freed! */ \
2719         \
2720         wkh_1_WellKnownValue; \
2721                 /* Invalid */ \
2722         wkh_2_TextualValue; \
2723                 /* Invalid */ \
2724         wkh_3_ValueWithLength; \
2725                 if (val_id <= 4) { /* Length field already parsed by macro! */ \
2726                         get_date_value(val, tvb, off, len, ok); \
2727                         if (ok) { \
2728                                 tv.secs = val; \
2729                                 tv.nsecs = 0; \
2730                                 str = abs_time_to_str(&tv); \
2731                                 g_assert(str); \
2732                                 ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
2733                                                 tvb, hdr_start, offset - hdr_start, str); \
2734                                 /* BEHOLD: do NOT try to free str, as this generates a core
2735                                  * dump!  It looks like abs_time_to_str() is buggy or works
2736                                  * with static data. */ \
2737                         } \
2738                 } \
2739         wkh_4_End(hf_hdr_ ## underscored); \
2740 }
2741
2742 /* Date-value only headers: */
2743 wkh_date_value_header(date, "Date")
2744 wkh_date_value_header(expires, "Expires")
2745 wkh_date_value_header(if_modified_since, "If-Modified-Since")
2746 wkh_date_value_header(if_unmodified_since, "If-Unmodified-Since")
2747 wkh_date_value_header(last_modified, "Last-Modified")
2748
2749
2750 /* Date-value with special interpretation of zero value */
2751 #define wkh_tod_value_header(underscored,Text) \
2752 static guint32 \
2753 wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start) \
2754 { \
2755         wkh_0_Declarations; \
2756         guint32 val = 0, off = val_start, len; \
2757         nstime_t tv; \
2758         gchar *str; /* may not be freed! */ \
2759         \
2760         wkh_1_WellKnownValue; \
2761                 if (val_id == 0x80) { /* Openwave TOD header uses this format */ \
2762                         ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
2763                                         tvb, hdr_start, offset - hdr_start, \
2764                                         "Requesting Time Of Day"); \
2765                         proto_item_append_text(ti, \
2766                                         " <Warning: should be encoded as long-integer>"); \
2767                         ok = TRUE; \
2768                 } \
2769                 /* It seems VERY unlikely that we'll see date values within the first \
2770                  * 127 seconds of the UNIX 1-1-1970 00:00:00 start of the date clocks \
2771                  * so I assume such a value is a genuine error */ \
2772         wkh_2_TextualValue; \
2773                 /* Invalid */ \
2774         wkh_3_ValueWithLength; \
2775                 if (val_id <= 4) { /* Length field already parsed by macro! */ \
2776                         get_date_value(val, tvb, off, len, ok); \
2777                         if (ok) { \
2778                                 if (val == 0) { \
2779                                         ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
2780                                                         tvb, hdr_start, offset - hdr_start, \
2781                                                         "Requesting Time Of Day"); \
2782                                 } else { \
2783                                         tv.secs = val; \
2784                                         tv.nsecs = 0; \
2785                                         str = abs_time_to_str(&tv); \
2786                                         g_assert(str); \
2787                                         ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
2788                                                         tvb, hdr_start, offset - hdr_start, str); \
2789                                 } \
2790                         } \
2791                 } \
2792         wkh_4_End(hf_hdr_ ## underscored); \
2793 }
2794
2795 wkh_tod_value_header(x_wap_tod, "X-Wap-Tod")
2796
2797
2798 /*
2799  * Age-value: Delta-seconds-value
2800  */
2801 static guint32
2802 wkh_age(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
2803 {
2804         wkh_0_Declarations;
2805         guint32 val = 0, off = val_start, len;
2806
2807         wkh_1_WellKnownValue;
2808                 val = val_id & 0x7F;
2809                 val_str = g_strdup_printf("%u second%s", val, PLURALIZE(val));
2810                 ti = proto_tree_add_string(tree, hf_hdr_age,
2811                                 tvb, hdr_start, offset - hdr_start, val_str);
2812                 g_free(val_str); /* proto_XXX creates a copy */
2813                 ok = TRUE;
2814         wkh_2_TextualValue;
2815                 /* Invalid */
2816         wkh_3_ValueWithLength;
2817                 if (val_id <= 4) { /* Length field already parsed by macro! */
2818                         get_long_integer(val, tvb, off, len, ok);
2819                         if (ok) {
2820                                 val_str = g_strdup_printf("%u second%s", val, PLURALIZE(val));
2821                                 ti = proto_tree_add_string(tree, hf_hdr_age,
2822                                                 tvb, hdr_start, offset - hdr_start, val_str);
2823                                 g_free(val_str); /* proto_XXX creates a copy */
2824                         }
2825                 }
2826         wkh_4_End(hf_hdr_age);
2827 }
2828
2829
2830 /*
2831  * Template for Integer lookup or text value headers:
2832  */
2833 #define wkh_integer_lookup_or_text_value(underscored,Text,valueString,valueName) \
2834 static guint32 \
2835 wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start) \
2836 { \
2837         wkh_0_Declarations; \
2838         guint32 val = 0, off = val_start, len; \
2839         \
2840         wkh_1_WellKnownValue; \
2841                 ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
2842                                 tvb, hdr_start, offset - hdr_start, \
2843                                 val_to_str(val_id & 0x7F, valueString, \
2844                                 "(Unknown " valueName " identifier 0x%X)")); \
2845                 ok = TRUE; \
2846         wkh_2_TextualValue; \
2847                 ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
2848                                 tvb, hdr_start, offset - hdr_start, val_str); \
2849                 ok = TRUE; \
2850         wkh_3_ValueWithLength; \
2851                 if (val_id <= 4) { /* Length field already parsed by macro! */ \
2852                         get_long_integer(val, tvb, off, len, ok); \
2853                         if (ok) { \
2854                                 ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
2855                                                 tvb, hdr_start, offset - hdr_start, \
2856                                                 val_to_str(val_id & 0x7F, valueString, \
2857                                                 "(Unknown " valueName " identifier 0x%X)")); \
2858                         } \
2859                 } \
2860         wkh_4_End(hf_hdr_ ## underscored); \
2861 }
2862
2863 /*
2864  * Wap-application-value: Uri-value | Integer-value
2865  */
2866 wkh_integer_lookup_or_text_value(x_wap_application_id, "X-Wap-Application-Id",
2867                 vals_wap_application_ids, "WAP application")
2868 wkh_integer_lookup_or_text_value(accept_application, "Accept-Application",
2869                 vals_wap_application_ids, "WAP application")
2870 wkh_integer_lookup_or_text_value(content_language, "Content-Language",
2871                 vals_languages, "language")
2872 /* NOTE - Although the WSP spec says this is an integer-value, the WSP headers
2873  * are encoded as a 7-bit entity! */
2874 wkh_integer_lookup_or_text_value(trailer, "Trailer",
2875                 vals_field_names, "well-known-header")
2876
2877
2878 /*
2879  * Challenge
2880  */
2881
2882 /*
2883  * Common code for headers with only a challenge value
2884  * is written in the macro below:
2885  */
2886 #define wkh_challenge_value_header(underscored,Text) \
2887 static guint32 \
2888 wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, \
2889                 guint32 hdr_start) \
2890 { \
2891         wkh_0_Declarations; \
2892         guint8 peek; \
2893         guint32 off, len; \
2894         proto_tree *subtree; \
2895         gchar *str; \
2896         \
2897         wkh_1_WellKnownValue; \
2898                 /* Invalid */ \
2899         wkh_2_TextualValue; \
2900                 /* Invalid */ \
2901         wkh_3_ValueWithLength; \
2902                 off = val_start + val_len_len; \
2903                 peek = tvb_get_guint8(tvb, off); \
2904                 if (peek == 0x80) { /* Basic */ \
2905                         ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
2906                                         tvb, hdr_start, offset - hdr_start, "basic"); \
2907                         subtree = proto_item_add_subtree(ti, ett_header); \
2908                         proto_tree_add_string(subtree, hf_hdr_ ## underscored ## _scheme, \
2909                                         tvb, off, 1, "basic"); \
2910                         off++; \
2911                         /* Realm: text-string */ \
2912                         get_text_string(str,tvb,off,len,ok); \
2913                         if (ok) { \
2914                                 proto_tree_add_string(subtree, \
2915                                                 hf_hdr_ ## underscored ## _realm, \
2916                                                 tvb, off, len, str); \
2917                                 val_str = g_strdup_printf("; realm=%s", str); \
2918                                 proto_item_append_string(ti, val_str); \
2919                                 g_free(val_str); \
2920                                 g_free(str); \
2921                                 off += len; \
2922                         } \
2923                 } else { /* Authentication-scheme: token-text */ \
2924                         get_token_text(str, tvb, off, len, ok); \
2925                         if (ok) { \
2926                                 ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
2927                                                 tvb, hdr_start, off - hdr_start, str); \
2928                                 subtree = proto_item_add_subtree(ti, ett_header); \
2929                                 proto_tree_add_string(subtree, \
2930                                                 hf_hdr_ ## underscored ## _scheme, \
2931                                                 tvb, hdr_start, off - hdr_start, str); \
2932                                 g_free(str); \
2933                                 off += len; \
2934                                 /* Realm: text-string */ \
2935                                 get_text_string(str,tvb,off,len,ok); \
2936                                 if (ok) { \
2937                                         proto_tree_add_string(subtree, \
2938                                                         hf_hdr_ ## underscored ## _realm, \
2939                                                         tvb, off, len, str); \
2940                                         val_str = g_strdup_printf("; realm=%s", str); \
2941                                         proto_item_append_string(ti, val_str); \
2942                                         g_free(val_str); \
2943                                         g_free(str); \
2944                                         off += len; \
2945                                         /* Auth-params: parameter - TODO */ \
2946                                         while (off < offset) /* Parse parameters */ \
2947                                                 off = parameter(subtree, ti, tvb, off, offset - off); \
2948                                 } \
2949                         } \
2950                 } \
2951         wkh_4_End(hf_hdr_ ## underscored); \
2952 }
2953
2954 /* Challenge-value only headers: */
2955 wkh_challenge_value_header(www_authenticate, "WWW-Authenticate")
2956 wkh_challenge_value_header(proxy_authenticate, "Proxy-Authenticate")
2957
2958
2959 /*
2960  * Credentials
2961  */
2962
2963 /*
2964  * Common code for headers with only a credentials value
2965  * is written in the macro below:
2966  */
2967 #define wkh_credentials_value_header(underscored,Text) \
2968 static guint32 \
2969 wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, \
2970                 guint32 hdr_start) \
2971 { \
2972         wkh_0_Declarations; \
2973         guint8 peek; \
2974         guint32 off, len; \
2975         proto_tree *subtree; \
2976         gchar *str; \
2977         \
2978         wkh_1_WellKnownValue; \
2979                 /* Invalid */ \
2980         wkh_2_TextualValue; \
2981                 /* Invalid */ \
2982         wkh_3_ValueWithLength; \
2983                 off = val_start + val_len_len; \
2984                 peek = tvb_get_guint8(tvb, off); \
2985                 if (peek == 0x80) { /* Basic */ \
2986                         ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
2987                                         tvb, hdr_start, offset - hdr_start, "basic"); \
2988                         subtree = proto_item_add_subtree(ti, ett_header); \
2989                         proto_tree_add_string(subtree, hf_hdr_ ## underscored ## _scheme, \
2990                                         tvb, off, 1, "basic"); \
2991                         off++; \
2992                         /* User-id: text-string */ \
2993                         get_text_string(str,tvb,off,len,ok); \
2994                         if (ok) { \
2995                                 proto_tree_add_string(subtree, \
2996                                                 hf_hdr_ ## underscored ## _user_id, \
2997                                                 tvb, off, len, str); \
2998                                 val_str = g_strdup_printf("; user-id=%s", str); \
2999                                 proto_item_append_string(ti, val_str); \
3000                                 g_free(val_str); \
3001                                 g_free(str); \
3002                                 off += len; \
3003                                 /* Password: text-string */ \
3004                                 get_text_string(str,tvb,off,len,ok); \
3005                                 if (ok) { \
3006                                         proto_tree_add_string(subtree, \
3007                                                         hf_hdr_ ## underscored ## _password, \
3008                                                         tvb, off, len, str); \
3009                                         val_str = g_strdup_printf("; password=%s", str); \
3010                                         proto_item_append_string(ti, val_str); \
3011                                         g_free(val_str); \
3012                                         g_free(str); \
3013                                         off += len; \
3014                                 } \
3015                         } \
3016                 } else { /* Authentication-scheme: token-text */ \
3017                         get_token_text(str, tvb, off, len, ok); \
3018                         if (ok) { \
3019                                 ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
3020                                                 tvb, hdr_start, off - hdr_start, str); \
3021                                 subtree = proto_item_add_subtree(ti, ett_header); \
3022                                 proto_tree_add_string(subtree, \
3023                                                 hf_hdr_ ## underscored ## _scheme, \
3024                                                 tvb, hdr_start, off - hdr_start, str); \
3025                                 g_free(str); \
3026                                 off += len; \
3027                                 /* Auth-params: parameter - TODO */ \
3028                                 while (off < offset) /* Parse parameters */ \
3029                                         off = parameter(subtree, ti, tvb, off, offset - off); \
3030                         } \
3031                 } \
3032         wkh_4_End(hf_hdr_ ## underscored); \
3033 }
3034
3035 /* Credentials-value only headers: */
3036 wkh_credentials_value_header(authorization, "Authorization")
3037 wkh_credentials_value_header(proxy_authorization, "Proxy-Authorization")
3038
3039
3040 /*
3041  * Content-md5-value = 16*16 OCTET
3042  */
3043 static guint32
3044 wkh_content_md5 (proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
3045 {
3046         wkh_0_Declarations;
3047         guint32 off;
3048
3049         wkh_1_WellKnownValue;
3050                 /* Invalid */
3051         wkh_2_TextualValue;
3052                 /* Invalid */
3053         wkh_3_ValueWithLength;
3054                 off = val_start + val_len_len;
3055                 if (val_len == 16) {
3056                         val_str = g_strdup_printf(
3057                                         "%02x%02x%02x%02x%02x%02x%02x%02x"
3058                                         "%02x%02x%02x%02x%02x%02x%02x%02x",
3059                                         tvb_get_guint8(tvb, off),
3060                                         tvb_get_guint8(tvb, off + 1),
3061                                         tvb_get_guint8(tvb, off + 2),
3062                                         tvb_get_guint8(tvb, off + 3),
3063                                         tvb_get_guint8(tvb, off + 4),
3064                                         tvb_get_guint8(tvb, off + 5),
3065                                         tvb_get_guint8(tvb, off + 6),
3066                                         tvb_get_guint8(tvb, off + 7),
3067                                         tvb_get_guint8(tvb, off + 8),
3068                                         tvb_get_guint8(tvb, off + 9),
3069                                         tvb_get_guint8(tvb, off + 10),
3070                                         tvb_get_guint8(tvb, off + 11),
3071                                         tvb_get_guint8(tvb, off + 12),
3072                                         tvb_get_guint8(tvb, off + 13),
3073                                         tvb_get_guint8(tvb, off + 14),
3074                                         tvb_get_guint8(tvb, off + 15)
3075                         );
3076                         ti = proto_tree_add_string(tree, hf_hdr_content_md5,
3077                                         tvb, hdr_start, offset - hdr_start, val_str);
3078                         g_free(val_str);
3079                         ok = TRUE;
3080                 }
3081         wkh_4_End(hf_hdr_content_md5);
3082 }
3083
3084
3085 /*
3086  * Pragma-value = 0x80 | Length Parameter
3087  */
3088 static guint32
3089 wkh_pragma(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
3090 {
3091         wkh_0_Declarations;
3092         guint32 off;
3093
3094         wkh_1_WellKnownValue;
3095                 if (val_id == 0x80) {
3096                         ti = proto_tree_add_string(tree, hf_hdr_pragma,
3097                                         tvb, hdr_start, offset - hdr_start, "no-cache");
3098                         ok = TRUE;
3099                 }
3100         wkh_2_TextualValue;
3101                 /* Invalid */
3102         wkh_3_ValueWithLength;
3103                 off = val_start + val_len_len;
3104                 ti = proto_tree_add_string(tree, hf_hdr_pragma,
3105                                 tvb, hdr_start, off - hdr_start, "");
3106                 /* NULL subtree for parameter() results in no subtree
3107                  * TODO - provide a single parameter dissector that appends data
3108                  * to the header field data. */
3109                 off = parameter(NULL, ti, tvb, off, offset - off);
3110                 ok = TRUE;
3111         wkh_4_End(hf_hdr_pragma);
3112 }
3113
3114
3115 /*
3116  * Integer-value
3117  */
3118 #define wkh_integer_value_header(underscored,Text) \
3119 static guint32 \
3120 wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start) \
3121 { \
3122         wkh_0_Declarations; \
3123         guint32 val = 0, off = val_start, len; \
3124         gchar *str; /* may not be freed! */ \
3125         \
3126         wkh_1_WellKnownValue; \
3127                 str = g_strdup_printf("%u", val_id & 0x7F); \
3128                 ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
3129                                 tvb, hdr_start, offset - hdr_start, str); \
3130                 g_free(str); \
3131                 ok = TRUE; \
3132         wkh_2_TextualValue; \
3133                 /* Invalid */ \
3134         wkh_3_ValueWithLength; \
3135                 if (val_id <= 4) { /* Length field already parsed by macro! */ \
3136                         get_long_integer(val, tvb, off, len, ok); \
3137                         if (ok) { \
3138                                 str = g_strdup_printf("%u", val); \
3139                                 ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
3140                                                 tvb, hdr_start, offset - hdr_start, str); \
3141                                 g_free(str); \
3142                         } \
3143                 } \
3144         wkh_4_End(hf_hdr_ ## underscored); \
3145 }
3146
3147 wkh_integer_value_header(content_length, "Content-Length")
3148 wkh_integer_value_header(max_forwards, "Max-Forwards")
3149
3150
3151 #define wkh_integer_lookup_value_header(underscored,Text,valueString,valueName) \
3152 static guint32 \
3153 wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start) \
3154 { \
3155         wkh_0_Declarations; \
3156         guint32 val = 0, off = val_start, len; \
3157         \
3158         wkh_1_WellKnownValue; \
3159                 val_str = match_strval(val_id & 0x7F, valueString); \
3160                 if (val_str) { \
3161                         ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
3162                                 tvb, hdr_start, offset - hdr_start, val_str); \
3163                         ok = TRUE; \
3164                 } else { \
3165                         ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
3166                                 tvb, hdr_start, offset - hdr_start, \
3167                                 "<Unknown " valueName ">"); \
3168                 } \
3169         wkh_2_TextualValue; \
3170                 /* Invalid */ \
3171         wkh_3_ValueWithLength; \
3172                 if (val_id <= 4) { /* Length field already parsed by macro! */ \
3173                         get_long_integer(val, tvb, off, len, ok); \
3174                         if (ok) { \
3175                                 val_str = match_strval(val_id & 0x7F, valueString); \
3176                                 if (val_str) { \
3177                                         ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
3178                                                 tvb, hdr_start, offset - hdr_start, val_str); \
3179                                         ok = TRUE; \
3180                                 } else { \
3181                                         ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
3182                                                 tvb, hdr_start, offset - hdr_start, \
3183                                                 "<Unknown " valueName ">"); \
3184                                 } \
3185                         } \
3186                 } \
3187         wkh_4_End(hf_hdr_ ## underscored); \
3188 }
3189
3190 wkh_integer_lookup_value_header(bearer_indication, "Bearer-Indication",
3191                 vals_bearer_types, "bearer type")
3192
3193
3194 /*
3195  * Cache-control-value
3196  */
3197 static guint32
3198 wkh_cache_control(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
3199 {
3200         wkh_0_Declarations;
3201         guint32 off, len, val = 0;
3202         guint8 peek, cache_control_directive;
3203         gchar *str;
3204
3205         wkh_1_WellKnownValue;
3206                 val = val_id & 0x7F;
3207                 val_str = match_strval(val, vals_cache_control);
3208                 if (val_str) {
3209                         ti = proto_tree_add_string(tree, hf_hdr_cache_control,
3210                                         tvb, hdr_start, offset - hdr_start, val_str);
3211                         ok = TRUE;
3212                 }
3213         wkh_2_TextualValue;
3214                 ti = proto_tree_add_string(tree, hf_hdr_cache_control,
3215                                 tvb, hdr_start, offset - hdr_start, val_str);
3216                 ok = TRUE;
3217         wkh_3_ValueWithLength;
3218                 /* General form:
3219                  *        ( no-cache | private ) 1*( Field-name )
3220                  *      | ( max-age | max-stale | min-fresh | s-maxage) Delta-seconds-value
3221                  *      | Token-text ( Integer-value | Text-value )
3222                  * Where:
3223                  *      Field-name = Short-integer | Token-text
3224                  */
3225                 off = val_start + val_len_len;
3226                 cache_control_directive = tvb_get_guint8(tvb, off++);
3227                 if (cache_control_directive & 0x80) { /* Well known cache directive */
3228                         switch (cache_control_directive & 0x7F) {
3229                                 case CACHE_CONTROL_NO_CACHE:
3230                                 case CACHE_CONTROL_PRIVATE:
3231                                         ti = proto_tree_add_string(tree, hf_hdr_cache_control,
3232                                                         tvb, hdr_start, offset - hdr_start,
3233                                                         val_to_str (cache_control_directive & 0x7F, vals_cache_control,
3234                                                                 "<Unknown cache control directive 0x%02X>"));
3235                                         /* TODO: split multiple entries */
3236                                         while (ok && (off < offset)) { /* 1*( Field-name ) */
3237                                                 ok = TRUE;
3238                                                 peek = tvb_get_guint8(tvb, off);
3239                                                 if (peek & 0x80) { /* Well-known-field-name */
3240                                                         proto_item_append_string(ti,
3241                                                                         val_to_str (peek, vals_field_names,
3242                                                                                 "<Unknown WSP header field 0x%02X>"));
3243                                                         off++;
3244                                                 } else { /* Token-text */
3245                                                         get_token_text(val_str, tvb, off, len, ok);
3246                                                         if (ok) {
3247                                                                 proto_item_append_string(ti, val_str);
3248                                                                 g_free(val_str);
3249                                                                 off += len;
3250                                                         }
3251                                                 }
3252                                         }
3253                                         break;
3254
3255                                 case CACHE_CONTROL_MAX_AGE:
3256                                 case CACHE_CONTROL_MAX_STALE:
3257                                 case CACHE_CONTROL_MIN_FRESH:
3258                                 case CACHE_CONTROL_S_MAXAGE:
3259                                         ti = proto_tree_add_string(tree, hf_hdr_cache_control,
3260                                                         tvb, hdr_start, offset - hdr_start,
3261                                                         val_to_str (cache_control_directive & 0x7F, vals_cache_control,
3262                                                                 "<Unknown cache control directive 0x%02X>"));
3263                                         get_delta_seconds_value(val, tvb, off, len, ok);
3264                                         if (ok) {
3265                                                 val_str = g_strdup_printf("=%u second%s",
3266                                                                 val, PLURALIZE(val));
3267                                                 proto_item_append_string(ti, val_str);
3268                                                 g_free(val_str); /* proto_XXX creates a copy */
3269                                         }
3270                                         break;
3271
3272                                 default:
3273                                         /* ok = FALSE */
3274                                         break;
3275                         }
3276                 } else if (is_token_text(cache_control_directive)) {
3277                         get_token_text(val_str, tvb, off, len, ok);
3278                         if (ok) {
3279                                 ti = proto_tree_add_string(tree, hf_hdr_cache_control,
3280                                                 tvb, hdr_start, offset - hdr_start, val_str);
3281                                 g_free(val_str);
3282                                 get_integer_value(val, tvb, off, len, ok);
3283                                 if (ok) { /* Integer-value */
3284                                         val_str = g_strdup_printf("=%u", val);
3285                                         proto_item_append_string(ti, val_str);
3286                                         g_free(val_str); /* proto_XXX creates a copy */
3287                                 } else { /* Text-value */
3288                                         get_text_string(val_str, tvb, off, len, ok);
3289                                         if (ok) {
3290                                                 if (is_quoted_string(val_str[0])) {
3291                                                         if (is_quoted_string(val_str[len-2])) {
3292                                                                 /* Trailing quote - issue a warning */
3293                                                                 str = g_strdup_printf("%s" TrailingQuoteWarning,
3294                                                                                 val_str);
3295                                                         } else { /* OK (no trailing quote) */
3296                                                                 str = g_strdup_printf("%s\"", val_str);
3297                                                         }
3298                                                         proto_item_append_string(ti, str);
3299                                                         g_free(str);
3300                                                 } else { /* Token-text | 0x00 */
3301                                                         /* TODO - check that we have Token-text or 0x00 */
3302                                                         proto_item_append_string(ti, val_str);
3303                                                 }
3304                                                 g_free(val_str);
3305                                         }
3306                                 }
3307                         }
3308                 }
3309         wkh_4_End(hf_hdr_cache_control);
3310 }
3311
3312
3313 /*
3314  * Warning-value =
3315  *        Short-integer
3316  *      | ( Value-length Short-integer Text-string Text-string )
3317  */
3318 static guint32
3319 wkh_warning(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
3320 {
3321         wkh_0_Declarations;
3322         guint32 off, len, val;
3323         guint8 warn_code;
3324         gchar *str;
3325         proto_tree *subtree;
3326
3327         /* TODO - subtree with values */
3328
3329         wkh_1_WellKnownValue;
3330                 val = val_id & 0x7F;
3331                 val_str = match_strval(val, vals_wsp_warning_code);
3332                 if (val_str) {
3333                         ti = proto_tree_add_string(tree, hf_hdr_warning,
3334                                         tvb, hdr_start, offset - hdr_start, val_str);
3335                         subtree = proto_item_add_subtree(ti, ett_header);
3336                         proto_tree_add_uint(subtree, hf_hdr_warning_code,
3337                                         tvb, val_start, 1, val);
3338                         ok = TRUE;
3339                 }
3340         wkh_2_TextualValue;
3341                 /* Invalid */
3342         wkh_3_ValueWithLength;
3343                 /* TODO - subtree with individual values */
3344                 off = val_start + val_len_len;
3345                 warn_code = tvb_get_guint8(tvb, off);
3346                 if (warn_code & 0x80) { /* Well known warn code */
3347                         val = warn_code & 0x7f;
3348                         val_str = match_strval(val, vals_wsp_warning_code_short);
3349                         if (val_str) { /* OK */
3350                                 str = g_strdup_printf("code=%s", val_str);
3351                                 ti = proto_tree_add_string(tree, hf_hdr_warning,
3352                                                 tvb, hdr_start, offset - hdr_start, str);
3353                                 g_free(str);
3354                                 subtree = proto_item_add_subtree(ti, ett_header);
3355                                 proto_tree_add_uint(subtree, hf_hdr_warning_code,
3356                                                 tvb, off, 1, val);
3357                                 off++; /* Now skip to the warn-agent subfield */
3358                                 get_text_string(str, tvb, off, len, ok);
3359                                 if (ok) { /* Valid warn-agent string */
3360                                         proto_tree_add_string(subtree, hf_hdr_warning_agent,
3361                                                         tvb, off, len, str);
3362                                         val_str = g_strdup_printf("; agent=%s", str);
3363                                         proto_item_append_string(ti, val_str);
3364                                         g_free(val_str); /* proto_XXX creates a copy */
3365                                         g_free(str);
3366                                         off += len;
3367                                         get_text_string(str, tvb, off, len, ok);
3368                                         if (ok) { /* Valid warn-text string */
3369                                                 proto_tree_add_string(subtree,
3370                                                                 hf_hdr_warning_text,
3371                                                                 tvb, off, len, str);
3372                                                 val_str = g_strdup_printf("; text=%s", str);
3373                                                 proto_item_append_string(ti, val_str);
3374                                                 g_free(val_str); /* proto_XXX creates a copy */
3375                                                 g_free(str);
3376                                                 off += len;
3377                                         }
3378                                 }
3379                         }
3380                 }
3381         wkh_4_End(hf_hdr_warning);
3382 }
3383
3384
3385 /*
3386  * Profile-warning-value =
3387  *        Short-integer
3388  *      | ( Value-length Short-integer Text-string *( Date-value ) )
3389  */
3390 static guint32
3391 wkh_profile_warning(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
3392 {
3393         wkh_0_Declarations;
3394         guint32 off, len, val = 0;
3395         nstime_t tv;
3396         guint8 warn_code;
3397         gchar *str;
3398
3399         wkh_1_WellKnownValue;
3400                 val = val_id & 0x7F;
3401                 val_str = match_strval(val, vals_wsp_profile_warning_code);
3402                 if (val_str) {
3403                         ti = proto_tree_add_string(tree, hf_hdr_profile_warning,
3404                                         tvb, hdr_start, offset - hdr_start, val_str);
3405                         ok = TRUE;
3406                 }
3407         wkh_2_TextualValue;
3408                 /* Invalid */
3409         wkh_3_ValueWithLength;
3410                 off = val_start + val_len_len;
3411                 warn_code = tvb_get_guint8(tvb, off++);
3412                 if (warn_code & 0x80) { /* Well known warn code */
3413                         val_str = match_strval(val, vals_wsp_profile_warning_code);
3414                         if (val_str) { /* OK */
3415                                 ti = proto_tree_add_string(tree, hf_hdr_profile_warning,
3416                                                 tvb, hdr_start, offset - hdr_start, val_str);
3417                                 get_uri_value(str, tvb, off, len, ok);
3418                                 if (ok) { /* Valid warn-target string */
3419                                         off += len;
3420                                         str = g_strdup_printf("; target=%s", val_str);
3421                                         proto_item_append_string(ti, str);
3422                                         g_free(str); /* proto_XXX creates a copy */
3423                                         /* Add zero or more dates */
3424                                         while (ok && (off < offset)) {
3425                                                 get_date_value(val, tvb, off, len, ok);
3426                                                 if (ok) { /* Valid warn-text string */
3427                                                         off += len;
3428                                                         tv.secs = val;
3429                                                         tv.nsecs = 0;
3430                                                         val_str = abs_time_to_str(&tv);
3431                                                         g_assert(val_str);
3432                                                         str = g_strdup_printf("; date=%s", val_str);
3433                                                         proto_item_append_string(ti, str);
3434                                                         g_free(str); /* proto_XXX creates a copy */
3435                                                         /* BEHOLD: do NOT try to free val_str, as this
3436                                                          * generates a core dump!
3437                                                          * It looks like abs_time_to_str() is
3438                                                          * buggy or works with static data. */
3439                                                 }
3440                                         }
3441                                 }
3442                         }
3443                 }
3444         wkh_4_End(hf_hdr_profile_warning);
3445 }
3446
3447
3448 /* Encoding-version-value =
3449  *        Short-integer
3450  *      | Text-string
3451  *      | Length Short-integer [ Short-integer | text-string ]
3452  */
3453 static guint32 wkh_encoding_version (proto_tree *tree, tvbuff_t *tvb,
3454                 guint32 hdr_start)
3455 {
3456         wkh_0_Declarations;
3457         guint32 off, val, len;
3458         guint8 *str;
3459
3460         wkh_1_WellKnownValue;
3461                 val = val_id & 0x7F;
3462                 val_str = g_strdup_printf("%u.%u", val >> 4, val & 0x0F);
3463                 proto_tree_add_string(tree, hf_hdr_encoding_version,
3464                                 tvb, hdr_start, offset - hdr_start, val_str);
3465                 g_free(val_str);
3466                 ok = TRUE;
3467         wkh_2_TextualValue;
3468                 proto_tree_add_string(tree, hf_hdr_encoding_version,
3469                                 tvb, hdr_start, offset - hdr_start, val_str);
3470                 ok = TRUE;
3471         wkh_3_ValueWithLength;
3472                 off = val_start + val_len_len;
3473                 val = tvb_get_guint8(tvb, off);
3474                 if (val & 0x80) { /* Header Code Page */
3475                         val_str = g_strdup_printf("code-page=%u", val & 0x7F);
3476                         ti = proto_tree_add_string(tree, hf_hdr_encoding_version,
3477                                         tvb, hdr_start, offset - hdr_start, val_str);
3478                         g_free(val_str);
3479                         off++;
3480                         ok = TRUE;
3481                         if (off < offset) { /* Extra version-value */
3482                                 get_version_value(val,val_str,tvb,off,len,ok);
3483                                 if (ok) { /* Always creates a string if OK */
3484                                         str = g_strdup_printf(": %s", val_str);
3485                                         proto_item_append_string(ti, str);
3486                                         g_free(str);
3487                                         g_free(val_str);
3488                                 }
3489                         }
3490                 }
3491
3492         wkh_4_End(hf_hdr_encoding_version);
3493 }
3494
3495
3496 /* Content-range-value =
3497  *        Length Uintvar-integer ( 0x80 | Uintvar-integer )
3498  */
3499 static guint32
3500 wkh_content_range(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
3501 {
3502         wkh_0_Declarations;
3503         guint32 off, val, len;
3504         proto_tree *subtree = NULL;
3505
3506         wkh_1_WellKnownValue;
3507                 /* Invalid */
3508         wkh_2_TextualValue;
3509                 /* Invalid */
3510         wkh_3_ValueWithLength;
3511                 off = val_start + val_len_len;
3512                 get_uintvar_integer (val, tvb, off, len, ok); /* Uintvar start */
3513                 if (ok) {
3514                         val_str = g_strdup_printf("first-byte-pos=%u", val);
3515                         ti = proto_tree_add_string(tree, hf_hdr_content_range,
3516                                         tvb, hdr_start, offset - hdr_start, val_str);
3517                         subtree = proto_item_add_subtree(ti, ett_header);
3518                         proto_tree_add_uint(subtree, hf_hdr_content_range_first_byte_pos,
3519                                         tvb, off, len, val);
3520                         g_free(val_str);
3521                         off += len;
3522                         /* Now check next value */
3523                         val = tvb_get_guint8(tvb, off);
3524                         if (val == 0x80) { /* Unknown length */
3525                                 proto_item_append_string(ti, "; entity-length=unknown");
3526                         } else { /* Uintvar entity length */
3527                                 get_uintvar_integer (val, tvb, off, len, ok);
3528                                 if (ok) {
3529                                         val_str = g_strdup_printf("; entity-length=%u", val);
3530                                         proto_item_append_string(ti, val_str);
3531                                         proto_tree_add_uint(subtree,
3532                                                         hf_hdr_content_range_entity_length,
3533                                                         tvb, off, len, val);
3534                                         g_free(val_str);
3535                                 }
3536                         }
3537                 }
3538
3539         wkh_4_End(hf_hdr_content_range);
3540 }
3541
3542
3543 /* Range-value =
3544  *      Length
3545  *              0x80 Uintvar-integer [ Uintvar-integer ]
3546  *        | 0x81 Uintvar-integer
3547  */
3548 static guint32
3549 wkh_range(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
3550 {
3551         wkh_0_Declarations;
3552         guint32 off, val, len;
3553         proto_tree *subtree = NULL;
3554
3555         wkh_1_WellKnownValue;
3556                 /* Invalid */
3557         wkh_2_TextualValue;
3558                 /* Invalid */
3559         wkh_3_ValueWithLength;
3560                 off = val_start + val_len_len;
3561                 val = tvb_get_guint8(tvb, off);
3562                 if (val == 0x80) { /* Byte-range */
3563                         ti = proto_tree_add_string(tree, hf_hdr_range,
3564                                         tvb, hdr_start, offset - hdr_start, "byte-range");
3565                         subtree = proto_item_add_subtree(ti, ett_header);
3566                         /* Get the First-byte-pos (Uintvar-integer) */
3567                         get_uintvar_integer (val, tvb, off, len, ok);
3568                         if (ok) {
3569                                 val_str = g_strdup_printf("; first-byte-pos=%u", val);
3570                                 proto_item_append_string(ti, val_str);
3571                                 proto_tree_add_uint(subtree, hf_hdr_range_first_byte_pos,
3572                                                 tvb, off, len, val);
3573                                 g_free(val_str);
3574                                 off += len;
3575                                 /* Get the optional Last-byte-pos (Uintvar-integer) */
3576                                 if (off < offset) {
3577                                         get_uintvar_integer (val, tvb, off, len, ok);
3578                                         if (ok) {
3579                                                 val_str = g_strdup_printf("; last-byte-pos=%u", val);
3580                                                 proto_item_append_string(ti, val_str);
3581                                                 proto_tree_add_uint(subtree,
3582                                                                 hf_hdr_range_last_byte_pos,
3583                                                                 tvb, off, len, val);
3584                                                 g_free(val_str);
3585                                         }
3586                                 }
3587                         }
3588                 } else if (val == 0x81) { /* Suffix-byte-range */
3589                         ti = proto_tree_add_string(tree, hf_hdr_range,
3590                                         tvb, hdr_start, offset - hdr_start, "suffix-byte-range");
3591                         subtree = proto_item_add_subtree(ti, ett_header);
3592                         /* Get the Suffix-length (Uintvar-integer) */
3593                         get_uintvar_integer (val, tvb, off, len, ok);
3594                         if (ok) {
3595                                 val_str = g_strdup_printf("; suffix-length=%u", val);
3596                                 proto_item_append_string(ti, val_str);
3597                                 proto_tree_add_uint(subtree, hf_hdr_range_suffix_length,
3598                                                 tvb, off, len, val);
3599                                 g_free(val_str);
3600                         }
3601                 }
3602
3603         wkh_4_End(hf_hdr_range);
3604 }
3605
3606
3607 /* TE-value =
3608  *        0x81
3609  *      | Value-length (0x82--0x86 | Token-text) [ Q-token Q-value ]
3610  */
3611 static guint32 wkh_te (proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
3612 {
3613         wkh_0_Declarations;
3614         guint32 off, val, len;
3615
3616         wkh_1_WellKnownValue;
3617                 if (val_id == 0x81) {
3618                         proto_tree_add_string(tree, hf_hdr_encoding_version,
3619                                         tvb, hdr_start, offset - hdr_start, "trailers");
3620                         ok = TRUE;
3621                 }
3622         wkh_2_TextualValue;
3623                 /* Invalid */
3624         wkh_3_ValueWithLength;
3625                 off = val_start + val_len_len;
3626                 val = tvb_get_guint8(tvb, off);
3627                 if (val & 0x80) { /* Well-known-TE */
3628                         val_str = match_strval((val & 0x7F), vals_well_known_te);
3629                         if (val_str) {
3630                                 ti = proto_tree_add_string(tree, hf_hdr_te,
3631                                                 tvb, hdr_start, off - hdr_start, val_str);
3632                                 off++;
3633                                 ok = TRUE;
3634                         }
3635                 } else { /* TE in Token-text format */
3636                         get_token_text(val_str, tvb, off, len, ok);
3637                         ti = proto_tree_add_string(tree, hf_hdr_te,
3638                                         tvb, hdr_start, off - hdr_start, val_str);
3639                         g_free(val_str);
3640                         off += len;
3641                         ok = TRUE;
3642                 }
3643                 if ((ok) && (off < offset)) { /* Q-token Q-value */
3644                         /* TODO */
3645                 }
3646
3647         wkh_4_End(hf_hdr_te);
3648 }
3649
3650
3651 /****************************************************************************
3652  *                     O p e n w a v e   h e a d e r s
3653  ****************************************************************************/
3654
3655
3656
3657
3658 /*
3659  * Redefine the WellKnownValue parsing so Openwave header field names are used
3660  * are used instead of the default WSP header field names
3661  */
3662 #undef wkh_1_WellKnownValue
3663 #define wkh_1_WellKnownValue                    /* Parse Well Known Value */ \
3664         proto_tree_add_string_hidden(tree, hf_hdr_name, \
3665                         tvb, hdr_start, offset - hdr_start, \
3666                         val_to_str (hdr_id, vals_openwave_field_names, \
3667                                         "<Unknown WSP header field 0x%02X>")); \
3668         if (val_id & 0x80) { /* Well-known value */ \
3669                 offset++; \
3670                 /* Well-known value processing starts HERE \
3671                  * \
3672                  * BEGIN */
3673
3674 /*
3675  * Redefine the End parsing so Openwave header field names are used
3676  * instead of the default WSP field names
3677  */
3678 #undef wkh_4_End
3679 #define wkh_4_End(hf)                                           /* End of value parsing */ \
3680                 /* END */ \
3681         } \
3682         /* Check for errors */ \
3683         if (! ok) { \
3684                 if (ti) { /* Append to protocol tree item label */ \
3685                         proto_item_append_text(ti, \
3686                                         "<Error: Invalid header value>"); \
3687                 } else if (hf > 0) { /* Create protocol tree item */ \
3688                         proto_tree_add_string(tree, hf, \
3689                                         tvb, hdr_start, offset - hdr_start, \
3690                                         " <Error: Invalid header value>"); \
3691                 } else { /* Create anonymous header field entry */ \
3692                         proto_tree_add_text(tree, tvb, hdr_start, offset - hdr_start, \
3693                                         "%s: <Error: Invalid header value>", \
3694                                         val_to_str (hdr_id, vals_openwave_field_names, \
3695                                                 "<Unknown WSP header field 0x%02X>")); \
3696                 } \
3697         } \
3698         return offset;
3699
3700
3701 /* Dissect the Openwave header value (generic) */
3702 static guint32
3703 wkh_openwave_default(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start)
3704 {
3705         wkh_0_Declarations;
3706
3707         ok = TRUE; /* Bypass error checking as we don't parse the values! */
3708
3709         wkh_1_WellKnownValue;
3710                 ti = proto_tree_add_text(tree, tvb, hdr_start, offset - hdr_start,
3711                                 "%s: (Undecoded well-known value 0x%02x)",
3712                                 val_to_str (hdr_id, vals_openwave_field_names,
3713                                         "<Unknown WSP header field 0x%02X>"), val_id & 0x7F);
3714         wkh_2_TextualValue;
3715                 ti = proto_tree_add_text(tree,tvb,hdr_start, offset - hdr_start,
3716                                 "%s: %s",
3717                                 val_to_str (hdr_id, vals_openwave_field_names,
3718                                         "<Unknown WSP header field 0x%02X>"), val_str);
3719         wkh_3_ValueWithLength;
3720                 ti = proto_tree_add_text(tree, tvb, hdr_start, offset - hdr_start,
3721                                 "%s: (Undecoded value in general form with length indicator)",
3722                                 val_to_str (hdr_id, vals_openwave_field_names,
3723                                         "<Unknown WSP header field 0x%02X>"));
3724
3725         wkh_4_End(HF_EMPTY); /* See wkh_default for explanation */
3726 }
3727
3728
3729 /* Textual Openwave headers */
3730 wkh_text_header(openwave_x_up_proxy_operator_domain,
3731                 "x-up-proxy-operator-domain");
3732 wkh_text_header(openwave_x_up_proxy_home_page,
3733                 "x-up-proxy-home-page");
3734 wkh_text_header(openwave_x_up_proxy_uplink_version,
3735                 "x-up-proxy-uplink-version");
3736 wkh_text_header(openwave_x_up_proxy_ba_realm,
3737                 "x-up-proxy-ba-realm");
3738 wkh_text_header(openwave_x_up_proxy_request_uri,
3739                 "x-up-proxy-request-uri");
3740 wkh_text_header(openwave_x_up_proxy_bookmark,
3741                 "x-up-proxy-bookmark");
3742
3743 /* Integer Openwave headers */
3744 wkh_integer_value_header(openwave_x_up_proxy_push_seq,
3745                 "x-up-proxy-push-seq")
3746 wkh_integer_value_header(openwave_x_up_proxy_notify,
3747                 "x-up-proxy-notify")
3748 wkh_integer_value_header(openwave_x_up_proxy_net_ask,
3749                 "x-up-proxy-net-ask")
3750 wkh_integer_value_header(openwave_x_up_proxy_ba_enable,
3751                 "x-up-proxy-ba-enable")
3752 wkh_integer_value_header(openwave_x_up_proxy_redirect_enable,
3753                 "x-up-proxy-redirect-enable")
3754 wkh_integer_value_header(openwave_x_up_proxy_redirect_status,
3755                 "x-up-proxy-redirect-status")
3756 wkh_integer_value_header(openwave_x_up_proxy_linger,
3757                 "x-up-proxy-linger")
3758 wkh_integer_value_header(openwave_x_up_proxy_enable_trust,
3759                 "x-up-proxy-enable-trust")
3760 wkh_integer_value_header(openwave_x_up_proxy_trust,
3761                 "x-up-proxy-trust")
3762
3763 wkh_integer_value_header(openwave_x_up_devcap_has_color,
3764                 "x-up-devcap-has-color")
3765 wkh_integer_value_header(openwave_x_up_devcap_num_softkeys,
3766                 "x-up-devcap-num-softkeys")
3767 wkh_integer_value_header(openwave_x_up_devcap_softkey_size,
3768                 "x-up-devcap-softkey-size")
3769 wkh_integer_value_header(openwave_x_up_devcap_screen_chars,
3770                 "x-up-devcap-screen-chars")
3771 wkh_integer_value_header(openwave_x_up_devcap_screen_pixels,
3772                 "x-up-devcap-screen-pixels")
3773 wkh_integer_value_header(openwave_x_up_devcap_em_size,
3774                 "x-up-devcap-em-size")
3775 wkh_integer_value_header(openwave_x_up_devcap_screen_depth,
3776                 "x-up-devcap-screen-depth")
3777 wkh_integer_value_header(openwave_x_up_devcap_immed_alert,
3778                 "x-up-devcap-immed_alert")
3779 wkh_integer_value_header(openwave_x_up_devcap_gui,
3780                 "x-up-devcap-gui")
3781
3782 /* Openwave Time-Of-Day value header */
3783 wkh_tod_value_header(openwave_x_up_proxy_tod,
3784                 "x-up-proxy-tod")
3785
3786 /* Openwave accept_x_q header */
3787 wkh_accept_x_q_header(openwave_x_up_proxy_trans_charset,
3788                 "x-up-proxy-trans-charset",
3789                 vals_character_sets, "character set")
3790
3791 /* Openwave content type header */
3792 wkh_content_type_header(openwave_x_up_proxy_push_accept,
3793                 "x-up-proxy-push-accept")
3794
3795 /*
3796  * Header value parameter parsing
3797  */
3798 #define InvalidParameterValue(parameter,value) \
3799         "<Error: Invalid " parameter " parameter value: invalid " value ">"
3800
3801
3802
3803
3804
3805 #define parameter_text(hf,lowercase,Uppercase,value) \
3806         get_text_string(val_str, tvb, offset, val_len, ok); \
3807         if (ok) { \
3808                 proto_tree_add_string(tree, hf, \
3809                                 tvb, start, type_len + val_len, val_str); \
3810                 str = g_strdup_printf("; " lowercase "=%s", val_str); \
3811                 proto_item_append_string(ti, str); \
3812                 g_free(str); \
3813                 g_free(val_str); \
3814                 offset += val_len; \
3815         } else { \
3816                 proto_tree_add_string(tree, hf, tvb, start, len - start, \
3817                                 InvalidParameterValue(Uppercase, value)); \
3818                 offset = start + len; /* Skip to end of buffer */ \
3819         }
3820
3821 #define parameter_text_value(hf,lowercase,Uppercase,value) \
3822         get_text_string(val_str, tvb, offset, val_len, ok); \
3823         if (ok) { \
3824                 if (is_quoted_string(val_str[0])) { \
3825                         if (is_quoted_string(val_str[val_len-2])) { \
3826                                 /* Trailing quote - issue a warning */ \
3827                                 str = g_strdup_printf("%s" TrailingQuoteWarning, val_str); \
3828                                 proto_tree_add_string(tree, hf, \
3829                                                 tvb, start, type_len + val_len, str); \
3830                                 g_free(str); \
3831                                 str = g_strdup_printf("; " lowercase "=%s", val_str); \
3832                         } else { /* OK (no trailing quote) */ \
3833                                 str = g_strdup_printf("%s\"", val_str); \
3834                                 proto_tree_add_string(tree, hf, \
3835                                                 tvb, start, type_len + val_len, str); \
3836                                 g_free(str); \
3837                                 str = g_strdup_printf("; " lowercase "=%s\"", val_str); \
3838                         } \
3839                 } else { /* Token-text | 0x00 */ \
3840                         /* TODO - verify that we have either Token-text or 0x00 */ \
3841                         proto_tree_add_string(tree, hf, \
3842                                         tvb, start, type_len + val_len, val_str); \
3843                         str = g_strdup_printf("; " lowercase "=%s", val_str); \
3844                 } \
3845                 proto_item_append_string(ti, str); \
3846                 g_free(str); \
3847                 g_free(val_str); \
3848                 offset += val_len; \
3849         } else { \
3850                 proto_tree_add_string(tree, hf, tvb, start, len - start, \
3851                                 InvalidParameterValue(Uppercase, value)); \
3852                 offset = start + len; /* Skip to end of buffer */ \
3853         }
3854
3855
3856 /* Parameter = Untyped-parameter | Typed-parameter
3857  * Untyped-parameter = Token-text ( Integer-value | Text-value )
3858  * Typed-parameter =
3859  *              Integer-value (
3860  *                      ( Integer-value | Date-value | Delta-seconds-value
3861  *                        | Q-value | Version-value | Uri-value )
3862  *                      | Text-value )
3863  *
3864  *
3865  * Returns: next offset
3866  *
3867  * TODO - Verify byte highlighting in case of invalid parameter values
3868  */
3869 static int
3870 parameter (proto_tree *tree, proto_item *ti, tvbuff_t *tvb, int start, int len)
3871 {
3872         int offset = start;
3873         guint8 peek = tvb_get_guint8 (tvb,start);
3874         guint32 val = 0, type = 0, type_len, val_len;
3875         gchar *str = NULL;
3876         gchar *val_str = NULL;
3877         gchar *s;
3878         gboolean ok;
3879
3880         if (is_token_text (peek)) {
3881                 /*
3882                  * Untyped parameter
3883                  */
3884                 get_token_text (str,tvb,start,val_len,ok); /* Should always succeed */
3885                 if (ok) { /* Found a textual parameter name: str */
3886                         offset += val_len;
3887                         get_text_value(val_str, tvb, offset, val_len, ok);
3888                         if (ok) { /* Also found a textual parameter value: val_str */
3889                                 offset += val_len;
3890                                 if (is_quoted_string(val_str[0])) { /* Add trailing quote! */
3891                                         if (is_quoted_string(val_str[val_len-2])) {
3892                                                 /* Trailing quote - issue a warning */
3893                                                 proto_tree_add_text(tree, tvb, start, offset - start,
3894                                                                 "%s: %s" TrailingQuoteWarning, str, val_str);
3895                                                 s = g_strdup_printf("; %s=%s", str, val_str);
3896                                         } else { /* OK (no trailing quote) */
3897                                                 proto_tree_add_text(tree, tvb, start, offset - start,
3898                                                                 "%s: %s\"", str, val_str);
3899                                                 s = g_strdup_printf("; %s=%s\"", str, val_str);
3900                                         }
3901                                 } else { /* Token-text | 0x00 */
3902                                         /* TODO - verify that it is either Token-text or 0x00
3903                                          * and flag with warning if invalid */
3904                                         proto_tree_add_text(tree, tvb, start, offset - start,
3905                                                         "%s: %s", str, val_str);
3906                                         s = g_strdup_printf("; %s=%s", str, val_str);
3907                                 }
3908                                 /* TODO - check if we can insert a searchable field in the
3909                                  * protocol tree for the untyped parameter case */
3910                                 proto_item_append_string(ti, s);
3911                                 g_free(s);
3912                                 g_free(val_str);
3913                         } else { /* Try integer value */
3914                                 get_integer_value (val,tvb,offset,val_len,ok);
3915                                 if (ok) { /* Also found a valid integer parameter value: val */
3916                                         offset += val_len;
3917                                         proto_tree_add_text(tree, tvb, start, offset - start,
3918                                                         "%s: %u", str, val);
3919                                         s = g_strdup_printf("; %s=%u", str, val);
3920                                         proto_item_append_string(ti, s);
3921                                         g_free(s);
3922                                         /* TODO - check if we can insert a searchable field in the
3923                                          * protocol tree for the untyped parameter case */
3924                                 } else { /* Error: neither token-text not Integer-value */
3925                                         proto_tree_add_text (tree, tvb, start, offset - start,
3926                                                         "<Error: Invalid untyped parameter definition>");
3927                                         offset = start + len; /* Skip to end of buffer */
3928                                 }
3929                         }
3930                         g_free(str);
3931                 }
3932                 return offset;
3933         }
3934         /*
3935          * Else: Typed parameter
3936          */
3937         get_integer_value (type,tvb,start,type_len,ok);
3938         if (!ok) {
3939                 proto_tree_add_text (tree, tvb, start, offset - start,
3940                                 "<Error: Invalid typed parameter definition>");
3941                 return (start + len); /* Skip to end of buffer */
3942         }
3943         offset += type_len;
3944         /* Now offset points to the parameter value */
3945         switch (type) {
3946                 case 0x01:      /* WSP 1.1 encoding - Charset: Well-known-charset */
3947                         get_integer_value(val, tvb, offset, val_len, ok);
3948                         if (ok) {
3949                                 val_str = val_to_str(val, vals_character_sets,
3950                                                 "<Unknown character set Identifier 0x%X>");
3951                                 proto_tree_add_string(tree, hf_parameter_charset,
3952                                                 tvb, start, type_len + val_len, val_str);
3953                                 str = g_strdup_printf("; charset=%s", val_str);
3954                                 proto_item_append_string(ti, str);
3955                                 g_free(str);
3956                                 offset += val_len;
3957                         } else {
3958                                 proto_tree_add_text (tree, tvb, start, offset,
3959                                                 InvalidParameterValue("Charset", "Integer-value"));
3960                                 offset = start + len; /* Skip to end of buffer */
3961                         }
3962                         break;
3963
3964                 case 0x03:      /* WSP 1.1 encoding - Type: Integer-value */
3965                         get_integer_value (val,tvb,offset,val_len,ok);
3966                         if (ok) {
3967                                 proto_tree_add_uint (tree, hf_wsp_parameter_type,
3968                                                 tvb, start, type_len + val_len, val);
3969                                 s = g_strdup_printf("; Type=%u", val);
3970                                 proto_item_append_string (ti, s);
3971                                 g_free(s);
3972                                 offset += val_len;
3973                         } else {
3974                                 proto_tree_add_text (tree, tvb, start, offset,
3975                                                 InvalidParameterValue("Type", "Integer-value"));
3976                                 offset = start + len; /* Skip to end of buffer */
3977                         }
3978                         break;
3979
3980                 case 0x05:      /* WSP 1.1 encoding - Name: Text-string */
3981                         parameter_text(hf_wsp_parameter_name, "name",
3982                                         "Name (WSP 1.1 encoding)", "Text-string");
3983                         break;
3984                 case 0x17:      /* WSP 1.4 encoding - Name: Text-value */
3985                         parameter_text_value(hf_wsp_parameter_name, "name",
3986                                         "Name (WSP 1.4 encoding)", "Text-value");
3987                         break;
3988
3989                 case 0x06:      /* WSP 1.1 encoding - Filename: Text-string */
3990                         parameter_text(hf_wsp_parameter_filename, "filename",
3991                                         "Filename (WSP 1.1 encoding)", "Text-string");
3992                         break;
3993                 case 0x18:      /* WSP 1.4 encoding - Filename: Text-value */
3994                         parameter_text_value(hf_wsp_parameter_filename, "filename",
3995                                         "Filename (WSP 1.4 encoding)", "Text-value");
3996                         break;
3997
3998                 case 0x09:      /* WSP 1.2 encoding - Type (special): Constrained-encoding */
3999                         /* This is similar to the Content-Type header decoding,
4000                          * but it is much simpler:
4001                          * Constrained-encoding = Short-integer | Extension-media
4002                          * Extension-media = *TEXT <Octet 0>
4003                          */
4004                         get_extension_media(val_str,tvb,offset,val_len,ok);
4005                         if (ok) { /* Extension-media */
4006                                 offset += val_len;
4007                         } else {
4008                                 get_short_integer(val,tvb,offset,val_len,ok);
4009                                 if (ok) {
4010                                         offset += val_len;
4011                                         val_str = val_to_str(val, vals_content_types,
4012                                                         "(Unknown content type identifier 0x%X)");
4013                                 } /* Else: invalid parameter value */
4014                         }
4015                         if (ok) {
4016                                 proto_tree_add_string (tree, hf_wsp_parameter_upart_type,
4017                                                 tvb, start, offset - start, val_str);
4018                                 str = g_strdup_printf("; type=%s", val_str);
4019                                 proto_item_append_string(ti, str);
4020                                 g_free(str);
4021                         } else { /* Invalid parameter value */
4022                                 proto_tree_add_text (tree, tvb, start, len - start,
4023                                                 InvalidParameterValue("Type",
4024                                                         "Constrained-encoding"));
4025                                 offset = start + len; /* Skip the parameters */
4026                         }
4027                         break;
4028
4029                 case 0x0A:      /* WSP 1.2 encoding - Start: Text-string */
4030                         parameter_text(hf_wsp_parameter_start, "start",
4031                                         "Start (WSP 1.2 encoding)", "Text-string");
4032                         break;
4033                 case 0x19:      /* WSP 1.4 encoding - Start (with multipart/related): Text-value */
4034                         parameter_text_value(hf_wsp_parameter_start, "start",
4035                                         "Start (WSP 1.4 encoding)", "Text-value");
4036                         break;
4037
4038                 case 0x0B:      /* WSP 1.2 encoding - Start-info: Text-string */
4039                         parameter_text(hf_wsp_parameter_start_info, "start-info",
4040                                         "Start-info (WSP 1.2 encoding)", "Text-string");
4041                         break;
4042                 case 0x1A:      /* WSP 1.4 encoding - Start-info (with multipart/related): Text-value */
4043                         parameter_text_value(hf_wsp_parameter_start_info, "start-info",
4044                                         "Start-info (WSP 1.4 encoding)", "Text-value");
4045                         break;
4046
4047                 case 0x0C:      /* WSP 1.3 encoding - Comment: Text-string */
4048                         parameter_text(hf_wsp_parameter_comment, "comment",
4049                                         "Comment (WSP 1.3 encoding)", "Text-string");
4050                         break;
4051                 case 0x1B:      /* WSP 1.4 encoding - Comment: Text-value */
4052                         parameter_text_value(hf_wsp_parameter_comment, "comment",
4053                                         "Comment (WSP 1.4 encoding)", "Text-value");
4054                         break;
4055
4056                 case 0x0D:      /* WSP 1.3 encoding - Domain: Text-string */
4057                         parameter_text(hf_wsp_parameter_domain, "domain",
4058                                         "Domain (WSP 1.3 encoding)", "Text-string");
4059                         break;
4060                 case 0x1C:      /* WSP 1.4 encoding - Domain: Text-value */
4061                         parameter_text_value(hf_wsp_parameter_domain, "domain",
4062                                         "Domain (WSP 1.4 encoding)", "Text-value");
4063                         break;
4064
4065                 case 0x0F:      /* WSP 1.3 encoding - Path: Text-string */
4066                         parameter_text(hf_wsp_parameter_path, "path",
4067                                         "Path (WSP 1.3 encoding)", "Text-string");
4068                         break;
4069                 case 0x1D:      /* WSP 1.4 encoding - Path: Text-value */
4070                         parameter_text_value(hf_wsp_parameter_path, "path",
4071                                         "Path (WSP 1.4 encoding)", "Text-value");
4072                         break;
4073
4074                 case 0x11:      /* WSP 1.4 encoding - SEC: Short-integer (OCTET) */
4075                         peek = tvb_get_guint8 (tvb, start+1);
4076                         if (peek & 0x80) { /* Valid Short-integer */
4077                                 peek &= 0x7F;
4078                                 proto_tree_add_uint (tree, hf_wsp_parameter_sec,
4079                                                 tvb, start, 2, peek);
4080                                 str = match_strval(peek, vals_wsp_parameter_sec);
4081                                 proto_item_append_text (ti, "; SEC=%s", str);
4082                                 offset++;
4083                         } else { /* Error */
4084                                 proto_tree_add_text (tree, tvb, start, len - start,
4085                                                 InvalidParameterValue("SEC", "Short-integer"));
4086                                 offset = start + len; /* Skip to end of buffer */
4087                         }
4088                         break;
4089
4090                 case 0x12:      /* WSP 1.4 encoding - MAC: Text-value */
4091                         parameter_text_value(hf_wsp_parameter_mac, "MAC",
4092                                         "MAC", "Text-value");
4093                         break;
4094
4095                 case 0x02:      /* WSP 1.1 encoding - Level: Version-value */
4096                         get_version_value(val,str,tvb,offset,val_len,ok);
4097                         if (ok) {
4098                                 proto_tree_add_string (tree, hf_wsp_parameter_level,
4099                                                 tvb, start, type_len + val_len, str);
4100                                 proto_item_append_text (ti, "; level=%s", str);
4101                                 offset += val_len;
4102                         } else {
4103                                 proto_tree_add_text (tree, tvb, start, len - start,
4104                                                 InvalidParameterValue("Level", "Version-value"));
4105                                 offset = start + len; /* Skip to end of buffer */
4106                         }
4107                         break;
4108
4109                 case 0x00:      /* WSP 1.1 encoding - Q: Q-value */
4110                         offset = parameter_value_q(tree, ti, tvb, offset);
4111                         break;
4112
4113                 case 0x07:      /* WSP 1.1 encoding - Differences: Field-name */
4114                 case 0x08:      /* WSP 1.1 encoding - Padding: Short-integer */
4115                 case 0x0E:      /* WSP 1.3 encoding - Max-Age: Delta-seconds-value */
4116                 case 0x10:      /* WSP 1.3 encoding - Secure: No-value */
4117                 case 0x13:      /* WSP 1.4 encoding - Creation-date: Date-value */
4118                 case 0x14:      /* WSP 1.4 encoding - Modification-date: Date-value */
4119                 case 0x15:      /* WSP 1.4 encoding - Read-date: Date-value */
4120                 case 0x16:      /* WSP 1.4 encoding - Size: Integer-value */
4121                 default:
4122                         proto_tree_add_text(tree, tvb, start, len - start, 
4123                                         "Undecoded parameter type 0x%02x - decoding stopped",
4124                                         type);
4125                         offset = start + len; /* Skip the parameters */
4126                         break;
4127         }
4128         return offset;
4129 }
4130
4131
4132 /*
4133  * Dissects the Q-value parameter value.
4134  * 
4135  * Returns: next offset
4136  */
4137 static int
4138 parameter_value_q (proto_tree *tree, proto_item *ti, tvbuff_t *tvb, int start)
4139 {
4140         int offset = start;
4141         guint32 val = 0, val_len;
4142         gchar *str = NULL;
4143         guint8 ok;
4144
4145         get_uintvar_integer (val, tvb, offset, val_len, ok);
4146         if (ok && (val < 1100)) {
4147                 if (val <= 100) { /* Q-value in 0.01 steps */
4148                         str = g_strdup_printf("0.%02u", val - 1);
4149                 } else { /* Q-value in 0.001 steps */
4150                         str = g_strdup_printf("0.%03u", val - 100);
4151                 }
4152                 proto_item_append_text (ti, "; q=%s", str);
4153                 proto_tree_add_string (tree, hf_parameter_q,
4154                                 tvb, start, val_len, str);
4155                 g_free(str);
4156                 offset += val_len;
4157         } else {
4158                 proto_tree_add_text (tree, tvb, start, offset,
4159                                 InvalidParameterValue("Q", "Q-value"));
4160                 offset += val_len;
4161         }
4162         return offset;
4163 }
4164
4165
4166 /* Code to actually dissect the packets */
4167
4168 /*
4169  * WSP redirect
4170  */
4171
4172 static void
4173 dissect_redirect(tvbuff_t *tvb, int offset, packet_info *pinfo,
4174     proto_tree *tree, dissector_handle_t dissector_handle)
4175 {
4176         guint8 flags;
4177         proto_item *ti;
4178         proto_tree *flags_tree;
4179         guint8 bearer_type;
4180         guint8 address_flags_len;
4181         int address_len;
4182         proto_tree *atf_tree;
4183         guint16 port_num;
4184         guint32 address_ipv4;
4185         struct e_in6_addr address_ipv6;
4186         address redir_address;
4187         conversation_t *conv;
4188
4189         flags = tvb_get_guint8 (tvb, offset);
4190         if (tree) {
4191                 ti = proto_tree_add_uint (tree, hf_wsp_redirect_flags,
4192                     tvb, offset, 1, flags);
4193                 flags_tree = proto_item_add_subtree (ti, ett_redirect_flags);
4194                 proto_tree_add_boolean (flags_tree, hf_wsp_redirect_permanent,
4195                     tvb, offset, 1, flags);
4196                 proto_tree_add_boolean (flags_tree, hf_wsp_redirect_reuse_security_session,
4197                     tvb, offset, 1, flags);
4198         }
4199         offset++;
4200         while (tvb_reported_length_remaining (tvb, offset) > 0) {
4201                 address_flags_len = tvb_get_guint8 (tvb, offset);
4202                 if (tree) {
4203                         ti = proto_tree_add_uint (tree, hf_wsp_redirect_afl,
4204                             tvb, offset, 1, address_flags_len);
4205                         atf_tree = proto_item_add_subtree (ti, ett_redirect_afl);
4206                         proto_tree_add_boolean (atf_tree, hf_wsp_redirect_afl_bearer_type_included,
4207                             tvb, offset, 1, address_flags_len);
4208                         proto_tree_add_boolean (atf_tree, hf_wsp_redirect_afl_port_number_included,
4209                             tvb, offset, 1, address_flags_len);
4210                         proto_tree_add_uint (atf_tree, hf_wsp_redirect_afl_address_len,
4211                             tvb, offset, 1, address_flags_len);
4212                 }
4213                 offset++;
4214                 if (address_flags_len & BEARER_TYPE_INCLUDED) {
4215                         bearer_type = tvb_get_guint8 (tvb, offset);
4216                         if (tree) {
4217                                 proto_tree_add_uint (tree, hf_wsp_redirect_bearer_type,
4218                                     tvb, offset, 1, bearer_type);
4219                         }
4220                         offset++;
4221                 } else
4222                         bearer_type = 0x00;     /* XXX */
4223                 if (address_flags_len & PORT_NUMBER_INCLUDED) {
4224                         port_num = tvb_get_ntohs (tvb, offset);
4225                         if (tree) {
4226                                 proto_tree_add_uint (tree, hf_wsp_redirect_port_num,
4227                                     tvb, offset, 2, port_num);
4228                         }
4229                         offset += 2;
4230                 } else {
4231                         /*
4232                          * Redirecting to the same server port number as was
4233                          * being used, i.e. the source port number of this
4234                          * redirect.
4235                          */
4236                         port_num = pinfo->srcport;
4237                 }
4238                 address_len = address_flags_len & ADDRESS_LEN;
4239                 if (!(address_flags_len & BEARER_TYPE_INCLUDED)) {
4240                         /*
4241                          * We don't have the bearer type in the message,
4242                          * so we don't know the address type.
4243                          * (It's the same bearer type as the original
4244                          * connection.)
4245                          */
4246                         goto unknown_address_type;
4247                 }
4248
4249                 /*
4250                  * We know the bearer type, so we know the address type.
4251                  */
4252                 switch (bearer_type) {
4253
4254                 case BT_IPv4:
4255                 case BT_IS_95_CSD:
4256                 case BT_IS_95_PACKET_DATA:
4257                 case BT_ANSI_136_CSD:
4258                 case BT_ANSI_136_PACKET_DATA:
4259                 case BT_GSM_CSD:
4260                 case BT_GSM_GPRS:
4261                 case BT_GSM_USSD_IPv4:
4262                 case BT_AMPS_CDPD:
4263                 case BT_PDC_CSD:
4264                 case BT_PDC_PACKET_DATA:
4265                 case BT_IDEN_CSD:
4266                 case BT_IDEN_PACKET_DATA:
4267                 case BT_PHS_CSD:
4268                 case BT_TETRA_PACKET_DATA:
4269                         /*
4270                          * IPv4.
4271                          */
4272                         if (address_len != 4) {
4273                                 /*
4274                                  * Say what?
4275                                  */
4276                                 goto unknown_address_type;
4277                         }
4278                         tvb_memcpy(tvb, (guint8 *)&address_ipv4, offset, 4);
4279                         if (tree) {
4280                                 proto_tree_add_ipv4 (tree,
4281                                     hf_wsp_redirect_ipv4_addr,
4282                                     tvb, offset, 4, address_ipv4);
4283                         }
4284
4285                         /*
4286                          * Create a conversation so that the
4287                          * redirected session will be dissected
4288                          * as WAP.
4289                          */
4290                         redir_address.type = AT_IPv4;
4291                         redir_address.len = 4;
4292                         redir_address.data = (const guint8 *)&address_ipv4;
4293                         conv = find_conversation(&redir_address, &pinfo->dst,
4294                             PT_UDP, port_num, 0, NO_PORT_B);
4295                         if (conv == NULL) {
4296                                 conv = conversation_new(&redir_address,
4297                                     &pinfo->dst, PT_UDP, port_num, 0, NO_PORT2);
4298                         }
4299                         conversation_set_dissector(conv, dissector_handle);
4300                         break;
4301
4302                 case BT_IPv6:
4303                         /*
4304                          * IPv6.
4305                          */
4306                         if (address_len != 16) {
4307                                 /*
4308                                  * Say what?
4309                                  */
4310                                 goto unknown_address_type;
4311                         }
4312                         tvb_memcpy(tvb, (guint8 *)&address_ipv6, offset, 16);
4313                         if (tree) {
4314                                 proto_tree_add_ipv6 (tree,
4315                                     hf_wsp_redirect_ipv6_addr,
4316                                     tvb, offset, 16, (guint8 *)&address_ipv6);
4317                         }
4318
4319                         /*
4320                          * Create a conversation so that the
4321                          * redirected session will be dissected
4322                          * as WAP.
4323                          */
4324                         redir_address.type = AT_IPv6;
4325                         redir_address.len = 16;
4326                         redir_address.data = (const guint8 *)&address_ipv4;
4327                         conv = find_conversation(&redir_address, &pinfo->dst,
4328                             PT_UDP, port_num, 0, NO_PORT_B);
4329                         if (conv == NULL) {
4330                                 conv = conversation_new(&redir_address,
4331                                     &pinfo->dst, PT_UDP, port_num, 0, NO_PORT2);
4332                         }
4333                         conversation_set_dissector(conv, dissector_handle);
4334                         break;
4335
4336                 unknown_address_type:
4337                 default:
4338                         if (address_len != 0) {
4339                                 if (tree) {
4340                                         proto_tree_add_item (tree,
4341                                             hf_wsp_redirect_addr,
4342                                             tvb, offset, address_len,
4343                                             bo_little_endian);
4344                                 }
4345                         }
4346                         break;
4347                 }
4348                 offset += address_len;
4349         }
4350 }
4351
4352 static void
4353 dissect_wsp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4354     dissector_handle_t dissector_handle, gboolean is_connectionless)
4355 {
4356         int offset = 0;
4357
4358         guint8 pdut;
4359         guint8 reply_status;
4360         guint count = 0;
4361         guint value = 0;
4362         guint uriLength = 0;
4363         guint uriStart = 0;
4364         guint capabilityLength = 0;
4365         guint capabilityStart = 0;
4366         guint headersLength = 0;
4367         guint headerLength = 0;
4368         guint headerStart = 0;
4369         guint nextOffset = 0;
4370         guint contentTypeStart = 0;
4371         guint contentType = 0;
4372         const char *contentTypeStr;
4373         tvbuff_t *tmp_tvb;
4374         gboolean found_match;
4375
4376 /* Set up structures we will need to add the protocol subtree and manage it */
4377         proto_item *ti;
4378         proto_tree *wsp_tree = NULL;
4379
4380         wsp_info_value_t *stat_info;
4381         stat_info = g_malloc( sizeof(wsp_info_value_t) );
4382         stat_info->status_code = 0;
4383
4384 /* This field shows up as the "Info" column in the display; you should make
4385    it, if possible, summarize what's in the packet, so that a user looking
4386    at the list of packets can tell what type of packet it is. */
4387
4388         /* Connection-less mode has a TID first */
4389         if (is_connectionless)
4390         {
4391                 offset++; /* Skip the 1-byte Transaction ID */
4392         };
4393
4394         /* Find the PDU type */
4395         pdut = tvb_get_guint8 (tvb, offset);
4396
4397         /* Develop the string to put in the Info column */
4398         if (check_col(pinfo->cinfo, COL_INFO))
4399         {
4400                 col_append_fstr(pinfo->cinfo, COL_INFO, "WSP %s",
4401                         val_to_str (pdut, vals_pdu_type, "Unknown PDU type (0x%02x)"));
4402         };
4403
4404         /* In the interest of speed, if "tree" is NULL, don't do any work not
4405          * necessary to generate protocol tree items. */
4406         if (tree) {
4407                 ti = proto_tree_add_item(tree, proto_wsp,
4408                                 tvb, 0, -1, bo_little_endian);
4409                 wsp_tree = proto_item_add_subtree(ti, ett_wsp);
4410
4411                 /* Add common items: only TID and PDU Type */
4412
4413                 /* If this is connectionless, then the TID Field is always first */
4414                 if (is_connectionless)
4415                 {
4416                         ti = proto_tree_add_item (wsp_tree, hf_wsp_header_tid,
4417                                         tvb, 0, 1, bo_little_endian);
4418                 }
4419                 ti = proto_tree_add_item( wsp_tree, hf_wsp_header_pdu_type,
4420                                 tvb, offset, 1, bo_little_endian);
4421         }
4422         offset++;
4423
4424         /* Map extended methods to the main method now the Column info has been
4425          * written; this way we can dissect the extended method PDUs. */
4426         if ((pdut >= 0x50) && (pdut <= 0x5F)) /* Extended GET --> GET */
4427                 pdut = WSP_PDU_GET;
4428         else if ((pdut >= 0x70) && (pdut <= 0x7F)) /* Extended POST --> POST */
4429                 pdut = WSP_PDU_POST;
4430
4431         switch (pdut)
4432         {
4433                 case WSP_PDU_CONNECT:
4434                 case WSP_PDU_CONNECTREPLY:
4435                 case WSP_PDU_RESUME:
4436                         if (tree) {
4437                                 if (pdut == WSP_PDU_CONNECT)
4438                                 {
4439                                         ti = proto_tree_add_item (wsp_tree, hf_wsp_version_major,
4440                                                         tvb, offset, 1, bo_little_endian);
4441                                         ti = proto_tree_add_item (wsp_tree, hf_wsp_version_minor,
4442                                                         tvb, offset, 1, bo_little_endian);
4443                                         offset++;
4444                                 } else {
4445                                         count = 0;      /* Initialise count */
4446                                         value = tvb_get_guintvar (tvb, offset, &count);
4447                                         ti = proto_tree_add_uint (wsp_tree,
4448                                                         hf_wsp_server_session_id,
4449                                                         tvb, offset, count, value);
4450                                         offset += count;
4451                                 }
4452                                 capabilityStart = offset;
4453                                 count = 0;      /* Initialise count */
4454                                 capabilityLength = tvb_get_guintvar (tvb, offset, &count);
4455                                 offset += count;
4456                                 ti = proto_tree_add_uint (wsp_tree, hf_wsp_capability_length,
4457                                                 tvb, capabilityStart, count, capabilityLength);
4458
4459                                 if (pdut != WSP_PDU_RESUME)
4460                                 {
4461                                         count = 0;      /* Initialise count */
4462                                         headerLength = tvb_get_guintvar (tvb, offset, &count);
4463                                         ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,
4464                                                         tvb, offset, count, headerLength);
4465                                         offset += count;
4466                                         capabilityStart = offset;
4467                                         headerStart = capabilityStart + capabilityLength;
4468                                 } else {
4469                                                 /* Resume computes the headerlength
4470                                                  * by remaining bytes */
4471                                         capabilityStart = offset;
4472                                         headerStart = capabilityStart + capabilityLength;
4473                                         headerLength = tvb_reported_length_remaining (tvb,
4474                                                         headerStart);
4475                                 }
4476                                 if (capabilityLength > 0)
4477                                 {
4478                                         tmp_tvb = tvb_new_subset (tvb, offset,
4479                                                         capabilityLength, capabilityLength);
4480                                         add_capabilities (wsp_tree, tmp_tvb, pdut);
4481                                         offset += capabilityLength;
4482                                 }
4483
4484                                 if (headerLength > 0)
4485                                 {
4486                                         tmp_tvb = tvb_new_subset (tvb, offset,
4487                                                         headerLength, headerLength);
4488                                         add_headers (wsp_tree, tmp_tvb);
4489                                 }
4490                         }
4491
4492                         break;
4493
4494                 case WSP_PDU_REDIRECT:
4495                         dissect_redirect(tvb, offset, pinfo, wsp_tree, dissector_handle);
4496                         break;
4497
4498                 case WSP_PDU_DISCONNECT:
4499                 case WSP_PDU_SUSPEND:
4500                         if (tree) {
4501                                 count = 0;      /* Initialise count */
4502                                 value = tvb_get_guintvar (tvb, offset, &count);
4503                                 ti = proto_tree_add_uint (wsp_tree,
4504                                                 hf_wsp_server_session_id,
4505                                                 tvb, offset, count, value);
4506                         }
4507                         break;
4508
4509                 case WSP_PDU_GET:
4510                         count = 0;      /* Initialise count */
4511                         /* Length of URI and size of URILen field */
4512                         value = tvb_get_guintvar (tvb, offset, &count);
4513                         nextOffset = offset + count;
4514                         add_uri (wsp_tree, pinfo, tvb, offset, nextOffset);
4515                         if (tree) {
4516                                 offset += value + count; /* VERIFY */
4517                                 tmp_tvb = tvb_new_subset (tvb, offset, -1, -1);
4518                                 add_headers (wsp_tree, tmp_tvb);
4519                         }
4520                         break;
4521
4522                 case WSP_PDU_POST:
4523                         uriStart = offset;
4524                         count = 0;      /* Initialise count */
4525                         uriLength = tvb_get_guintvar (tvb, offset, &count);
4526                         headerStart = uriStart+count;
4527                         count = 0;      /* Initialise count */
4528                         headersLength = tvb_get_guintvar (tvb, headerStart, &count);
4529                         offset = headerStart + count;
4530
4531                         add_uri (wsp_tree, pinfo, tvb, uriStart, offset);
4532                         offset += uriLength;
4533
4534                         if (tree)
4535                                 ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,
4536                                                 tvb, headerStart, count, headersLength);
4537
4538                         if (headersLength == 0)
4539                                 break;
4540
4541                         contentTypeStart = offset;
4542                         nextOffset = add_content_type (wsp_tree,
4543                                         tvb, offset, &contentType, &contentTypeStr);
4544
4545                         if (tree) {
4546                                 /* Add headers subtree that will hold the headers fields */
4547                                 /* Runs from nextOffset for
4548                                  * headersLength - (length of content-type field) */
4549                                 headerLength = headersLength - (nextOffset - contentTypeStart);
4550                                 if (headerLength > 0)
4551                                 {
4552                                         tmp_tvb = tvb_new_subset (tvb, nextOffset,
4553                                                         headerLength, headerLength);
4554                                         add_headers (wsp_tree, tmp_tvb);
4555                                 }
4556                                 offset = nextOffset+headerLength;
4557                         }
4558                         /* WSP_PDU_POST data - First check whether a subdissector exists
4559                          * for the content type */
4560                         if (tvb_reported_length_remaining(tvb,
4561                                                 headerStart + count + uriLength + headersLength) > 0)
4562                         {
4563                                 tmp_tvb = tvb_new_subset (tvb,
4564                                                 headerStart + count + uriLength + headersLength,
4565                                                 -1, -1);
4566                                 /*
4567                                  * Try finding a dissector for the content
4568                                  * first, then fallback.
4569                                  */
4570                                 if (contentTypeStr == NULL) {
4571                                         /*
4572                                          * Content type is numeric.
4573                                          */
4574                                         found_match = dissector_try_port(wsp_dissector_table,
4575                                               contentType, tmp_tvb, pinfo, tree);
4576                                 } else {
4577                                         /*
4578                                          * Content type is a string.
4579                                          */
4580                                         found_match = dissector_try_string(wsp_dissector_table_text,
4581                                                         contentTypeStr, tmp_tvb, pinfo, tree);
4582                                 }
4583                                 if (! found_match) {
4584                                         if (! dissector_try_heuristic(heur_subdissector_list,
4585                                                                 tmp_tvb, pinfo, tree))
4586                                                 if (tree) /* Only display if needed */
4587                                                         add_post_data (wsp_tree, tmp_tvb,
4588                                                                         contentType, contentTypeStr);
4589                                 }
4590                         }
4591                         break;
4592
4593                 case WSP_PDU_REPLY:
4594                         count = 0;      /* Initialise count */
4595                         headersLength = tvb_get_guintvar (tvb, offset+1, &count);
4596                         headerStart = offset + count + 1;
4597                         reply_status = tvb_get_guint8(tvb, offset);
4598                         if (tree)
4599                                 ti = proto_tree_add_item (wsp_tree, hf_wsp_header_status,
4600                                                 tvb, offset, 1, bo_little_endian);
4601                         stat_info->status_code = (gint) tvb_get_guint8(tvb, offset);                            
4602                         if (check_col(pinfo->cinfo, COL_INFO))
4603                         { /* Append status code to INFO column */
4604                                 col_append_fstr(pinfo->cinfo, COL_INFO,
4605                                                 ": \"0x%02x %s\"", reply_status,
4606                                                 val_to_str (reply_status, vals_status,
4607                                                         "Unknown response status (0x%02x)"));
4608                         }
4609                         nextOffset = offset + 1 + count;
4610                         if (tree)
4611                                 ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,
4612                                                 tvb, offset + 1, count, headersLength);
4613
4614                         if (headersLength == 0)
4615                                 break;
4616
4617                         contentTypeStart = nextOffset;
4618                         nextOffset = add_content_type (wsp_tree, tvb,
4619                                         nextOffset, &contentType, &contentTypeStr);
4620
4621                         if (tree) {
4622                                 /* Add headers subtree that will hold the headers fields */
4623                                 /* Runs from nextOffset for
4624                                  * headersLength - (length of content-type field) */
4625                                 headerLength = headersLength - (nextOffset - contentTypeStart);
4626                                 if (headerLength > 0)
4627                                 {
4628                                         tmp_tvb = tvb_new_subset (tvb, nextOffset,
4629                                                         headerLength, headerLength);
4630                                         add_headers (wsp_tree, tmp_tvb);
4631                                 }
4632                                 offset += count+headersLength+1;
4633                         }
4634                         /* WSP_PDU_REPLY data - First check whether a subdissector exists
4635                          * for the content type */
4636                         if (tvb_reported_length_remaining(tvb, headerStart + headersLength)
4637                                         > 0)
4638                         {
4639                                 tmp_tvb = tvb_new_subset (tvb, headerStart + headersLength,
4640                                                 -1, -1);
4641                                 /*
4642                                  * Try finding a dissector for the content
4643                                  * first, then fallback.
4644                                  */
4645                                 if (contentTypeStr == NULL) {
4646                                         /*
4647                                          * Content type is numeric.
4648                                          */
4649                                         found_match = dissector_try_port(wsp_dissector_table,
4650                                                         contentType, tmp_tvb, pinfo, tree);
4651                                 } else {
4652                                         /*
4653                                          * Content type is a string.
4654                                          */
4655                                         found_match = dissector_try_string(wsp_dissector_table_text,
4656                                                         contentTypeStr, tmp_tvb, pinfo, tree);
4657                                 }
4658                                 if (! found_match) {
4659                                         if (! dissector_try_heuristic(heur_subdissector_list,
4660                                             tmp_tvb, pinfo, tree))
4661                                                 if (tree) /* Only display if needed */
4662                                                         ti = proto_tree_add_item (wsp_tree,
4663                                                             hf_wsp_reply_data,
4664                                                             tmp_tvb, 0, -1, bo_little_endian);
4665                                 }
4666                         }
4667                         break;
4668
4669                 case WSP_PDU_PUSH:
4670                 case WSP_PDU_CONFIRMEDPUSH:
4671                         count = 0;      /* Initialise count */
4672                         headersLength = tvb_get_guintvar (tvb, offset, &count);
4673                         headerStart = offset + count;
4674
4675                         if (tree)
4676                                 ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,
4677                                                 tvb, offset, count, headersLength);
4678
4679                         if (headersLength == 0)
4680                                 break;
4681
4682                         offset += count;
4683                         contentTypeStart = offset;
4684                         nextOffset = add_content_type (wsp_tree,
4685                                         tvb, offset, &contentType, &contentTypeStr);
4686
4687                         if (tree) {
4688                                 /* Add headers subtree that will hold the headers fields */
4689                                 /* Runs from nextOffset for
4690                                  * headersLength-(length of content-type field) */
4691                                 headerLength = headersLength-(nextOffset-contentTypeStart);
4692                                 if (headerLength > 0)
4693                                 {
4694                                         tmp_tvb = tvb_new_subset (tvb, nextOffset,
4695                                                         headerLength, headerLength);
4696                                         add_headers (wsp_tree, tmp_tvb);
4697                                 }
4698                                 offset += headersLength;
4699                         }
4700                         /* WSP_PDU_PUSH data - First check whether a subdissector exists
4701                          * for the content type */
4702                         if (tvb_reported_length_remaining(tvb, headerStart + headersLength)
4703                                         > 0)
4704                         {
4705                                 tmp_tvb = tvb_new_subset (tvb, headerStart + headersLength,
4706                                                 -1, -1);
4707                                 /*
4708                                  * Try finding a dissector for the content
4709                                  * first, then fallback.
4710                                  */
4711                                 if (contentTypeStr == NULL) {
4712                                         /*
4713                                          * Content type is numeric.
4714                                          */
4715                                         found_match = dissector_try_port(wsp_dissector_table,
4716                                                         contentType, tmp_tvb, pinfo, tree);
4717                                 } else {
4718                                         /*
4719                                          * Content type is a string.
4720                                          */
4721                                         found_match = dissector_try_string(wsp_dissector_table_text,
4722                                                         contentTypeStr, tmp_tvb, pinfo, tree);
4723                                 }
4724                                 if (! found_match) {
4725                                         if (! dissector_try_heuristic(heur_subdissector_list,
4726                                                                 tmp_tvb, pinfo, tree))
4727                                                 if (tree) /* Only display if needed */
4728                                                         ti = proto_tree_add_item (wsp_tree,
4729                                                                         hf_wsp_push_data,
4730                                                                         tmp_tvb, 0, -1, bo_little_endian);
4731                                 }
4732                         }
4733                         break;
4734
4735         }
4736         stat_info->pdut = pdut;
4737         tap_queue_packet (wsp_tap, pinfo, stat_info);
4738 }
4739
4740
4741 /*
4742  * Called directly from UDP.
4743  * Put "WSP" into the "Protocol" column.
4744  */
4745 static void
4746 dissect_wsp_fromudp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4747 {
4748         if (check_col(pinfo->cinfo, COL_PROTOCOL))
4749                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "WSP" );
4750         if (check_col(pinfo->cinfo, COL_INFO))
4751                 col_clear(pinfo->cinfo, COL_INFO);
4752
4753         dissect_wsp_common(tvb, pinfo, tree, wsp_fromudp_handle, TRUE);
4754 }
4755
4756
4757 /*
4758  * Called from a higher-level WAP dissector, in connection-oriented mode.
4759  * Leave the "Protocol" column alone - the dissector calling us should
4760  * have set it.
4761  */
4762 static void
4763 dissect_wsp_fromwap_co(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4764 {
4765         /*
4766          * XXX - what about WTLS->WTP->WSP?
4767          */
4768         dissect_wsp_common(tvb, pinfo, tree, wtp_fromudp_handle, FALSE);
4769 }
4770
4771
4772 /*
4773  * Called from a higher-level WAP dissector, in connectionless mode.
4774  * Leave the "Protocol" column alone - the dissector calling us should
4775  * have set it.
4776  */
4777 static void
4778 dissect_wsp_fromwap_cl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4779 {
4780         /*
4781          * XXX - what about WTLS->WSP?
4782          */
4783         if (check_col(pinfo->cinfo, COL_INFO))
4784         {
4785                 col_clear(pinfo->cinfo, COL_INFO);
4786         }
4787         dissect_wsp_common(tvb, pinfo, tree, wtp_fromudp_handle, TRUE);
4788 }
4789
4790
4791 static void
4792 add_uri (proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
4793                 guint URILenOffset, guint URIOffset)
4794 {
4795         proto_item *ti;
4796
4797         guint count = 0;
4798         guint uriLen = tvb_get_guintvar (tvb, URILenOffset, &count);
4799
4800         if (tree)
4801                 ti = proto_tree_add_uint (tree, hf_wsp_header_uri_len,
4802                                 tvb, URILenOffset, count, uriLen);
4803
4804         tvb_ensure_bytes_exist(tvb, URIOffset, uriLen);
4805         if (tree)
4806                 ti = proto_tree_add_item (tree, hf_wsp_header_uri,
4807                                 tvb, URIOffset, uriLen, bo_little_endian);
4808         if (check_col(pinfo->cinfo, COL_INFO)) {
4809                 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
4810                     tvb_format_text (tvb, URIOffset, uriLen));
4811         }
4812 }
4813
4814
4815 /*
4816  * CO-WSP capability negotiation
4817  */
4818 static void
4819 add_capabilities (proto_tree *tree, tvbuff_t *tvb, int type)
4820 {
4821         proto_item *ti;
4822         proto_tree *wsp_capabilities;
4823         guint offset = 0;
4824         guint offsetStr = 0;
4825         guint capabilitiesLen = tvb_reported_length (tvb);
4826         guint capabilitiesStart = 0;
4827         guint peek = 0;
4828         guint length = 0;
4829         guint value = 0;
4830         guint i;
4831         int ret;
4832         char valString[VAL_STRING_SIZE];
4833
4834 #ifdef DEBUG
4835         fprintf (stderr, "dissect_wsp: Offset is %d, size is %d\n", offset, capabilitiesLen);
4836 #endif
4837
4838         /* End of buffer */
4839         if (capabilitiesLen <= 0)
4840         {
4841 #ifdef DEBUG
4842                 fprintf (stderr, "dissect_wsp: Capabilities = 0\n");
4843 #endif
4844                 return;
4845         }
4846
4847 #ifdef DEBUG
4848         fprintf (stderr, "dissect_wsp: capabilities to process\n");
4849 #endif
4850
4851         ti = proto_tree_add_item (tree, hf_wsp_capabilities_section,tvb,offset,capabilitiesLen,bo_little_endian);
4852         wsp_capabilities = proto_item_add_subtree( ti, ett_capabilities );
4853
4854         /* Parse Headers */
4855
4856         while (offset < capabilitiesLen)
4857         {
4858                 /* Loop round each header */
4859                 capabilitiesStart = offset;
4860                 length = tvb_get_guint8 (tvb, capabilitiesStart);
4861
4862                 if (length >= 127)              /* length */
4863                 {
4864 #ifdef DEBUG
4865                         fprintf (stderr, "dissect_wsp: capabilities length invalid %d\n",length);
4866 #endif
4867                         offset+=length;
4868                         continue;
4869                 }
4870                 offset++;
4871                 peek = tvb_get_guint8 (tvb, offset);
4872                 offset++;
4873                 switch (peek & 0x7f)
4874                 {
4875                         case 0x00 : /* Client-SDU-Size */
4876                                 value = get_uintvar (tvb, offset, length+capabilitiesStart+1);
4877                                 proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_client_SDU, tvb, capabilitiesStart, length+1, value);
4878                                 break;
4879                         case 0x01 : /* Server-SDU-Size */
4880                                 value = get_uintvar (tvb, offset, length+capabilitiesStart+1);
4881                                 proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_server_SDU, tvb, capabilitiesStart, length+1, value);
4882                                 break;
4883                         case 0x02 : /* Protocol Options */
4884                                 value = get_uintvar (tvb, offset, length+capabilitiesStart+1);
4885                                 i = 0;
4886                                 valString[0]=0;
4887                                 if (value & 0x80)
4888                                 {
4889                                         ret = snprintf(valString+i,VAL_STRING_SIZE-i,"%s","(Confirmed push facility) ");
4890                                         if (ret == -1 || (unsigned int) ret >= VAL_STRING_SIZE-i) {
4891                                                 /*
4892                                                  * We've been truncated
4893                                                  */
4894                                                 goto add_string;
4895                                         }
4896                                         i += ret;
4897                                 }
4898                                 if (value & 0x40)
4899                                 {
4900                                         if (i >= 200) {
4901                                                 /* No more room. */
4902                                                 goto add_string;
4903                                         }
4904                                         ret = snprintf(valString+i,VAL_STRING_SIZE-i,"%s","(Push facility) ");
4905                                         if (ret == -1 || (unsigned int) ret >= VAL_STRING_SIZE-i) {
4906                                                 /*
4907                                                  * We've been truncated
4908                                                  */
4909                                                 goto add_string;
4910                                         }
4911                                         i += ret;
4912                                 }
4913                                 if (value & 0x20)
4914                                 {
4915                                         if (i >= 200) {
4916                                                 /* No more room. */
4917                                                 goto add_string;
4918                                         }
4919                                         ret = snprintf(valString+i,VAL_STRING_SIZE-i,"%s","(Session resume facility) ");
4920                                         if (ret == -1 || (unsigned int) ret >= VAL_STRING_SIZE-i) {
4921                                                 /*
4922                                                  * We've been truncated
4923                                                  */
4924                                                 goto add_string;
4925                                         }
4926                                         i += ret;
4927                                 }
4928                                 if (value & 0x10)
4929                                 {
4930                                         if (i >= VAL_STRING_SIZE) {
4931                                                 /* No more room. */
4932                                                 goto add_string;
4933                                         }
4934                                         ret = snprintf(valString+i,VAL_STRING_SIZE-i,"%s","(Acknowledgement headers) ");
4935                                         if (ret == -1 || (unsigned int) ret >= VAL_STRING_SIZE-i) {
4936                                                 /*
4937                                                  * We've been truncated
4938                                                  */
4939                                                 goto add_string;
4940                                         }
4941                                         i += ret;
4942                                 }
4943                         add_string:
4944                                 valString[VAL_STRING_SIZE-1] = '\0';
4945                                 proto_tree_add_string(wsp_capabilities, hf_wsp_capabilities_protocol_opt, tvb, capabilitiesStart, length+1, valString);
4946                                 break;
4947                         case 0x03 : /* Method-MOR */
4948                                 value = tvb_get_guint8(tvb, offset);
4949                                 proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_method_MOR, tvb, capabilitiesStart, length+1, value);
4950                                 break;
4951                         case 0x04 : /* Push-MOR */
4952                                 value = tvb_get_guint8(tvb, offset);
4953                                 proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_push_MOR, tvb, capabilitiesStart, length+1, value);
4954                                 break;
4955                                 break;
4956                         case 0x05 : /* Extended Methods */
4957                                 offsetStr = offset;
4958                                 offset++;
4959                                 add_capability_vals(tvb, (type == WSP_PDU_CONNECT),
4960                                     offsetStr, length, capabilitiesStart,
4961                                     valString, sizeof valString);
4962                                 proto_tree_add_string(wsp_capabilities, hf_wsp_capabilities_extended_methods, tvb, capabilitiesStart, length+1, valString);
4963                                 break;
4964                         case 0x06 : /* Header Code Pages */
4965                                 offsetStr = offset;
4966                                 offset++;
4967                                 add_capability_vals(tvb, (type == WSP_PDU_CONNECT),
4968                                     offsetStr, length, capabilitiesStart,
4969                                     valString, sizeof valString);
4970                                 proto_tree_add_string(wsp_capabilities, hf_wsp_capabilities_header_code_pages, tvb, capabilitiesStart, length+1, valString);
4971                                 break;
4972                         case 0x07 : /* Aliases */
4973                                 break;
4974                         default:
4975                                 proto_tree_add_text (wsp_capabilities, tvb , capabilitiesStart, length+1,
4976                                        "Undecoded Header (0x%02X)", peek & 0x7F);
4977                                 break;
4978                 }
4979                 offset=capabilitiesStart+length+1;
4980         }
4981 }
4982
4983 static void
4984 add_capability_vals(tvbuff_t *tvb, gboolean add_string, int offsetStr,
4985     guint length, guint capabilitiesStart, char *valString,
4986     size_t valStringSize)
4987 {
4988         guint i;
4989         int ret;
4990         guint value;
4991         guint8 c;
4992
4993         i = 0;
4994         while ((offsetStr-capabilitiesStart) <= length)
4995         {
4996                 value = tvb_get_guint8(tvb, offsetStr);
4997                 if (i >= valStringSize) {
4998                         /* No more room. */
4999                         break;
5000                 }
5001                 if (add_string)
5002                 {
5003                         ret = snprintf(valString+i,valStringSize-i,
5004                             "(0x%02x - ",value);
5005                 }
5006                 else
5007                 {
5008                         ret = snprintf(valString+i,valStringSize-i,"(0x%02x) ",
5009                             value);
5010                 }
5011                 if (ret == -1 || (unsigned int) ret >= valStringSize-i) {
5012                         /*
5013                          * We've been truncated.
5014                          */
5015                         break;
5016                 }
5017                 i += ret;
5018                 offsetStr++;
5019                 if (add_string)
5020                 {
5021                         for (;(c = tvb_get_guint8(tvb, offsetStr))
5022                             && i < valStringSize - 1; i++,offsetStr++)
5023                                 valString[i] = c;
5024                         offsetStr++;
5025                         if (i < valStringSize - 2) {
5026                                 valString[i++] = ')';
5027                                 valString[i++] = ' ';
5028                         }
5029                 }
5030         }
5031         valString[i] = '\0';
5032 }
5033
5034
5035 static guint
5036 get_uintvar (tvbuff_t *tvb, guint offset, guint offsetEnd)
5037 {
5038         guint value = 0;
5039         guint octet;
5040
5041         do
5042         {
5043                 octet = tvb_get_guint8 (tvb, offset);
5044                 offset++;
5045                 value <<= 7;
5046                 value += octet & 0x7f;
5047         }
5048         while ((offsetEnd > offset) && (octet & 0x80));
5049         return value;
5050 }
5051
5052
5053 void
5054 add_post_data (proto_tree *tree, tvbuff_t *tvb, guint contentType,
5055     const char *contentTypeStr)
5056 {
5057         guint offset = 0;
5058         guint variableStart = 0;
5059         guint variableEnd = 0;
5060         guint valueStart = 0;
5061         guint valueEnd = 0;
5062         guint8 peek = 0;
5063         proto_item *ti;
5064         proto_tree *sub_tree;
5065
5066         /* VERIFY ti = proto_tree_add_item (tree, hf_wsp_post_data,tvb,offset,-1,bo_little_endian); */
5067         ti = proto_tree_add_item (tree, hf_wsp_post_data,tvb,offset,-1,bo_little_endian);
5068         sub_tree = proto_item_add_subtree(ti, ett_post);
5069
5070         if ( (contentTypeStr == NULL && contentType == 0x12) 
5071                         || (contentTypeStr && (strcasecmp(contentTypeStr,
5072                                                 "application/x-www-form-urlencoded") == 0)) )
5073         {
5074                 /*
5075                  * URL Encoded data.
5076                  * Iterate through post data.
5077                  */
5078                 for (offset = 0; offset < tvb_reported_length (tvb); offset++)
5079                 {
5080                         peek = tvb_get_guint8 (tvb, offset);
5081                         if (peek == '=')
5082                         {
5083                                 variableEnd = offset;
5084                                 valueStart = offset+1;
5085                         }
5086                         else if (peek == '&')
5087                         {
5088                                 if (variableEnd > 0)
5089                                 {
5090                                         add_post_variable (sub_tree, tvb, variableStart, variableEnd, valueStart, offset);
5091                                 }
5092                                 variableStart = offset+1;
5093                                 variableEnd = 0;
5094                                 valueStart = 0;
5095                                 valueEnd = 0;
5096                         }
5097                 }
5098
5099                 /* See if there's outstanding data */
5100                 if (variableEnd > 0)
5101                 {
5102                         add_post_variable (sub_tree, tvb, variableStart, variableEnd, valueStart, offset);
5103                 }
5104         }
5105         else if ((contentType == 0x22) || (contentType == 0x23) || (contentType == 0x24) ||
5106                  (contentType == 0x25) || (contentType == 0x26) || (contentType == 0x33))
5107         {
5108                 add_multipart_data(sub_tree, tvb);
5109         }
5110 }
5111
5112 static void
5113 add_post_variable (proto_tree *tree, tvbuff_t *tvb, guint variableStart, guint variableEnd, guint valueStart, guint valueEnd)
5114 {
5115         int variableLength = variableEnd-variableStart;
5116         int valueLength = 0;
5117         char *variableBuffer;
5118         char *valueBuffer;
5119
5120         variableBuffer = g_malloc (variableLength+1);
5121         strncpy (variableBuffer, tvb_get_ptr (tvb, variableStart, variableLength), variableLength);
5122         variableBuffer[variableLength] = 0;
5123
5124         if (valueEnd < valueStart)
5125         {
5126                 valueBuffer = g_malloc (1);
5127                 valueBuffer[0] = 0;
5128                 valueEnd = valueStart;
5129         }
5130         else
5131         {
5132                 valueLength = valueEnd-valueStart;
5133                 valueBuffer = g_malloc (valueLength+1);
5134                 strncpy (valueBuffer, tvb_get_ptr (tvb, valueStart, valueLength), valueLength);
5135                 valueBuffer[valueLength] = 0;
5136         }
5137
5138         /* Check for variables with no value */
5139         if (valueStart >= tvb_reported_length (tvb))
5140         {
5141                 valueStart = tvb_reported_length (tvb);
5142                 valueEnd = valueStart;
5143         }
5144         valueLength = valueEnd-valueStart;
5145
5146         proto_tree_add_text (tree, tvb, variableStart, valueEnd-variableStart, "%s: %s", variableBuffer, valueBuffer);
5147
5148         g_free (variableBuffer);
5149         g_free (valueBuffer);
5150 }
5151
5152 static void
5153 add_multipart_data (proto_tree *tree, tvbuff_t *tvb)
5154 {
5155         int              offset = 0;
5156         guint            nextOffset;
5157         guint            nEntries = 0;
5158         guint            count;
5159         guint            HeadersLen;
5160         guint            DataLen;
5161         guint            contentType = 0;
5162         const char      *contentTypeStr;
5163         tvbuff_t        *tmp_tvb;
5164         int              partnr = 1;
5165         int              part_start;
5166
5167         proto_item      *sub_tree = NULL,
5168                         *ti;
5169         proto_tree      *mpart_tree;
5170
5171 #ifdef DEBUG
5172         printf("DBG: public: add_multipart_data: (offset = %u, 0x%02x): ", offset, tvb_get_guint8(tvb,offset));
5173 #endif
5174         nEntries = tvb_get_guintvar (tvb, offset, &count);
5175 #ifdef DEBUG
5176         printf("parts = %u\n", nEntries);
5177 #endif
5178         offset += count;
5179         if (nEntries)
5180         {
5181                 sub_tree = proto_tree_add_text(tree, tvb, offset - count, 0,
5182                                         "Multipart body");
5183                 proto_item_add_subtree(sub_tree, ett_mpartlist);
5184         }
5185         while (nEntries--)
5186         {
5187 #ifdef DEBUG
5188                 printf("DBG: add_multipart_data: Parts to do after this: %u"
5189                                 " (offset = %u, 0x%02x): ",
5190                                 nEntries, offset, tvb_get_guint8(tvb,offset));
5191 #endif
5192                 part_start = offset;
5193                 HeadersLen = tvb_get_guintvar (tvb, offset, &count);
5194                 offset += count;
5195                 DataLen = tvb_get_guintvar (tvb, offset, &count);
5196                 offset += count;
5197                 ti = proto_tree_add_uint(sub_tree, hf_wsp_mpart, tvb, part_start,
5198                                         HeadersLen + DataLen + (offset - part_start), partnr);
5199                 mpart_tree = proto_item_add_subtree(ti, ett_multiparts);
5200                 nextOffset = add_content_type (mpart_tree, tvb, offset, &contentType, &contentTypeStr);
5201                 HeadersLen -= (nextOffset - offset);
5202                 if (HeadersLen > 0)
5203                 {
5204                         tmp_tvb = tvb_new_subset (tvb, nextOffset, HeadersLen, HeadersLen);
5205                         add_headers (mpart_tree, tmp_tvb);
5206                 }
5207                 offset = nextOffset + HeadersLen;
5208                 /* TODO - Try the dissectors of the multipart content */
5209                 proto_tree_add_item (mpart_tree, hf_wsp_multipart_data, tvb, offset, DataLen, bo_little_endian);
5210                 offset += DataLen;
5211                 partnr++;
5212         }
5213 }
5214
5215
5216 /* Register the protocol with Ethereal */
5217 void
5218 proto_register_wsp(void)
5219 {
5220
5221 /* Setup list of header fields */
5222         static hf_register_info hf[] = {
5223                 { &hf_wsp_header_tid,
5224                         {       "Transaction ID",
5225                                 "wsp.TID",
5226                                  FT_UINT8, BASE_HEX, NULL, 0x00,
5227                                 "Transaction ID", HFILL
5228                         }
5229                 },
5230                 { &hf_wsp_header_pdu_type,
5231                         {       "PDU Type",
5232                                 "wsp.pdu_type",
5233                                  FT_UINT8, BASE_HEX, VALS( vals_pdu_type ), 0x00,
5234                                 "PDU Type", HFILL
5235                         }
5236                 },
5237                 { &hf_wsp_version_major,
5238                         {       "Version (Major)",
5239                                 "wsp.version.major",
5240                                  FT_UINT8, BASE_DEC, NULL, 0xF0,
5241                                 "Version (Major)", HFILL
5242                         }
5243                 },
5244                 { &hf_wsp_version_minor,
5245                         {       "Version (Minor)",
5246                                 "wsp.version.minor",
5247                                  FT_UINT8, BASE_DEC, NULL, 0x0F,
5248                                 "Version (Minor)", HFILL
5249                         }
5250                 },
5251                 { &hf_wsp_capability_length,
5252                         {       "Capability Length",
5253                                 "wsp.capability.length",
5254                                  FT_UINT32, BASE_DEC, NULL, 0x00,
5255                                 "Capability Length", HFILL
5256                         }
5257                 },
5258                 { &hf_wsp_header_length,
5259                         {       "Headers Length",
5260                                 "wsp.headers_length",
5261                                  FT_UINT32, BASE_DEC, NULL, 0x00,
5262                                 "Headers Length", HFILL
5263                         }
5264                 },
5265                 { &hf_wsp_capabilities_section,
5266                         {       "Capabilities",
5267                                 "wsp.capabilities",
5268                                  FT_NONE, BASE_DEC, NULL, 0x00,
5269                                 "Capabilities", HFILL
5270                         }
5271                 },
5272                 { &hf_wsp_headers_section,
5273                         {       "Headers",
5274                                 "wsp.headers",
5275                                  FT_NONE, BASE_DEC, NULL, 0x00,
5276                                 "Headers", HFILL
5277                         }
5278                 },
5279                 { &hf_wsp_header,
5280                         {       "Header",
5281                                 "wsp.headers.header",
5282                                  FT_NONE, BASE_DEC, NULL, 0x00,
5283                                 "Header", HFILL
5284                         }
5285                 },
5286                 { &hf_wsp_header_uri_len,
5287                         {       "URI Length",
5288                                 "wsp.uri_length",
5289                                  FT_UINT32, BASE_DEC, NULL, 0x00,
5290                                 "URI Length", HFILL
5291                         }
5292                 },
5293                 { &hf_wsp_header_uri,
5294                         {       "URI",
5295                                 "wsp.uri",
5296                                  FT_STRING, BASE_NONE, NULL, 0x00,
5297                                 "URI", HFILL
5298                         }
5299                 },
5300                 { &hf_wsp_server_session_id,
5301                         {       "Server Session ID",
5302                                 "wsp.server.session_id",
5303                                  FT_UINT32, BASE_DEC, NULL, 0x00,
5304                                 "Server Session ID", HFILL
5305                         }
5306                 },
5307                 { &hf_wsp_header_status,
5308                         {       "Status",
5309                                 "wsp.reply.status",
5310                                  FT_UINT8, BASE_HEX, VALS( vals_status ), 0x00,
5311                                 "Status", HFILL
5312                         }
5313                 },
5314                 { &hf_wsp_content_type,
5315                         {       "Content Type",
5316                                 "wsp.content_type.type",
5317                                  FT_UINT8, BASE_HEX, VALS ( vals_content_types ), 0x00,
5318                                 "Content Type", HFILL
5319                         }
5320                 },
5321                 { &hf_wsp_content_type_str,
5322                         {       "Content Type",
5323                                 "wsp.content_type.type.string",
5324                                  FT_STRING, BASE_NONE, NULL, 0x00,
5325                                 "Content Type", HFILL
5326                         }
5327                 },
5328                 { &hf_wsp_parameter_well_known_charset,
5329                         {       "Charset",
5330                                 "wsp.parameter.charset",
5331                                  FT_UINT16, BASE_HEX, VALS ( vals_character_sets ), 0x00,
5332                                 "Charset", HFILL
5333                         }
5334                 },
5335                 { &hf_wsp_parameter_type,
5336                         {       "Type",
5337                                 "wsp.parameter.type",
5338                                  FT_UINT32, BASE_DEC, NULL, 0x00,
5339                                 "Type", HFILL
5340                         }
5341                 },
5342                 { &hf_wsp_parameter_name,
5343                         {       "Name",
5344                                 "wsp.parameter.name",
5345                                  FT_STRING, BASE_NONE, NULL, 0x00,
5346                                 "Name", HFILL
5347                         }
5348                 },
5349                 { &hf_wsp_parameter_filename,
5350                         {       "Filename",
5351                                 "wsp.parameter.filename",
5352                                  FT_STRING, BASE_NONE, NULL, 0x00,
5353                                 "Filename", HFILL
5354                         }
5355                 },
5356                 { &hf_wsp_parameter_start,
5357                         {       "Start",
5358                                 "wsp.parameter.start",
5359                                  FT_STRING, BASE_NONE, NULL, 0x00,
5360                                 "Start", HFILL
5361                         }
5362                 },
5363                 { &hf_wsp_parameter_start_info,
5364                         {       "Start-info",
5365                                 "wsp.parameter.start_info",
5366                                  FT_STRING, BASE_NONE, NULL, 0x00,
5367                                 "Start-info", HFILL
5368                         }
5369                 },
5370                 { &hf_wsp_parameter_comment,
5371                         {       "Comment",
5372                                 "wsp.parameter.comment",
5373                                  FT_STRING, BASE_NONE, NULL, 0x00,
5374                                 "Comment", HFILL
5375                         }
5376                 },
5377                 { &hf_wsp_parameter_domain,
5378                         {       "Domain",
5379                                 "wsp.parameter.domain",
5380                                  FT_STRING, BASE_NONE, NULL, 0x00,
5381                                 "Domain", HFILL
5382                         }
5383                 },
5384                 { &hf_wsp_parameter_path,
5385                         {       "Path",
5386                                 "wsp.parameter.path",
5387                                  FT_STRING, BASE_NONE, NULL, 0x00,
5388                                 "Path", HFILL
5389                         }
5390                 },
5391                 { &hf_wsp_parameter_sec,
5392                         {       "SEC",
5393                                 "wsp.parameter.sec",
5394                                  FT_UINT8, BASE_HEX, VALS (vals_wsp_parameter_sec), 0x00,
5395                                 "SEC parameter (Content-Type: application/vnd.wap.connectivity-wbxml)", HFILL
5396                         }
5397                 },
5398                 { &hf_wsp_parameter_mac,
5399                         {       "MAC",
5400                                 "wsp.parameter.mac",
5401                                  FT_STRING, BASE_NONE, NULL, 0x00,
5402                                 "MAC parameter (Content-Type: application/vnd.wap.connectivity-wbxml)", HFILL
5403                         }
5404                 },
5405                 { &hf_wsp_parameter_upart_type,
5406                         {       "Type",
5407                                 "wsp.parameter.upart.type",
5408                                  FT_STRING, BASE_NONE, NULL, 0x00,
5409                                 "Multipart type", HFILL
5410                         }
5411                 },
5412                 { &hf_wsp_parameter_upart_type_value,
5413                         {       "Type",
5414                                 "wsp.parameter.upart.type.int",
5415                                  FT_UINT8, BASE_DEC, NULL, 0x00,
5416                                 "Multipart type (int value)", HFILL
5417                         }
5418                 },
5419                 { &hf_wsp_parameter_level,
5420                         {       "Level",
5421                                 "wsp.parameter.level",
5422                                  FT_STRING, BASE_NONE, NULL, 0x00,
5423                                 "Level parameter", HFILL
5424                         }
5425                 },
5426                 { &hf_wsp_reply_data,
5427                         {       "Data",
5428                                 "wsp.reply.data",
5429                                  FT_NONE, BASE_NONE, NULL, 0x00,
5430                                 "Data", HFILL
5431                         }
5432                 },
5433                 { &hf_wsp_header_shift_code,
5434                         {       "Switching to WSP header code-page",
5435                                 "wsp.code_page",
5436                                  FT_UINT8, BASE_DEC, NULL, 0x00,
5437                                 "Header code-page shift code", HFILL
5438                         }
5439                 },
5440                 /*
5441                  * CO-WSP capability negotiation
5442                  */
5443                 { &hf_wsp_capabilities_client_SDU,
5444                         {       "Client SDU",
5445                                 "wsp.capabilities.client_SDU",
5446                                  FT_UINT8, BASE_DEC, NULL, 0x00,
5447                                 "Client SDU", HFILL
5448                         }
5449                 },
5450                 { &hf_wsp_capabilities_server_SDU,
5451                         {       "Server SDU",
5452                                 "wsp.capabilities.server_SDU",
5453                                  FT_UINT8, BASE_DEC, NULL, 0x00,
5454                                 "Server SDU", HFILL
5455                         }
5456                 },
5457                 { &hf_wsp_capabilities_protocol_opt,
5458                         {       "Protocol Options",
5459                                 "wsp.capabilities.protocol_opt",
5460                                  FT_STRING, BASE_HEX, NULL, 0x00,
5461                                 "Protocol Options", HFILL
5462                         }
5463                 },
5464                 { &hf_wsp_capabilities_method_MOR,
5465                         {       "Method MOR",
5466                                 "wsp.capabilities.method_mor",
5467                                  FT_UINT8, BASE_DEC, NULL, 0x00,
5468                                 "Method MOR", HFILL
5469                         }
5470                 },
5471                 { &hf_wsp_capabilities_push_MOR,
5472                         {       "Push MOR",
5473                                 "wsp.capabilities.push_mor",
5474                                  FT_UINT8, BASE_DEC, NULL, 0x00,
5475                                 "Push MOR", HFILL
5476                         }
5477                 },
5478                 { &hf_wsp_capabilities_extended_methods,
5479                         {       "Extended Methods",
5480                                 "wsp.capabilities.extend_methods",
5481                                  FT_STRING, BASE_HEX, NULL, 0x00,
5482                                 "Extended Methods", HFILL
5483                         }
5484                 },
5485                 { &hf_wsp_capabilities_header_code_pages,
5486                         {       "Header Code Pages",
5487                                 "wsp.capabilities.code_pages",
5488                                  FT_STRING, BASE_HEX, NULL, 0x00,
5489                                 "Header Code Pages", HFILL
5490                         }
5491                 },
5492                 { &hf_wsp_capabilities_aliases,
5493                         {       "Aliases",
5494                                 "wsp.capabilities.aliases",
5495                                  FT_UINT8, BASE_HEX, NULL, 0x00,
5496                                 "Aliases", HFILL
5497                         }
5498                 },
5499                 { &hf_wsp_post_data,
5500                         {       "Data (Post)",
5501                                 "wsp.post.data",
5502                                  FT_NONE, BASE_NONE, NULL, 0x00,
5503                                 "Post Data", HFILL
5504                         }
5505                 },
5506                 { &hf_wsp_push_data,
5507                         {       "Push Data",
5508                                 "wsp.push.data",
5509                                  FT_NONE, BASE_NONE, NULL, 0x00,
5510                                 "Push Data", HFILL
5511                         }
5512                 },
5513                 { &hf_wsp_multipart_data,
5514                         {       "Data in this part",
5515                                 "wsp.multipart.data",
5516                                  FT_NONE, BASE_NONE, NULL, 0x00,
5517                                 "The data of 1 MIME-multipart part.", HFILL
5518                         }
5519                 },
5520                 { &hf_wsp_mpart,
5521                         {       "Part",
5522                                 "wsp.multipart",
5523                                  FT_UINT32, BASE_DEC, NULL, 0x00,
5524                                 "MIME part of multipart data.", HFILL
5525                         }
5526                 },
5527                 { &hf_wsp_redirect_flags,
5528                         {       "Flags",
5529                                 "wsp.redirect_flags",
5530                                  FT_UINT8, BASE_HEX, NULL, 0x00,
5531                                 "Redirect Flags", HFILL
5532                         }
5533                 },
5534                 { &hf_wsp_redirect_permanent,
5535                         {       "Permanent Redirect",
5536                                 "wsp.redirect_flags.permanent",
5537                                  FT_BOOLEAN, 8, TFS(&yes_no_truth), PERMANENT_REDIRECT,
5538                                 "Permanent Redirect", HFILL
5539                         }
5540                 },
5541                 { &hf_wsp_redirect_reuse_security_session,
5542                         {       "Reuse Security Session",
5543                                 "wsp.redirect_flags.reuse_security_session",
5544                                  FT_BOOLEAN, 8, TFS(&yes_no_truth), REUSE_SECURITY_SESSION,
5545                                 "Permanent Redirect", HFILL
5546                         }
5547                 },
5548                 { &hf_wsp_redirect_afl,
5549                         {       "Flags/Length",
5550                                 "wsp.redirect_afl",
5551                                  FT_UINT8, BASE_HEX, NULL, 0x00,
5552                                 "Redirect Address Flags/Length", HFILL
5553                         }
5554                 },
5555                 { &hf_wsp_redirect_afl_bearer_type_included,
5556                         {       "Bearer Type Included",
5557                                 "wsp.redirect_afl.bearer_type_included",
5558                                  FT_BOOLEAN, 8, TFS(&yes_no_truth), BEARER_TYPE_INCLUDED,
5559                                 "Redirect Address bearer type included", HFILL
5560                         }
5561                 },
5562                 { &hf_wsp_redirect_afl_port_number_included,
5563                         {       "Port Number Included",
5564                                 "wsp.redirect_afl.port_number_included",
5565                                  FT_BOOLEAN, 8, TFS(&yes_no_truth), PORT_NUMBER_INCLUDED,
5566                                 "Redirect Address port number included", HFILL
5567                         }
5568                 },
5569                 { &hf_wsp_redirect_afl_address_len,
5570                         {       "Address Len",
5571                                 "wsp.redirect_afl.address_len",
5572                                  FT_UINT8, BASE_DEC, NULL, ADDRESS_LEN,
5573                                 "Redirect Address Length", HFILL
5574                         }
5575                 },
5576                 { &hf_wsp_redirect_bearer_type,
5577                         {       "Bearer Type",
5578                                 "wsp.redirect_bearer_type",
5579                                  FT_UINT8, BASE_HEX, VALS(vals_bearer_types), 0x0,
5580                                 "Redirect Bearer Type", HFILL
5581                         }
5582                 },
5583                 { &hf_wsp_redirect_port_num,
5584                         {       "Port Number",
5585                                 "wsp.redirect_port_num",
5586                                  FT_UINT16, BASE_DEC, NULL, 0x0,
5587                                 "Redirect Port Number", HFILL
5588                         }
5589                 },
5590                 { &hf_wsp_redirect_ipv4_addr,
5591                         {       "IP Address",
5592                                 "wsp.redirect_ipv4_addr",
5593                                  FT_IPv4, BASE_NONE, NULL, 0x0,
5594                                 "Redirect Address (IP)", HFILL
5595                         }
5596                 },
5597                 { &hf_wsp_redirect_ipv6_addr,
5598                         {       "IPv6 Address",
5599                                 "wsp.redirect_ipv6_addr",
5600                                  FT_IPv6, BASE_NONE, NULL, 0x0,
5601                                 "Redirect Address (IPv6)", HFILL
5602                         }
5603                 },
5604                 { &hf_wsp_redirect_addr,
5605                         {       "Address",
5606                                 "wsp.redirect_addr",
5607                                  FT_BYTES, BASE_NONE, NULL, 0x0,
5608                                 "Redirect Address", HFILL
5609                         }
5610                 },
5611
5612
5613                 /*
5614                  * New WSP header fields
5615                  */
5616
5617
5618                 /* WSP header name */
5619                 { &hf_hdr_name,
5620                         {       "Header name",
5621                                 "wsp.header.name",
5622                                 FT_STRING, BASE_NONE, NULL, 0x00,
5623                                 "Name of the WSP header", HFILL
5624                         }
5625                 },
5626                 /* WSP well-known header ID */
5627                 { &hf_hdr_id,
5628                         {       "Header well-known ID",
5629                                 "wsp.header.id",
5630                                 FT_STRING, BASE_NONE, NULL, 0x00,
5631                                 "7-bit identifier of a well-known WSP header", HFILL
5632                         }
5633                 },
5634                 /* WSP headers start here */
5635                 { &hf_hdr_accept,
5636                         {       "Accept",
5637                                 "wsp.hdr.accept",
5638                                 FT_STRING, BASE_NONE, NULL, 0x00,
5639                                 "WSP header Accept", HFILL
5640                         }
5641                 },
5642                 { &hf_hdr_accept_charset,
5643                         {       "Accept-Charset",
5644                                 "wsp.hdr.accept_charset",
5645                                 FT_STRING, BASE_NONE, NULL, 0x00,
5646                                 "WSP header Accept-Charset", HFILL
5647                         }
5648                 },
5649                 { &hf_hdr_accept_encoding,
5650                         {       "Accept-Encoding",
5651                                 "wsp.hdr.accept_encoding",
5652                                 FT_STRING, BASE_NONE, NULL, 0x00,
5653                                 "WSP header Accept-Encoding", HFILL
5654                         }
5655                 },
5656                 { &hf_hdr_accept_language,
5657                         {       "Accept-Language",
5658                                 "wsp.hdr.accept_language",
5659                                 FT_STRING, BASE_NONE, NULL, 0x00,
5660                                 "WSP header Accept-Language", HFILL
5661                         }
5662                 },
5663                 { &hf_hdr_accept_ranges,
5664                         {       "Accept-Ranges",
5665                                 "wsp.hdr.accept_ranges",
5666                                 FT_STRING, BASE_NONE, NULL, 0x00,
5667                                 "WSP header Accept-Ranges", HFILL
5668                         }
5669                 },
5670                 { &hf_hdr_age,
5671                         {       "Age",
5672                                 "wsp.hdr.age",
5673                                 FT_STRING, BASE_NONE, NULL, 0x00,
5674                                 "WSP header Age", HFILL
5675                         }
5676                 },
5677                 { &hf_hdr_allow,
5678                         {       "Allow",
5679                                 "wsp.hdr.allow",
5680                                 FT_STRING, BASE_NONE, NULL, 0x00,
5681                                 "WSP header Allow", HFILL
5682                         }
5683                 },
5684                 { &hf_hdr_authorization,
5685                         {       "Authorization",
5686                                 "wsp.hdr.authorization",
5687                                 FT_STRING, BASE_NONE, NULL, 0x00,
5688                                 "WSP header Authorization", HFILL
5689                         }
5690                 },
5691                 { &hf_hdr_authorization_scheme,
5692                         {       "Authorization Scheme",
5693                                 "wsp.hdr.authorization.scheme",
5694                                 FT_STRING, BASE_NONE, NULL, 0x00,
5695                                 "WSP header Authorization: used scheme", HFILL
5696                         }
5697                 },
5698                 { &hf_hdr_authorization_user_id,
5699                         {       "User-id",
5700                                 "wsp.hdr.authorization.user_id",
5701                                 FT_STRING, BASE_NONE, NULL, 0x00,
5702                                 "WSP header Authorization: user ID for basic authorization", HFILL
5703                         }
5704                 },
5705                 { &hf_hdr_authorization_password,
5706                         {       "Password",
5707                                 "wsp.hdr.authorization.password",
5708                                 FT_STRING, BASE_NONE, NULL, 0x00,
5709                                 "WSP header Authorization: password for basic authorization", HFILL
5710                         }
5711                 },
5712                 { &hf_hdr_cache_control,
5713                         {       "Cache-Control",
5714                                 "wsp.hdr.cache_control",
5715                                 FT_STRING, BASE_NONE, NULL, 0x00,
5716                                 "WSP header Cache-Control", HFILL
5717                         }
5718                 },
5719                 { &hf_hdr_connection,
5720                         {       "Connection",
5721                                 "wsp.hdr.connection",
5722                                 FT_STRING, BASE_NONE, NULL, 0x00,
5723                                 "WSP header Connection", HFILL
5724                         }
5725                 },
5726                 { &hf_hdr_content_base,
5727                         {       "Content-Base",
5728                                 "wsp.hdr.content_base",
5729                                 FT_STRING, BASE_NONE, NULL, 0x00,
5730                                 "WSP header Content-Base", HFILL
5731                         }
5732                 },
5733                 { &hf_hdr_content_encoding,
5734                         {       "Content-Encoding",
5735                                 "wsp.hdr.content_encoding",
5736                                 FT_STRING, BASE_NONE, NULL, 0x00,
5737                                 "WSP header Content-Encoding", HFILL
5738                         }
5739                 },
5740                 { &hf_hdr_content_language,
5741                         {       "Content-Language",
5742                                 "wsp.hdr.content_language",
5743                                 FT_STRING, BASE_NONE, NULL, 0x00,
5744                                 "WSP header Content-Language", HFILL
5745                         }
5746                 },
5747                 { &hf_hdr_content_length,
5748                         {       "Content-Length",
5749                                 "wsp.hdr.content_length",
5750                                 FT_STRING, BASE_NONE, NULL, 0x00,
5751                                 "WSP header Content-Length", HFILL
5752                         }
5753                 },
5754                 { &hf_hdr_content_location,
5755                         {       "Content-Location",
5756                                 "wsp.hdr.content_location",
5757                                 FT_STRING, BASE_NONE, NULL, 0x00,
5758                                 "WSP header Content-Location", HFILL
5759                         }
5760                 },
5761                 { &hf_hdr_content_md5,
5762                         {       "Content-Md5",
5763                                 "wsp.hdr.content_md5",
5764                                 FT_STRING, BASE_NONE, NULL, 0x00,
5765                                 "WSP header Content-Md5", HFILL
5766                         }
5767                 },
5768                 { &hf_hdr_content_range,
5769                         {       "Content-Range",
5770                                 "wsp.hdr.content_range",
5771                                 FT_STRING, BASE_NONE, NULL, 0x00,
5772                                 "WSP header Content-Range", HFILL
5773                         }
5774                 },
5775                 { &hf_hdr_content_range_first_byte_pos,
5776                         {       "First-byte-position",
5777                                 "wsp.hdr.content_range.first_byte_pos",
5778                                 FT_UINT32, BASE_DEC, NULL, 0x00,
5779                                 "WSP header Content-Range: position of first byte", HFILL
5780                         }
5781                 },
5782                 { &hf_hdr_content_range_entity_length,
5783                         {       "Entity-length",
5784                                 "wsp.hdr.content_range.entity_length",
5785                                 FT_UINT32, BASE_DEC, NULL, 0x00,
5786                                 "WSP header Content-Range: length of the entity", HFILL
5787                         }
5788                 },
5789                 { &hf_hdr_content_type,
5790                         {       "Content-Type",
5791                                 "wsp.hdr.content_type",
5792                                 FT_STRING, BASE_NONE, NULL, 0x00,
5793                                 "WSP header Content-Type", HFILL
5794                         }
5795                 },
5796                 { &hf_hdr_date,
5797                         {       "Date",
5798                                 "wsp.hdr.date",
5799                                 FT_STRING, BASE_NONE, NULL, 0x00,
5800                                 "WSP header Date", HFILL
5801                         }
5802                 },
5803                 { &hf_hdr_etag,
5804                         {       "ETag",
5805                                 "wsp.hdr.etag",
5806                                 FT_STRING, BASE_NONE, NULL, 0x00,
5807                                 "WSP header ETag", HFILL
5808                         }
5809                 },
5810                 { &hf_hdr_expires,
5811                         {       "Expires",
5812                                 "wsp.hdr.expires",
5813                                 FT_STRING, BASE_NONE, NULL, 0x00,
5814                                 "WSP header Expires", HFILL
5815                         }
5816                 },
5817                 { &hf_hdr_from,
5818                         {       "From",
5819                                 "wsp.hdr.from",
5820                                 FT_STRING, BASE_NONE, NULL, 0x00,
5821                                 "WSP header From", HFILL
5822                         }
5823                 },
5824                 { &hf_hdr_host,
5825                         {       "Host",
5826                                 "wsp.hdr.host",
5827                                 FT_STRING, BASE_NONE, NULL, 0x00,
5828                                 "WSP header Host", HFILL
5829                         }
5830                 },
5831                 { &hf_hdr_if_modified_since,
5832                         {       "If-Modified-Since",
5833                                 "wsp.hdr.if_modified_since",
5834                                 FT_STRING, BASE_NONE, NULL, 0x00,
5835                                 "WSP header If-Modified-Since", HFILL
5836                         }
5837                 },
5838                 { &hf_hdr_if_match,
5839                         {       "If-Match",
5840                                 "wsp.hdr.if_match",
5841                                 FT_STRING, BASE_NONE, NULL, 0x00,
5842                                 "WSP header If-Match", HFILL
5843                         }
5844                 },
5845                 { &hf_hdr_if_none_match,
5846                         {       "If-None-Match",
5847                                 "wsp.hdr.if_none_match",
5848                                 FT_STRING, BASE_NONE, NULL, 0x00,
5849                                 "WSP header If-None-Match", HFILL
5850                         }
5851                 },
5852                 { &hf_hdr_if_range,
5853                         {       "If-Range",
5854                                 "wsp.hdr.if_range",
5855                                 FT_STRING, BASE_NONE, NULL, 0x00,
5856                                 "WSP header If-Range", HFILL
5857                         }
5858                 },
5859                 { &hf_hdr_if_unmodified_since,
5860                         {       "If-Unmodified-Since",
5861                                 "wsp.hdr.if_unmodified_since",
5862                                 FT_STRING, BASE_NONE, NULL, 0x00,
5863                                 "WSP header If-Unmodified-Since", HFILL
5864                         }
5865                 },
5866                 { &hf_hdr_last_modified,
5867                         {       "Last-Modified",
5868                                 "wsp.hdr.last_modified",
5869                                 FT_STRING, BASE_NONE, NULL, 0x00,
5870                                 "WSP header Last-Modified", HFILL
5871                         }
5872                 },
5873                 { &hf_hdr_location,
5874                         {       "Location",
5875                                 "wsp.hdr.location",
5876                                 FT_STRING, BASE_NONE, NULL, 0x00,
5877                                 "WSP header Location", HFILL
5878                         }
5879                 },
5880                 { &hf_hdr_max_forwards,
5881                         {       "Max-Forwards",
5882                                 "wsp.hdr.max_forwards",
5883                                 FT_STRING, BASE_NONE, NULL, 0x00,
5884                                 "WSP header Max-Forwards", HFILL
5885                         }
5886                 },
5887                 { &hf_hdr_pragma,
5888                         {       "Pragma",
5889                                 "wsp.hdr.pragma",
5890                                 FT_STRING, BASE_NONE, NULL, 0x00,
5891                                 "WSP header Pragma", HFILL
5892                         }
5893                 },
5894                 { &hf_hdr_proxy_authenticate,
5895                         {       "Proxy-Authenticate",
5896                                 "wsp.hdr.proxy_authenticate",
5897                                 FT_STRING, BASE_NONE, NULL, 0x00,
5898                                 "WSP header Proxy-Authenticate", HFILL
5899                         }
5900                 },
5901                 { &hf_hdr_proxy_authenticate_scheme,
5902                         {       "Authentication Scheme",
5903                                 "wsp.hdr.proxy_authenticate.scheme",
5904                                 FT_STRING, BASE_NONE, NULL, 0x00,
5905                                 "WSP header Proxy-Authenticate: used scheme", HFILL
5906                         }
5907                 },
5908                 { &hf_hdr_proxy_authenticate_realm,
5909                         {       "Authentication Realm",
5910                                 "wsp.hdr.proxy_authenticate.realm",
5911                                 FT_STRING, BASE_NONE, NULL, 0x00,
5912                                 "WSP header Proxy-Authenticate: used realm", HFILL
5913                         }
5914                 },
5915                 { &hf_hdr_proxy_authorization,
5916                         {       "Proxy-Authorization",
5917                                 "wsp.hdr.proxy_authorization",
5918                                 FT_STRING, BASE_NONE, NULL, 0x00,
5919                                 "WSP header Proxy-Authorization", HFILL
5920                         }
5921                 },
5922                 { &hf_hdr_proxy_authorization_scheme,
5923                         {       "Authorization Scheme",
5924                                 "wsp.hdr.proxy_authorization.scheme",
5925                                 FT_STRING, BASE_NONE, NULL, 0x00,
5926                                 "WSP header Proxy-Authorization: used scheme", HFILL
5927                         }
5928                 },
5929                 { &hf_hdr_proxy_authorization_user_id,
5930                         {       "User-id",
5931                                 "wsp.hdr.proxy_authorization.user_id",
5932                                 FT_STRING, BASE_NONE, NULL, 0x00,
5933                                 "WSP header Proxy-Authorization: user ID for basic authorization", HFILL
5934                         }
5935                 },
5936                 { &hf_hdr_proxy_authorization_password,
5937                         {       "Password",
5938                                 "wsp.hdr.proxy_authorization.password",
5939                                 FT_STRING, BASE_NONE, NULL, 0x00,
5940                                 "WSP header Proxy-Authorization: password for basic authorization", HFILL
5941                         }
5942                 },
5943                 { &hf_hdr_public,
5944                         {       "Public",
5945                                 "wsp.hdr.public",
5946                                 FT_STRING, BASE_NONE, NULL, 0x00,
5947                                 "WSP header Public", HFILL
5948                         }
5949                 },
5950                 { &hf_hdr_range,
5951                         {       "Range",
5952                                 "wsp.hdr.range",
5953                                 FT_STRING, BASE_NONE, NULL, 0x00,
5954                                 "WSP header Range", HFILL
5955                         }
5956                 },
5957                 { &hf_hdr_range_first_byte_pos,
5958                         {       "First-byte-position",
5959                                 "wsp.hdr.range.first_byte_pos",
5960                                 FT_UINT32, BASE_DEC, NULL, 0x00,
5961                                 "WSP header Range: position of first byte", HFILL
5962                         }
5963                 },
5964                 { &hf_hdr_range_last_byte_pos,
5965                         {       "Last-byte-position",
5966                                 "wsp.hdr.range.last_byte_pos",
5967                                 FT_UINT32, BASE_DEC, NULL, 0x00,
5968                                 "WSP header Range: position of last byte", HFILL
5969                         }
5970                 },
5971                 { &hf_hdr_range_suffix_length,
5972                         {       "Suffix-length",
5973                                 "wsp.hdr.range.suffix_length",
5974                                 FT_UINT32, BASE_DEC, NULL, 0x00,
5975                                 "WSP header Range: length of the suffix", HFILL
5976                         }
5977                 },
5978                 { &hf_hdr_referer,
5979                         {       "Referer",
5980                                 "wsp.hdr.referer",
5981                                 FT_STRING, BASE_NONE, NULL, 0x00,
5982                                 "WSP header Referer", HFILL
5983                         }
5984                 },
5985                 { &hf_hdr_retry_after,
5986                         {       "Retry-After",
5987                                 "wsp.hdr.retry_after",
5988                                 FT_STRING, BASE_NONE, NULL, 0x00,
5989                                 "WSP header Retry-After", HFILL
5990                         }
5991                 },
5992                 { &hf_hdr_server,
5993                         {       "Server",
5994                                 "wsp.hdr.server",
5995                                 FT_STRING, BASE_NONE, NULL, 0x00,
5996                                 "WSP header Server", HFILL
5997                         }
5998                 },
5999                 { &hf_hdr_transfer_encoding,
6000                         {       "Transfer-Encoding",
6001                                 "wsp.hdr.transfer_encoding",
6002                                 FT_STRING, BASE_NONE, NULL, 0x00,
6003                                 "WSP header Transfer-Encoding", HFILL
6004                         }
6005                 },
6006                 { &hf_hdr_upgrade,
6007                         {       "Upgrade",
6008                                 "wsp.hdr.upgrade",
6009                                 FT_STRING, BASE_NONE, NULL, 0x00,
6010                                 "WSP header Upgrade", HFILL
6011                         }
6012                 },
6013                 { &hf_hdr_user_agent,
6014                         {       "User-Agent",
6015                                 "wsp.hdr.user_agent",
6016                                 FT_STRING, BASE_NONE, NULL, 0x00,
6017                                 "WSP header User-Agent", HFILL
6018                         }
6019                 },
6020                 { &hf_hdr_vary,
6021                         {       "Vary",
6022                                 "wsp.hdr.vary",
6023                                 FT_STRING, BASE_NONE, NULL, 0x00,
6024                                 "WSP header Vary", HFILL
6025                         }
6026                 },
6027                 { &hf_hdr_via,
6028                         {       "Via",
6029                                 "wsp.hdr.via",
6030                                 FT_STRING, BASE_NONE, NULL, 0x00,
6031                                 "WSP header Via", HFILL
6032                         }
6033                 },
6034                 { &hf_hdr_warning,
6035                         {       "Warning",
6036                                 "wsp.hdr.warning",
6037                                 FT_STRING, BASE_NONE, NULL, 0x00,
6038                                 "WSP header Warning", HFILL
6039                         }
6040                 },
6041                 { &hf_hdr_warning_code,
6042                         {       "Warning code",
6043                                 "wsp.hdr.warning.code",
6044                                 FT_UINT8, BASE_HEX, VALS(vals_wsp_warning_code), 0x00,
6045                                 "WSP header Warning code", HFILL
6046                         }
6047                 },
6048                 { &hf_hdr_warning_agent,
6049                         {       "Warning agent",
6050                                 "wsp.hdr.warning.agent",
6051                                 FT_STRING, BASE_NONE, NULL, 0x00,
6052                                 "WSP header Warning agent", HFILL
6053                         }
6054                 },
6055                 { &hf_hdr_warning_text,
6056                         {       "Warning text",
6057                                 "wsp.hdr.warning.text",
6058                                 FT_STRING, BASE_NONE, NULL, 0x00,
6059                                 "WSP header Warning text", HFILL
6060                         }
6061                 },
6062                 { &hf_hdr_www_authenticate,
6063                         {       "Www-Authenticate",
6064                                 "wsp.hdr.www_authenticate",
6065                                 FT_STRING, BASE_NONE, NULL, 0x00,
6066                                 "WSP header Www-Authenticate", HFILL
6067                         }
6068                 },
6069                 { &hf_hdr_www_authenticate_scheme,
6070                         {       "Authentication Scheme",
6071                                 "wsp.hdr.www_authenticate.scheme",
6072                                 FT_STRING, BASE_NONE, NULL, 0x00,
6073                                 "WSP header WWW-Authenticate: used scheme", HFILL
6074                         }
6075                 },
6076                 { &hf_hdr_www_authenticate_realm,
6077                         {       "Authentication Realm",
6078                                 "wsp.hdr.www_authenticate.realm",
6079                                 FT_STRING, BASE_NONE, NULL, 0x00,
6080                                 "WSP header WWW-Authenticate: used realm", HFILL
6081                         }
6082                 },
6083                 { &hf_hdr_content_disposition,
6084                         {       "Content-Disposition",
6085                                 "wsp.hdr.content_disposition",
6086                                 FT_STRING, BASE_NONE, NULL, 0x00,
6087                                 "WSP header Content-Disposition", HFILL
6088                         }
6089                 },
6090                 { &hf_hdr_application_id,
6091                         {       "Application-Id",
6092                                 "wsp.hdr.application_id",
6093                                 FT_STRING, BASE_NONE, NULL, 0x00,
6094                                 "WSP header Application-Id", HFILL
6095                         }
6096                 },
6097                 { &hf_hdr_content_uri,
6098                         {       "Content-Uri",
6099                                 "wsp.hdr.content_uri",
6100                                 FT_STRING, BASE_NONE, NULL, 0x00,
6101                                 "WSP header Content-Uri", HFILL
6102                         }
6103                 },
6104                 { &hf_hdr_initiator_uri,
6105                         {       "Initiator-Uri",
6106                                 "wsp.hdr.initiator_uri",
6107                                 FT_STRING, BASE_NONE, NULL, 0x00,
6108                                 "WSP header Initiator-Uri", HFILL
6109                         }
6110                 },
6111                 { &hf_hdr_bearer_indication,
6112                         {       "Bearer-Indication",
6113                                 "wsp.hdr.bearer_indication",
6114                                 FT_STRING, BASE_NONE, NULL, 0x00,
6115                                 "WSP header Bearer-Indication", HFILL
6116                         }
6117                 },
6118                 { &hf_hdr_push_flag,
6119                         {       "Push-Flag",
6120                                 "wsp.hdr.push_flag",
6121                                 FT_STRING, BASE_NONE, NULL, 0x00,
6122                                 "WSP header Push-Flag", HFILL
6123                         }
6124                 },
6125                 { &hf_hdr_push_flag_auth,
6126                         {       "Initiator URI is authenticated",
6127                                 "wsp.hdr.push_flag.authenticated",
6128                                 FT_UINT8, BASE_DEC, VALS(vals_false_true), 0x01,
6129                                 "The X-Wap-Initiator-URI has been authenticated.", HFILL
6130                         }
6131                 },
6132                 { &hf_hdr_push_flag_trust,
6133                         {       "Content is trusted",
6134                                 "wsp.hdr.push_flag.trusted",
6135                                 FT_UINT8, BASE_DEC, VALS(vals_false_true), 0x02,
6136                                 "The push content is trusted.", HFILL
6137                         }
6138                 },
6139                 { &hf_hdr_push_flag_last,
6140                         {       "Last push message",
6141                                 "wsp.hdr.push_flag.last",
6142                                 FT_UINT8, BASE_DEC, VALS(vals_false_true), 0x04,
6143                                 "Indicates whether this is the last push message.", HFILL
6144                         }
6145                 },
6146                 { &hf_hdr_profile,
6147                         {       "Profile",
6148                                 "wsp.hdr.profile",
6149                                 FT_STRING, BASE_NONE, NULL, 0x00,
6150                                 "WSP header Profile", HFILL
6151                         }
6152                 },
6153                 { &hf_hdr_profile_diff,
6154                         {       "Profile-Diff",
6155                                 "wsp.hdr.profile_diff",
6156                                 FT_STRING, BASE_NONE, NULL, 0x00,
6157                                 "WSP header Profile-Diff", HFILL
6158                         }
6159                 },
6160                 { &hf_hdr_profile_warning,
6161                         {       "Profile-Warning",
6162                                 "wsp.hdr.profile_warning",
6163                                 FT_STRING, BASE_NONE, NULL, 0x00,
6164                                 "WSP header Profile-Warning", HFILL
6165                         }
6166                 },
6167                 { &hf_hdr_expect,
6168                         {       "Expect",
6169                                 "wsp.hdr.expect",
6170                                 FT_STRING, BASE_NONE, NULL, 0x00,
6171                                 "WSP header Expect", HFILL
6172                         }
6173                 },
6174                 { &hf_hdr_te,
6175                         {       "Te",
6176                                 "wsp.hdr.te",
6177                                 FT_STRING, BASE_NONE, NULL, 0x00,
6178                                 "WSP header Te", HFILL
6179                         }
6180                 },
6181                 { &hf_hdr_trailer,
6182                         {       "Trailer",
6183                                 "wsp.hdr.trailer",
6184                                 FT_STRING, BASE_NONE, NULL, 0x00,
6185                                 "WSP header Trailer", HFILL
6186                         }
6187                 },
6188                 { &hf_hdr_x_wap_tod,
6189                         {       "X-Wap-Tod",
6190                                 "wsp.hdr.x_wap_tod",
6191                                 FT_STRING, BASE_NONE, NULL, 0x00,
6192                                 "WSP header X-Wap-Tod", HFILL
6193                         }
6194                 },
6195                 { &hf_hdr_content_id,
6196                         {       "Content-Id",
6197                                 "wsp.hdr.content_id",
6198                                 FT_STRING, BASE_NONE, NULL, 0x00,
6199                                 "WSP header Content-Id", HFILL
6200                         }
6201                 },
6202                 { &hf_hdr_set_cookie,
6203                         {       "Set-Cookie",
6204                                 "wsp.hdr.set_cookie",
6205                                 FT_STRING, BASE_NONE, NULL, 0x00,
6206                                 "WSP header Set-Cookie", HFILL
6207                         }
6208                 },
6209                 { &hf_hdr_cookie,
6210                         {       "Cookie",
6211                                 "wsp.hdr.cookie",
6212                                 FT_STRING, BASE_NONE, NULL, 0x00,
6213                                 "WSP header Cookie", HFILL
6214                         }
6215                 },
6216                 { &hf_hdr_encoding_version,
6217                         {       "Encoding-Version",
6218                                 "wsp.hdr.encoding_version",
6219                                 FT_STRING, BASE_NONE, NULL, 0x00,
6220                                 "WSP header Encoding-Version", HFILL
6221                         }
6222                 },
6223                 { &hf_hdr_x_wap_security,
6224                         {       "X-Wap-Security",
6225                                 "wsp.hdr.x_wap_security",
6226                                 FT_STRING, BASE_NONE, NULL, 0x00,
6227                                 "WSP header X-Wap-Security", HFILL
6228                         }
6229                 },
6230                 { &hf_hdr_x_wap_application_id,
6231                         {       "X-Wap-Application-Id",
6232                                 "wsp.hdr.x_wap_application_id",
6233                                 FT_STRING, BASE_NONE, NULL, 0x00,
6234                                 "WSP header X-Wap-Application-Id", HFILL
6235                         }
6236                 },
6237                 { &hf_hdr_accept_application,
6238                         {       "Accept-Application",
6239                                 "wsp.hdr.accept_application",
6240                                 FT_STRING, BASE_NONE, NULL, 0x00,
6241                                 "WSP header Accept-Application", HFILL
6242                         }
6243                 },
6244
6245
6246                 /*
6247                  * Openwave headers
6248                  */
6249
6250                 /* Textual headers */
6251                 { &hf_hdr_openwave_x_up_proxy_operator_domain,
6252                         {       "x-up-proxy-operator-domain",
6253                                 "wsp.hdr.openwave.x_up_proxy_operator_domain",
6254                                 FT_STRING, BASE_NONE, NULL, 0x00,
6255                                 "WSP Openwave header x-up-proxy-operator-domain", HFILL
6256                         }
6257                 },
6258                 { &hf_hdr_openwave_x_up_proxy_home_page,
6259                         {       "x-up-proxy-home-page",
6260                                 "wsp.hdr.openwave.x_up_proxy_home_page",
6261                                 FT_STRING, BASE_NONE, NULL, 0x00,
6262                                 "WSP Openwave header x-up-proxy-home-page", HFILL
6263                         }
6264                 },
6265                 { &hf_hdr_openwave_x_up_proxy_uplink_version,
6266                         {       "x-up-proxy-uplink-version",
6267                                 "wsp.hdr.openwave.x_up_proxy_uplink_version",
6268                                 FT_STRING, BASE_NONE, NULL, 0x00,
6269                                 "WSP Openwave header x-up-proxy-uplink-version", HFILL
6270                         }
6271                 },
6272                 { &hf_hdr_openwave_x_up_proxy_ba_realm,
6273                         {       "x-up-proxy-ba-realm",
6274                                 "wsp.hdr.openwave.x_up_proxy_ba_realm",
6275                                 FT_STRING, BASE_NONE, NULL, 0x00,
6276                                 "WSP Openwave header x-up-proxy-ba-realm", HFILL
6277                         }
6278                 },
6279                 { &hf_hdr_openwave_x_up_proxy_request_uri,
6280                         {       "x-up-proxy-request-uri",
6281                                 "wsp.hdr.openwave.x_up_proxy_request_uri",
6282                                 FT_STRING, BASE_NONE, NULL, 0x00,
6283                                 "WSP Openwave header x-up-proxy-request-uri", HFILL
6284                         }
6285                 },
6286                 { &hf_hdr_openwave_x_up_proxy_bookmark,
6287                         {       "x-up-proxy-bookmark",
6288                                 "wsp.hdr.openwave.x_up_proxy_bookmark",
6289                                 FT_STRING, BASE_NONE, NULL, 0x00,
6290                                 "WSP Openwave header x-up-proxy-bookmark", HFILL
6291                         }
6292                 },
6293                 /* Integer-value headers */
6294                 { &hf_hdr_openwave_x_up_proxy_push_seq,
6295                         {       "x-up-proxy-push-seq",
6296                                 "wsp.hdr.openwave.x_up_proxy_push_seq",
6297                                 FT_STRING, BASE_NONE, NULL, 0x00,
6298                                 "WSP Openwave header x-up-proxy-push-seq", HFILL
6299                         }
6300                 },
6301                 { &hf_hdr_openwave_x_up_proxy_notify,
6302                         {       "x-up-proxy-notify",
6303                                 "wsp.hdr.openwave.x_up_proxy_notify",
6304                                 FT_STRING, BASE_NONE, NULL, 0x00,
6305                                 "WSP Openwave header x-up-proxy-notify", HFILL
6306                         }
6307                 },
6308                 { &hf_hdr_openwave_x_up_proxy_net_ask,
6309                         {       "x-up-proxy-net-ask",
6310                                 "wsp.hdr.openwave.x_up_proxy_net_ask",
6311                                 FT_STRING, BASE_NONE, NULL, 0x00,
6312                                 "WSP Openwave header x-up-proxy-net-ask", HFILL
6313                         }
6314                 },
6315                 { &hf_hdr_openwave_x_up_proxy_tod,
6316                         {       "x-up-proxy-tod",
6317                                 "wsp.hdr.openwave.x_up_proxy_tod",
6318                                 FT_STRING, BASE_NONE, NULL, 0x00,
6319                                 "WSP Openwave header x-up-proxy-tod", HFILL
6320                         }
6321                 },
6322                 { &hf_hdr_openwave_x_up_proxy_ba_enable,
6323                         {       "x-up-proxy-ba-enable",
6324                                 "wsp.hdr.openwave.x_up_proxy_ba_enable",
6325                                 FT_STRING, BASE_NONE, NULL, 0x00,
6326                                 "WSP Openwave header x-up-proxy-ba-enable", HFILL
6327                         }
6328                 },
6329                 { &hf_hdr_openwave_x_up_proxy_redirect_enable,
6330                         {       "x-up-proxy-redirect-enable",
6331                                 "wsp.hdr.openwave.x_up_proxy_redirect_enable",
6332                                 FT_STRING, BASE_NONE, NULL, 0x00,
6333                                 "WSP Openwave header x-up-proxy-redirect-enable", HFILL
6334                         }
6335                 },
6336                 { &hf_hdr_openwave_x_up_proxy_redirect_status,
6337                         {       "x-up-proxy-redirect-status",
6338                                 "wsp.hdr.openwave.x_up_proxy_redirect_status",
6339                                 FT_STRING, BASE_NONE, NULL, 0x00,
6340                                 "WSP Openwave header x-up-proxy-redirect-status", HFILL
6341                         }
6342                 },
6343                 { &hf_hdr_openwave_x_up_proxy_linger,
6344                         {       "x-up-proxy-linger",
6345                                 "wsp.hdr.openwave.x_up_proxy_linger",
6346                                 FT_STRING, BASE_NONE, NULL, 0x00,
6347                                 "WSP Openwave header x-up-proxy-linger", HFILL
6348                         }
6349                 },
6350                 { &hf_hdr_openwave_x_up_proxy_enable_trust,
6351                         {       "x-up-proxy-enable-trust",
6352                                 "wsp.hdr.openwave.x_up_proxy_enable_trust",
6353                                 FT_STRING, BASE_NONE, NULL, 0x00,
6354                                 "WSP Openwave header x-up-proxy-enable-trust", HFILL
6355                         }
6356                 },
6357                 { &hf_hdr_openwave_x_up_proxy_trust,
6358                         {       "x-up-proxy-trust",
6359                                 "wsp.hdr.openwave.x_up_proxy_trust",
6360                                 FT_STRING, BASE_NONE, NULL, 0x00,
6361                                 "WSP Openwave header x-up-proxy-trust", HFILL
6362                         }
6363                 },
6364                 { &hf_hdr_openwave_x_up_devcap_has_color,
6365                         {       "x-up-devcap-has-color",
6366                                 "wsp.hdr.openwave.x_up_devcap_has_color",
6367                                 FT_STRING, BASE_NONE, NULL, 0x00,
6368                                 "WSP Openwave header x-up-devcap-has-color", HFILL
6369                         }
6370                 },
6371                 { &hf_hdr_openwave_x_up_devcap_num_softkeys,
6372                         {       "x-up-devcap-num-softkeys",
6373                                 "wsp.hdr.openwave.x_up_devcap_num_softkeys",
6374                                 FT_STRING, BASE_NONE, NULL, 0x00,
6375                                 "WSP Openwave header x-up-devcap-num-softkeys", HFILL
6376                         }
6377                 },
6378                 { &hf_hdr_openwave_x_up_devcap_softkey_size,
6379                         {       "x-up-devcap-softkey-size",
6380                                 "wsp.hdr.openwave.x_up_devcap_softkey_size",
6381                                 FT_STRING, BASE_NONE, NULL, 0x00,
6382                                 "WSP Openwave header x-up-devcap-softkey-size", HFILL
6383                         }
6384                 },
6385                 { &hf_hdr_openwave_x_up_devcap_screen_chars,
6386                         {       "x-up-devcap-screen-chars",
6387                                 "wsp.hdr.openwave.x_up_devcap_screen_chars",
6388                                 FT_STRING, BASE_NONE, NULL, 0x00,
6389                                 "WSP Openwave header x-up-devcap-screen-chars", HFILL
6390                         }
6391                 },
6392                 { &hf_hdr_openwave_x_up_devcap_screen_pixels,
6393                         {       "x-up-devcap-screen-pixels",
6394                                 "wsp.hdr.openwave.x_up_devcap_screen_pixels",
6395                                 FT_STRING, BASE_NONE, NULL, 0x00,
6396                                 "WSP Openwave header x-up-devcap-screen-pixels", HFILL
6397                         }
6398                 },
6399                 { &hf_hdr_openwave_x_up_devcap_em_size,
6400                         {       "x-up-devcap-em-size",
6401                                 "wsp.hdr.openwave.x_up_devcap_em_size",
6402                                 FT_STRING, BASE_NONE, NULL, 0x00,
6403                                 "WSP Openwave header x-up-devcap-em-size", HFILL
6404                         }
6405                 },
6406                 { &hf_hdr_openwave_x_up_devcap_screen_depth,
6407                         {       "x-up-devcap-screen-depth",
6408                                 "wsp.hdr.openwave.x_up_devcap_screen_depth",
6409                                 FT_STRING, BASE_NONE, NULL, 0x00,
6410                                 "WSP Openwave header x-up-devcap-screen-depth", HFILL
6411                         }
6412                 },
6413                 { &hf_hdr_openwave_x_up_devcap_immed_alert,
6414                         {       "x-up-devcap-immed-alert",
6415                                 "wsp.hdr.openwave.x_up_devcap_immed_alert",
6416                                 FT_STRING, BASE_NONE, NULL, 0x00,
6417                                 "WSP Openwave header x-up-devcap-immed-alert", HFILL
6418                         }
6419                 },
6420                 { &hf_hdr_openwave_x_up_devcap_gui,
6421                         {       "x-up-devcap-gui",
6422                                 "wsp.hdr.openwave.x_up_devcap_gui",
6423                                 FT_STRING, BASE_NONE, NULL, 0x00,
6424                                 "WSP Openwave header x-up-devcap-gui", HFILL
6425                         }
6426                 },
6427                 { &hf_hdr_openwave_x_up_proxy_trans_charset,
6428                         {       "x-up-proxy-trans-charset",
6429                                 "wsp.hdr.openwave.x_up_proxy_trans_charset",
6430                                 FT_STRING, BASE_NONE, NULL, 0x00,
6431                                 "WSP Openwave header x-up-proxy-trans-charset", HFILL
6432                         }
6433                 },
6434                 { &hf_hdr_openwave_x_up_proxy_push_accept,
6435                         {       "x-up-proxy-push-accept",
6436                                 "wsp.hdr.openwave.x_up_proxy_push_accept",
6437                                 FT_STRING, BASE_NONE, NULL, 0x00,
6438                                 "WSP Openwave header x-up-proxy-push-accept", HFILL
6439                         }
6440                 },
6441
6442                 /* Not used for now
6443                 { &hf_hdr_openwave_x_up_proxy_client_id,
6444                         {       "x-up-proxy-client-id",
6445                                 "wsp.hdr.openwave.x_up_proxy_client_id",
6446                                 FT_STRING, BASE_NONE, NULL, 0x00,
6447                                 "WSP Openwave header x-up-proxy-client-id", HFILL
6448                         }
6449                 },
6450                 */
6451
6452                 /*
6453                  * Header value parameters
6454                  */
6455
6456                 { &hf_parameter_q,
6457                         {       "Q",
6458                                 "wsp.parameter.q",
6459                                  FT_STRING, BASE_NONE, NULL, 0x00,
6460                                 "Q parameter", HFILL
6461                         }
6462                 },
6463                 { &hf_parameter_charset,
6464                         {       "Charset",
6465                                 "wsp.parameter.charset",
6466                                  FT_STRING, BASE_NONE, NULL, 0x00,
6467                                 "Charset parameter", HFILL
6468                         }
6469                 },
6470         };
6471
6472
6473 /* Setup protocol subtree array */
6474         static gint *ett[] = { /* TODO - remove unneeded subtrees */
6475                 &ett_wsp,
6476                 &ett_header, /* Header field subtree */
6477                 &ett_headers, /* Subtree for WSP headers */
6478                 &ett_capabilities, /* CO-WSP Session Capabilities */
6479                 &ett_post,
6480                 &ett_redirect_flags,
6481                 &ett_redirect_afl,
6482                 &ett_multiparts,
6483                 &ett_mpartlist,
6484         };
6485
6486 /* Register the protocol name and description */
6487         proto_wsp = proto_register_protocol(
6488                 "Wireless Session Protocol",    /* protocol name for use by ethereal */
6489                 "WSP",                          /* short version of name */
6490                 "wap-wsp"                       /* Abbreviated protocol name,
6491                                                                                    should Match IANA:
6492             < URL:http://www.isi.edu/in-notes/iana/assignments/port-numbers/ >
6493                                                                                 */
6494         );
6495         wsp_tap = register_tap("wsp");
6496         /* Init the hash table */
6497 /*      wsp_sessions = g_hash_table_new(
6498                         (GHashFunc) wsp_session_hash,
6499                         (GEqualFunc)wsp_session_equal);*/
6500
6501 /* Required function calls to register the header fields and subtrees used  */
6502         proto_register_field_array(proto_wsp, hf, array_length(hf));
6503         proto_register_subtree_array(ett, array_length(ett));
6504
6505         register_dissector("wsp-co", dissect_wsp_fromwap_co, proto_wsp);
6506         register_dissector("wsp-cl", dissect_wsp_fromwap_cl, proto_wsp);
6507         wsp_dissector_table = register_dissector_table(
6508                         "wsp.content_type.integer",
6509                         "WSP content type (well-known integer value)",
6510                         FT_UINT32, BASE_HEX);
6511         /* As the media types for WSP and HTTP are the same, the WSP dissector
6512          * uses the same string dissector table as the HTTP protocol. This is
6513          * not true for the integer representation of the WSP media types. */
6514         wsp_dissector_table_text = find_dissector_table("media_type");
6515         register_heur_dissector_list("wsp", &heur_subdissector_list);
6516
6517         wsp_fromudp_handle = create_dissector_handle(dissect_wsp_fromudp,
6518             proto_wsp);
6519 };
6520
6521 void
6522 proto_reg_handoff_wsp(void)
6523 {
6524         /*
6525          * Get a handle for the WBXML dissector.
6526          */
6527         wbxml_handle = find_dissector("wbxml");
6528
6529         /*
6530          * And get a handle for the WTP-over-UDP dissector.
6531          */
6532         wtp_fromudp_handle = find_dissector("wtp-udp");
6533
6534         /* Only connection-less WSP has no previous handler */
6535         dissector_add("udp.port", UDP_PORT_WSP, wsp_fromudp_handle);
6536         dissector_add("udp.port", UDP_PORT_WSP_PUSH, wsp_fromudp_handle);
6537
6538         /* SMPP dissector can also carry WSP */
6539         dissector_add("smpp.udh.port", UDP_PORT_WSP, wsp_fromudp_handle);
6540         dissector_add("smpp.udh.port", UDP_PORT_WSP_PUSH, wsp_fromudp_handle);
6541
6542         /* This dissector is also called from the WTP and WTLS dissectors */
6543 }