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